diff --git a/package.json b/package.json index 256d3320eb..3a99e16d17 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ "translate:app": "bun run script/translate-app.ts", "test": "echo 'do not run tests from root' && exit 1", "extension": "bun --cwd packages/kilo-vscode script/launch.ts", + "extension:isolated": "bun --cwd packages/kilo-vscode script/launch.ts --isolated", + "extension:isolated:clean": "bun --cwd packages/kilo-vscode script/launch.ts --isolated --clean", "dev-setup": "bun run --cwd packages/opencode --conditions=browser src/index.ts dev-setup", "dev:local": "bun run packages/opencode/script/dev-local.ts" }, diff --git a/packages/client/package.json b/packages/client/package.json index 3e13a995f1..464041fe71 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -12,6 +12,7 @@ "generate": "bun run script/build.ts", "check:generated": "bun run generate && git diff --exit-code -- src/generated src/generated-effect", "test": "bun test --timeout 5000", + "test:ci": "mkdir -p .artifacts/unit && bun test --timeout 10000 --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml", "typecheck": "tsgo --noEmit" }, "dependencies": { diff --git a/packages/codemode/package.json b/packages/codemode/package.json index d90649cdbf..f275421046 100644 --- a/packages/codemode/package.json +++ b/packages/codemode/package.json @@ -11,7 +11,8 @@ }, "scripts": { "typecheck": "tsgo --noEmit", - "test": "bun test" + "test": "bun test", + "test:ci": "mkdir -p .artifacts/unit && bun test --timeout 30000 --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml" }, "dependencies": { "acorn": "8.15.0", diff --git a/packages/core/test/models.test.ts b/packages/core/test/models.test.ts index e7adc4c090..077b7d7652 100644 --- a/packages/core/test/models.test.ts +++ b/packages/core/test/models.test.ts @@ -18,16 +18,22 @@ import path from "path" // bun process. const ORIGINAL_MODELS_PATH = Flag.KILO_MODELS_PATH const ORIGINAL_DISABLE_FETCH = Flag.KILO_DISABLE_MODELS_FETCH +// kilocode_change start - isolate the mutable cache fixture from parallel package test processes +const original = Global.Path.cache +const root = path.join(Global.Path.tmp, `models-test-${process.pid}-${Math.random().toString(36).slice(2)}`) +// kilocode_change end beforeAll(() => { Flag.KILO_MODELS_PATH = undefined Flag.KILO_DISABLE_MODELS_FETCH = true + Global.Path.cache = root // kilocode_change }) afterAll(() => { Flag.KILO_MODELS_PATH = ORIGINAL_MODELS_PATH Flag.KILO_DISABLE_MODELS_FETCH = ORIGINAL_DISABLE_FETCH + Global.Path.cache = original // kilocode_change }) -const cacheFile = path.join(Global.Path.cache, "models.json") +const cacheFile = path.join(root, "models.json") // kilocode_change const fixture: Record = { acme: { @@ -117,7 +123,7 @@ beforeEach(async () => { }) afterAll(async () => { - await rm(cacheFile, { force: true }) + await rm(root, { recursive: true, force: true }) // kilocode_change }) const initialState: MockState = { diff --git a/packages/http-recorder/package.json b/packages/http-recorder/package.json index 7b4004ee08..0b01f0809b 100644 --- a/packages/http-recorder/package.json +++ b/packages/http-recorder/package.json @@ -10,8 +10,8 @@ "url": "git+https://github.com/Kilo-Org/kilocode.git", "directory": "packages/http-recorder" }, - "homepage": "https://github.com/anomalyco/opencode/tree/dev/packages/http-recorder", - "bugs": "https://github.com/anomalyco/opencode/issues", + "homepage": "https://github.com/Kilo-Org/kilocode/tree/main/packages/http-recorder", + "bugs": "https://github.com/Kilo-Org/kilocode/issues", "keywords": [ "effect", "http", diff --git a/packages/httpapi-codegen/package.json b/packages/httpapi-codegen/package.json index 40d0b18baf..1a1e2d7911 100644 --- a/packages/httpapi-codegen/package.json +++ b/packages/httpapi-codegen/package.json @@ -8,6 +8,7 @@ }, "scripts": { "test": "bun test --timeout 5000 --only-failures", + "test:ci": "mkdir -p .artifacts/unit && bun test --timeout 5000 --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml", "typecheck": "tsgo --noEmit" }, "dependencies": { diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 3566354759..bed3260a49 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -432,7 +432,12 @@ const layer = Layer.effect( }) const ensureGitignore = Effect.fn("Config.ensureGitignore")(function* (dir: string) { - yield* fs.ensureDir(dir) + // kilocode_change start - optional config setup must not abort tools after entering filesystem confinement + yield* fs.ensureDir(dir).pipe( + Effect.catchReason("PlatformError", "PermissionDenied", () => Effect.void), + Effect.catchReason("PlatformError", "NotFound", () => Effect.void), + ) + // kilocode_change end const gitignore = path.join(dir, ".gitignore") const hasIgnore = yield* fs.existsSafe(gitignore) if (!hasIgnore) { diff --git a/packages/opencode/src/session/prompt/meta.txt b/packages/opencode/src/session/prompt/meta.txt index 8f0c926c03..4d6e30f27c 100644 --- a/packages/opencode/src/session/prompt/meta.txt +++ b/packages/opencode/src/session/prompt/meta.txt @@ -6,7 +6,7 @@ IMPORTANT: You must NEVER generate or guess URLs for the user unless you are con If the user asks for help or wants to give feedback inform them of the following: - ctrl+p to list available actions - To give feedback, users should report the issue at - https://github.com/anomalyco/opencode + https://github.com/Kilo-Org/kilocode When the user directly asks about OpenCode (eg. "can OpenCode do...", "does OpenCode have..."), or asks in second person (eg. "are you able...", "can you do..."), or asks how to use a specific OpenCode feature (eg. implement a hook, write a slash command, or install an MCP server), use the WebFetch tool to gather information to answer the question from OpenCode docs. The list of available docs is available at https://opencode.ai/docs # Tone and style - Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked. diff --git a/packages/opencode/src/session/tools.ts b/packages/opencode/src/session/tools.ts index 31e872da69..6ceae9fe34 100644 --- a/packages/opencode/src/session/tools.ts +++ b/packages/opencode/src/session/tools.ts @@ -74,6 +74,7 @@ export const resolve = Effect.fn("SessionTools.resolve")(function* (input: { const permissionOrigins = cfg.permission_origins // kilocode_change end const flags = yield* RuntimeFlags.Service + const restricted = yield* SandboxPolicy.networkRestricted(input.session.id) // kilocode_change const context = (args: Record, options: ToolExecutionOptions): Tool.Context => ({ sessionID: input.session.id, @@ -127,6 +128,7 @@ export const resolve = Effect.fn("SessionTools.resolve")(function* (input: { family: input.model.family, // kilocode_change agent: input.agent, permission: input.session.permission, + networkRestricted: restricted, // kilocode_change - let the registry suppress code-mode in restricted sessions })) { // kilocode_change start - SWE-Pruner (experimental): advertise the focus parameter on prunable tools const pruner = swe && SwePruner.prunable(item.id) @@ -178,7 +180,6 @@ export const resolve = Effect.fn("SessionTools.resolve")(function* (input: { }) } - const restricted = yield* SandboxPolicy.networkRestricted(input.session.id) // kilocode_change const hasMcpResourceServer = Object.values(yield* mcp.clients()).some( (client) => !!client.getServerCapabilities()?.resources, ) diff --git a/packages/opencode/src/tool/code-mode.ts b/packages/opencode/src/tool/code-mode.ts index ff949efd33..737e1250db 100644 --- a/packages/opencode/src/tool/code-mode.ts +++ b/packages/opencode/src/tool/code-mode.ts @@ -219,7 +219,8 @@ export const CodeModeTool = Tool.define( const agent = yield* agents.get(ctx.agent) const session = yield* sessions.get(ctx.sessionID).pipe(Effect.orDie) const ruleset = Permission.merge(agent.permission, session.permission ?? []) - const mcpTools = Permission.visibleTools(yield* mcp.tools(), ruleset) + const restricted = yield* bridge.run(SandboxPolicy.networkRestricted(ctx.sessionID)) // kilocode_change + const mcpTools = restricted ? {} : Permission.visibleTools(yield* mcp.tools(), ruleset) // kilocode_change const servers = Object.keys(yield* mcp.clients()).map(McpCatalog.sanitize) const catalog = [...groupByServer(mcpTools, servers).values()].flat() diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts index ad0c98843f..716484e6e5 100644 --- a/packages/opencode/src/tool/registry.ts +++ b/packages/opencode/src/tool/registry.ts @@ -105,6 +105,7 @@ export interface Interface { family?: string agent: Agent.Info permission?: PermissionV1.Ruleset + networkRestricted?: boolean // kilocode_change - hide network-backed code-mode catalogs in restricted sessions }) => Effect.Effect // kilocode_change end } @@ -359,8 +360,10 @@ const layer = Layer.effect( const describeCodeMode = Effect.fn("ToolRegistry.describeCodeMode")(function* (input: { agent: Agent.Info permission?: PermissionV1.Ruleset + networkRestricted?: boolean // kilocode_change }) { if (!codeMode) return + if (input.networkRestricted) return // kilocode_change const ruleset = Permission.merge(input.agent.permission, input.permission ?? []) const tools = Permission.visibleTools(yield* mcp.tools(), ruleset) if (Object.keys(tools).length === 0) return diff --git a/packages/opencode/test/account/service.test.ts b/packages/opencode/test/account/service.test.ts index 26e7a7a7b3..672d549716 100644 --- a/packages/opencode/test/account/service.test.ts +++ b/packages/opencode/test/account/service.test.ts @@ -36,7 +36,7 @@ const insideEagerRefreshWindow = Duration.toMillis(Duration.minutes(1)) const outsideEagerRefreshWindow = Duration.toMillis(Duration.minutes(10)) const live = (client: HttpClient.HttpClient) => - LayerNode.compile(Account.node, [[httpClient, Layer.succeed(HttpClient.HttpClient, client)]]) // kilocode_change + LayerNode.compile(Account.node, [[httpClient, Layer.succeed(HttpClient.HttpClient, client)]]) const json = (req: Parameters[0], body: unknown, status = 200) => HttpClientResponse.fromWeb( diff --git a/packages/opencode/test/cli/run/footer.view.test.tsx b/packages/opencode/test/cli/run/footer.view.test.tsx index ee5b21835c..c8db280e81 100644 --- a/packages/opencode/test/cli/run/footer.view.test.tsx +++ b/packages/opencode/test/cli/run/footer.view.test.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @opentui/solid */ import { expect, test } from "bun:test" import { BoxRenderable, RGBA, type RootRenderable } from "@opentui/core" -import { testRender, useRenderer } from "@opentui/solid" +import { extend, testRender, useRenderer } from "@opentui/solid" // kilocode_change - register test components in this renderer instance import { createSignal } from "solid-js" import { createDefaultOpenTuiKeymap } from "@opentui/keymap/opentui" import type { QuestionRequest } from "@kilocode/sdk/v2" @@ -35,6 +35,10 @@ import { RunQuestionBody } from "@/cli/cmd/run/footer.question" import { RejectField } from "@/cli/cmd/run/footer.permission" import { createTuiResolvedConfig } from "../../fixture/tui-runtime" +// kilocode_change start - keep renderer tests independent of the animated spinner's native teardown +extend({ spinner: BoxRenderable }) +// kilocode_change end + const tuiConfig = createTuiResolvedConfig() function command(input: { name: string; description: string; source?: "command" | "mcp" | "skill" }) { diff --git a/packages/opencode/test/kilocode/issue-8656-stall.test.ts b/packages/opencode/test/kilocode/issue-8656-stall.test.ts index dbdbf2a46b..35bf5edcf8 100644 --- a/packages/opencode/test/kilocode/issue-8656-stall.test.ts +++ b/packages/opencode/test/kilocode/issue-8656-stall.test.ts @@ -127,7 +127,7 @@ async function stalled(api: ReturnType, state: string) { const stalls = (await readStallState(state)).stalls const parts = timeline(await api.messages(id)) return stalls > 0 && parts.includes("step-finish:tool-calls") - }, 30_000) + }, 60_000) expect(ready).toBe(true) return id } diff --git a/packages/opencode/test/tool/code-mode-integration.test.ts b/packages/opencode/test/tool/code-mode-integration.test.ts index f1146cbeea..7469fcb1e7 100644 --- a/packages/opencode/test/tool/code-mode-integration.test.ts +++ b/packages/opencode/test/tool/code-mode-integration.test.ts @@ -158,7 +158,9 @@ async function buildTool() { tools: () => Effect.succeed(mcpTools), clients: () => Effect.succeed({ [SERVER]: {} as any }), }), - TestConfig.layer(), // kilocode_change - production code mode captures config for sandbox policy + TestConfig.layer({ + get: () => Effect.succeed({ sandbox: { enabled: false, network: "deny" } }), + }), // kilocode_change - production code mode captures config for sandbox policy Layer.succeed(InstanceRef, { directory: process.cwd(), worktree: process.cwd(), project: {} as any }), // kilocode_change AppNodeBuilder.build(Database.node), // kilocode_change - sandbox state uses the session database ) diff --git a/packages/opencode/test/tool/code-mode.test.ts b/packages/opencode/test/tool/code-mode.test.ts index 5aa674c4b2..0722f0317f 100644 --- a/packages/opencode/test/tool/code-mode.test.ts +++ b/packages/opencode/test/tool/code-mode.test.ts @@ -73,7 +73,7 @@ function harness(input: { clients: () => Effect.succeed(Object.fromEntries(input.servers.map((name) => [name, {} as any]))), }), TestConfig.layer({ - get: () => Effect.succeed({ sandbox: { enabled: input.sandbox, network: "deny" } }), + get: () => Effect.succeed({ sandbox: { enabled: input.sandbox ?? false, network: "deny" } }), }), // kilocode_change - production code mode captures config for sandbox policy Layer.succeed(InstanceRef, { directory: process.cwd(), worktree: process.cwd(), project: {} as any }), // kilocode_change AppNodeBuilder.build(Database.node), // kilocode_change - sandbox state uses the session database @@ -159,6 +159,27 @@ describe("code mode execute", () => { expect(tool.description).not.toContain("list_issues") }) + test("does not expose MCP tools when the session network is restricted", async () => { + const called: string[] = [] + const tool = await build( + { + github_list_issues: mcpTool("list_issues", () => { + called.push("github_list_issues") + return "unexpected" + }), + }, + ["github"], + [], + undefined, + true, + ) + + const restrictedCtx = { ...ctx, sessionID: SessionID.make("ses_code-mode-restricted") } + const error = await failure(tool.execute({ code: "return await tools.github.list_issues({})" }, restrictedCtx)) + expect(error.message).toContain("Unknown tool 'github.list_issues'") + expect(called).toEqual([]) + }) + test("small catalogs inline every full signature in the appended catalog", () => { const description = describeFor({ github_create_issue: mcpTool("create_issue", () => "", { @@ -386,8 +407,8 @@ describe("code mode execute", () => { expect(asked.map((req: any) => req.permission)).toEqual(["a_tool", "b_tool"]) }) - // kilocode_change start - code-mode must preserve remote MCP authority through the sandbox boundary - test("denies remote MCP delegated authority in a network-restricted sandbox", async () => { + // kilocode_change start - code-mode must not advertise remote MCP tools in a network-restricted sandbox + test("does not expose remote MCP tools in a network-restricted sandbox", async () => { let called = false const entry = SandboxNetwork.remote( mcpTool("tool", () => { @@ -404,8 +425,7 @@ describe("code mode execute", () => { ), ) - expect(output.output).toContain("Sandbox denied outbound network access") - expect(output.output).toContain("remote MCP delegated authority") + expect(output.output).toContain("Unknown tool 'remote.tool'") expect(called).toBe(false) }) // kilocode_change end diff --git a/packages/opencode/test/tool/registry.test.ts b/packages/opencode/test/tool/registry.test.ts index 770797fbea..ad6feb888f 100644 --- a/packages/opencode/test/tool/registry.test.ts +++ b/packages/opencode/test/tool/registry.test.ts @@ -117,6 +117,30 @@ const withEmptyCodeMode = testEffect( }), }), ) +// kilocode_change start - verify the execute catalog is suppressed in restricted sessions +const withRestrictedCodeMode = testEffect( + registryLayer({ + flags: { experimentalCodeMode: true }, + config: { + get: () => Effect.succeed({ sandbox: { enabled: true, network: "deny" } }), + }, + mcp: Layer.mock(MCP.Service, { + tools: () => + Effect.succeed({ + weather_current: { + def: { + name: "current", + description: "current weather", + inputSchema: { type: "object", properties: { city: { type: "string" } }, required: ["city"] }, + } as MCPToolDef, + client: {} as MCP.McpTool["client"], + }, + }), + clients: () => Effect.succeed({ weather: {} as MCP.McpTool["client"] }), + }), + }), +) +// kilocode_change end afterEach(async () => { await disposeAllInstances() @@ -266,6 +290,23 @@ describe("tool.registry", () => { }), ) + // kilocode_change start + withRestrictedCodeMode.instance("does not advertise code mode in a network-restricted session", () => + Effect.gen(function* () { + const registry = yield* ToolRegistry.Service + const agents = yield* Agent.Service + const tools = yield* registry.tools({ + providerID: ProviderV2.ID.opencode, + modelID: ModelV2.ID.make("test"), + agent: yield* agents.defaultInfo(), + networkRestricted: true, + }) + + expect(tools.map((tool) => tool.id)).not.toContain("execute") + }), + ) + // kilocode_change end + it.instance("hides task background parameter unless experimental background subagents are enabled", () => Effect.gen(function* () { const registry = yield* ToolRegistry.Service diff --git a/packages/sdk-next/package.json b/packages/sdk-next/package.json index 8bdfce727d..e81813908f 100644 --- a/packages/sdk-next/package.json +++ b/packages/sdk-next/package.json @@ -9,6 +9,7 @@ }, "scripts": { "test": "bun test --timeout 5000", + "test:ci": "mkdir -p .artifacts/unit && bun test --timeout 10000 --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml", "typecheck": "tsgo --noEmit" }, "dependencies": { diff --git a/packages/session-ui/package.json b/packages/session-ui/package.json index 4d309bd329..04acb178cb 100644 --- a/packages/session-ui/package.json +++ b/packages/session-ui/package.json @@ -22,7 +22,8 @@ }, "scripts": { "typecheck": "tsgo --noEmit", - "test": "bun test src --only-failures" + "test": "bun test src --only-failures", + "test:ci": "mkdir -p .artifacts/unit && bun test src --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml" }, "devDependencies": { "@tsconfig/node22": "catalog:", diff --git a/packages/tui/src/component/prompt/index.tsx b/packages/tui/src/component/prompt/index.tsx index 0633d28b59..3449a9b099 100644 --- a/packages/tui/src/component/prompt/index.tsx +++ b/packages/tui/src/component/prompt/index.tsx @@ -67,7 +67,6 @@ import { useVim, VimModeIndicator, vimToggleCommand } from "@/kilocode/cli/cmd/t import { usePromptWorkspace } from "./workspace" import { usePromptMove } from "./move" import { readLocalAttachment } from "./local-attachment" -import { useLocation } from "../../context/location" registerOpencodeSpinner() @@ -163,7 +162,6 @@ export function Prompt(props: PromptProps) { const local = useLocal() const args = useArgs() const paths = useTuiPaths() - const location = useLocation() const terminalEnvironment = useTuiTerminalEnvironment() const clipboard = useClipboard() const sdk = useSDK() @@ -1835,15 +1833,9 @@ export function Prompt(props: PromptProps) { (new working copy) - - {props.hint ?? ( - - - {location()?.directory ?? paths.cwd} - - - )} - + {/* kilocode_change start - Kilo already shows the working directory in its sidebar */} + {props.hint ?? } + {/* kilocode_change end */} diff --git a/packages/ui/src/i18n/it.ts b/packages/ui/src/i18n/it.ts index 9c1d13344c..c4fa753f1b 100644 --- a/packages/ui/src/i18n/it.ts +++ b/packages/ui/src/i18n/it.ts @@ -16,6 +16,22 @@ export const dict: Record = { "ui.sessionReview.largeDiff.title": "Diff troppo grande da mostrare", "ui.sessionReview.largeDiff.meta": "Limite: {{limit}} righe modificate. Corrente: {{current}} righe modificate.", "ui.sessionReview.largeDiff.renderAnyway": "Mostra comunque", + "ui.sessionReviewV2.expandMode": "Expand or collapse diff", + "ui.sessionReviewV2.filterFiles": "Filter files", + "ui.sessionReviewV2.toggleSidebar": "Toggle file tree", + "ui.sessionReviewV2.showAllLines": "Show all lines", + "ui.sessionReviewV2.hideNonDiffLines": "Hide non-diff lines", + "ui.sessionReviewV2.unifiedDiff": "Unified diff", + "ui.sessionReviewV2.splitDiff": "Split diff", + "ui.sessionReviewV2.previousFile": "Previous file", + "ui.sessionReviewV2.nextFile": "Next file", + "ui.sessionReviewV2.diffView": "Diff view", + "ui.sessionReviewV2.empty.noGit.title": "No tracked changes", + "ui.sessionReviewV2.empty.noGit.description": "Track, review, and undo changes in this project", + "ui.sessionReviewV2.empty.noGit.action": "Create Git repository", + "ui.sessionReviewV2.empty.noGit.actionLoading": "Creating Git repository...", + "ui.sessionReviewV2.empty.changes.title": "No file changes yet", + "ui.sessionReviewV2.empty.changes.description": "Project changes will appear here", "ui.sessionReview.openFile": "Apri file", "ui.sessionReview.selection.line": "riga {{line}}", "ui.sessionReview.selection.lines": "righe {{start}}-{{end}}", @@ -36,12 +52,15 @@ export const dict: Record = { "ui.lineComment.editorLabel.suffix": "", "ui.lineComment.placeholder": "Aggiungi commento", "ui.lineComment.submit": "Commenta", + "ui.lineComment.cancel": "Cancel", "ui.sessionTurn.steps.show": "Mostra passaggi", "ui.sessionTurn.steps.hide": "Nascondi passaggi", "ui.sessionTurn.summary.response": "Risposta", "ui.sessionTurn.diff.showMore": "Mostra altre modifiche ({{count}})", "ui.sessionTurn.diffs.changed": "Modificato", + "ui.sessionTurn.diffs.changed.one": "{{count}} Changed file", + "ui.sessionTurn.diffs.changed.other": "{{count}} Changed files", "ui.sessionTurn.diffs.showAll": "Mostra tutto", "ui.sessionTurn.diffs.showLess": "Mostra meno", "ui.sessionTurn.diffs.more": "+{{count}} file aggiuntivi", @@ -161,6 +180,7 @@ export const dict: Record = { "ui.common.close": "Chiudi", "ui.common.next": "Avanti", "ui.common.submit": "Invia", + "ui.common.showMore": "Show more", "ui.permission.deny": "Nega", "ui.permission.allowAlways": "Consenti sempre", diff --git a/packages/ui/src/i18n/nl.ts b/packages/ui/src/i18n/nl.ts index 7404d03ae6..83fc0a7ea1 100644 --- a/packages/ui/src/i18n/nl.ts +++ b/packages/ui/src/i18n/nl.ts @@ -1,3 +1,4 @@ +// kilocode_change - new file export const dict: Record = { "ui.sessionReview.title": "Sessiewijzigingen", "ui.sessionReview.title.git": "Git-wijzigingen", @@ -15,6 +16,22 @@ export const dict: Record = { "ui.sessionReview.largeDiff.title": "Diff te groot om weer te geven", "ui.sessionReview.largeDiff.meta": "Limiet: {{limit}} gewijzigde regels. Huidig: {{current}} gewijzigde regels.", "ui.sessionReview.largeDiff.renderAnyway": "Toch weergeven", + "ui.sessionReviewV2.expandMode": "Expand or collapse diff", + "ui.sessionReviewV2.filterFiles": "Filter files", + "ui.sessionReviewV2.toggleSidebar": "Toggle file tree", + "ui.sessionReviewV2.showAllLines": "Show all lines", + "ui.sessionReviewV2.hideNonDiffLines": "Hide non-diff lines", + "ui.sessionReviewV2.unifiedDiff": "Unified diff", + "ui.sessionReviewV2.splitDiff": "Split diff", + "ui.sessionReviewV2.previousFile": "Previous file", + "ui.sessionReviewV2.nextFile": "Next file", + "ui.sessionReviewV2.diffView": "Diff view", + "ui.sessionReviewV2.empty.noGit.title": "No tracked changes", + "ui.sessionReviewV2.empty.noGit.description": "Track, review, and undo changes in this project", + "ui.sessionReviewV2.empty.noGit.action": "Create Git repository", + "ui.sessionReviewV2.empty.noGit.actionLoading": "Creating Git repository...", + "ui.sessionReviewV2.empty.changes.title": "No file changes yet", + "ui.sessionReviewV2.empty.changes.description": "Project changes will appear here", "ui.sessionReview.openFile": "Bestand openen", "ui.sessionReview.selection.line": "regel {{line}}", "ui.sessionReview.selection.lines": "regels {{start}}-{{end}}", @@ -35,12 +52,15 @@ export const dict: Record = { "ui.lineComment.editorLabel.suffix": "", "ui.lineComment.placeholder": "Opmerking toevoegen", "ui.lineComment.submit": "Reageren", + "ui.lineComment.cancel": "Cancel", "ui.sessionTurn.steps.show": "Stappen tonen", "ui.sessionTurn.steps.hide": "Stappen verbergen", "ui.sessionTurn.summary.response": "Antwoord", "ui.sessionTurn.diff.showMore": "Toon meer wijzigingen ({{count}})", "ui.sessionTurn.diffs.changed": "Gewijzigd", + "ui.sessionTurn.diffs.changed.one": "{{count}} Changed file", + "ui.sessionTurn.diffs.changed.other": "{{count}} Changed files", "ui.sessionTurn.diffs.showAll": "Alles tonen", "ui.sessionTurn.diffs.showLess": "Minder tonen", "ui.sessionTurn.diffs.more": "+{{count}} extra bestanden", @@ -164,6 +184,7 @@ export const dict: Record = { "ui.common.close": "Sluiten", "ui.common.next": "Volgende", "ui.common.submit": "Verzenden", + "ui.common.showMore": "Show more", "ui.permission.deny": "Weigeren", "ui.permission.allowAlways": "Altijd toestaan", diff --git a/packages/ui/src/i18n/uk.ts b/packages/ui/src/i18n/uk.ts index b83c53e980..d71d2cb1ce 100644 --- a/packages/ui/src/i18n/uk.ts +++ b/packages/ui/src/i18n/uk.ts @@ -78,7 +78,7 @@ export const dict: Record = { "dialog.usageExceeded.freeTier.title": "Безкоштовний ліміт вичерпано", "dialog.usageExceeded.freeTier.description": - "Підпишіться на Kilo Go для надійного доступу до найкращих моделей із відкритим кодом від $5 на місяць.", + "Підпишіться на Kilo Go для надійного доступу до найкращих моделей із відкритим кодом від $5 на місяць.", // kilocode_change "dialog.usageExceeded.freeTier.actionLabel": "Підписатися", "dialog.usageExceeded.accountRateLimit.title": "Ліміт Go вичерпано", "dialog.usageExceeded.accountRateLimit.description": diff --git a/script/check-model-tool-network.ts b/script/check-model-tool-network.ts index a3ac2799e7..5a9fe8f05d 100644 --- a/script/check-model-tool-network.ts +++ b/script/check-model-tool-network.ts @@ -123,7 +123,8 @@ const structure = [ ...(!mcp.includes("SandboxNetwork.remote(tool)") ? [" mcp/index.ts must classify remote MCP delegated authority"] : []), - ...(!/SandboxPolicy\.executeMcp\(\s*ctx\.sessionID,\s*item,/.test(session) + // kilocode_change - v1.18 preserves remote authority on the native MCP entry before adapting it to an AI SDK tool + ...(!/SandboxPolicy\.executeMcp\(\s*ctx\.sessionID,\s*entry,/.test(session) ? [" session/tools.ts must route MCP delegated authority through session-aware executeMcp"] : []), ] diff --git a/script/upstream/transforms/transform-package-json.test.ts b/script/upstream/transforms/transform-package-json.test.ts index 2ad35eb5b7..85b95f8c4b 100644 --- a/script/upstream/transforms/transform-package-json.test.ts +++ b/script/upstream/transforms/transform-package-json.test.ts @@ -18,6 +18,8 @@ test("fixScripts preserves Kilo-only root scripts from base", () => { "dev-setup": "kilo dev-setup", postinstall: "bun run --cwd packages/opencode fix-node-pty && bun run script/setup-git.ts", extension: "bun --cwd packages/kilo-vscode script/launch.ts", + "extension:isolated": "bun --cwd packages/kilo-vscode script/launch.ts --isolated", + "extension:isolated:clean": "bun --cwd packages/kilo-vscode script/launch.ts --isolated --clean", }, } const pkg: Record = { @@ -29,6 +31,8 @@ test("fixScripts preserves Kilo-only root scripts from base", () => { expect(scripts.postinstall).toBe(ours.scripts.postinstall) expect(scripts["dev-setup"]).toBe(ours.scripts["dev-setup"]) expect(scripts.extension).toBe(ours.scripts.extension) + expect(scripts["extension:isolated"]).toBe(ours.scripts["extension:isolated"]) + expect(scripts["extension:isolated:clean"]).toBe(ours.scripts["extension:isolated:clean"]) expect(changes.some((c) => c.includes("postinstall"))).toBe(true) expect(changes.some((c) => c.includes("dev-setup"))).toBe(true) }) @@ -95,12 +99,17 @@ test("fixScripts preserves dev:local and shared-package test:ci scripts", () => expect((root.scripts as Record)["dev:local"]).toBe("bun run packages/opencode/script/dev-local.ts") for (const path of [ + "packages/client/package.json", + "packages/httpapi-codegen/package.json", "packages/core/package.json", "packages/effect-drizzle-sqlite/package.json", "packages/http-recorder/package.json", "packages/llm/package.json", + "packages/sdk-next/package.json", + "packages/session-ui/package.json", "packages/tui/package.json", "packages/ui/package.json", + "packages/codemode/package.json", ]) { const pkg: Record = { scripts: { test: "bun test" } } fixScripts(pkg, path, { scripts: { "test:ci": junit } }, changes) diff --git a/script/upstream/transforms/transform-package-json.ts b/script/upstream/transforms/transform-package-json.ts index 87c26debcc..0e958fdb52 100644 --- a/script/upstream/transforms/transform-package-json.ts +++ b/script/upstream/transforms/transform-package-json.ts @@ -282,16 +282,30 @@ const TRANSFORM_PACKAGE_NAMES: Record = { // Upstream's version wholesale-replaces the scripts block, so anything listed // here gets re-applied from ours after taking theirs. const PRESERVE_SCRIPTS: Record = { - "package.json": ["extension", "changeset", "changeset:version", "dev-setup", "postinstall", "dev:local"], + "package.json": [ + "extension", + "extension:isolated", + "extension:isolated:clean", + "changeset", + "changeset:version", + "dev-setup", + "postinstall", + "dev:local", + ], "packages/opencode/package.json": ["test", "test:ci"], // Upstream-shared packages where Kilo adds a JUnit test:ci script for CI. // Without these entries every merge silently schedules zero tests for them. "packages/core/package.json": ["test:ci"], "packages/effect-drizzle-sqlite/package.json": ["test:ci"], "packages/http-recorder/package.json": ["test:ci"], + "packages/client/package.json": ["test:ci"], + "packages/httpapi-codegen/package.json": ["test:ci"], "packages/llm/package.json": ["test:ci"], + "packages/sdk-next/package.json": ["test:ci"], + "packages/session-ui/package.json": ["test:ci"], "packages/tui/package.json": ["test:ci"], "packages/ui/package.json": ["test:ci"], + "packages/codemode/package.json": ["test:ci"], } // Upstream-only trusted dependencies to delete per package.json. Trusted deps