@kontextmind/kxm 0.7.0 → 0.7.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.kxm/roles/writer.yaml +2 -0
- package/docs/README.md +3 -0
- package/docs/adr/ADR-0002-browser-automation-steel-doks.md +103 -0
- package/docs/agent-skills.md +19 -2
- package/docs/browser-automation.md +116 -0
- package/docs/configuration.md +10 -1
- package/docs/getting-started.md +21 -0
- package/docs/kb/how-credentials-retrieved-safely.md +31 -0
- package/docs/kb/how-to-capture-and-annotate-section.md +60 -0
- package/docs/kb/how-to-connect-playwright-to-steel.md +54 -0
- package/docs/kb/how-to-recover-expired-session-or-orphan.md +54 -0
- package/docs/kb/how-to-resume-after-mfa.md +28 -0
- package/docs/kb/how-to-take-over-session.md +32 -0
- package/docs/kb/why-authentication-disappeared.md +32 -0
- package/docs/kb/why-automation-opened-different-browser.md +32 -0
- package/docs/kb/why-session-viewer-cannot-control.md +31 -0
- package/docs/operations.md +24 -0
- package/docs/prompts/browser-annotate-feedback.md +41 -0
- package/docs/prompts/browser-diagnose-recover.md +38 -0
- package/docs/prompts/browser-explore.md +42 -0
- package/docs/prompts/browser-repro-fix.md +48 -0
- package/docs/prompts/browser-start.md +41 -0
- package/docs/prompts/browser-takeover.md +50 -0
- package/docs/skills/repo-work-delivery.md +5 -0
- package/docs/skills.md +2 -0
- package/docs/troubleshooting.md +22 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +41203 -38364
- package/plugins/kxm/dist/core.js +57 -0
- package/plugins/kxm/dist/extension.js +40 -3
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime.js +1582 -81
- package/plugins/kxm/dist/server.js +129 -4
- package/plugins/kxm/dist/vnext-runtime-supervisor.js +221 -41
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/hints.json +30 -0
- package/plugins/kxm/skills/kxm-browser-annotate/SKILL.md +90 -0
- package/plugins/kxm/skills/kxm-browser-auth/SKILL.md +47 -0
- package/plugins/kxm/skills/kxm-browser-diagnostics/SKILL.md +48 -0
- package/plugins/kxm/skills/kxm-browser-explore/SKILL.md +48 -0
- package/plugins/kxm/skills/kxm-browser-session/SKILL.md +94 -0
- package/plugins/kxm/skills/kxm-browser-takeover/SKILL.md +87 -0
- package/plugins/kxm/skills/kxm-browser-verify/SKILL.md +71 -0
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +9 -0
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +9 -2
- package/plugins/kxm/src/autocomplete.ts +1 -1
- package/plugins/kxm/src/browser.ts +603 -0
- package/plugins/kxm/src/cli/context-skills.ts +373 -0
- package/plugins/kxm/src/cli/hub.ts +614 -0
- package/plugins/kxm/src/cli/roles.ts +615 -0
- package/plugins/kxm/src/cli/system.ts +906 -0
- package/plugins/kxm/src/cli/tasks.ts +364 -0
- package/plugins/kxm/src/cli/types.ts +270 -0
- package/plugins/kxm/src/cli/vnext.ts +698 -0
- package/plugins/kxm/src/cli/workflows.ts +699 -0
- package/plugins/kxm/src/cli.ts +238 -3791
- package/plugins/kxm/src/completion-install.ts +223 -0
- package/plugins/kxm/src/database.ts +1 -1
- package/plugins/kxm/src/external-effects.ts +1 -1
- package/plugins/kxm/src/hub-env.ts +193 -0
- package/plugins/kxm/src/init-guide-setup.ts +547 -0
- package/plugins/kxm/src/local-snapshot.ts +1 -1
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/model-inventory.ts +8 -8
- package/plugins/kxm/src/modes.ts +348 -0
- package/plugins/kxm/src/protocol.ts +111 -0
- package/plugins/kxm/src/role.ts +335 -0
- package/plugins/kxm/src/runtime.ts +4 -0
- package/plugins/kxm/src/safety-integrity.ts +76 -0
- package/plugins/kxm/src/sqlite.ts +76 -0
- package/plugins/kxm/src/ssh-remote.ts +560 -0
- package/plugins/kxm/src/store.ts +1 -1
- package/plugins/kxm/src/subagent-control.ts +312 -0
- package/plugins/kxm/src/vnext-bindings.ts +1 -1
- package/plugins/kxm/src/vnext-config.ts +38 -1
- package/plugins/kxm/src/vnext-engine-command.ts +2 -0
- package/plugins/kxm/src/vnext-engine.ts +16 -0
- package/plugins/kxm/src/vnext-harness.ts +92 -22
- package/plugins/kxm/src/vnext-oneshot-evidence.ts +39 -7
- package/plugins/kxm/src/vnext-oneshot-process.ts +46 -8
- package/plugins/kxm/src/vnext-oneshot-producer.ts +22 -1
- package/plugins/kxm/src/vnext-pi-producer.ts +11 -7
- package/plugins/kxm/src/vnext-runtime-store.ts +1 -1
- package/plugins/kxm/src/vnext-runtime-supervisor.ts +5 -3
- package/plugins/kxm/src/workflow-tui.ts +1 -1
- package/plugins/kxm/src/workflow.ts +144 -0
- package/schemas/vnext/modes.schema.json +56 -0
- package/scripts/kxm-bump-version.mjs +146 -0
- package/scripts/kxm-hub.mjs +145 -3
- package/scripts/kxm-publish-npm.mjs +3 -1
- package/scripts/kxm-release-github.mjs +3 -1
- package/scripts/kxm.mjs +0 -0
|
@@ -7431,6 +7431,61 @@ function parseBoundedInteger(value, field, fallback, min, max) {
|
|
|
7431
7431
|
}
|
|
7432
7432
|
return value;
|
|
7433
7433
|
}
|
|
7434
|
+
var TERMINAL_RECEIPT_SCHEMA = "kxm.terminal-receipt.v1";
|
|
7435
|
+
var VALID_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["accepted", "audit_escalation", "rejected", "error"]);
|
|
7436
|
+
function validateTerminalReceipt(value) {
|
|
7437
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
7438
|
+
throw new ProtocolError(400, "terminal receipt must be an object", "invalid_terminal_receipt");
|
|
7439
|
+
}
|
|
7440
|
+
const record = value;
|
|
7441
|
+
if (record.schema !== void 0 && record.schema !== TERMINAL_RECEIPT_SCHEMA) {
|
|
7442
|
+
throw new ProtocolError(400, `terminal receipt schema must be ${TERMINAL_RECEIPT_SCHEMA}`, "invalid_terminal_receipt");
|
|
7443
|
+
}
|
|
7444
|
+
const status = record.status;
|
|
7445
|
+
if (!status || !VALID_TERMINAL_STATUSES.has(status)) {
|
|
7446
|
+
throw new ProtocolError(
|
|
7447
|
+
400,
|
|
7448
|
+
`terminal receipt status must be one of: ${Array.from(VALID_TERMINAL_STATUSES).join(", ")}`,
|
|
7449
|
+
"invalid_terminal_receipt"
|
|
7450
|
+
);
|
|
7451
|
+
}
|
|
7452
|
+
const seat = requireString(record.seat, "seat", { max: 64 });
|
|
7453
|
+
const runId = requireString(record.runId, "runId", { max: 128 });
|
|
7454
|
+
const stageId = requireString(record.stageId, "stageId", { max: 128 });
|
|
7455
|
+
const timestamp = requireString(record.timestamp, "timestamp", { max: 64 });
|
|
7456
|
+
const host2 = requireString(record.host, "host", { max: 64 });
|
|
7457
|
+
const model = requireString(record.model, "model", { max: 128 });
|
|
7458
|
+
let evidence;
|
|
7459
|
+
if (record.evidence !== void 0) {
|
|
7460
|
+
if (!record.evidence || typeof record.evidence !== "object" || Array.isArray(record.evidence)) {
|
|
7461
|
+
throw new ProtocolError(400, "terminal receipt evidence must be an object", "invalid_terminal_receipt");
|
|
7462
|
+
}
|
|
7463
|
+
evidence = record.evidence;
|
|
7464
|
+
}
|
|
7465
|
+
let metrics;
|
|
7466
|
+
if (record.metrics !== void 0) {
|
|
7467
|
+
if (!record.metrics || typeof record.metrics !== "object" || Array.isArray(record.metrics)) {
|
|
7468
|
+
throw new ProtocolError(400, "terminal receipt metrics must be an object", "invalid_terminal_receipt");
|
|
7469
|
+
}
|
|
7470
|
+
metrics = record.metrics;
|
|
7471
|
+
}
|
|
7472
|
+
const escalationReason = optionalString(record.escalationReason, "escalationReason", 1024);
|
|
7473
|
+
const ruling = optionalString(record.ruling, "ruling", 2048);
|
|
7474
|
+
return {
|
|
7475
|
+
schema: TERMINAL_RECEIPT_SCHEMA,
|
|
7476
|
+
status,
|
|
7477
|
+
seat,
|
|
7478
|
+
runId,
|
|
7479
|
+
stageId,
|
|
7480
|
+
timestamp,
|
|
7481
|
+
host: host2,
|
|
7482
|
+
model,
|
|
7483
|
+
...evidence ? { evidence } : {},
|
|
7484
|
+
...metrics ? { metrics } : {},
|
|
7485
|
+
...escalationReason ? { escalationReason } : {},
|
|
7486
|
+
...ruling ? { ruling } : {}
|
|
7487
|
+
};
|
|
7488
|
+
}
|
|
7434
7489
|
|
|
7435
7490
|
// plugins/kxm/src/diagnostics.ts
|
|
7436
7491
|
function workflowScopeExtras(operation, assignedCoordinatorName) {
|
|
@@ -7982,12 +8037,17 @@ function parseWorkflowDefinitions(raw, environment = process.env, onWarning) {
|
|
|
7982
8037
|
if (stageMaxTransitions !== void 0 && (!Number.isInteger(stageMaxTransitions) || stageMaxTransitions < 1 || stageMaxTransitions > 100)) {
|
|
7983
8038
|
throw new Error(`stage ${stageId} maxTransitions must be an integer between 1 and 100`);
|
|
7984
8039
|
}
|
|
8040
|
+
const autoResumeLimit = stage.autoResumeLimit;
|
|
8041
|
+
if (autoResumeLimit !== void 0 && (!Number.isInteger(autoResumeLimit) || autoResumeLimit < 1 || autoResumeLimit > 20)) {
|
|
8042
|
+
throw new Error(`stage ${stageId} autoResumeLimit must be an integer between 1 and 20`);
|
|
8043
|
+
}
|
|
7985
8044
|
return {
|
|
7986
8045
|
id: stageId,
|
|
7987
8046
|
label: requireString(stage.label ?? stageId, "stage.label", { max: 128 }),
|
|
7988
8047
|
instructions: requireString(stage.instructions, "stage.instructions", { max: 4e3 }),
|
|
7989
8048
|
requiredEvidence,
|
|
7990
8049
|
maxAttempts,
|
|
8050
|
+
...autoResumeLimit !== void 0 ? { autoResumeLimit } : {},
|
|
7991
8051
|
...area ? { area } : {},
|
|
7992
8052
|
...evidencePolicies ? { evidencePolicies } : {},
|
|
7993
8053
|
...on ? { on } : {},
|
|
@@ -8266,6 +8326,31 @@ function checkpointRun(run, stageId, status, summary, evidence, timestamp, verif
|
|
|
8266
8326
|
delete run.currentStage;
|
|
8267
8327
|
return { retry: false, completed: false, run };
|
|
8268
8328
|
}
|
|
8329
|
+
if (stage.autoResumeLimit !== void 0 && stage.attempts >= stage.autoResumeLimit) {
|
|
8330
|
+
stage.status = "in_progress";
|
|
8331
|
+
const reason = summary || `autoResumeLimit of ${stage.autoResumeLimit} reached on stage ${stage.id}`;
|
|
8332
|
+
const receipt = validateTerminalReceipt({
|
|
8333
|
+
schema: TERMINAL_RECEIPT_SCHEMA,
|
|
8334
|
+
status: "audit_escalation",
|
|
8335
|
+
seat: stage.id,
|
|
8336
|
+
runId: run.id,
|
|
8337
|
+
stageId: stage.id,
|
|
8338
|
+
timestamp,
|
|
8339
|
+
host: "pi",
|
|
8340
|
+
model: "default",
|
|
8341
|
+
escalationReason: reason
|
|
8342
|
+
});
|
|
8343
|
+
const expiresAt = new Date(Date.parse(timestamp) + 24 * 60 * 60 * 1e3).toISOString();
|
|
8344
|
+
waitForWorkflowSignal(run, stage.id, "audit_escalation", reason, timestamp, expiresAt);
|
|
8345
|
+
stage.receipt = receipt;
|
|
8346
|
+
stage.auditEscalation = {
|
|
8347
|
+
reason,
|
|
8348
|
+
timestamp,
|
|
8349
|
+
receipt
|
|
8350
|
+
};
|
|
8351
|
+
return { retry: false, completed: false, run };
|
|
8352
|
+
}
|
|
8353
|
+
stage.status = status;
|
|
8269
8354
|
const outcomeKey = outcome ?? status;
|
|
8270
8355
|
const rule = resolveOutcomeRule(stage, outcomeKey);
|
|
8271
8356
|
if (rule && stage.attempts < stage.maxAttempts) {
|
|
@@ -10833,7 +10918,45 @@ import {
|
|
|
10833
10918
|
writeFileSync as writeFileSync4
|
|
10834
10919
|
} from "node:fs";
|
|
10835
10920
|
import { basename as basename3, dirname as dirname3, join as join4, resolve as resolve4 } from "node:path";
|
|
10836
|
-
|
|
10921
|
+
|
|
10922
|
+
// plugins/kxm/src/sqlite.ts
|
|
10923
|
+
import { createRequire } from "node:module";
|
|
10924
|
+
var requireFromHere = createRequire(import.meta.url);
|
|
10925
|
+
function loadNative() {
|
|
10926
|
+
try {
|
|
10927
|
+
const mod = requireFromHere("node:sqlite");
|
|
10928
|
+
if (mod.DatabaseSync) return { Ctor: mod.DatabaseSync, bun: false };
|
|
10929
|
+
} catch {
|
|
10930
|
+
}
|
|
10931
|
+
try {
|
|
10932
|
+
const mod = requireFromHere("bun:sqlite");
|
|
10933
|
+
const Ctor = mod?.DatabaseSync ?? mod?.Database;
|
|
10934
|
+
if (Ctor) return { Ctor, bun: true };
|
|
10935
|
+
} catch {
|
|
10936
|
+
}
|
|
10937
|
+
throw new Error("kxm: no supported sqlite module found (need node:sqlite or bun:sqlite)");
|
|
10938
|
+
}
|
|
10939
|
+
var native = loadNative();
|
|
10940
|
+
var DatabaseSync = class {
|
|
10941
|
+
inner;
|
|
10942
|
+
constructor(path, options) {
|
|
10943
|
+
let normalized = options;
|
|
10944
|
+
if (native.bun && options) {
|
|
10945
|
+
const { readOnly, ...rest } = options;
|
|
10946
|
+
normalized = readOnly === void 0 ? rest : { ...rest, readonly: readOnly };
|
|
10947
|
+
}
|
|
10948
|
+
this.inner = normalized === void 0 ? new native.Ctor(path) : new native.Ctor(path, normalized);
|
|
10949
|
+
}
|
|
10950
|
+
prepare(sql) {
|
|
10951
|
+
return this.inner.prepare(sql);
|
|
10952
|
+
}
|
|
10953
|
+
exec(sql) {
|
|
10954
|
+
return this.inner.exec(sql);
|
|
10955
|
+
}
|
|
10956
|
+
close() {
|
|
10957
|
+
this.inner.close();
|
|
10958
|
+
}
|
|
10959
|
+
};
|
|
10837
10960
|
|
|
10838
10961
|
// plugins/kxm/src/vnext-config.ts
|
|
10839
10962
|
import { basename as basename2, dirname as dirname2, extname as extname2, isAbsolute, join as join3, relative, resolve as resolve3, sep } from "node:path";
|
|
@@ -11090,7 +11213,9 @@ function parseAgyOneShotUsage(stdout, _stderr) {
|
|
|
11090
11213
|
var READ_ONLY_ONESHOT_ARGS = Object.freeze({
|
|
11091
11214
|
claude: Object.freeze(["--tools", "Read,Glob,Grep", "--restricted", "--safe-mode", "--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}', "--disable-slash-commands", "--no-session-persistence"]),
|
|
11092
11215
|
codex: Object.freeze(["--sandbox", "read-only", "--ignore-user-config", "-c", 'approval_policy="never"']),
|
|
11093
|
-
grok: Object.freeze(["--sandbox", "read-only", "--permission-mode", "plan", "--tools", "Read,Glob,Grep", "--no-subagents", "--disable-web-search"])
|
|
11216
|
+
grok: Object.freeze(["--sandbox", "read-only", "--permission-mode", "plan", "--tools", "Read,Glob,Grep", "--no-subagents", "--disable-web-search"]),
|
|
11217
|
+
agy: Object.freeze(["--mode", "plan", "--sandbox", "--disable-slash-commands"]),
|
|
11218
|
+
kimi: Object.freeze(["--plan"])
|
|
11094
11219
|
});
|
|
11095
11220
|
function oneShotReadOnlyArgs(harness) {
|
|
11096
11221
|
return Object.hasOwn(READ_ONLY_ONESHOT_ARGS, harness) ? READ_ONLY_ONESHOT_ARGS[harness] : void 0;
|
|
@@ -11144,7 +11269,7 @@ var BUILTIN_HARNESSES = Object.freeze([
|
|
|
11144
11269
|
authArgs: ["provider", "list"],
|
|
11145
11270
|
update: { self: ["upgrade"] },
|
|
11146
11271
|
oneShot: {
|
|
11147
|
-
argv: ["--output-format", "stream-json", "-p"],
|
|
11272
|
+
argv: [...oneShotReadOnlyArgs("kimi"), "--output-format", "stream-json", "-p"],
|
|
11148
11273
|
promptVia: "arg",
|
|
11149
11274
|
outputFormat: "stream-json",
|
|
11150
11275
|
usageParser: parseKimiOneShotUsage
|
|
@@ -11207,7 +11332,7 @@ var BUILTIN_HARNESSES = Object.freeze([
|
|
|
11207
11332
|
authArgs: ["models"],
|
|
11208
11333
|
update: { self: ["update"] },
|
|
11209
11334
|
oneShot: {
|
|
11210
|
-
argv: ["--output-format", "json", "-p"],
|
|
11335
|
+
argv: [...oneShotReadOnlyArgs("agy"), "--output-format", "json", "-p"],
|
|
11211
11336
|
promptVia: "arg",
|
|
11212
11337
|
outputFormat: "json",
|
|
11213
11338
|
usageParser: parseAgyOneShotUsage
|
|
@@ -15126,6 +15126,19 @@ var OUTPUT_LIMIT = 8 * 1024 * 1024;
|
|
|
15126
15126
|
var KILL_GRACE_MS = 250;
|
|
15127
15127
|
var DRAIN_GRACE_MS = 500;
|
|
15128
15128
|
var REAP_GRACE_MS = 1e3;
|
|
15129
|
+
function killProcessTree(child, signal = "SIGKILL") {
|
|
15130
|
+
if (process.platform !== "win32" && child.pid) {
|
|
15131
|
+
try {
|
|
15132
|
+
process.kill(-child.pid, signal);
|
|
15133
|
+
return;
|
|
15134
|
+
} catch {
|
|
15135
|
+
}
|
|
15136
|
+
}
|
|
15137
|
+
try {
|
|
15138
|
+
child.kill(signal);
|
|
15139
|
+
} catch {
|
|
15140
|
+
}
|
|
15141
|
+
}
|
|
15129
15142
|
function defaultSpawn(command, args, options) {
|
|
15130
15143
|
if (options.signal?.aborted) {
|
|
15131
15144
|
return Promise.resolve({ stdout: "", stderr: "", code: null, started: false, observedChildExit: false, error: new Error("process_aborted") });
|
|
@@ -15150,6 +15163,7 @@ function defaultSpawn(command, args, options) {
|
|
|
15150
15163
|
let child;
|
|
15151
15164
|
const finish = () => {
|
|
15152
15165
|
if (finished) return;
|
|
15166
|
+
if (stopping && !killSent) return;
|
|
15153
15167
|
finished = true;
|
|
15154
15168
|
for (const timer of [wallTimer, killTimer, drainTimer, reapTimer]) clearTimeout(timer);
|
|
15155
15169
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -15159,14 +15173,21 @@ function defaultSpawn(command, args, options) {
|
|
|
15159
15173
|
child?.unref();
|
|
15160
15174
|
const started = Boolean(child?.pid);
|
|
15161
15175
|
if (started && !observedChildExit) error ??= new Error("process_exit_unobserved");
|
|
15162
|
-
|
|
15176
|
+
const unverifiedDescendants = stopping || started && !observedChildExit;
|
|
15177
|
+
resolve7({
|
|
15178
|
+
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
15179
|
+
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
15180
|
+
code,
|
|
15181
|
+
signal,
|
|
15182
|
+
started,
|
|
15183
|
+
observedChildExit,
|
|
15184
|
+
terminationRequested: stopping,
|
|
15185
|
+
...unverifiedDescendants ? { unverifiedDescendants: true } : {},
|
|
15186
|
+
...error ? { error } : {}
|
|
15187
|
+
});
|
|
15163
15188
|
};
|
|
15164
15189
|
const kill = (requested) => {
|
|
15165
|
-
|
|
15166
|
-
if (process.platform !== "win32" && child.pid) process.kill(-child.pid, requested);
|
|
15167
|
-
else child.kill(requested);
|
|
15168
|
-
} catch {
|
|
15169
|
-
}
|
|
15190
|
+
killProcessTree(child, requested);
|
|
15170
15191
|
};
|
|
15171
15192
|
const stop = (reason) => {
|
|
15172
15193
|
if (finished) return;
|
|
@@ -15194,7 +15215,7 @@ function defaultSpawn(command, args, options) {
|
|
|
15194
15215
|
cwd: options.cwd,
|
|
15195
15216
|
env: options.env ?? process.env,
|
|
15196
15217
|
stdio: ["pipe", "pipe", "pipe"],
|
|
15197
|
-
shell:
|
|
15218
|
+
shell: options.shell === true,
|
|
15198
15219
|
windowsHide: true,
|
|
15199
15220
|
detached: process.platform !== "win32"
|
|
15200
15221
|
});
|
|
@@ -15238,7 +15259,7 @@ function defaultSpawn(command, args, options) {
|
|
|
15238
15259
|
closed = true;
|
|
15239
15260
|
code = exitCode;
|
|
15240
15261
|
signal = exitSignal;
|
|
15241
|
-
|
|
15262
|
+
finish();
|
|
15242
15263
|
});
|
|
15243
15264
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
15244
15265
|
if (options.signal?.aborted) onAbort();
|
|
@@ -15493,7 +15514,9 @@ function parseAgyOneShotUsage(stdout, _stderr) {
|
|
|
15493
15514
|
var READ_ONLY_ONESHOT_ARGS = Object.freeze({
|
|
15494
15515
|
claude: Object.freeze(["--tools", "Read,Glob,Grep", "--restricted", "--safe-mode", "--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}', "--disable-slash-commands", "--no-session-persistence"]),
|
|
15495
15516
|
codex: Object.freeze(["--sandbox", "read-only", "--ignore-user-config", "-c", 'approval_policy="never"']),
|
|
15496
|
-
grok: Object.freeze(["--sandbox", "read-only", "--permission-mode", "plan", "--tools", "Read,Glob,Grep", "--no-subagents", "--disable-web-search"])
|
|
15517
|
+
grok: Object.freeze(["--sandbox", "read-only", "--permission-mode", "plan", "--tools", "Read,Glob,Grep", "--no-subagents", "--disable-web-search"]),
|
|
15518
|
+
agy: Object.freeze(["--mode", "plan", "--sandbox", "--disable-slash-commands"]),
|
|
15519
|
+
kimi: Object.freeze(["--plan"])
|
|
15497
15520
|
});
|
|
15498
15521
|
function oneShotReadOnlyArgs(harness) {
|
|
15499
15522
|
return Object.hasOwn(READ_ONLY_ONESHOT_ARGS, harness) ? READ_ONLY_ONESHOT_ARGS[harness] : void 0;
|
|
@@ -15547,7 +15570,7 @@ var BUILTIN_HARNESSES = Object.freeze([
|
|
|
15547
15570
|
authArgs: ["provider", "list"],
|
|
15548
15571
|
update: { self: ["upgrade"] },
|
|
15549
15572
|
oneShot: {
|
|
15550
|
-
argv: ["--output-format", "stream-json", "-p"],
|
|
15573
|
+
argv: [...oneShotReadOnlyArgs("kimi"), "--output-format", "stream-json", "-p"],
|
|
15551
15574
|
promptVia: "arg",
|
|
15552
15575
|
outputFormat: "stream-json",
|
|
15553
15576
|
usageParser: parseKimiOneShotUsage
|
|
@@ -15610,7 +15633,7 @@ var BUILTIN_HARNESSES = Object.freeze([
|
|
|
15610
15633
|
authArgs: ["models"],
|
|
15611
15634
|
update: { self: ["update"] },
|
|
15612
15635
|
oneShot: {
|
|
15613
|
-
argv: ["--output-format", "json", "-p"],
|
|
15636
|
+
argv: [...oneShotReadOnlyArgs("agy"), "--output-format", "json", "-p"],
|
|
15614
15637
|
promptVia: "arg",
|
|
15615
15638
|
outputFormat: "json",
|
|
15616
15639
|
usageParser: parseAgyOneShotUsage
|
|
@@ -15677,6 +15700,31 @@ function defaultRunner(env) {
|
|
|
15677
15700
|
}
|
|
15678
15701
|
};
|
|
15679
15702
|
}
|
|
15703
|
+
function commandResultFromSpawn(result) {
|
|
15704
|
+
const errno = result.error && "code" in result.error ? result.error.code : void 0;
|
|
15705
|
+
const error = (typeof errno === "string" && errno ? errno : void 0) ?? result.error?.message ?? (result.observedChildExit !== true ? "auth_probe_exit_unobserved" : void 0);
|
|
15706
|
+
return {
|
|
15707
|
+
ok: result.code === 0 && !error,
|
|
15708
|
+
code: result.code,
|
|
15709
|
+
stdout: result.stdout,
|
|
15710
|
+
stderr: result.stderr,
|
|
15711
|
+
...error ? { error } : {}
|
|
15712
|
+
};
|
|
15713
|
+
}
|
|
15714
|
+
function defaultAsyncRunner(env, signal) {
|
|
15715
|
+
return async (command, args, timeoutMs) => {
|
|
15716
|
+
try {
|
|
15717
|
+
return commandResultFromSpawn(await defaultSpawn(command, args, {
|
|
15718
|
+
env,
|
|
15719
|
+
timeoutMs,
|
|
15720
|
+
signal,
|
|
15721
|
+
shell: harnessSpawnUsesShell(command)
|
|
15722
|
+
}));
|
|
15723
|
+
} catch (error) {
|
|
15724
|
+
return { ok: false, code: null, stdout: "", stderr: "", error: error instanceof Error ? error.message : "spawn_failed" };
|
|
15725
|
+
}
|
|
15726
|
+
};
|
|
15727
|
+
}
|
|
15680
15728
|
function firstLine(text) {
|
|
15681
15729
|
const line = text.split(/\r?\n/).map((candidate) => candidate.trim()).find(Boolean);
|
|
15682
15730
|
return line && line.length <= 200 ? line : void 0;
|
|
@@ -16092,35 +16140,31 @@ var PendingHarnessCommand = class {
|
|
|
16092
16140
|
this.key = key;
|
|
16093
16141
|
}
|
|
16094
16142
|
};
|
|
16095
|
-
async function
|
|
16143
|
+
async function replayHarnessProbe(run, execute, limit) {
|
|
16096
16144
|
const observed = /* @__PURE__ */ new Map();
|
|
16097
|
-
|
|
16098
|
-
const result = await defaultSpawn(command, args, { env: options.env, timeoutMs, signal: options.signal });
|
|
16099
|
-
const error = result.error?.message ?? (result.observedChildExit !== true ? "auth_probe_exit_unobserved" : void 0);
|
|
16100
|
-
return {
|
|
16101
|
-
ok: result.code === 0 && !error,
|
|
16102
|
-
code: result.code,
|
|
16103
|
-
stdout: result.stdout,
|
|
16104
|
-
stderr: result.stderr,
|
|
16105
|
-
...error ? { error } : {}
|
|
16106
|
-
};
|
|
16107
|
-
});
|
|
16108
|
-
for (let commands = 0; commands <= 32; commands++) {
|
|
16145
|
+
for (let commands = 0; commands <= limit; commands++) {
|
|
16109
16146
|
try {
|
|
16110
|
-
return
|
|
16147
|
+
return execute((command, args, timeoutMs) => {
|
|
16111
16148
|
const key = JSON.stringify([command, args, timeoutMs]);
|
|
16112
16149
|
const result = observed.get(key);
|
|
16113
16150
|
if (result) return result;
|
|
16114
16151
|
throw new PendingHarnessCommand(command, args, timeoutMs, key);
|
|
16115
|
-
}
|
|
16152
|
+
});
|
|
16116
16153
|
} catch (pending) {
|
|
16117
16154
|
if (!(pending instanceof PendingHarnessCommand)) throw pending;
|
|
16118
|
-
if (commands ===
|
|
16155
|
+
if (commands === limit) throw new Error("auth_probe_command_limit");
|
|
16119
16156
|
observed.set(pending.key, await run(pending.command, pending.args, pending.timeoutMs));
|
|
16120
16157
|
}
|
|
16121
16158
|
}
|
|
16122
16159
|
throw new Error("auth_probe_command_limit");
|
|
16123
16160
|
}
|
|
16161
|
+
async function probeHarnessAssignmentAsync(options) {
|
|
16162
|
+
return replayHarnessProbe(
|
|
16163
|
+
options.runCommand ?? defaultAsyncRunner(options.env ?? process.env, options.signal),
|
|
16164
|
+
(runCommand) => probeHarnessAssignment({ ...options, runCommand }),
|
|
16165
|
+
32
|
|
16166
|
+
);
|
|
16167
|
+
}
|
|
16124
16168
|
|
|
16125
16169
|
// plugins/kxm/src/vnext-config.ts
|
|
16126
16170
|
var VnextConfigError = class extends Error {
|
|
@@ -16905,7 +16949,7 @@ function validateModelReferences(models, issues) {
|
|
|
16905
16949
|
};
|
|
16906
16950
|
for (const id of models.keys()) walk(id, []);
|
|
16907
16951
|
}
|
|
16908
|
-
function validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry) {
|
|
16952
|
+
function validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, projectRoot) {
|
|
16909
16953
|
const issues = [];
|
|
16910
16954
|
const entries = valuesOf(project.value, "repositories").map((candidate) => objectValue(candidate)).filter((candidate) => Boolean(candidate));
|
|
16911
16955
|
const repositoryIds = /* @__PURE__ */ new Set();
|
|
@@ -16973,6 +17017,33 @@ function validateBundle(project, repositories, agents, models, workflows, enviro
|
|
|
16973
17017
|
const defaultWorkflow = stringValue(project.value.defaultWorkflow) ?? "default";
|
|
16974
17018
|
if (!workflows.has(defaultWorkflow)) issues.push(issue2("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
|
|
16975
17019
|
for (const workflow of workflows.values()) validateWorkflow(workflow, agents, models, repositoryIds, gates, issues);
|
|
17020
|
+
if (projectRoot) {
|
|
17021
|
+
const writerRolePath = join(projectRoot, ".kxm", "roles", "writer.yaml");
|
|
17022
|
+
const implementerAgent = agents.get("implementer") ?? agents.get("writer");
|
|
17023
|
+
if (existsSync2(writerRolePath) && implementerAgent) {
|
|
17024
|
+
try {
|
|
17025
|
+
const rawRole = parseRestrictedYaml2(readFileSync(writerRolePath, "utf8"));
|
|
17026
|
+
const roleObj = objectValue(rawRole);
|
|
17027
|
+
const rosterEntries = valuesOf(roleObj ?? {}, "roster").map((candidate) => objectValue(candidate)).filter((entry) => Boolean(entry));
|
|
17028
|
+
const enabledRosterModels = rosterEntries.filter((entry) => entry.enabled !== false).map((entry) => stringValue(entry.model)).filter((m) => Boolean(m));
|
|
17029
|
+
const agentModelObj = objectValue(implementerAgent.value.model);
|
|
17030
|
+
const agentModelStr = stringValue(implementerAgent.value.model);
|
|
17031
|
+
const agentProvider = agentModelObj ? stringValue(agentModelObj.provider) : void 0;
|
|
17032
|
+
const agentModel = agentModelObj ? stringValue(agentModelObj.model) : agentModelStr;
|
|
17033
|
+
const canonicalAgentModel = agentProvider && agentModel ? `${agentProvider}/${agentModel}` : agentModel;
|
|
17034
|
+
if (enabledRosterModels.length > 0 && canonicalAgentModel) {
|
|
17035
|
+
const matches = enabledRosterModels.some((rm) => rm === canonicalAgentModel || rm === agentModel || rm.endsWith(`/${agentModel}`));
|
|
17036
|
+
if (!matches) {
|
|
17037
|
+
issues.push(issue2("semantic", "role_roster_conflicts_with_agent", ".kxm/roles/writer.yaml", `role roster in .kxm/roles/writer.yaml does not include agent model ${canonicalAgentModel} from ${implementerAgent.logicalPath}`));
|
|
17038
|
+
}
|
|
17039
|
+
}
|
|
17040
|
+
} catch (error) {
|
|
17041
|
+
if (error instanceof VnextConfigError) {
|
|
17042
|
+
issues.push(...error.issues);
|
|
17043
|
+
}
|
|
17044
|
+
}
|
|
17045
|
+
}
|
|
17046
|
+
}
|
|
16976
17047
|
return sortIssues2(issues);
|
|
16977
17048
|
}
|
|
16978
17049
|
function vnextCanonicalJson(value) {
|
|
@@ -17153,7 +17224,7 @@ function loadVnextProject(projectRoot, options = {}) {
|
|
|
17153
17224
|
}
|
|
17154
17225
|
}
|
|
17155
17226
|
if (loadIssues.length > 0) throw new VnextConfigError(loadIssues);
|
|
17156
|
-
const issues = validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry);
|
|
17227
|
+
const issues = validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, root);
|
|
17157
17228
|
if (issues.length > 0) throw new VnextConfigError(issues);
|
|
17158
17229
|
const resources = [project, ...repositories.values(), ...agents.values(), ...models.values(), ...workflows.values(), ...environments, ...gateRegistry ? [gateRegistry] : []].sort((left, right) => compareCodeUnits3(left.logicalPath, right.logicalPath));
|
|
17159
17230
|
return {
|
|
@@ -17265,7 +17336,47 @@ import { dirname as dirname4, join as join4, resolve as resolve4 } from "node:pa
|
|
|
17265
17336
|
|
|
17266
17337
|
// plugins/kxm/src/vnext-bindings.ts
|
|
17267
17338
|
import { homedir } from "node:os";
|
|
17268
|
-
|
|
17339
|
+
|
|
17340
|
+
// plugins/kxm/src/sqlite.ts
|
|
17341
|
+
import { createRequire } from "node:module";
|
|
17342
|
+
var requireFromHere = createRequire(import.meta.url);
|
|
17343
|
+
function loadNative() {
|
|
17344
|
+
try {
|
|
17345
|
+
const mod = requireFromHere("node:sqlite");
|
|
17346
|
+
if (mod.DatabaseSync) return { Ctor: mod.DatabaseSync, bun: false };
|
|
17347
|
+
} catch {
|
|
17348
|
+
}
|
|
17349
|
+
try {
|
|
17350
|
+
const mod = requireFromHere("bun:sqlite");
|
|
17351
|
+
const Ctor = mod?.DatabaseSync ?? mod?.Database;
|
|
17352
|
+
if (Ctor) return { Ctor, bun: true };
|
|
17353
|
+
} catch {
|
|
17354
|
+
}
|
|
17355
|
+
throw new Error("kxm: no supported sqlite module found (need node:sqlite or bun:sqlite)");
|
|
17356
|
+
}
|
|
17357
|
+
var native = loadNative();
|
|
17358
|
+
var DatabaseSync = class {
|
|
17359
|
+
inner;
|
|
17360
|
+
constructor(path, options) {
|
|
17361
|
+
let normalized = options;
|
|
17362
|
+
if (native.bun && options) {
|
|
17363
|
+
const { readOnly, ...rest } = options;
|
|
17364
|
+
normalized = readOnly === void 0 ? rest : { ...rest, readonly: readOnly };
|
|
17365
|
+
}
|
|
17366
|
+
this.inner = normalized === void 0 ? new native.Ctor(path) : new native.Ctor(path, normalized);
|
|
17367
|
+
}
|
|
17368
|
+
prepare(sql) {
|
|
17369
|
+
return this.inner.prepare(sql);
|
|
17370
|
+
}
|
|
17371
|
+
exec(sql) {
|
|
17372
|
+
return this.inner.exec(sql);
|
|
17373
|
+
}
|
|
17374
|
+
close() {
|
|
17375
|
+
this.inner.close();
|
|
17376
|
+
}
|
|
17377
|
+
};
|
|
17378
|
+
|
|
17379
|
+
// plugins/kxm/src/vnext-bindings.ts
|
|
17269
17380
|
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join2, parse, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
17270
17381
|
var MAX_BINDING_RECORD_BYTES = 256 * 1024;
|
|
17271
17382
|
var BINDING_LABEL = "Runtime-local repository bindings";
|
|
@@ -17308,7 +17419,6 @@ import {
|
|
|
17308
17419
|
writeFileSync
|
|
17309
17420
|
} from "node:fs";
|
|
17310
17421
|
import { basename as basename2, dirname as dirname3, join as join3, resolve as resolve3 } from "node:path";
|
|
17311
|
-
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
17312
17422
|
function databaseError(code, file, message) {
|
|
17313
17423
|
const issue3 = { phase: "semantic", code, file, message };
|
|
17314
17424
|
return new VnextConfigError([issue3]);
|
|
@@ -17388,7 +17498,7 @@ function openDatabase(file, description, spec) {
|
|
|
17388
17498
|
}
|
|
17389
17499
|
}
|
|
17390
17500
|
}
|
|
17391
|
-
const database = new
|
|
17501
|
+
const database = new DatabaseSync(file);
|
|
17392
17502
|
let transaction = false;
|
|
17393
17503
|
try {
|
|
17394
17504
|
database.exec(`PRAGMA busy_timeout = ${spec.timeoutMs ?? 5e3}`);
|
|
@@ -21827,9 +21937,28 @@ import { join as join11 } from "node:path";
|
|
|
21827
21937
|
import { createHash as createHash6, randomUUID as randomUUID3 } from "node:crypto";
|
|
21828
21938
|
import { lstat, mkdir, open, rename } from "node:fs/promises";
|
|
21829
21939
|
import { join as join6 } from "node:path";
|
|
21940
|
+
var ONESHOT_EVIDENCE_SCHEMA = "kxm.oneshot-evidence.v2";
|
|
21941
|
+
var RETIRED_ONESHOT_EVIDENCE_SCHEMAS = /* @__PURE__ */ new Set(["kxm.oneshot-evidence.v1"]);
|
|
21830
21942
|
var TEXT_LIMIT = 4 * 1024 * 1024;
|
|
21943
|
+
var ARGV_LIMIT = 64 * 1024;
|
|
21831
21944
|
var RECORD_LIMIT = 16 * 1024 * 1024;
|
|
21832
21945
|
var digest = (value) => `sha256:${createHash6("sha256").update(value).digest("hex")}`;
|
|
21946
|
+
function parseOneShotEvidenceRecord(bytes) {
|
|
21947
|
+
let parsed;
|
|
21948
|
+
try {
|
|
21949
|
+
parsed = JSON.parse(bytes);
|
|
21950
|
+
} catch {
|
|
21951
|
+
throw new Error("oneshot_evidence_record_invalid");
|
|
21952
|
+
}
|
|
21953
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
21954
|
+
throw new Error("oneshot_evidence_record_invalid");
|
|
21955
|
+
}
|
|
21956
|
+
const schema = parsed.schema;
|
|
21957
|
+
if (typeof schema !== "string") throw new Error("oneshot_evidence_record_invalid");
|
|
21958
|
+
if (RETIRED_ONESHOT_EVIDENCE_SCHEMAS.has(schema)) throw new Error("oneshot_evidence_schema_retired");
|
|
21959
|
+
if (schema !== ONESHOT_EVIDENCE_SCHEMA) throw new Error("oneshot_evidence_schema_unknown");
|
|
21960
|
+
return parsed;
|
|
21961
|
+
}
|
|
21833
21962
|
async function beginOneShotEvidence(root, intent, sensitive) {
|
|
21834
21963
|
await mkdir(root, { recursive: true, mode: 448 });
|
|
21835
21964
|
const stat = await lstat(root);
|
|
@@ -21843,11 +21972,11 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
21843
21972
|
const redact = (value) => {
|
|
21844
21973
|
let text = value;
|
|
21845
21974
|
for (const secret of secrets) text = text.replaceAll(secret, "[REDACTED]");
|
|
21846
|
-
return text.replace(/(\b(?:authorization|api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret)\b["']?\s*[:=]\s*["']?)(?:Bearer\s+)?[^\s"',;}]+/gi, "$1[REDACTED]");
|
|
21975
|
+
return text.replace(/(\b(?:authorization|api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret)\b["']?\s*[:=]\s*["']?)(?:Bearer\s+)?[^\s"',;}]+/gi, "$1[REDACTED]").replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/gi, "Bearer [REDACTED]");
|
|
21847
21976
|
};
|
|
21848
|
-
const bounded = (value) => {
|
|
21977
|
+
const bounded = (value, max = TEXT_LIMIT) => {
|
|
21849
21978
|
const bytes = Buffer.from(redact(value));
|
|
21850
|
-
return { text: bytes.subarray(0,
|
|
21979
|
+
return { text: bytes.subarray(0, max).toString("utf8"), truncated: bytes.length > max, sha256: digest(redact(value)) };
|
|
21851
21980
|
};
|
|
21852
21981
|
const write = async (name, value) => {
|
|
21853
21982
|
const current = await lstat(dir);
|
|
@@ -21856,6 +21985,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
21856
21985
|
}
|
|
21857
21986
|
const bytes = JSON.stringify(value);
|
|
21858
21987
|
if (Buffer.byteLength(bytes) > RECORD_LIMIT) throw new Error("oneshot_evidence_record_limit");
|
|
21988
|
+
parseOneShotEvidenceRecord(bytes);
|
|
21859
21989
|
const target = join6(dir, name);
|
|
21860
21990
|
const partial = `${target}.partial`;
|
|
21861
21991
|
const file = await open(partial, "wx", 384);
|
|
@@ -21877,7 +22007,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
21877
22007
|
return digest(bytes);
|
|
21878
22008
|
};
|
|
21879
22009
|
await write("intent.json", {
|
|
21880
|
-
schema:
|
|
22010
|
+
schema: ONESHOT_EVIDENCE_SCHEMA,
|
|
21881
22011
|
id,
|
|
21882
22012
|
recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21883
22013
|
runId: intent.runId,
|
|
@@ -21888,9 +22018,10 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
21888
22018
|
provider: intent.provider,
|
|
21889
22019
|
requestedModel: intent.model,
|
|
21890
22020
|
cwd: intent.cwd,
|
|
21891
|
-
command: intent.command,
|
|
21892
|
-
argv: bounded(JSON.stringify(intent.args)),
|
|
22021
|
+
command: redact(intent.command),
|
|
22022
|
+
argv: bounded(JSON.stringify(intent.args), ARGV_LIMIT),
|
|
21893
22023
|
stdin: intent.input === void 0 ? null : bounded(intent.input),
|
|
22024
|
+
env: null,
|
|
21894
22025
|
acceptance: false
|
|
21895
22026
|
});
|
|
21896
22027
|
let finished = false;
|
|
@@ -21900,7 +22031,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
21900
22031
|
if (finished) throw new Error("oneshot_evidence_already_finished");
|
|
21901
22032
|
finished = true;
|
|
21902
22033
|
return write("result.json", {
|
|
21903
|
-
schema:
|
|
22034
|
+
schema: ONESHOT_EVIDENCE_SCHEMA,
|
|
21904
22035
|
id,
|
|
21905
22036
|
recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21906
22037
|
stdout: bounded(result.stdout),
|
|
@@ -21910,6 +22041,7 @@ async function beginOneShotEvidence(root, intent, sensitive) {
|
|
|
21910
22041
|
started: result.started ?? null,
|
|
21911
22042
|
observedChildExit: result.observedChildExit ?? null,
|
|
21912
22043
|
terminationRequested: result.terminationRequested ?? null,
|
|
22044
|
+
unverifiedDescendants: result.unverifiedDescendants ?? null,
|
|
21913
22045
|
error: result.error ? bounded(result.error.message) : null,
|
|
21914
22046
|
observation: bounded(JSON.stringify(observation)),
|
|
21915
22047
|
acceptance: false
|
|
@@ -22465,6 +22597,32 @@ function evaluateArtifactsGate(context, definition) {
|
|
|
22465
22597
|
// plugins/kxm/src/vnext-engine-command.ts
|
|
22466
22598
|
import { spawn as spawn2 } from "node:child_process";
|
|
22467
22599
|
import { createHash as createHash8 } from "node:crypto";
|
|
22600
|
+
|
|
22601
|
+
// plugins/kxm/src/safety-integrity.ts
|
|
22602
|
+
var DESTRUCTIVE_COMMAND_PATTERNS = Object.freeze([
|
|
22603
|
+
/^\s*rm\s+.*-[a-zA-Z]*r[a-zA-Z]*f/i,
|
|
22604
|
+
/^\s*rm\s+.*-[a-zA-Z]*f[a-zA-Z]*r/i,
|
|
22605
|
+
/^\s*rm\s+.*(-[a-zA-Z]*r[a-zA-Z]*\s+.*-[a-zA-Z]*f[a-zA-Z]*|-[a-zA-Z]*f[a-zA-Z]*\s+.*-[a-zA-Z]*r[a-zA-Z]*)/i,
|
|
22606
|
+
/^\s*git\s+reset\s+--hard/i,
|
|
22607
|
+
/^\s*git\s+clean\s+-[a-zA-Z]*f/i,
|
|
22608
|
+
/^\s*git\s+checkout\s+--\s+/i,
|
|
22609
|
+
/^\s*git\s+restore\s+(\.|\*|--staged\s+(\.|\*))/i
|
|
22610
|
+
]);
|
|
22611
|
+
function assertCommandSeatbelt(command) {
|
|
22612
|
+
for (const pattern of DESTRUCTIVE_COMMAND_PATTERNS) {
|
|
22613
|
+
if (pattern.test(command)) {
|
|
22614
|
+
throw new Error(
|
|
22615
|
+
`Command blocked by KXM safety seatbelt: "${command}". Destructive workspace mutations require explicit operator override.`
|
|
22616
|
+
);
|
|
22617
|
+
}
|
|
22618
|
+
}
|
|
22619
|
+
}
|
|
22620
|
+
var INSECURE_SSH_HOST_KEY_PATTERNS = Object.freeze([
|
|
22621
|
+
/StrictHostKeyChecking=(accept-new|no|off)/i,
|
|
22622
|
+
/UserKnownHostsFile=\/dev\/null/i
|
|
22623
|
+
]);
|
|
22624
|
+
|
|
22625
|
+
// plugins/kxm/src/vnext-engine-command.ts
|
|
22468
22626
|
var MAX_DIRECT_TIMER_MS = 2147483647;
|
|
22469
22627
|
var COMMAND_TERM_GRACE_MS = 2e3;
|
|
22470
22628
|
var COMMAND_FINAL_WAIT_MS = 2e3;
|
|
@@ -22581,6 +22739,7 @@ var CommandObserver = class {
|
|
|
22581
22739
|
if (!Number.isInteger(this.definition.timeoutMs) || this.definition.timeoutMs < 1 || this.definition.timeoutMs > MAX_DIRECT_TIMER_MS) {
|
|
22582
22740
|
throw runtimeError("run_events_illegal", "command", "command timeoutMs exceeds the direct timer bound");
|
|
22583
22741
|
}
|
|
22742
|
+
assertCommandSeatbelt(this.definition.argv.join(" "));
|
|
22584
22743
|
this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22585
22744
|
let child;
|
|
22586
22745
|
try {
|
|
@@ -23706,6 +23865,7 @@ async function stepLocked(context, runId, producer, token) {
|
|
|
23706
23865
|
return drivePanel(context, prepared.panel, producer);
|
|
23707
23866
|
}
|
|
23708
23867
|
async function runPreparedCommandGate(context, prepared, definition, token) {
|
|
23868
|
+
assertCommandSeatbelt(definition.argv.join(" "));
|
|
23709
23869
|
const storePath = context.eventStore.path;
|
|
23710
23870
|
const observer = createCommandObserver({
|
|
23711
23871
|
definition,
|
|
@@ -25483,6 +25643,24 @@ function createVnextOneShotProducer(options = {}) {
|
|
|
25483
25643
|
"--output-format",
|
|
25484
25644
|
"json"
|
|
25485
25645
|
];
|
|
25646
|
+
} else if (harness === "agy") {
|
|
25647
|
+
args = [
|
|
25648
|
+
"-m",
|
|
25649
|
+
resolved.model,
|
|
25650
|
+
...permissionArgs,
|
|
25651
|
+
"--output-format",
|
|
25652
|
+
"json",
|
|
25653
|
+
"-p"
|
|
25654
|
+
];
|
|
25655
|
+
} else if (harness === "kimi") {
|
|
25656
|
+
args = [
|
|
25657
|
+
"-m",
|
|
25658
|
+
resolved.model,
|
|
25659
|
+
...permissionArgs,
|
|
25660
|
+
"--output-format",
|
|
25661
|
+
"stream-json",
|
|
25662
|
+
"-p"
|
|
25663
|
+
];
|
|
25486
25664
|
} else {
|
|
25487
25665
|
throw new Error(`oneshot_harness_unsupported: ${harness} permission_profile_unaudited`);
|
|
25488
25666
|
}
|
|
@@ -25525,7 +25703,8 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
|
|
|
25525
25703
|
parsed = { text: "", isError: true };
|
|
25526
25704
|
}
|
|
25527
25705
|
const aborted = request.signal.aborted || procResult.error?.message === "process_aborted";
|
|
25528
|
-
const
|
|
25706
|
+
const unverifiedDescendants = procResult.unverifiedDescendants === true || procResult.terminationRequested === true || procResult.error?.message === "process_exit_unobserved" || procResult.observedChildExit === false && procResult.started !== false;
|
|
25707
|
+
const effectUncertain = unverifiedDescendants || Boolean(procResult.signal);
|
|
25529
25708
|
const transportFailed = procResult.code !== 0 || Boolean(procResult.error) || effectUncertain;
|
|
25530
25709
|
const outcome = aborted ? "cancelled" : transportFailed || parsed.isError ? "failed" : determineOutcome(parsed.text, request.allowedOutcomes);
|
|
25531
25710
|
const providerMetadata = {
|
|
@@ -25537,6 +25716,7 @@ Return a final JSON object with an "outcome" field chosen from ${JSON.stringify(
|
|
|
25537
25716
|
if (procResult.observedChildExit !== void 0) providerMetadata.observedChildExit = procResult.observedChildExit;
|
|
25538
25717
|
if (procResult.started !== void 0) providerMetadata.processStarted = procResult.started;
|
|
25539
25718
|
if (procResult.terminationRequested !== void 0) providerMetadata.terminationRequested = procResult.terminationRequested;
|
|
25719
|
+
if (unverifiedDescendants) providerMetadata.descendantEffects = "unverified";
|
|
25540
25720
|
if (procResult.error) {
|
|
25541
25721
|
const reason = procResult.error.message;
|
|
25542
25722
|
providerMetadata.processError = /^process_(aborted|timeout|output_limit|stdin_error|stdio_error|stdio_unclosed|exit_unobserved)$/.test(reason) ? reason : "process_error";
|
|
@@ -26017,7 +26197,6 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
|
|
|
26017
26197
|
});
|
|
26018
26198
|
} catch (err) {
|
|
26019
26199
|
earlyError = err;
|
|
26020
|
-
drivePromise = Promise.reject(err);
|
|
26021
26200
|
}
|
|
26022
26201
|
await Promise.resolve();
|
|
26023
26202
|
if (earlyError) {
|
|
@@ -26043,6 +26222,7 @@ async function startVnextRuntimeSupervisorInner(paths, requestedPortOption, now)
|
|
|
26043
26222
|
} catch {
|
|
26044
26223
|
}
|
|
26045
26224
|
}
|
|
26225
|
+
}).catch(() => {
|
|
26046
26226
|
});
|
|
26047
26227
|
sendJson(response, 202, {
|
|
26048
26228
|
ok: true,
|