@astrosheep/keiyaku 2.9.2 → 2.9.4
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/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +13 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +25 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +47 -4
- package/build/agents/harness/projection.js +42 -59
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +50 -53
- package/build/agents/providers/codex-app-server/events.js +67 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +8 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/arc/handler.js +7 -1
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +34 -7
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/petition/handler.js +4 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +5 -4
- package/build/cli/commands/metadata.js +58 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +7 -2
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/task/add/handler.js +5 -13
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/ls/handler.js +3 -5
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/update/handler.js +4 -8
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +19 -3
- package/build/cli/help.js +4 -11
- package/build/cli/index.js +57 -83
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/parse-flags.js +14 -5
- package/build/cli/parse-metadata.js +3 -3
- package/build/cli/parse-selectors.js +1 -1
- package/build/cli/parse.js +21 -0
- package/build/cli/projection-address.js +7 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +55 -12
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +3 -0
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +37 -14
- package/build/cli/render/success-response.js +77 -0
- package/build/cli/render/task.js +54 -14
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +58 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +38 -36
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +1 -1
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +135 -18
- package/build/core/arc.js +19 -67
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +21 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +20 -3
- package/build/core/draft.js +123 -16
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +2 -38
- package/build/core/projection/generation/model.js +42 -1
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +19 -49
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +5 -3
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +18 -3
- package/build/core/projection/generation/store.js +2 -2
- package/build/core/projection/generation/transitions.js +1 -1
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +14 -19
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +2 -57
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +1 -1
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +98 -25
- package/build/core/projection/projection-terminal-failure.js +104 -0
- package/build/core/projection/projection-wait.js +278 -0
- package/build/core/projection/projection-wake.js +203 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +426 -99
- package/build/core/scope.js +143 -66
- package/build/core/seal.js +139 -35
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +9 -14
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +22 -18
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +1 -1
- package/build/core/{petition.js → settlement/petition.js} +12 -10
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +295 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/status/board.js +24 -23
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +3 -0
- package/build/core/task/board.js +40 -4
- package/build/core/task/commands.js +30 -21
- package/build/core/task/index.js +12 -0
- package/build/core/task/settlement-git.js +157 -65
- package/build/core/task/settlement-policy.js +54 -24
- package/build/core/task/task-contract.js +370 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +92 -29
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +5 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +5 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +85 -39
- package/build/fs/durability.js +27 -0
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +3 -3
- package/build/keiyaku.js +2 -36
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +3 -2
- package/skills/keiyaku-akuma/SKILL.md +10 -6
- package/skills/keiyaku-task/SKILL.md +1 -1
- package/skills/keiyaku-workflow/SKILL.md +25 -4
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { repositoryCoordinateFromAddress } from "../commands/shared.js";
|
|
2
|
+
import { renderResolvedAddressReceipt } from "./address.js";
|
|
3
|
+
import { formatCallNextAction } from "./shared.js";
|
|
4
|
+
function responseText(response) {
|
|
5
|
+
return response.text;
|
|
6
|
+
}
|
|
7
|
+
function responseData(response) {
|
|
8
|
+
const payload = response.payload;
|
|
9
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload) || "error" in payload)
|
|
10
|
+
return {};
|
|
11
|
+
return payload;
|
|
12
|
+
}
|
|
13
|
+
function isCallProjectionFacts(value) {
|
|
14
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
15
|
+
return false;
|
|
16
|
+
const facts = value;
|
|
17
|
+
return typeof facts.id === "string"
|
|
18
|
+
&& (facts.phase === "active" || facts.phase === "done" || facts.phase === "failed"
|
|
19
|
+
|| facts.phase === "dismissed" || facts.phase === "lost" || facts.phase === "quiescent");
|
|
20
|
+
}
|
|
21
|
+
function conversationalFooter(response) {
|
|
22
|
+
const data = responseData(response);
|
|
23
|
+
const lines = [];
|
|
24
|
+
if (response.address) {
|
|
25
|
+
const projection = data.projection;
|
|
26
|
+
const projectionFacts = isCallProjectionFacts(projection) ? projection : undefined;
|
|
27
|
+
const receiptArtifactId = typeof data.revivedArtifactId === "string"
|
|
28
|
+
? data.revivedArtifactId
|
|
29
|
+
: typeof data.artifactId === "string" ? data.artifactId : undefined;
|
|
30
|
+
lines.push(renderResolvedAddressReceipt(response.address, { artifactId: receiptArtifactId, projectionId: projectionFacts?.id }));
|
|
31
|
+
}
|
|
32
|
+
const responsePath = typeof data.responsePath === "string" ? data.responsePath : undefined;
|
|
33
|
+
const agent = typeof data.agent === "string" ? data.agent : undefined;
|
|
34
|
+
const meta = data.meta && typeof data.meta === "object" && !Array.isArray(data.meta) ? data.meta : undefined;
|
|
35
|
+
const warnings = Array.isArray(meta?.warnings) ? meta.warnings.filter((warning) => typeof warning === "string") : [];
|
|
36
|
+
if (responsePath) {
|
|
37
|
+
lines.push(`Saved to ${responsePath}.`);
|
|
38
|
+
}
|
|
39
|
+
if (agent) {
|
|
40
|
+
lines.push(`Akuma: ${agent}`);
|
|
41
|
+
}
|
|
42
|
+
if (warnings.length > 0) {
|
|
43
|
+
lines.push("Warnings:", ...warnings.map((warning) => `- ${warning}`));
|
|
44
|
+
}
|
|
45
|
+
if (typeof data.summary === "string") {
|
|
46
|
+
const projection = data.projection;
|
|
47
|
+
const projectionFacts = isCallProjectionFacts(projection) ? projection : undefined;
|
|
48
|
+
const artifactId = typeof data.artifactId === "string" ? data.artifactId : undefined;
|
|
49
|
+
lines.push(formatCallNextAction({
|
|
50
|
+
projection: projectionFacts,
|
|
51
|
+
artifactId,
|
|
52
|
+
repositoryCoordinate: repositoryCoordinateFromAddress(response.address),
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
return lines.join("\n");
|
|
56
|
+
}
|
|
57
|
+
export function writeSuccessResponse(command, flags, response) {
|
|
58
|
+
// Plain tell is always silent; tell --wait owns the ordinary wait response.
|
|
59
|
+
if (command === "tell" && flags.timeoutMs === undefined)
|
|
60
|
+
return;
|
|
61
|
+
if (command === "bind" && flags.dryRun) {
|
|
62
|
+
// Canonical Markdown already ends with exactly one newline.
|
|
63
|
+
process.stdout.write(responseText(response));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (command !== "revive") {
|
|
67
|
+
process.stdout.write(`${responseText(response)}\n`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const data = responseData(response);
|
|
71
|
+
const answer = typeof data.summary === "string" ? data.summary.trim() : responseText(response).trim();
|
|
72
|
+
const footer = conversationalFooter(response);
|
|
73
|
+
process.stdout.write(`${answer}\n`);
|
|
74
|
+
if (footer) {
|
|
75
|
+
process.stderr.write(`${footer}\n`);
|
|
76
|
+
}
|
|
77
|
+
}
|
package/build/cli/render/task.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
return id.slice(0, 9);
|
|
3
|
-
}
|
|
1
|
+
import { commissionSlug } from "../../core/ids.js";
|
|
4
2
|
export function shortContractId(contractId) {
|
|
5
|
-
|
|
6
|
-
return separator > 0 ? contractId.slice(0, separator) : contractId;
|
|
3
|
+
return commissionSlug(contractId);
|
|
7
4
|
}
|
|
8
5
|
export function deriveTaskDisplay(task) {
|
|
9
6
|
if (task.state === "done")
|
|
@@ -20,7 +17,7 @@ function renderTaskRowWithId(task, id) {
|
|
|
20
17
|
return `${id} · P${task.pri} · ${deriveTaskDisplay(task)} · ${task.title}`;
|
|
21
18
|
}
|
|
22
19
|
export function renderTaskListRow(task) {
|
|
23
|
-
return renderTaskRowWithId(task,
|
|
20
|
+
return renderTaskRowWithId(task, task.id);
|
|
24
21
|
}
|
|
25
22
|
export function renderTaskMutationRow(task) {
|
|
26
23
|
return renderTaskRowWithId(task, task.id);
|
|
@@ -67,27 +64,56 @@ export function renderTaskList(tasks, options = {}) {
|
|
|
67
64
|
return groupAndSortTasks(tasks, options.selection).map(renderTaskListRow).join("\n");
|
|
68
65
|
}
|
|
69
66
|
function renderIds(ids) {
|
|
70
|
-
return ids.length === 0 ? "(none)" : ids.
|
|
67
|
+
return ids.length === 0 ? "(none)" : ids.join(", ");
|
|
71
68
|
}
|
|
72
|
-
|
|
69
|
+
function renderTaskDetails(task) {
|
|
73
70
|
const released = new Set(task.releasedNeeds);
|
|
74
71
|
const needs = task.needs.length === 0
|
|
75
72
|
? "(none)"
|
|
76
73
|
: task.needs
|
|
77
|
-
.map((id) => `${
|
|
74
|
+
.map((id) => `${id}${released.has(id) ? " (dropped)" : ""}`)
|
|
78
75
|
.join(", ");
|
|
79
76
|
return [
|
|
80
|
-
`${
|
|
77
|
+
`${task.id} · ${task.title}`,
|
|
81
78
|
`state: ${deriveTaskDisplay(task)}`,
|
|
82
79
|
`priority: ${task.pri}`,
|
|
83
80
|
`needs: ${needs}`,
|
|
84
81
|
`blocks: ${renderIds(task.blocks)}`,
|
|
85
|
-
`parent: ${task.parent === null ? "(none)" :
|
|
82
|
+
`parent: ${task.parent === null ? "(none)" : task.parent}`,
|
|
86
83
|
`from: ${renderIds(task.from)}`,
|
|
87
84
|
`created: ${task.createdAt} by ${task.creator}`,
|
|
88
85
|
"",
|
|
89
86
|
task.body,
|
|
90
|
-
]
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
function renderTreeNode(node, prefix, last) {
|
|
90
|
+
const branch = last ? "`- " : "|- ";
|
|
91
|
+
const nestedPrefix = `${prefix}${last ? " " : "| "}`;
|
|
92
|
+
const task = node.task;
|
|
93
|
+
const released = new Set(task.releasedNeeds);
|
|
94
|
+
const needs = task.needs.length === 0
|
|
95
|
+
? "(none)"
|
|
96
|
+
: task.needs.map((id) => `${id}${released.has(id) ? " (dropped)" : ""}`).join(", ");
|
|
97
|
+
const lines = [
|
|
98
|
+
`${prefix}${branch}${task.id} · ${deriveTaskDisplay(task)} · P${task.pri} · ${task.title}`,
|
|
99
|
+
`${nestedPrefix}needs: ${needs}`,
|
|
100
|
+
`${nestedPrefix}blocks: ${renderIds(task.blocks)}`,
|
|
101
|
+
`${nestedPrefix}from: ${renderIds(task.from)}`,
|
|
102
|
+
];
|
|
103
|
+
node.children.forEach((child, index) => lines.push(...renderTreeNode(child, nestedPrefix, index === node.children.length - 1)));
|
|
104
|
+
return lines;
|
|
105
|
+
}
|
|
106
|
+
function treeDiagnostic(diagnostic) {
|
|
107
|
+
const id = diagnostic.id ? `${diagnostic.id} · ` : "";
|
|
108
|
+
return `! ${diagnostic.code}: ${id}${diagnostic.message}`;
|
|
109
|
+
}
|
|
110
|
+
export function renderTaskShow(task, tree) {
|
|
111
|
+
const treeLines = tree.descendants.length === 0
|
|
112
|
+
? ["children tree: (empty)"]
|
|
113
|
+
: ["children tree:", ...tree.descendants.flatMap((node, index) => renderTreeNode(node, "", index === tree.descendants.length - 1))];
|
|
114
|
+
if (tree.diagnostics.length > 0)
|
|
115
|
+
treeLines.push("tree diagnostics:", ...tree.diagnostics.map(treeDiagnostic));
|
|
116
|
+
return [...renderTaskDetails(task), "", ...treeLines].join("\n");
|
|
91
117
|
}
|
|
92
118
|
export function taskJson(task) {
|
|
93
119
|
return {
|
|
@@ -105,8 +131,22 @@ export function taskJson(task) {
|
|
|
105
131
|
creator: task.creator,
|
|
106
132
|
};
|
|
107
133
|
}
|
|
108
|
-
|
|
109
|
-
return
|
|
134
|
+
function taskTreeNodeJson(node) {
|
|
135
|
+
return { ...taskJson(node.task), children: node.children.map(taskTreeNodeJson) };
|
|
136
|
+
}
|
|
137
|
+
export function taskTreeJson(tree) {
|
|
138
|
+
return {
|
|
139
|
+
children: tree.descendants.map(taskTreeNodeJson),
|
|
140
|
+
diagnostics: tree.diagnostics.map((diagnostic) => ({
|
|
141
|
+
code: diagnostic.code,
|
|
142
|
+
message: diagnostic.message,
|
|
143
|
+
id: diagnostic.id ?? null,
|
|
144
|
+
relatedIds: [...(diagnostic.relatedIds ?? [])],
|
|
145
|
+
})),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
export function renderTaskShowJson(task, tree) {
|
|
149
|
+
return `${JSON.stringify({ ...taskJson(task), body: task.body, descendants: taskTreeJson(tree) })}\n`;
|
|
110
150
|
}
|
|
111
151
|
export function renderTaskListJson(tasks, selection = "default") {
|
|
112
152
|
return `${JSON.stringify(groupAndSortTasks(tasks, selection).map(taskJson))}\n`;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Aggregate status strips the SUBAGENT_ prefix from the public code suffix. */
|
|
2
|
+
export function terminalFailureCodeSuffix(code) {
|
|
3
|
+
return code.startsWith("SUBAGENT_") ? code.slice("SUBAGENT_".length) : code;
|
|
4
|
+
}
|
|
5
|
+
export function terminalFailureColdStatement(failure) {
|
|
6
|
+
if (failure.publicCause?.kind === "rate_limit_exhausted") {
|
|
7
|
+
return "the provider rate limit is exhausted";
|
|
8
|
+
}
|
|
9
|
+
if (failure.class === "runner") {
|
|
10
|
+
return failure.code === "SUBAGENT_SPAWN_ERROR"
|
|
11
|
+
? "the akuma never woke"
|
|
12
|
+
: "the akuma broke mid-flight";
|
|
13
|
+
}
|
|
14
|
+
switch (failure.code) {
|
|
15
|
+
case "SUBAGENT_TIMEOUT":
|
|
16
|
+
return "the akuma went silent";
|
|
17
|
+
case "SUBAGENT_PROVIDER_UNAVAILABLE":
|
|
18
|
+
return "the provider did not answer";
|
|
19
|
+
case "SUBAGENT_NON_ZERO_EXIT":
|
|
20
|
+
return failure.exitCode === undefined ? undefined : `the akuma died · exit ${failure.exitCode}`;
|
|
21
|
+
case "SUBAGENT_EXEC_ERROR":
|
|
22
|
+
return "the akuma broke mid-flight";
|
|
23
|
+
default:
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function terminalFailureEvidence(failure, statement) {
|
|
28
|
+
const exitAlreadyInStatement = statement !== undefined
|
|
29
|
+
&& failure.code === "SUBAGENT_NON_ZERO_EXIT"
|
|
30
|
+
&& failure.exitCode !== undefined;
|
|
31
|
+
const parts = [];
|
|
32
|
+
if (failure.timeoutMs !== undefined)
|
|
33
|
+
parts.push(`idle ${failure.timeoutMs}ms`);
|
|
34
|
+
if (failure.signal)
|
|
35
|
+
parts.push(`signal ${failure.signal}`);
|
|
36
|
+
if (!exitAlreadyInStatement && failure.exitCode !== undefined)
|
|
37
|
+
parts.push(`exit ${failure.exitCode}`);
|
|
38
|
+
parts.push(`phase ${failure.phase}`);
|
|
39
|
+
return parts.length > 0 ? parts.join(" · ") : undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Ordinary wait / single-projection status terminal face.
|
|
43
|
+
* Shape is the locked error-line stream: ✕ cold · CODE, then typed evidence.
|
|
44
|
+
*/
|
|
45
|
+
export function renderTerminalFailureFace(_projectionId, failure) {
|
|
46
|
+
const lines = [];
|
|
47
|
+
if (failure) {
|
|
48
|
+
const statement = terminalFailureColdStatement(failure);
|
|
49
|
+
if (statement)
|
|
50
|
+
lines.push(`✕ ${statement} · ${failure.code}`);
|
|
51
|
+
const evidence = terminalFailureEvidence(failure, statement);
|
|
52
|
+
if (evidence)
|
|
53
|
+
lines.push(` ${evidence}`);
|
|
54
|
+
if (failure.artifactId)
|
|
55
|
+
lines.push(` record ${failure.artifactId}`);
|
|
56
|
+
}
|
|
57
|
+
return lines;
|
|
58
|
+
}
|
package/build/cli/render/wait.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { formatTimelineDuration, renderProjectionActivity, } from "./projection-activity.js";
|
|
2
2
|
import { displayColumns, resolveLineColumns, truncateColumns } from "./line-width.js";
|
|
3
|
-
import { projectionRejoinHintLines, textResponse } from "./shared.js";
|
|
3
|
+
import { formatTellCommand, projectionRejoinHintLines, textResponse } from "./shared.js";
|
|
4
|
+
import { renderTerminalFailureFace } from "./terminal-failure.js";
|
|
4
5
|
const WAIT_HEADER_MAX_COLUMNS = 60;
|
|
5
6
|
function shortAddress(projectionId) {
|
|
6
7
|
return /\/([0-9a-f]{8})$/.exec(projectionId)?.[1] ?? projectionId;
|
|
@@ -19,6 +20,11 @@ function phaseState(phase) {
|
|
|
19
20
|
case "quiescent": return "running";
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
function isTerminalPhase(phase) {
|
|
24
|
+
// `lost` is intentionally absent: it can be an observation failure without
|
|
25
|
+
// a verdict. Core marks the excluded lost-runner-verdict case explicitly.
|
|
26
|
+
return ["done", "failed", "killed", "dismissed"].includes(phase);
|
|
27
|
+
}
|
|
22
28
|
function waitStateText(snapshot) {
|
|
23
29
|
switch (snapshot.phase) {
|
|
24
30
|
case "active":
|
|
@@ -63,12 +69,6 @@ function waitHeader(projectionId, akuma, snapshot, outputColumns) {
|
|
|
63
69
|
const dashCount = Math.max(1, maxColumns - displayColumns(`${prefix} ${state}`));
|
|
64
70
|
return `${prefix} ${"─".repeat(dashCount)} ${state}`;
|
|
65
71
|
}
|
|
66
|
-
function terminalDiagnostic(result) {
|
|
67
|
-
if (result.state !== "terminal" || result.verdict.state !== "failed")
|
|
68
|
-
return undefined;
|
|
69
|
-
const text = result.verdict.detail?.replace(/\s+/g, " ").trim();
|
|
70
|
-
return text ? { at: result.verdict.at, text } : undefined;
|
|
71
|
-
}
|
|
72
72
|
function ledgerHint(projectionId, snapshot) {
|
|
73
73
|
const file = snapshot.eventLedgerFile ?? "events.jsonl";
|
|
74
74
|
return `· ledger: .keiyaku/projection/${projectionId}/${file}`;
|
|
@@ -91,33 +91,14 @@ function nextActionLines(projectionId, result, state) {
|
|
|
91
91
|
"The akuma is back.",
|
|
92
92
|
...(snapshot.artifactId ? [`record: ${snapshot.artifactId}`] : []),
|
|
93
93
|
"talk to it:",
|
|
94
|
-
` »
|
|
94
|
+
` » ${formatTellCommand(projectionId, '"your words"')}`,
|
|
95
95
|
];
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
if (result.state === "terminal" && result.verdict.state === "failed") {
|
|
104
|
-
if (snapshot.failureCode === "SUBAGENT_PROVIDER_UNAVAILABLE") {
|
|
105
|
-
return snapshot.sourceArtifactId
|
|
106
|
-
? [
|
|
107
|
-
"× provider unavailable — no turn accepted",
|
|
108
|
-
`» nothing was consumed · retry from the same artifact: keiyaku revive ${snapshot.sourceArtifactId}`,
|
|
109
|
-
]
|
|
110
|
-
: [
|
|
111
|
-
"× provider unavailable — no turn accepted",
|
|
112
|
-
"» nothing was consumed · safe to call again",
|
|
113
|
-
];
|
|
114
|
-
}
|
|
115
|
-
return [
|
|
116
|
-
"The akuma failed and stopped.",
|
|
117
|
-
...(snapshot.artifactId ? [`record: ${snapshot.artifactId}`] : []),
|
|
118
|
-
"talk to it:",
|
|
119
|
-
` » keiyaku tell ${projectionId} "your words"`,
|
|
120
|
-
];
|
|
97
|
+
if (result.state === "terminal" && (result.verdict.terminalFailure
|
|
98
|
+
|| result.verdict.state === "failed"
|
|
99
|
+
|| result.verdict.state === "launch-failed"
|
|
100
|
+
|| result.verdict.state === "lost-runner")) {
|
|
101
|
+
return renderTerminalFailureFace(projectionId, result.verdict.terminalFailure);
|
|
121
102
|
}
|
|
122
103
|
if (snapshot.phase === "lost") {
|
|
123
104
|
return snapshot.artifactId
|
|
@@ -142,7 +123,7 @@ function startupTimeoutResponse(projectionId, akuma) {
|
|
|
142
123
|
"the launch was never adopted — no akuma exists",
|
|
143
124
|
"",
|
|
144
125
|
"the next wake retries the launch:",
|
|
145
|
-
` »
|
|
126
|
+
` » ${formatTellCommand(projectionId, '"your words"')}`,
|
|
146
127
|
].join("\n")),
|
|
147
128
|
exitCode: 1,
|
|
148
129
|
};
|
|
@@ -198,7 +179,13 @@ export function buildWaitResponse(projectionId, result, options = {}) {
|
|
|
198
179
|
if (result.state === "unknown") {
|
|
199
180
|
return identityUnavailableResponse(projectionId, result.diagnostic);
|
|
200
181
|
}
|
|
201
|
-
|
|
182
|
+
// A plural deadline may observe a verdict whose timestamp is at or after
|
|
183
|
+
// the cutoff. The typed timeout result owns presentation in that case; the
|
|
184
|
+
// later terminal-looking snapshot must not turn it into a terminal face.
|
|
185
|
+
const snapshot = result.state === "timeout"
|
|
186
|
+
&& (result.terminalSnapshot || isTerminalPhase(result.snapshot.phase))
|
|
187
|
+
? { ...result.snapshot, phase: "active" }
|
|
188
|
+
: result.snapshot;
|
|
202
189
|
const maxColumns = options.maxColumns ?? resolveLineColumns();
|
|
203
190
|
if (result.state === "terminal" && result.verdict.state === "killed") {
|
|
204
191
|
return {
|
|
@@ -216,13 +203,11 @@ export function buildWaitResponse(projectionId, result, options = {}) {
|
|
|
216
203
|
if (state === "returned") {
|
|
217
204
|
return returnedResponse(projectionId, result);
|
|
218
205
|
}
|
|
219
|
-
const diagnostic = terminalDiagnostic(result);
|
|
220
206
|
const rendered = renderProjectionActivity(snapshot.activity, {
|
|
221
207
|
anchorMs: snapshot.observedAtMs,
|
|
222
208
|
state,
|
|
223
209
|
showPlan: state === "running",
|
|
224
210
|
...(snapshot.workspaceRoot ? { workspaceRoot: snapshot.workspaceRoot } : {}),
|
|
225
|
-
...(diagnostic ? { terminalDiagnostic: diagnostic } : {}),
|
|
226
211
|
maxColumns,
|
|
227
212
|
});
|
|
228
213
|
const storageDiagnostics = (snapshot.eventDiagnostics ?? []).map((diagnostic) => `‼ ${diagnostic.kind} · ${diagnostic.detail}`);
|
|
@@ -247,3 +232,20 @@ export function buildWaitResponse(projectionId, result, options = {}) {
|
|
|
247
232
|
}
|
|
248
233
|
return response;
|
|
249
234
|
}
|
|
235
|
+
/** The plural face labels every member because a successful singleton face is answer-only. */
|
|
236
|
+
export function buildProjectionWaitSetResponse(result) {
|
|
237
|
+
const rendered = result.results
|
|
238
|
+
.slice()
|
|
239
|
+
.sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0)
|
|
240
|
+
.map((member) => ({ id: member.id, response: buildWaitResponse(member.id, member.result) }));
|
|
241
|
+
const text = rendered.map(({ id, response }) => `${id}\n${response.text}`).join("\n\n");
|
|
242
|
+
const selectionSucceeded = result.selection === "all"
|
|
243
|
+
? result.results.every((member) => member.result.state === "terminal" && member.result.verdict.state === "completed")
|
|
244
|
+
: result.selectedId !== undefined;
|
|
245
|
+
const exitCode = rendered.reduce((current, { response }) => {
|
|
246
|
+
if (response.exitCode === 130)
|
|
247
|
+
return 130;
|
|
248
|
+
return response.exitCode === 1 ? 1 : current;
|
|
249
|
+
}, selectionSucceeded ? undefined : 1);
|
|
250
|
+
return exitCode === undefined ? textResponse(text) : { ...textResponse(text), exitCode };
|
|
251
|
+
}
|
package/build/cli/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const TASK_SUBCOMMANDS = ["add", "
|
|
1
|
+
export const TASK_SUBCOMMANDS = ["add", "show", "ls", "start", "stop", "done", "drop", "update", "doctor"];
|
|
@@ -200,11 +200,6 @@ export async function loadAkumaCatalog(cwd) {
|
|
|
200
200
|
profile: freezeProfile({
|
|
201
201
|
provider: profile.provider,
|
|
202
202
|
...(profile.description !== undefined ? { description: profile.description } : {}),
|
|
203
|
-
...("model" in profile && profile.model !== undefined ? { model: profile.model } : {}),
|
|
204
|
-
...("effort" in profile && profile.effort !== undefined ? { effort: profile.effort } : {}),
|
|
205
|
-
...("effortOptions" in profile && profile.effortOptions !== undefined
|
|
206
|
-
? { effortOptions: Object.freeze([...profile.effortOptions]) }
|
|
207
|
-
: {}),
|
|
208
203
|
}),
|
|
209
204
|
});
|
|
210
205
|
candidates.push(candidate);
|
package/build/config/env-keys.js
CHANGED
|
@@ -25,7 +25,7 @@ export const ENV_KEYS = {
|
|
|
25
25
|
const ENV_KEY_ENTRIES = [
|
|
26
26
|
{ key: ENV_KEYS.AGENT_OVERRIDE, defaultValue: "", description: "Override default agent name", category: "subagent" },
|
|
27
27
|
{ key: ENV_KEYS.DISABLE_SUBAGENT_SPAWN, defaultValue: "0", description: "Disable subprocess subagent spawning when set to 1", category: "subagent" },
|
|
28
|
-
{ key: ENV_KEYS.SUBAGENT_EXEC_IDLE_TIMEOUT_MS, defaultValue: "
|
|
28
|
+
{ key: ENV_KEYS.SUBAGENT_EXEC_IDLE_TIMEOUT_MS, defaultValue: "300000", description: "Subagent provider-ingress idle timeout in milliseconds", category: "subagent" },
|
|
29
29
|
{ key: ENV_KEYS.CODEX_EXEC_MAX_CAPTURE_CHARS, defaultValue: "200000", description: "Codex runtime output/diagnostics capture cap", category: "subagent" },
|
|
30
30
|
{ key: ENV_KEYS.CLAUDE_EXEC_MAX_CAPTURE_CHARS, defaultValue: "200000", description: "Claude runtime output/diagnostics capture cap", category: "subagent" },
|
|
31
31
|
{ key: ENV_KEYS.OPENCODE_EXEC_MAX_CAPTURE_CHARS, defaultValue: "200000", description: "OpenCode runtime output/diagnostics capture cap", category: "subagent" },
|
|
@@ -1,39 +1,10 @@
|
|
|
1
|
+
import { getProviderRegistration } from "../agents/providers/registry.js";
|
|
1
2
|
const EMPTY_OWNERSHIP = Object.freeze({
|
|
2
3
|
access: Object.freeze([]),
|
|
3
4
|
network: Object.freeze([]),
|
|
4
5
|
webSearch: Object.freeze([]),
|
|
5
6
|
});
|
|
6
|
-
function owns(config, key) {
|
|
7
|
-
return Object.prototype.hasOwnProperty.call(config, key);
|
|
8
|
-
}
|
|
9
7
|
export function nativePolicyOwnership(instanceName, instance) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
const config = instance.config;
|
|
14
|
-
if (!config)
|
|
15
|
-
return EMPTY_OWNERSHIP;
|
|
16
|
-
const access = [];
|
|
17
|
-
const network = [];
|
|
18
|
-
const webSearch = [];
|
|
19
|
-
const add = (target, key) => {
|
|
20
|
-
target.push({ path: `providers.${instanceName}.config.${key}`, value: config[key] });
|
|
21
|
-
};
|
|
22
|
-
if (owns(config, "sandbox_mode"))
|
|
23
|
-
add(access, "sandbox_mode");
|
|
24
|
-
if (owns(config, "approval_policy"))
|
|
25
|
-
add(access, "approval_policy");
|
|
26
|
-
for (const key of Object.keys(config)) {
|
|
27
|
-
if (key !== "sandbox_workspace_write" && !key.startsWith("sandbox_workspace_write."))
|
|
28
|
-
continue;
|
|
29
|
-
add(access, key);
|
|
30
|
-
add(network, key);
|
|
31
|
-
}
|
|
32
|
-
if (owns(config, "web_search"))
|
|
33
|
-
add(webSearch, "web_search");
|
|
34
|
-
return Object.freeze({
|
|
35
|
-
access: Object.freeze(access),
|
|
36
|
-
network: Object.freeze(network),
|
|
37
|
-
webSearch: Object.freeze(webSearch),
|
|
38
|
-
});
|
|
8
|
+
const owned = getProviderRegistration(instance.kind).nativePolicyOwnership(instanceName, instance);
|
|
9
|
+
return owned ?? EMPTY_OWNERSHIP;
|
|
39
10
|
}
|
|
@@ -21,6 +21,13 @@ export function assertSettingsKnobUsable(loaded, knob) {
|
|
|
21
21
|
if (hits.length === 0)
|
|
22
22
|
return;
|
|
23
23
|
throw new FlowError("INVALID_SETTINGS", `Invalid settings in ${SETTINGS_FILE} (diseased knob '${knob}').`, {
|
|
24
|
-
|
|
24
|
+
facts: {
|
|
25
|
+
kind: "invalid_settings",
|
|
26
|
+
diseases: hits.map((disease) => ({
|
|
27
|
+
source: disease.source,
|
|
28
|
+
...(disease.knob !== undefined ? { knob: disease.knob } : {}),
|
|
29
|
+
reason: disease.reason,
|
|
30
|
+
})),
|
|
31
|
+
},
|
|
25
32
|
});
|
|
26
33
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import { getProviderRegistration } from "../../agents/providers/registry.js";
|
|
3
4
|
import { isErrnoException } from "../../errno.js";
|
|
4
5
|
import { SETTINGS_FILE } from "../../keiyaku.js";
|
|
5
6
|
import { getKeiyakuHome } from "../env.js";
|
|
@@ -85,10 +86,17 @@ function collectProviderCandidates(source, rawProviders) {
|
|
|
85
86
|
continue;
|
|
86
87
|
}
|
|
87
88
|
const instance = instanceResult.data;
|
|
88
|
-
|
|
89
|
+
const registration = getProviderRegistration(instance.kind);
|
|
90
|
+
const writableRoots = registration.rejectsGlobalWritableRoots &&
|
|
91
|
+
instance &&
|
|
92
|
+
typeof instance === "object" &&
|
|
93
|
+
"writableRoots" in instance
|
|
94
|
+
? instance.writableRoots
|
|
95
|
+
: undefined;
|
|
96
|
+
if (writableRoots !== undefined && source === "global") {
|
|
89
97
|
let relativeIndex;
|
|
90
|
-
for (let i = 0; i <
|
|
91
|
-
if (!path.posix.isAbsolute(
|
|
98
|
+
for (let i = 0; i < writableRoots.length; i++) {
|
|
99
|
+
if (!path.posix.isAbsolute(writableRoots[i])) {
|
|
92
100
|
relativeIndex = i;
|
|
93
101
|
break;
|
|
94
102
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Local leaf copy of the Claude setting-source vocabulary so this module never
|
|
3
|
+
// imports keiyaku.js (which re-exports the provider registry and would cycle).
|
|
4
|
+
const CLAUDE_SETTING_SOURCES = ["project", "user", "local"];
|
|
5
|
+
export const tomlValueSchema = z.lazy(() => z.union([
|
|
6
|
+
z.string(),
|
|
7
|
+
z.number(),
|
|
8
|
+
z.boolean(),
|
|
9
|
+
z.array(tomlValueSchema),
|
|
10
|
+
z.record(z.string(), tomlValueSchema),
|
|
11
|
+
]));
|
|
12
|
+
export const structuredTomlValueSchema = z.record(z.string(), tomlValueSchema);
|
|
13
|
+
export const executableSchema = z.string().superRefine((value, ctx) => {
|
|
14
|
+
if (value.length === 0 || /\s/.test(value) || value.includes("\"") || value.includes("'")) {
|
|
15
|
+
ctx.addIssue({
|
|
16
|
+
code: z.ZodIssueCode.custom,
|
|
17
|
+
message: "must be a single program name token with no spaces or quotes.",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
export const nonblankOptionalString = z
|
|
22
|
+
.string()
|
|
23
|
+
.refine((value) => value.trim().length > 0, { message: "must not be blank." })
|
|
24
|
+
.optional();
|
|
25
|
+
export const providerCommonFields = {
|
|
26
|
+
description: nonblankOptionalString,
|
|
27
|
+
};
|
|
28
|
+
export const providerEnvSchema = z.record(z.string(), z.string()).optional();
|
|
29
|
+
export const FORBIDDEN_CONFIG_KEYS = ["model", "model_reasoning_effort"];
|
|
30
|
+
export function isConfigKeyForbidden(key) {
|
|
31
|
+
return FORBIDDEN_CONFIG_KEYS.includes(key);
|
|
32
|
+
}
|
|
33
|
+
export const claudeSettingSourceSchema = z.enum(CLAUDE_SETTING_SOURCES);
|
|
34
|
+
export const writableRootItemSchema = z.string().superRefine((value, ctx) => {
|
|
35
|
+
if (value.length === 0) {
|
|
36
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not be empty." });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (value.startsWith("~")) {
|
|
40
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not begin with tilde." });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (value.includes("\0")) {
|
|
44
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not contain NUL byte." });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (/\$[A-Za-z_]/.test(value) || /\$\{/.test(value)) {
|
|
48
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not contain environment variable references." });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
});
|