Merge remote-tracking branch 'origin/main' into trial/kilo-opencode-v1.14.42

# Conflicts:
#	packages/opencode/src/cli/cmd/run.ts
This commit is contained in:
marius-kilocode
2026-06-02 11:41:28 +02:00
3 changed files with 49 additions and 3 deletions
+2 -3
View File
@@ -21,6 +21,7 @@ import { UI } from "../ui"
import { effectCmd } from "../effect-cmd"
import { Flag } from "@opencode-ai/core/flag/flag"
import { ServerAuth } from "@/server/auth"
import { buildRunMessage } from "@/kilocode/cli/cmd/run-message" // kilocode_change
import { EOL } from "os"
import { Filesystem } from "@/util/filesystem"
import { createKiloClient, type KiloClient, type ToolPart } from "@kilocode/sdk/v2"
@@ -263,9 +264,7 @@ export const RunCommand = effectCmd({
throw error
}
let message = [...args.message, ...(args["--"] || [])]
.map((arg) => (arg.includes(" ") ? `"${arg.replace(/"/g, '\\"')}"` : arg))
.join(" ")
let message = buildRunMessage(args.message, args["--"]) // kilocode_change
if (args.interactive && args.command) {
die("--interactive cannot be used with --command")
@@ -0,0 +1,11 @@
// Atoms before `--` are positional shell arguments where re-quoting around
// embedded spaces preserves the user's word-binding intent (PR #4979).
// Atoms in `args["--"]` are raw passthrough per yargs `populate--` semantics:
// the user typed `--` to opt out of further parsing, so the assembler must
// not synthesize quote bytes around them. Re-quoting raw atoms breaks
// leading-dash inputs like `kilo run -- "- Who are you?"` (#9622) by
// emitting `"- Who are you?"` (literal quotes) into the model prompt.
export function buildRunMessage(positionals: string[], dash?: string[]): string {
const quoted = positionals.map((arg) => (arg.includes(" ") ? `"${arg.replace(/"/g, '\\"')}"` : arg))
return [...quoted, ...(dash ?? [])].join(" ")
}
@@ -0,0 +1,36 @@
import { describe, expect, test } from "bun:test"
import { buildRunMessage } from "../../../../src/kilocode/cli/cmd/run-message"
describe("buildRunMessage", () => {
test("preserves shell-bound multi-word positionals via wrap-quote (PR #4979)", () => {
expect(buildRunMessage(["hello", "world foo", "bar"], undefined)).toBe('hello "world foo" bar')
})
test("does not quote single-word positionals", () => {
expect(buildRunMessage(["hello", "world"], undefined)).toBe("hello world")
})
test("escapes embedded double quotes inside positionals", () => {
expect(buildRunMessage(['say "hi"'], undefined)).toBe('"say \\"hi\\""')
})
test("passes args['--'] through verbatim without wrap-quote (#9622)", () => {
// `kilo run -- "- Who are you?"` - yargs+populate-- captures the leading-dash
// phrase as a single atom in args["--"]. The assembler must NOT wrap it,
// because the user typed `--` precisely to opt out of further parsing.
expect(buildRunMessage([], ["- Who are you?"])).toBe("- Who are you?")
})
test("does not synthesize quote bytes around dash atoms even when they contain spaces", () => {
expect(buildRunMessage([], ["one two", "three"])).toBe("one two three")
})
test("combines positionals and dash args with appropriate quoting per source", () => {
expect(buildRunMessage(["pre", "fix arg"], ["raw arg", "tail"])).toBe('pre "fix arg" raw arg tail')
})
test("handles undefined and empty dash args identically", () => {
expect(buildRunMessage(["x"], undefined)).toBe("x")
expect(buildRunMessage(["x"], [])).toBe("x")
})
})