-
Notifications
You must be signed in to change notification settings - Fork 46
feat(extension): add browser agent side panel #4164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
iscekic
wants to merge
52
commits into
main
Choose a base branch
from
feat/add-extension-app
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
4376194
feat(extension): add browser extension app
iscekic c1a07cb
chore(extension): update extension icon
iscekic c288663
chore(extension): refine extension logo icon
iscekic 9ef1055
feat(extension): make sidebar toggle reliable
iscekic c961978
test(extension): add browser debug harness
iscekic f0121ef
style(extension): align sidebar with kilo design
iscekic 31ffdc1
feat(extension): use native side panel
iscekic 20fa2e5
feat(extension): gate side panel with device auth
iscekic 68acf61
style(extension): use kilo logo in side panel header
iscekic 77113e9
style(extension): simplify side panel header logo
iscekic ea5d8d0
feat(extension): target local backend in dev
iscekic 0229a68
chore(extension): run dev server on port 3001
iscekic fd5de66
style(extension): align account controls in header
iscekic 339465f
feat(extension): add debugger html length probe
iscekic 381b0c2
style(extension): add agent chat placeholder shell
iscekic cd0b129
style(extension): compact agent chat controls
iscekic 8206523
style(extension): use icon-only mode control
iscekic 5c26cf7
style(extension): explain agent mode picker
iscekic ff82985
feat(extension): load gateway models in side panel
iscekic 3394d93
feat(extension): run eval from dangerous chat mode
iscekic 52bf61c
feat(extension): add chat header actions
iscekic 1b9a329
feat(extension): run eval through gateway llm
iscekic 4a73cfa
feat(extension): submit chat input on enter
iscekic 91a674d
fix(extension): keep sidebar shell fixed
iscekic 524b5f7
feat(extension): virtualize message pane
iscekic 344fde8
feat(extension): stream agent responses
iscekic 4e99458
fix(extension): prevent eval code horizontal overflow
iscekic 3991ece
refactor(extension): simplify side panel agent
iscekic 7659196
Merge remote-tracking branch 'origin/main' into feat/add-extension-app
iscekic 0dc7af7
fix(extension): keep agent turns ordered
iscekic 3302b56
feat(extension): add organization credit picker
iscekic 237bd07
fix(extension): keep streaming output scrolled
iscekic 89fd45e
feat(extension): stop running agent requests
iscekic 7a2e190
feat(extension): refresh target tabs
iscekic 52ce5f8
feat(extension): persist agent conversations
iscekic 785e525
feat(extension): continue eval tool rounds
iscekic a2098e4
feat(extension): send thinking effort to gateway
iscekic b7354d1
fix(extension): clear unavailable organization selection
iscekic 946d4e7
fix(extension): abort running request on remount
iscekic abd7da7
fix(extension): wait for model catalog
iscekic f6a652f
fix(extension): clear missing selected organization
iscekic 017f3ff
test(extension): observe chat request abort
iscekic f1e2c9f
fix(extension): retry model catalog load
iscekic 447c633
fix(extension): ignore stale model retries
iscekic a701fb4
fix(extension): clear model during catalog reload
iscekic 4ec7201
fix(extension): polish side panel chat
iscekic 04ce1fc
test(extension): assert virtual rows
iscekic 5d7dced
fix(extension): neutralize completed eval panel
iscekic 3218fac
fix(extension): prevent eval panel overflow
iscekic 3efee7c
fix(extension): snapshot tab context in user prompts
iscekic 9eec7a8
test(extension): add firefox e2e smoke
iscekic 6c49bb7
test(extension): cover firefox dangerous mode e2e
iscekic File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Logs | ||
| logs | ||
| *.log | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
| pnpm-debug.log* | ||
| lerna-debug.log* | ||
|
|
||
| node_modules | ||
| .output | ||
| coverage | ||
| playwright-report | ||
| test-results | ||
| stats.html | ||
| stats-*.json | ||
| .wxt | ||
| web-ext.config.ts | ||
| web-ext-artifacts | ||
|
|
||
| # Editor directories and files | ||
| .vscode/* | ||
| !.vscode/extensions.json | ||
| .idea | ||
| .DS_Store | ||
| *.suo | ||
| *.ntvs* | ||
| *.njsproj | ||
| *.sln | ||
| *.sw? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "$schema": "../../node_modules/oxfmt/configuration_schema.json", | ||
| "ignorePatterns": [".wxt/**", ".output/**", "node_modules/**"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| { | ||
| "$schema": "../../node_modules/oxlint/configuration_schema.json", | ||
| "plugins": [ | ||
| "typescript", | ||
| "unicorn", | ||
| "oxc", | ||
| "import", | ||
| "react", | ||
| "react-perf", | ||
| "jsx-a11y", | ||
| "promise", | ||
| "vitest" | ||
| ], | ||
| "categories": { | ||
| "correctness": "error", | ||
| "suspicious": "error", | ||
| "pedantic": "error", | ||
| "perf": "error", | ||
| "style": "error" | ||
| }, | ||
| "rules": { | ||
| "eslint/func-style": "off", | ||
| "eslint/max-lines-per-function": "off", | ||
| "eslint/max-statements": "off", | ||
| "eslint/no-duplicate-imports": "off", | ||
| "eslint/no-magic-numbers": "off", | ||
| "eslint/no-ternary": "off", | ||
| "eslint/no-void": "off", | ||
| "eslint/sort-imports": "off", | ||
| "import/exports-last": "off", | ||
| "import/group-exports": "off", | ||
| "import/no-default-export": "off", | ||
| "import/no-named-export": "off", | ||
| "import/no-unassigned-import": "off", | ||
| "import/prefer-default-export": "off", | ||
| "react/jsx-filename-extension": "off", | ||
| "react/jsx-max-depth": "off", | ||
| "react/jsx-no-literals": "off", | ||
| "react/only-export-components": "off", | ||
| "react/react-in-jsx-scope": "off", | ||
| "react-perf/jsx-no-new-function-as-prop": "off", | ||
| "typescript/prefer-readonly-parameter-types": "off", | ||
| "typescript/strict-void-return": "off", | ||
| "unicorn/no-null": "off", | ||
| "vitest/no-importing-vitest-globals": "off", | ||
| "vitest/prefer-to-be-falsy": "off", | ||
| "vitest/prefer-to-be-truthy": "off", | ||
| "vitest/require-hook": "off", | ||
| "vitest/require-test-timeout": "off" | ||
| }, | ||
| "env": { | ||
| "browser": true, | ||
| "builtin": true, | ||
| "node": true | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| import { enableActionClickSidePanel } from '@/src/shared/side-panel'; | ||
| import { | ||
| EVAL_TAB_MESSAGE, | ||
| LIST_INSPECTABLE_TABS_MESSAGE, | ||
| evalInTab, | ||
| evalInTabWithScripting, | ||
| isTabDebuggerRequest, | ||
| listInspectableTabs, | ||
| listInspectableTabsWithTabsApi, | ||
| } from '@/src/shared/tab-debugger'; | ||
| import type { | ||
| BrowserScriptingApi, | ||
| BrowserTabsApi, | ||
| ChromeDebuggerApi, | ||
| TabDebuggerRequest, | ||
| TabDebuggerResponse, | ||
| } from '@/src/shared/tab-debugger'; | ||
|
|
||
| interface ChromeRuntimeApi { | ||
| readonly onMessage?: { | ||
| readonly addListener: ( | ||
| listener: ( | ||
| message: unknown, | ||
| sender: unknown, | ||
| sendResponse: (response: TabDebuggerResponse) => void | ||
| ) => boolean | void | ||
| ) => void; | ||
| }; | ||
| } | ||
|
|
||
| const handleTabDebuggerRequest = async ({ | ||
| debuggerApi, | ||
| request, | ||
| scriptingApi, | ||
| tabsApi, | ||
| }: { | ||
| debuggerApi: ChromeDebuggerApi | undefined; | ||
| request: TabDebuggerRequest; | ||
| scriptingApi: BrowserScriptingApi | undefined; | ||
| tabsApi: BrowserTabsApi | undefined; | ||
| }): Promise<TabDebuggerResponse> => { | ||
| try { | ||
| if (request.type === LIST_INSPECTABLE_TABS_MESSAGE) { | ||
| if (debuggerApi) { | ||
| return { | ||
| ok: true, | ||
| tabs: await listInspectableTabs(debuggerApi), | ||
| type: LIST_INSPECTABLE_TABS_MESSAGE, | ||
| }; | ||
| } | ||
|
|
||
| if (tabsApi) { | ||
| return { | ||
| ok: true, | ||
| tabs: await listInspectableTabsWithTabsApi(tabsApi), | ||
| type: LIST_INSPECTABLE_TABS_MESSAGE, | ||
| }; | ||
| } | ||
|
|
||
| return { error: 'Tab listing API is unavailable.', ok: false }; | ||
| } | ||
|
|
||
| if (debuggerApi) { | ||
| return { | ||
| ok: true, | ||
| result: await evalInTab({ | ||
| code: request.code, | ||
| debuggerApi, | ||
| tabId: request.tabId, | ||
| ...(request.timeoutMs === undefined ? {} : { timeoutMs: request.timeoutMs }), | ||
| }), | ||
| type: EVAL_TAB_MESSAGE, | ||
| }; | ||
| } | ||
|
|
||
| if (scriptingApi) { | ||
| return { | ||
| ok: true, | ||
| result: await evalInTabWithScripting({ | ||
| code: request.code, | ||
| scriptingApi, | ||
| tabId: request.tabId, | ||
| }), | ||
| type: EVAL_TAB_MESSAGE, | ||
| }; | ||
| } | ||
|
|
||
| return { error: 'Tab evaluation API is unavailable.', ok: false }; | ||
| } catch (error) { | ||
| return { | ||
| error: error instanceof Error ? error.message : 'Debugger request failed.', | ||
| ok: false, | ||
| }; | ||
| } | ||
| }; | ||
|
|
||
| export default defineBackground(() => { | ||
| const chromeApi = ( | ||
| globalThis as typeof globalThis & { | ||
| chrome?: { | ||
| debugger?: ChromeDebuggerApi; | ||
| runtime?: ChromeRuntimeApi; | ||
| scripting?: BrowserScriptingApi; | ||
| sidePanel?: Parameters<typeof enableActionClickSidePanel>[0]; | ||
| tabs?: BrowserTabsApi; | ||
| }; | ||
| } | ||
| ).chrome; | ||
|
|
||
| void enableActionClickSidePanel(chromeApi?.sidePanel); | ||
|
|
||
| chromeApi?.runtime?.onMessage?.addListener((message, sender, sendResponse) => { | ||
| void sender; | ||
|
|
||
| if (!isTabDebuggerRequest(message)) { | ||
| return; | ||
| } | ||
|
|
||
| void (async (): Promise<void> => { | ||
| const response = await handleTabDebuggerRequest({ | ||
| debuggerApi: chromeApi.debugger, | ||
| request: message, | ||
| scriptingApi: chromeApi.scripting, | ||
| tabsApi: chromeApi.tabs, | ||
| }); | ||
| sendResponse(response); | ||
| })(); | ||
|
|
||
| return true; | ||
| }); | ||
| }); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WARNING: Firefox eval requests drop the timeout contract
The Chrome debugger path still forwards
request.timeoutMs, but the new Firefox scripting fallback ignores it entirely. That means the same dangerous-mode eval can time out cleanly in Chromium yet hang indefinitely in Firefox if the generated snippet loops or awaits something that never resolves. Keeping the existing timeout behavior in both backends avoids browser-specific stalls.Reply with
@kilocode-bot fix itto have Kilo Code address this issue.