Merge remote-tracking branch 'origin/main' into maphew/main

# Conflicts:
#	packages/opencode/src/kilocode/review/local-review-uncommitted.txt
#	packages/opencode/src/kilocode/review/review.txt
#	packages/opencode/test/kilocode/local-review-command.test.ts
#	packages/opencode/test/session/prompt.test.ts
This commit is contained in:
Alex Alecu
2026-06-25 14:13:04 +03:00
1395 changed files with 93146 additions and 96800 deletions
+150
View File
@@ -0,0 +1,150 @@
#!/usr/bin/env bun
// kilocode_change - new file
// This is a CI-only architecture test, not production network enforcement. Model tools run
// inside the trusted kilo serve process, so macOS Seatbelt can only confine their spawned
// children. In-process tools must use the policy-aware HTTP capability instead of direct fetch,
// sockets, or ad hoc clients. Keep this narrow scan to prevent future tool implementations from
// accidentally bypassing that boundary; trusted provider and model-inference code is intentionally
// outside the scanned directories. Runtime enforcement remains in @kilocode/sandbox.
import path from "node:path"
import { opaque } from "../packages/opencode/src/kilocode/sandbox/network-tools"
const root = path.resolve(import.meta.dir, "..")
const source = path.join(root, "packages", "opencode", "src")
const dirs = ["tool", "kilocode/tool", "mcp"]
const checks = [
{ name: "direct fetch", pattern: /\b(?:globalThis\.)?fetch\s*\(/g },
{ name: "raw FetchHttpClient layer", pattern: /\bFetchHttpClient\.layer\b/g },
{ name: "direct Bun socket", pattern: /\bBun\.(?:connect|udpSocket)\s*\(/g },
{
name: "raw network module",
pattern:
/\bfrom\s+["'](?:(?:node:)?(?:http|https|http2|net|tls|dgram)(?:\/[^"']*)?|(?:undici|axios|got)(?:\/[^"']*)?)["']/g,
},
{
name: "dynamic network module",
pattern:
/\b(?:require|import)\s*\(\s*["'](?:(?:node:)?(?:http|https|http2|net|tls|dgram)(?:\/[^"']*)?|(?:undici|axios|got)(?:\/[^"']*)?)["']/g,
},
{
name: "ad hoc network client",
pattern:
/\bnew\s+(?:WarpGrepClient|OpenAI|QdrantClient|BedrockRuntimeClient|WebSocket|EventSource|StreamableHTTPClientTransport|SSEClientTransport)\s*\(/g,
},
]
const allow = new Map([
...opaque.flatMap((item) =>
"client" in item
? [[`${item.file}:${item.client.name}`, { ...item.client, file: item.file, id: item.id }] as const]
: [],
),
[
"mcp/index.ts:ad hoc network client",
{
count: 3,
file: "mcp/index.ts",
id: "remote_mcp",
reason: "MCP SDK transports are classified as remote delegated authority before model execution",
},
] as const,
])
const excluded = new Map([
["mcp/oauth-callback.ts", "OAuth callback listener is trusted MCP control-plane setup, not model tool execution"],
])
const hits: Array<{ file: string; name: string; line: number }> = []
const glob = new Bun.Glob("**/*.ts")
for (const dir of dirs) {
for (const file of glob.scanSync({ cwd: path.join(source, dir), onlyFiles: true })) {
const rel = path.posix.join(dir, file.replaceAll("\\", "/"))
if (excluded.has(rel)) continue
const text = await Bun.file(path.join(source, rel)).text()
for (const check of checks) {
for (const match of text.matchAll(check.pattern)) {
hits.push({
file: rel,
name: check.name,
line: text.slice(0, match.index ?? 0).split("\n").length,
})
}
}
}
}
const invalid = hits.filter((hit) => !allow.has(`${hit.file}:${hit.name}`))
const clients = [...allow.entries()].flatMap(([key, entry]) => {
const split = key.lastIndexOf(":")
const file = key.slice(0, split)
const name = key.slice(split + 1)
const count = hits.filter((hit) => hit.file === file && hit.name === name).length
if (count === entry.count) return []
return [` packages/opencode/src/${file}: expected ${entry.count} ${name} site(s), found ${count} (${entry.reason})`]
})
const tools = (
await Promise.all(
opaque.map(async (item) => {
const text = await Bun.file(path.join(source, item.file)).text()
const id = item.id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
if (new RegExp(`Tool\\.define\\(\\s*["']${id}["']`).test(text)) return []
return [` packages/opencode/src/${item.file}: opaque classification must match Tool.define("${item.id}")`]
}),
)
).flat()
const drift = [...clients, ...tools]
const network = await Bun.file(path.join(source, "kilocode", "sandbox", "network.ts")).text()
const registry = await Bun.file(path.join(source, "tool", "registry.ts")).text()
const session = await Bun.file(path.join(source, "session", "tools.ts")).text()
const mcp = await Bun.file(path.join(source, "mcp", "index.ts")).text()
const structure = [
...(!network.includes('import { opaque } from "./network-tools"') ||
!network.includes("opaque.map((item) => item.id)")
? [" kilocode/sandbox/network.ts must derive runtime opaque tool IDs from network-tools.ts"]
: []),
...(!registry.includes("Layer.provide(ToolNetwork.httpLayer)")
? [" tool/registry.ts must provide the policy-aware ToolNetwork HTTP layer"]
: []),
...(registry.includes("FetchHttpClient.layer")
? [" tool/registry.ts must not provide a raw FetchHttpClient layer"]
: []),
...(!registry.includes("ToolNetwork.builtin(result)")
? [" tool/registry.ts must distinguish built-in tools from untrusted custom tools"]
: []),
...(!/SandboxPolicy\.executeTool\(\s*ctx\.sessionID,\s*item,/.test(session)
? [" session/tools.ts must route built-in and custom tools through session-aware executeTool"]
: []),
...(!mcp.includes("SandboxNetwork.remote(tool)")
? [" mcp/index.ts must classify remote MCP delegated authority"]
: []),
...(!/SandboxPolicy\.executeMcp\(\s*ctx\.sessionID,\s*item,/.test(session)
? [" session/tools.ts must route MCP delegated authority through session-aware executeMcp"]
: []),
]
if (invalid.length > 0 || drift.length > 0 || structure.length > 0) {
if (invalid.length > 0) {
console.error("Found model-tool network clients that bypass the sandbox capability:")
for (const hit of invalid) console.error(` packages/opencode/src/${hit.file}:${hit.line} (${hit.name})`)
console.error("")
}
if (drift.length > 0) {
console.error("Classified model-tool network exceptions no longer match source:")
for (const item of drift) console.error(item)
console.error("")
}
if (structure.length > 0) {
console.error("Model-tool network boundary wiring is incomplete:")
for (const item of structure) console.error(item)
console.error("")
}
console.error(
"Use the @kilocode/sandbox network capability or classify an opaque client at the common tool boundary.",
)
process.exit(1)
}
console.log(
`check-model-tool-network: ${hits.length} classified client site(s), policy-aware tool and MCP boundaries verified.`,
)
+1
View File
@@ -50,6 +50,7 @@ const EXEMPT_SCOPES = [
"script/check-opencode-annotations.ts",
"packages/script/tests/check-opencode-annotations.test.ts",
".github/workflows/check-opencode-annotations.yml",
".github/workflows/watch-opencode-releases.yml",
]
const args = process.argv.slice(2)
+2 -7
View File
@@ -29,18 +29,13 @@ const allow: Record<string, string> = {
}
const testAllow: Record<string, { count: number; reason: string }> = {
"control-plane/workspace.test.ts": { count: 5, reason: "existing runtime integration test" },
"kilocode/config-resilience.test.ts": { count: 4, reason: "existing runtime integration test" },
"kilocode/config-validation.test.ts": { count: 2, reason: "existing runtime integration test" },
"kilocode/plan-followup.test.ts": { count: 4, reason: "existing runtime integration test" },
"kilocode/session/platform-attribution.test.ts": { count: 5, reason: "existing runtime integration test" },
"kilocode/session/platform-attribution.test.ts": { count: 2, reason: "existing runtime integration test" },
"kilocode/session-prompt-queue.test.ts": { count: 5, reason: "prompt queue legacy instance bridge regression" },
"kilocode/session/session.test.ts": { count: 5, reason: "existing runtime integration test" },
"provider/amazon-bedrock.test.ts": { count: 2, reason: "existing runtime integration test" },
"provider/provider.test.ts": { count: 3, reason: "existing runtime integration test" },
"server/experimental-session-list.test.ts": { count: 2, reason: "Kilo session list integration test" },
"server/httpapi-event.test.ts": { count: 6, reason: "event stream integration test" },
"session/llm.test.ts": { count: 2, reason: "existing runtime integration test" },
"kilocode/server/listener-runtime.test.ts": { count: 3, reason: "listener and AppRuntime integration test" },
"tool/recall.test.ts": { count: 11, reason: "existing runtime integration test" },
}
+2 -1
View File
@@ -86,13 +86,14 @@ const SKIP_DIRS = ["node_modules", ".storybook", "stories", "test", "tests", "__
const SKIP_PATH_SEGMENTS = ["continuedev"]
// Individual files to skip (data files full of non-user-facing URLs)
const SKIP_FILES = ["models-snapshot.ts", "models-snapshot.js", "check-forbidden-strings.ts"] // kilocode_change
const SKIP_FILES = ["check-forbidden-strings.ts"] // kilocode_change
function shouldExclude(url: string): boolean {
return EXCLUDE_PATTERNS.some((re) => re.test(url))
}
function shouldSkipFile(filepath: string): boolean {
if (filepath === "packages/opencode/src/cli/cmd/account.ts") return true // kilocode_change - command is not registered in Kilo
const rel = path.relative(ROOT, filepath)
const parts = rel.split(path.sep)
if (parts.some((p) => SKIP_DIRS.includes(p))) return true
-2
View File
@@ -7,5 +7,3 @@ await $`bun ./packages/sdk/js/script/build.ts`
await $`bun dev generate > ../sdk/openapi.json`.cwd("packages/opencode")
await $`bun ./script/generate-cli-docs.ts`
await $`./script/format.ts`
+123 -14
View File
@@ -2,14 +2,39 @@
import path from "node:path"
const raw = process.argv[2]
if (!raw) {
console.error("Usage: bun run script/upgrade-opentui.ts <version>")
const args = process.argv.slice(2)
const usage = "Usage: bun run script/upgrade-opentui.ts [--snapshot] <version>"
if (args.includes("--help") || args.includes("-h")) {
console.log(usage)
process.exit(0)
}
const snapshotArg = args.find((arg) => arg.startsWith("--snapshot="))
const snapshot = args.includes("--snapshot") || snapshotArg !== undefined
const unknown = args.find((arg) => arg.startsWith("-") && arg !== "--snapshot" && !arg.startsWith("--snapshot="))
if (unknown) {
console.error(`Unknown option: ${unknown}`)
console.error(usage)
process.exit(1)
}
const positional = args.filter((arg) => arg !== "--snapshot" && !arg.startsWith("--snapshot="))
const raw = snapshotArg?.slice("--snapshot=".length) || positional[0]
if (!raw || positional.length > (snapshotArg ? 0 : 1)) {
console.error(usage)
process.exit(1)
}
if (snapshotArg === "--snapshot=") {
console.error("Missing snapshot version")
console.error(usage)
process.exit(1)
}
const ver = raw.replace(/^v/, "")
const root = path.resolve(import.meta.dir, "..")
const lockfile = path.join(root, "bun.lock")
const skip = new Set([".git", ".opencode", ".turbo", "dist", "node_modules"])
const keys = ["@opentui/core", "@opentui/keymap", "@opentui/solid"] as const
@@ -17,22 +42,24 @@ const files = (await Array.fromAsync(new Bun.Glob("**/package.json").scan({ cwd:
(file) => !file.split("/").some((part) => skip.has(part)),
)
const setVersion = (cur: string) => {
const setVersion = (cur: string, kind: "dep" | "peer") => {
if (cur === "catalog:" || cur.startsWith("workspace:")) return cur
if (snapshot) return ver
if (kind === "peer") return `>=${ver}`
if (cur.startsWith(">=")) return `>=${ver}`
if (cur.startsWith("^")) return `^${ver}`
if (cur.startsWith("~")) return `~${ver}`
return ver
}
const editDeps = (obj: unknown) => {
const editDeps = (obj: unknown, kind: "dep" | "peer") => {
if (!obj || typeof obj !== "object") return false
const map = obj as Record<string, unknown>
return keys
.map((key) => {
const cur = map[key]
if (typeof cur !== "string") return false
const next = setVersion(cur)
const next = setVersion(cur, kind)
if (next === cur) return false
map[key] = next
return true
@@ -53,6 +80,21 @@ const editCatalog = (obj: unknown) => {
.some(Boolean)
}
const editOverrides = (obj: unknown) => {
if (!obj || typeof obj !== "object") return false
const map = obj as Record<string, unknown>
return keys
.map((key) => {
const cur = map[key]
if (typeof cur !== "string") return false
const next = snapshot ? ver : "catalog:"
if (next === cur) return false
map[key] = next
return true
})
.some(Boolean)
}
const out = (
await Promise.all(
files.map(async (rel) => {
@@ -61,9 +103,10 @@ const out = (
const json = JSON.parse(txt)
const hit = [
editCatalog(json.workspaces?.catalog),
editDeps(json.dependencies),
editDeps(json.devDependencies),
editDeps(json.peerDependencies),
editOverrides(json.overrides),
editDeps(json.dependencies, "dep"),
editDeps(json.devDependencies, "dep"),
editDeps(json.peerDependencies, "peer"),
].some(Boolean)
if (!hit) return null
await Bun.write(file, `${JSON.stringify(json, null, 2)}\n`)
@@ -73,11 +116,77 @@ const out = (
).filter((item): item is string => item !== null)
if (out.length === 0) {
console.log("No opentui deps found")
process.exit(0)
console.log(`No opentui manifest updates needed for ${ver}`)
}
console.log(`Updated opentui to ${ver} in:`)
for (const file of out) {
console.log(`- ${file}`)
if (out.length > 0) {
console.log(`Updated opentui${snapshot ? " snapshot" : ""} to ${ver} in:`)
for (const file of out) {
console.log(`- ${file}`)
}
}
console.log("Running bun install to update bun.lock...")
const install = Bun.spawn([process.execPath, "install"], {
cwd: root,
stdout: "inherit",
stderr: "inherit",
})
const installCode = await install.exited
if (installCode !== 0) process.exit(installCode)
const fixed = await fixKnownLockfileIssues()
if (fixed.length > 0) {
console.log("Removed stale opentui-spinner peer lockfile entries:")
for (const item of fixed) {
console.log(`- ${item}`)
}
}
const stale = await findStaleLockfileEntries()
if (stale.length > 0) {
console.error(`bun.lock still contains stale opentui versions after upgrading to ${ver}:`)
for (const item of stale) {
console.error(`- ${item.entry}: ${item.pkg}@${item.version}`)
}
process.exit(1)
}
console.log("bun.lock opentui versions are consistent")
async function fixKnownLockfileIssues() {
const txt = await Bun.file(lockfile).text()
const stale = findStaleLockfileEntriesInText(txt)
if (stale.length === 0) return []
if (stale.some((item) => !item.entry.startsWith("opentui-spinner/@opentui/"))) return []
const removed = txt
.split("\n")
.map((line) => line.match(/^ "(opentui-spinner\/@opentui\/[^\"]+)": /)?.[1])
.filter((item): item is string => item !== undefined)
if (removed.length === 0) return []
await Bun.write(
lockfile,
txt
.split("\n")
.filter((line) => !line.match(/^ "opentui-spinner\/@opentui\//))
.join("\n"),
)
return removed
}
async function findStaleLockfileEntries() {
return findStaleLockfileEntriesInText(await Bun.file(lockfile).text())
}
function findStaleLockfileEntriesInText(txt: string) {
return Array.from(txt.matchAll(/^ "([^"]+)": \["(@opentui\/(?:core(?:-[^@"]+)?|keymap|solid))@([^"]+)"/gm))
.map((match) => ({
entry: match[1]!,
pkg: match[2]!,
version: match[3]!,
}))
.filter((item) => item.version !== ver)
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@kilocode/upstream-merge",
"version": "7.3.46",
"version": "7.3.54",
"private": true,
"type": "module",
"description": "Scripts for automating upstream opencode merges into Kilo",
@@ -11,6 +11,16 @@ test("matches removed app package glob paths", () => {
expect(shouldSkip("packages/app/package.json", ["packages/app/**"])).toBe(true)
})
test("matches upstream CLI scaffold glob paths", () => {
expect(shouldSkip("packages/cli/package.json", ["packages/cli/**"])).toBe(true)
expect(shouldSkip("packages/cli/src/index.ts", ["packages/cli/**"])).toBe(true)
})
test("matches upstream stats package glob paths", () => {
expect(shouldSkip("packages/stats/app/package.json", ["packages/stats/**"])).toBe(true)
expect(shouldSkip("packages/stats/core/src/index.ts", ["packages/stats/**"])).toBe(true)
})
test("matches removed vscode sdk glob paths", () => {
expect(shouldSkip("sdks/vscode/package.json", ["sdks/vscode/**"])).toBe(true)
expect(shouldSkip("sdks/vscode/src/extension.ts", ["sdks/vscode/**"])).toBe(true)
+2
View File
@@ -159,6 +159,8 @@ export const defaultConfig: MergeConfig = {
"packages/app/**",
"packages/desktop/**",
"packages/desktop-electron/**",
"packages/cli/**",
"packages/stats/**",
"sdks/vscode/**",
// GitHub Action - Kilo version is fully ported and complete
"github/index.ts",