Skip to content
Open
Show file tree
Hide file tree
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 Jun 22, 2026
c1a07cb
chore(extension): update extension icon
iscekic Jun 22, 2026
c288663
chore(extension): refine extension logo icon
iscekic Jun 22, 2026
9ef1055
feat(extension): make sidebar toggle reliable
iscekic Jun 22, 2026
c961978
test(extension): add browser debug harness
iscekic Jun 22, 2026
f0121ef
style(extension): align sidebar with kilo design
iscekic Jun 22, 2026
31ffdc1
feat(extension): use native side panel
iscekic Jun 22, 2026
20fa2e5
feat(extension): gate side panel with device auth
iscekic Jun 22, 2026
68acf61
style(extension): use kilo logo in side panel header
iscekic Jun 22, 2026
77113e9
style(extension): simplify side panel header logo
iscekic Jun 22, 2026
ea5d8d0
feat(extension): target local backend in dev
iscekic Jun 22, 2026
0229a68
chore(extension): run dev server on port 3001
iscekic Jun 22, 2026
fd5de66
style(extension): align account controls in header
iscekic Jun 22, 2026
339465f
feat(extension): add debugger html length probe
iscekic Jun 22, 2026
381b0c2
style(extension): add agent chat placeholder shell
iscekic Jun 22, 2026
cd0b129
style(extension): compact agent chat controls
iscekic Jun 22, 2026
8206523
style(extension): use icon-only mode control
iscekic Jun 22, 2026
5c26cf7
style(extension): explain agent mode picker
iscekic Jun 22, 2026
ff82985
feat(extension): load gateway models in side panel
iscekic Jun 22, 2026
3394d93
feat(extension): run eval from dangerous chat mode
iscekic Jun 22, 2026
52bf61c
feat(extension): add chat header actions
iscekic Jun 22, 2026
1b9a329
feat(extension): run eval through gateway llm
iscekic Jun 22, 2026
4a73cfa
feat(extension): submit chat input on enter
iscekic Jun 22, 2026
91a674d
fix(extension): keep sidebar shell fixed
iscekic Jun 22, 2026
524b5f7
feat(extension): virtualize message pane
iscekic Jun 22, 2026
344fde8
feat(extension): stream agent responses
iscekic Jun 22, 2026
4e99458
fix(extension): prevent eval code horizontal overflow
iscekic Jun 22, 2026
3991ece
refactor(extension): simplify side panel agent
iscekic Jun 22, 2026
7659196
Merge remote-tracking branch 'origin/main' into feat/add-extension-app
iscekic Jun 22, 2026
0dc7af7
fix(extension): keep agent turns ordered
iscekic Jun 22, 2026
3302b56
feat(extension): add organization credit picker
iscekic Jun 22, 2026
237bd07
fix(extension): keep streaming output scrolled
iscekic Jun 22, 2026
89fd45e
feat(extension): stop running agent requests
iscekic Jun 22, 2026
7a2e190
feat(extension): refresh target tabs
iscekic Jun 22, 2026
52ce5f8
feat(extension): persist agent conversations
iscekic Jun 22, 2026
785e525
feat(extension): continue eval tool rounds
iscekic Jun 22, 2026
a2098e4
feat(extension): send thinking effort to gateway
iscekic Jun 22, 2026
b7354d1
fix(extension): clear unavailable organization selection
iscekic Jun 22, 2026
946d4e7
fix(extension): abort running request on remount
iscekic Jun 22, 2026
abd7da7
fix(extension): wait for model catalog
iscekic Jun 22, 2026
f6a652f
fix(extension): clear missing selected organization
iscekic Jun 22, 2026
017f3ff
test(extension): observe chat request abort
iscekic Jun 22, 2026
f1e2c9f
fix(extension): retry model catalog load
iscekic Jun 22, 2026
447c633
fix(extension): ignore stale model retries
iscekic Jun 22, 2026
a701fb4
fix(extension): clear model during catalog reload
iscekic Jun 22, 2026
4ec7201
fix(extension): polish side panel chat
iscekic Jun 22, 2026
04ce1fc
test(extension): assert virtual rows
iscekic Jun 22, 2026
5d7dced
fix(extension): neutralize completed eval panel
iscekic Jun 22, 2026
3218fac
fix(extension): prevent eval panel overflow
iscekic Jun 22, 2026
3efee7c
fix(extension): snapshot tab context in user prompts
iscekic Jun 22, 2026
9eec7a8
test(extension): add firefox e2e smoke
iscekic Jun 22, 2026
6c49bb7
test(extension): cover firefox dangerous mode e2e
iscekic Jun 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions apps/extension/.gitignore
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?
4 changes: 4 additions & 0 deletions apps/extension/.oxfmtrc.json
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/**"]
}
56 changes: 56 additions & 0 deletions apps/extension/.oxlintrc.json
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
}
}
131 changes: 131 additions & 0 deletions apps/extension/entrypoints/background.ts
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({

Copy link
Copy Markdown
Contributor

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 it to have Kilo Code address this issue.

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;
});
});
Loading