@astrosheep/keiyaku 4.0.0 → 4.0.1
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/README.md +2 -9
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +11 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +9 -6
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +94 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +162 -45
- package/build/src/akuma/akuma.d.ts +33 -25
- package/build/src/akuma/akuma.js +93 -61
- package/build/src/akuma/archetype.d.ts +8 -0
- package/build/src/akuma/archetype.js +28 -9
- package/build/src/akuma/body.js +196 -84
- package/build/src/akuma/coordinate.d.ts +9 -0
- package/build/src/akuma/coordinate.js +22 -0
- package/build/src/akuma/heart/facts.d.ts +67 -15
- package/build/src/akuma/heart/facts.js +3 -3
- package/build/src/akuma/heart/index.d.ts +41 -29
- package/build/src/akuma/heart/index.js +72 -193
- package/build/src/akuma/heart/rows.d.ts +30 -53
- package/build/src/akuma/heart/rows.js +91 -111
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +55 -8
- package/build/src/akuma/heart/storage.d.ts +33 -0
- package/build/src/akuma/heart/storage.js +164 -0
- package/build/src/akuma/heart/tells.d.ts +12 -0
- package/build/src/akuma/heart/tells.js +79 -0
- package/build/src/akuma/heart/timeline.d.ts +15 -0
- package/build/src/akuma/heart/timeline.js +86 -0
- package/build/src/akuma/index.d.ts +4 -2
- package/build/src/akuma/index.js +1 -1
- package/build/src/akuma/projection.d.ts +97 -0
- package/build/src/akuma/projection.js +145 -0
- package/build/src/akuma/provider.d.ts +57 -11
- package/build/src/akuma/provider.js +57 -37
- package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
- package/build/src/akuma/providers/claude/events.js +185 -0
- package/build/src/akuma/providers/claude/index.d.ts +46 -0
- package/build/src/akuma/providers/claude/index.js +265 -0
- package/build/src/akuma/providers/claude/input.d.ts +13 -0
- package/build/src/akuma/providers/claude/input.js +109 -0
- package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
- package/build/src/akuma/providers/codex-app-server/events.js +12 -12
- package/build/src/akuma/providers/codex-app-server/index.d.ts +13 -11
- package/build/src/akuma/providers/codex-app-server/index.js +73 -22
- package/build/src/akuma/providers/index.js +22 -8
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +48 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +116 -0
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +32 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +203 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +41 -0
- package/build/src/akuma/providers/opencode-sdk/session.js +62 -0
- package/build/src/akuma/providers/pi/events.d.ts +33 -0
- package/build/src/akuma/providers/pi/events.js +128 -0
- package/build/src/akuma/providers/pi/index.d.ts +11 -0
- package/build/src/akuma/providers/pi/index.js +162 -0
- package/build/src/akuma/requests.d.ts +1 -0
- package/build/src/akuma/requests.js +5 -2
- package/build/src/alias/index.d.ts +4 -3
- package/build/src/alias/index.js +2 -3
- package/build/src/body/render.js +2 -1
- package/build/src/body/shape.js +7 -1
- package/build/src/body/verification.js +19 -4
- package/build/src/cli/accepted.d.ts +2 -0
- package/build/src/cli/accepted.js +2 -1
- package/build/src/cli/commands/akuma-invoke.d.ts +42 -18
- package/build/src/cli/commands/akuma-invoke.js +94 -50
- package/build/src/cli/commands/akuma.d.ts +15 -7
- package/build/src/cli/commands/akuma.js +94 -56
- package/build/src/cli/commands/contract.d.ts +142 -0
- package/build/src/cli/commands/contract.js +14 -0
- package/build/src/cli/commands/install.js +2 -0
- package/build/src/cli/commands/task-invoke.d.ts +3 -1
- package/build/src/cli/commands/task-invoke.js +27 -2
- package/build/src/cli/commands/task.js +2 -2
- package/build/src/cli/invoke.d.ts +6 -1
- package/build/src/cli/invoke.js +241 -43
- package/build/src/cli/main.js +20 -1
- package/build/src/cli/parse.d.ts +13 -116
- package/build/src/cli/parse.js +51 -78
- package/build/src/cli/render/akuma-tool.d.ts +2 -0
- package/build/src/cli/render/akuma-tool.js +6 -2
- package/build/src/cli/render/akuma.d.ts +2 -1
- package/build/src/cli/render/akuma.js +157 -217
- package/build/src/cli/render/catalog.d.ts +2 -0
- package/build/src/cli/render/catalog.js +16 -0
- package/build/src/cli/render/contract.d.ts +1 -1
- package/build/src/cli/render/contract.js +38 -5
- package/build/src/cli/render/kanshi.js +53 -5
- package/build/src/cli/render/refusal.js +17 -0
- package/build/src/cli/render/terminal.d.ts +13 -0
- package/build/src/cli/render/terminal.js +75 -0
- package/build/src/cli/render/text.js +5 -0
- package/build/src/cli/result.d.ts +15 -3
- package/build/src/contract-worktree.d.ts +43 -0
- package/build/src/contract-worktree.js +213 -0
- package/build/src/coordination/durable-file.d.ts +3 -0
- package/build/src/coordination/durable-file.js +44 -1
- package/build/src/core/facts/codec.js +23 -4
- package/build/src/core/facts/eligibility.d.ts +1 -10
- package/build/src/core/facts/eligibility.js +0 -49
- package/build/src/core/facts/observation.d.ts +3 -0
- package/build/src/core/facts/observation.js +12 -0
- package/build/src/core/facts/types.d.ts +10 -3
- package/build/src/core/subject.js +2 -2
- package/build/src/core/verbs/amend.js +12 -16
- package/build/src/core/verbs/bind.js +2 -16
- package/build/src/core/verbs/deliver.js +20 -4
- package/build/src/core/verbs/placement.js +3 -8
- package/build/src/dispatch/index.d.ts +3 -1
- package/build/src/dispatch/index.js +14 -5
- package/build/src/duration.d.ts +10 -0
- package/build/src/duration.js +22 -0
- package/build/src/git/admission.d.ts +2 -2
- package/build/src/git/admission.js +26 -16
- package/build/src/git/hooks.d.ts +15 -0
- package/build/src/git/hooks.js +57 -5
- package/build/src/git/identity.d.ts +5 -1
- package/build/src/git/identity.js +23 -4
- package/build/src/git/integration.d.ts +49 -0
- package/build/src/git/integration.js +214 -0
- package/build/src/git/observe.d.ts +25 -13
- package/build/src/git/observe.js +175 -72
- package/build/src/git/read-observation.d.ts +41 -0
- package/build/src/git/read-observation.js +361 -0
- package/build/src/git/reconcile.d.ts +15 -5
- package/build/src/git/reconcile.js +238 -85
- package/build/src/git/repository.d.ts +19 -4
- package/build/src/git/repository.js +77 -43
- package/build/src/git/scratch.d.ts +13 -0
- package/build/src/git/scratch.js +66 -0
- package/build/src/git/target-placement.d.ts +56 -0
- package/build/src/git/target-placement.js +255 -0
- package/build/src/git/tender.d.ts +48 -0
- package/build/src/git/tender.js +82 -0
- package/build/src/git/terminal-seal.d.ts +24 -0
- package/build/src/git/terminal-seal.js +87 -0
- package/build/src/git/tree.d.ts +2 -2
- package/build/src/git/tree.js +4 -0
- package/build/src/git/workspace.d.ts +21 -0
- package/build/src/git/workspace.js +104 -0
- package/build/src/identity/selector.d.ts +6 -0
- package/build/src/identity/selector.js +19 -0
- package/build/src/index.d.ts +4 -2
- package/build/src/index.js +2 -1
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.d.ts +5 -2
- package/build/src/kanshi/read.js +154 -45
- package/build/src/kanshi/report.d.ts +31 -6
- package/build/src/kanshi/select.js +1 -1
- package/build/src/library/address.d.ts +48 -0
- package/build/src/library/address.js +134 -0
- package/build/src/library/akuma-creation.d.ts +10 -6
- package/build/src/library/akuma-creation.js +12 -11
- package/build/src/library/bind.d.ts +21 -0
- package/build/src/library/bind.js +56 -0
- package/build/src/library/catalog.d.ts +58 -0
- package/build/src/library/catalog.js +72 -0
- package/build/src/library/configuration.d.ts +6 -15
- package/build/src/library/configuration.js +14 -17
- package/build/src/library/contract.d.ts +21 -46
- package/build/src/library/contract.js +193 -183
- package/build/src/library/delivery.d.ts +23 -0
- package/build/src/library/delivery.js +21 -0
- package/build/src/library/fleet.d.ts +65 -0
- package/build/src/library/fleet.js +189 -0
- package/build/src/library/input.d.ts +3 -0
- package/build/src/library/input.js +19 -0
- package/build/src/library/keiyaku.d.ts +16 -2
- package/build/src/library/keiyaku.js +11 -1
- package/build/src/library/mutation.d.ts +38 -0
- package/build/src/library/mutation.js +39 -0
- package/build/src/library/refusal.d.ts +21 -0
- package/build/src/library/refusal.js +29 -0
- package/build/src/library/region.d.ts +2 -1
- package/build/src/library/region.js +3 -3
- package/build/src/library/repo.d.ts +4 -1
- package/build/src/library/repo.js +31 -16
- package/build/src/protocol/attempt.d.ts +16 -3
- package/build/src/protocol/attempt.js +39 -8
- package/build/src/protocol/bind.d.ts +9 -2
- package/build/src/protocol/bind.js +47 -39
- package/build/src/protocol/intent.d.ts +42 -18
- package/build/src/protocol/intent.js +36 -75
- package/build/src/protocol/operations.d.ts +93 -35
- package/build/src/protocol/operations.js +235 -123
- package/build/src/protocol/outcome.d.ts +7 -2
- package/build/src/protocol/outcome.js +9 -3
- package/build/src/protocol/placement.d.ts +30 -0
- package/build/src/protocol/placement.js +114 -0
- package/build/src/protocol/read/audit.d.ts +9 -3
- package/build/src/protocol/read/audit.js +25 -9
- package/build/src/protocol/read/documents.d.ts +2 -2
- package/build/src/protocol/read/documents.js +4 -4
- package/build/src/protocol/read/status.d.ts +11 -5
- package/build/src/protocol/read/status.js +28 -15
- package/build/src/protocol/run.d.ts +49 -7
- package/build/src/protocol/run.js +53 -25
- package/build/src/runtime/proc/line-rpc.d.ts +1 -0
- package/build/src/runtime/proc/line-rpc.js +21 -0
- package/build/src/runtime/proc/run.d.ts +18 -2
- package/build/src/runtime/proc/run.js +34 -8
- package/build/src/settings.d.ts +6 -0
- package/build/src/settings.js +29 -14
- package/build/src/settlement/fence.d.ts +9 -0
- package/build/src/settlement/fence.js +23 -0
- package/build/src/settlement/holder.d.ts +25 -4
- package/build/src/settlement/holder.js +102 -28
- package/build/src/settlement/settle.d.ts +8 -0
- package/build/src/settlement/settle.js +102 -28
- package/build/src/task/board.d.ts +20 -2
- package/build/src/task/board.js +11 -1
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +2 -2
- package/build/src/task/context.js +2 -7
- package/build/src/task/index.d.ts +9 -9
- package/build/src/task/index.js +15 -12
- package/build/src/task/operations.d.ts +31 -12
- package/build/src/task/operations.js +8 -4
- package/build/src/task/store.d.ts +4 -6
- package/build/src/task/store.js +3 -3
- package/build/src/verification/declaration.d.ts +1 -0
- package/build/src/verification/execution.d.ts +49 -0
- package/build/src/verification/execution.js +104 -0
- package/build/src/world.d.ts +13 -0
- package/build/src/world.js +103 -0
- package/package.json +7 -4
- package/build/src/akuma/activity.d.ts +0 -66
- package/build/src/akuma/activity.js +0 -139
- package/build/src/akuma/providers/claude.js +0 -305
- package/build/src/context-root.d.ts +0 -4
- package/build/src/context-root.js +0 -15
- package/build/src/git/delivery.d.ts +0 -20
- package/build/src/git/delivery.js +0 -109
- package/build/src/git/verification.d.ts +0 -14
- package/build/src/git/verification.js +0 -56
- package/build/src/verification/producer.d.ts +0 -23
- package/build/src/verification/producer.js +0 -54
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { AgentEventChannel, } from "../../provider.js";
|
|
3
|
+
import { emitClaudeMessage, } from "./events.js";
|
|
4
|
+
import { claudeUserMessage, createClaudeInput, isClaudeTurnEnded } from "./input.js";
|
|
5
|
+
export { CLAUDE_MESSAGE_DISPOSITIONS, CLAUDE_SYSTEM_DISPOSITIONS } from "./events.js";
|
|
6
|
+
class ReceiptChannel {
|
|
7
|
+
queued = [];
|
|
8
|
+
waiters = [];
|
|
9
|
+
ended = false;
|
|
10
|
+
emit(receipt) {
|
|
11
|
+
if (this.ended)
|
|
12
|
+
throw new Error("Claude receipt stream already ended");
|
|
13
|
+
const waiter = this.waiters.shift();
|
|
14
|
+
if (waiter === undefined)
|
|
15
|
+
this.queued.push(receipt);
|
|
16
|
+
else
|
|
17
|
+
waiter.resolve({ done: false, value: receipt });
|
|
18
|
+
}
|
|
19
|
+
end() {
|
|
20
|
+
if (this.ended)
|
|
21
|
+
return;
|
|
22
|
+
this.ended = true;
|
|
23
|
+
for (const waiter of this.waiters.splice(0))
|
|
24
|
+
waiter.resolve({ done: true, value: undefined });
|
|
25
|
+
}
|
|
26
|
+
[Symbol.asyncIterator]() {
|
|
27
|
+
return {
|
|
28
|
+
next: () => {
|
|
29
|
+
const receipt = this.queued.shift();
|
|
30
|
+
if (receipt !== undefined)
|
|
31
|
+
return Promise.resolve({ done: false, value: receipt });
|
|
32
|
+
if (this.ended)
|
|
33
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
34
|
+
return new Promise((resolve) => this.waiters.push({ resolve }));
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function admitClaudeOptions(options) {
|
|
40
|
+
if (options.network !== undefined) {
|
|
41
|
+
return { kind: "refused", diagnostic: "Claude provider does not support the Archetype network option" };
|
|
42
|
+
}
|
|
43
|
+
return { kind: "admitted", options: Object.freeze({ ...options }) };
|
|
44
|
+
}
|
|
45
|
+
function permissionMode(access) {
|
|
46
|
+
if (access === "read")
|
|
47
|
+
return "plan";
|
|
48
|
+
if (access === "write")
|
|
49
|
+
return "acceptEdits";
|
|
50
|
+
return "bypassPermissions";
|
|
51
|
+
}
|
|
52
|
+
function claudeSessionId(coordinate) {
|
|
53
|
+
if (!("sessionId" in coordinate) || coordinate.sessionId === undefined) {
|
|
54
|
+
throw new Error("Claude resume requires sessionId");
|
|
55
|
+
}
|
|
56
|
+
return coordinate.sessionId;
|
|
57
|
+
}
|
|
58
|
+
function claudeQueryOptions(input, execution, abortController) {
|
|
59
|
+
const access = permissionMode(input.options.access);
|
|
60
|
+
return {
|
|
61
|
+
cwd: input.cwd,
|
|
62
|
+
abortController,
|
|
63
|
+
...(execution.executable === undefined ? {} : { pathToClaudeCodeExecutable: execution.executable }),
|
|
64
|
+
...(execution.env === undefined ? {} : { env: { ...process.env, ...execution.env } }),
|
|
65
|
+
permissionMode: access,
|
|
66
|
+
...(access === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {}),
|
|
67
|
+
settingSources: ["user", "project", "local"],
|
|
68
|
+
...(input.options.model === undefined ? {} : { model: input.options.model }),
|
|
69
|
+
...(input.options.effort === undefined ? {} : { effort: input.options.effort }),
|
|
70
|
+
...(input.options.systemPrompt === undefined || input.options.systemPrompt.length === 0 ? {} : {
|
|
71
|
+
systemPrompt: { type: "preset", preset: "claude_code", append: input.options.systemPrompt },
|
|
72
|
+
}),
|
|
73
|
+
...(input.session.kind === "fresh" ? {} : { resume: claudeSessionId(input.session.coordinate) }),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async function forkClaude(load, execution, input) {
|
|
77
|
+
const sessionId = claudeSessionId(input.session);
|
|
78
|
+
if (execution.env !== undefined)
|
|
79
|
+
throw new Error("Claude fork cannot apply the frozen provider environment");
|
|
80
|
+
const sdk = await load();
|
|
81
|
+
if (sdk.forkSession === undefined)
|
|
82
|
+
throw new Error("Claude SDK does not expose forkSession");
|
|
83
|
+
const forked = await sdk.forkSession(sessionId, { dir: input.cwd, upToMessageId: input.at });
|
|
84
|
+
if (forked.sessionId.trim().length === 0)
|
|
85
|
+
throw new Error("Claude fork returned an empty child session id");
|
|
86
|
+
if (forked.sessionId === sessionId)
|
|
87
|
+
throw new Error("Claude fork reused the source session id");
|
|
88
|
+
return { session: { sessionId: forked.sessionId } };
|
|
89
|
+
}
|
|
90
|
+
function launchText(input) {
|
|
91
|
+
return [input.body, ...input.launchTells.map((tell) => tell.text)]
|
|
92
|
+
.filter((part) => part.length > 0).join("\n\n");
|
|
93
|
+
}
|
|
94
|
+
function successfulResult(message, historyId) {
|
|
95
|
+
return historyId === undefined
|
|
96
|
+
? { kind: "failed", diagnostic: "Claude query succeeded without an assistant history id" }
|
|
97
|
+
: { kind: "answered", answer: message.subtype === "success" ? message.result : "", historyId };
|
|
98
|
+
}
|
|
99
|
+
function finishClaudeInput(input, terminal) {
|
|
100
|
+
if (terminal?.kind === "answered")
|
|
101
|
+
input.end();
|
|
102
|
+
else
|
|
103
|
+
input.close();
|
|
104
|
+
}
|
|
105
|
+
function observeClaudeQuery(context) {
|
|
106
|
+
const { query, input, events, receipts, accepted, state } = context;
|
|
107
|
+
const observation = { tools: new Map() };
|
|
108
|
+
let admit;
|
|
109
|
+
let rejectAdmission;
|
|
110
|
+
const admission = new Promise((resolve, reject) => { admit = resolve; rejectAdmission = reject; });
|
|
111
|
+
let settle;
|
|
112
|
+
const completion = new Promise((resolve) => { settle = resolve; });
|
|
113
|
+
let checkpoint = 0, ended = false;
|
|
114
|
+
const settleReceipts = () => {
|
|
115
|
+
if (ended && state.openSubmissions === 0 && accepted.every((tell) => tell.visible))
|
|
116
|
+
receipts.end();
|
|
117
|
+
};
|
|
118
|
+
const flushReceipts = () => {
|
|
119
|
+
for (let index = 0; index < accepted.length;) {
|
|
120
|
+
const tell = accepted[index];
|
|
121
|
+
if (!tell.visible || tell.afterCheckpoint >= checkpoint) {
|
|
122
|
+
index += 1;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
accepted.splice(index, 1);
|
|
126
|
+
receipts.emit({ evidence: "exact", tellId: tell.id, kind: "consumed" });
|
|
127
|
+
}
|
|
128
|
+
closeWhenIdle();
|
|
129
|
+
settleReceipts();
|
|
130
|
+
};
|
|
131
|
+
const closeWhenIdle = () => {
|
|
132
|
+
if (state.openSubmissions === 0 && accepted.length === 0 && input.pending === 0)
|
|
133
|
+
input.close();
|
|
134
|
+
};
|
|
135
|
+
void (async () => {
|
|
136
|
+
let admitted = false;
|
|
137
|
+
let terminal = null;
|
|
138
|
+
let historyId;
|
|
139
|
+
try {
|
|
140
|
+
for await (const message of query) {
|
|
141
|
+
if (!admitted && "session_id" in message && typeof message.session_id === "string") {
|
|
142
|
+
admitted = true;
|
|
143
|
+
events.emit({ type: "session", coordinate: { sessionId: message.session_id } });
|
|
144
|
+
admit();
|
|
145
|
+
}
|
|
146
|
+
emitClaudeMessage(message, events, observation);
|
|
147
|
+
if (message.type === "assistant" && message.parent_tool_use_id === null
|
|
148
|
+
&& typeof message.uuid === "string" && message.uuid.length > 0)
|
|
149
|
+
historyId = message.uuid;
|
|
150
|
+
if (message.type !== "result")
|
|
151
|
+
continue;
|
|
152
|
+
if (message.subtype === "success") {
|
|
153
|
+
terminal = successfulResult(message, historyId);
|
|
154
|
+
checkpoint += 1;
|
|
155
|
+
flushReceipts();
|
|
156
|
+
queueMicrotask(closeWhenIdle);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
terminal = { kind: "failed", diagnostic: message.errors.join("; ") || message.subtype };
|
|
160
|
+
input.close();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
ended = true;
|
|
164
|
+
const result = terminal ?? { kind: "failed", diagnostic: "Claude query ended without a result" };
|
|
165
|
+
if (!admitted)
|
|
166
|
+
rejectAdmission(new Error(result.kind === "failed" ? result.diagnostic : "Claude query ended before session admission"));
|
|
167
|
+
settle(result);
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
ended = true;
|
|
171
|
+
input.fail(error);
|
|
172
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
173
|
+
if (!admitted)
|
|
174
|
+
rejectAdmission(failure);
|
|
175
|
+
settle({ kind: "failed", diagnostic: failure.message });
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
finishClaudeInput(input, terminal);
|
|
179
|
+
events.end();
|
|
180
|
+
settleReceipts();
|
|
181
|
+
}
|
|
182
|
+
})();
|
|
183
|
+
return {
|
|
184
|
+
admission,
|
|
185
|
+
completion,
|
|
186
|
+
get ended() { return ended; },
|
|
187
|
+
get checkpoint() { return checkpoint; },
|
|
188
|
+
flushReceipts,
|
|
189
|
+
settleReceipts,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
async function driveClaude(load, execution, drive) {
|
|
193
|
+
if (drive.session.kind === "resume")
|
|
194
|
+
claudeSessionId(drive.session.coordinate);
|
|
195
|
+
const sdk = await load();
|
|
196
|
+
const events = new AgentEventChannel();
|
|
197
|
+
const receipts = new ReceiptChannel();
|
|
198
|
+
const input = createClaudeInput();
|
|
199
|
+
const abortController = new AbortController();
|
|
200
|
+
const run = randomUUID();
|
|
201
|
+
const accepted = [];
|
|
202
|
+
let submission = 0;
|
|
203
|
+
let openSubmissions = 0;
|
|
204
|
+
const launchAcknowledged = input.push(claudeUserMessage(launchText(drive)));
|
|
205
|
+
const query = sdk.query({
|
|
206
|
+
prompt: input.iterable,
|
|
207
|
+
options: claudeQueryOptions(drive, execution, abortController),
|
|
208
|
+
});
|
|
209
|
+
const observed = observeClaudeQuery({
|
|
210
|
+
query, input, events, receipts, accepted,
|
|
211
|
+
state: { get openSubmissions() { return openSubmissions; } },
|
|
212
|
+
});
|
|
213
|
+
await Promise.all([launchAcknowledged, observed.admission]);
|
|
214
|
+
return {
|
|
215
|
+
admission: { fence: `claude:${run}:0` },
|
|
216
|
+
events,
|
|
217
|
+
receipts,
|
|
218
|
+
completion: observed.completion,
|
|
219
|
+
tell(tell) {
|
|
220
|
+
if (observed.ended || input.closed)
|
|
221
|
+
return Promise.resolve({ kind: "turn-ended" });
|
|
222
|
+
openSubmissions += 1;
|
|
223
|
+
const ordinal = ++submission;
|
|
224
|
+
return new Promise((resolve, reject) => {
|
|
225
|
+
const pending = { id: tell.id, afterCheckpoint: 0, visible: false };
|
|
226
|
+
void input.push(claudeUserMessage(tell.text), () => {
|
|
227
|
+
pending.afterCheckpoint = observed.checkpoint;
|
|
228
|
+
accepted.push(pending);
|
|
229
|
+
}).then(() => {
|
|
230
|
+
openSubmissions -= 1;
|
|
231
|
+
resolve({ kind: "accepted", fence: `claude:${run}:${ordinal}` });
|
|
232
|
+
queueMicrotask(() => {
|
|
233
|
+
pending.visible = true;
|
|
234
|
+
observed.flushReceipts();
|
|
235
|
+
observed.settleReceipts();
|
|
236
|
+
});
|
|
237
|
+
}, (error) => {
|
|
238
|
+
openSubmissions -= 1;
|
|
239
|
+
if (isClaudeTurnEnded(error))
|
|
240
|
+
resolve({ kind: "turn-ended" });
|
|
241
|
+
else
|
|
242
|
+
reject(error);
|
|
243
|
+
observed.settleReceipts();
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
},
|
|
247
|
+
async abort() {
|
|
248
|
+
const error = new Error("Claude query aborted");
|
|
249
|
+
abortController.abort(error);
|
|
250
|
+
input.fail(error);
|
|
251
|
+
query.close();
|
|
252
|
+
await observed.completion;
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
export function createClaudeProvider(load, execution = {}) {
|
|
257
|
+
return {
|
|
258
|
+
confinement: () => ({ kind: "unconfined" }),
|
|
259
|
+
admitOptions: admitClaudeOptions,
|
|
260
|
+
fork: (input) => forkClaude(load, execution, input),
|
|
261
|
+
start: (input) => driveClaude(load, execution, input),
|
|
262
|
+
resume: (input) => driveClaude(load, execution, input),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
export const claudeProvider = createClaudeProvider(async () => await import("@anthropic-ai/claude-agent-sdk"));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
export declare function isClaudeTurnEnded(error: unknown): boolean;
|
|
3
|
+
export type ClaudeInput = Readonly<{
|
|
4
|
+
iterable: AsyncIterable<SDKUserMessage>;
|
|
5
|
+
get closed(): boolean;
|
|
6
|
+
get pending(): number;
|
|
7
|
+
push(message: SDKUserMessage, onPulled?: () => void): Promise<void>;
|
|
8
|
+
end(): void;
|
|
9
|
+
close(): void;
|
|
10
|
+
fail(error: unknown): void;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function claudeUserMessage(text: string): SDKUserMessage;
|
|
13
|
+
export declare function createClaudeInput(): ClaudeInput;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
function deferred() {
|
|
2
|
+
let resolve;
|
|
3
|
+
let reject;
|
|
4
|
+
const promise = new Promise((accept, refuse) => {
|
|
5
|
+
resolve = accept;
|
|
6
|
+
reject = refuse;
|
|
7
|
+
});
|
|
8
|
+
return { promise, resolve, reject };
|
|
9
|
+
}
|
|
10
|
+
function ended() {
|
|
11
|
+
return new Error("Claude input ended before the SDK acknowledged the message");
|
|
12
|
+
}
|
|
13
|
+
const turnEnded = Symbol("claude-turn-ended");
|
|
14
|
+
class ClaudeTurnEndedError extends Error {
|
|
15
|
+
[turnEnded] = true;
|
|
16
|
+
}
|
|
17
|
+
function turnEndedError() {
|
|
18
|
+
return new ClaudeTurnEndedError("Claude query ended before the SDK acknowledged the message");
|
|
19
|
+
}
|
|
20
|
+
export function isClaudeTurnEnded(error) {
|
|
21
|
+
return typeof error === "object" && error !== null && error[turnEnded] === true;
|
|
22
|
+
}
|
|
23
|
+
export function claudeUserMessage(text) {
|
|
24
|
+
return {
|
|
25
|
+
type: "user",
|
|
26
|
+
message: { role: "user", content: text },
|
|
27
|
+
parent_tool_use_id: null,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function createClaudeInput() {
|
|
31
|
+
const queue = [];
|
|
32
|
+
const waiters = [];
|
|
33
|
+
let previous;
|
|
34
|
+
let failure;
|
|
35
|
+
let closed = false;
|
|
36
|
+
const acknowledgePrevious = () => {
|
|
37
|
+
previous?.onPulled?.();
|
|
38
|
+
previous?.pulled.resolve();
|
|
39
|
+
previous = undefined;
|
|
40
|
+
};
|
|
41
|
+
const take = (entry) => {
|
|
42
|
+
previous = entry;
|
|
43
|
+
return { done: false, value: entry.message };
|
|
44
|
+
};
|
|
45
|
+
const rejectUnresolved = (error) => {
|
|
46
|
+
previous?.pulled.reject(error);
|
|
47
|
+
previous = undefined;
|
|
48
|
+
for (const entry of queue.splice(0))
|
|
49
|
+
entry.pulled.reject(error);
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
get closed() { return closed; },
|
|
53
|
+
get pending() { return queue.length + (previous === undefined ? 0 : 1); },
|
|
54
|
+
push(message, onPulled) {
|
|
55
|
+
if (closed)
|
|
56
|
+
return Promise.reject(failure ?? ended());
|
|
57
|
+
const entry = { message, pulled: deferred(), ...(onPulled === undefined ? {} : { onPulled }) };
|
|
58
|
+
const waiter = waiters.shift();
|
|
59
|
+
if (waiter === undefined)
|
|
60
|
+
queue.push(entry);
|
|
61
|
+
else
|
|
62
|
+
waiter.resolve(take(entry));
|
|
63
|
+
return entry.pulled.promise;
|
|
64
|
+
},
|
|
65
|
+
end() {
|
|
66
|
+
if (closed)
|
|
67
|
+
return;
|
|
68
|
+
closed = true;
|
|
69
|
+
rejectUnresolved(turnEndedError());
|
|
70
|
+
for (const waiter of waiters.splice(0))
|
|
71
|
+
waiter.resolve({ done: true, value: undefined });
|
|
72
|
+
},
|
|
73
|
+
close() {
|
|
74
|
+
if (closed)
|
|
75
|
+
return;
|
|
76
|
+
closed = true;
|
|
77
|
+
const error = ended();
|
|
78
|
+
rejectUnresolved(error);
|
|
79
|
+
for (const waiter of waiters.splice(0))
|
|
80
|
+
waiter.resolve({ done: true, value: undefined });
|
|
81
|
+
},
|
|
82
|
+
fail(error) {
|
|
83
|
+
if (closed)
|
|
84
|
+
return;
|
|
85
|
+
closed = true;
|
|
86
|
+
failure = error;
|
|
87
|
+
rejectUnresolved(error);
|
|
88
|
+
for (const waiter of waiters.splice(0))
|
|
89
|
+
waiter.reject(error);
|
|
90
|
+
},
|
|
91
|
+
iterable: {
|
|
92
|
+
[Symbol.asyncIterator]() {
|
|
93
|
+
return {
|
|
94
|
+
next() {
|
|
95
|
+
acknowledgePrevious();
|
|
96
|
+
const entry = queue.shift();
|
|
97
|
+
if (entry !== undefined)
|
|
98
|
+
return Promise.resolve(take(entry));
|
|
99
|
+
if (failure !== undefined)
|
|
100
|
+
return Promise.reject(failure);
|
|
101
|
+
if (closed)
|
|
102
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
103
|
+
return new Promise((resolve, reject) => waiters.push({ resolve, reject }));
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { noteEvent, unknownEvent, } from "../../provider.js";
|
|
2
2
|
export const CODEX_NOTIFICATION_DISPOSITIONS = {
|
|
3
3
|
"account/login/completed": "drop",
|
|
4
4
|
"account/rateLimits/updated": "drop",
|
|
@@ -160,7 +160,7 @@ function itemChanges(item) {
|
|
|
160
160
|
const diffstat = typeof change?.diff === "string" ? diffstatFromUnifiedPatch(change.diff) : undefined;
|
|
161
161
|
return [{
|
|
162
162
|
op,
|
|
163
|
-
path
|
|
163
|
+
path,
|
|
164
164
|
...(diffstat === undefined ? {} : { diffstat }),
|
|
165
165
|
}];
|
|
166
166
|
});
|
|
@@ -179,20 +179,20 @@ function reasoningSummary(item) {
|
|
|
179
179
|
}
|
|
180
180
|
function itemToolCall(item, kind) {
|
|
181
181
|
if (kind === "commandExecution") {
|
|
182
|
-
return { kind: "run", command:
|
|
182
|
+
return { kind: "run", command: codexText(item.command) ?? "command" };
|
|
183
183
|
}
|
|
184
184
|
if (kind === "imageView") {
|
|
185
185
|
const path = codexText(item.path);
|
|
186
|
-
return path === undefined ? { kind: "other", display: "image view" } : { kind: "read", path
|
|
186
|
+
return path === undefined ? { kind: "other", display: "image view" } : { kind: "read", path };
|
|
187
187
|
}
|
|
188
188
|
if (kind === "webSearch") {
|
|
189
|
-
return { kind: "search", query:
|
|
189
|
+
return { kind: "search", query: codexText(item.query) ?? "web search" };
|
|
190
190
|
}
|
|
191
191
|
if (kind === "fileChange") {
|
|
192
192
|
const changes = itemChanges(item);
|
|
193
193
|
return changes.length === 0 ? { kind: "other", display: "fileChange" } : { kind: "fileChange", changes };
|
|
194
194
|
}
|
|
195
|
-
return { kind: "other", display:
|
|
195
|
+
return { kind: "other", display: itemToolName(item, kind) };
|
|
196
196
|
}
|
|
197
197
|
function itemToolResult(item) {
|
|
198
198
|
const error = codexObject(item.error);
|
|
@@ -202,7 +202,7 @@ function itemToolResult(item) {
|
|
|
202
202
|
const exitCode = typeof item.exitCode === "number" && Number.isSafeInteger(item.exitCode) ? item.exitCode : undefined;
|
|
203
203
|
return {
|
|
204
204
|
status: failed || (exitCode !== undefined && exitCode !== 0) ? "error" : "ok",
|
|
205
|
-
...(detail === undefined ? {} : { message:
|
|
205
|
+
...(detail === undefined ? {} : { message: detail }),
|
|
206
206
|
...(exitCode === undefined ? {} : { exitCode }),
|
|
207
207
|
};
|
|
208
208
|
}
|
|
@@ -216,10 +216,10 @@ function emitItem(item, completed, events, state) {
|
|
|
216
216
|
if (disposition === "assistant") {
|
|
217
217
|
if (!completed)
|
|
218
218
|
return;
|
|
219
|
-
const message =
|
|
219
|
+
const message = typeof item.text === "string" ? item.text : undefined;
|
|
220
220
|
if (message !== undefined) {
|
|
221
|
-
state.
|
|
222
|
-
events.emit({ type: "assistant", text:
|
|
221
|
+
state.lastAnswer = message;
|
|
222
|
+
events.emit({ type: "assistant", text: message });
|
|
223
223
|
}
|
|
224
224
|
return;
|
|
225
225
|
}
|
|
@@ -233,7 +233,7 @@ function emitItem(item, completed, events, state) {
|
|
|
233
233
|
return;
|
|
234
234
|
const summary = reasoningSummary(item);
|
|
235
235
|
if (summary !== undefined)
|
|
236
|
-
events.emit({ type: "thought", text:
|
|
236
|
+
events.emit({ type: "thought", text: summary });
|
|
237
237
|
return;
|
|
238
238
|
}
|
|
239
239
|
if (disposition === "note") {
|
|
@@ -300,7 +300,7 @@ function terminalResult(params, state) {
|
|
|
300
300
|
return { kind: "failed", diagnostic: "codex app-server completed a different turn" };
|
|
301
301
|
}
|
|
302
302
|
return status === "completed"
|
|
303
|
-
? { kind: "answered", answer: state.
|
|
303
|
+
? { kind: "answered", answer: state.lastAnswer ?? "", historyId: completedId }
|
|
304
304
|
: { kind: "failed", diagnostic: turnError(turn?.error) ?? state.error ?? `codex app-server turn ended ${status}` };
|
|
305
305
|
}
|
|
306
306
|
export function codexNotificationResult(notification, state, events) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Session, type ProviderAdapter, type ProviderOptions } from "../../provider.js";
|
|
2
2
|
import type { ProviderExecution } from "../../heart/index.js";
|
|
3
3
|
export { CODEX_ITEM_DISPOSITIONS, CODEX_NOTIFICATION_DISPOSITIONS } from "./events.js";
|
|
4
4
|
export declare function createCodexAppServerProvider(input?: string | ProviderExecution): ProviderAdapter;
|
|
@@ -9,19 +9,21 @@ export declare const codexAppServerProvider: Readonly<{
|
|
|
9
9
|
}>): import("../../heart/facts.js").Confinement;
|
|
10
10
|
admitOptions(options: ProviderOptions): import("../../provider.js").ProviderOptionAdmission;
|
|
11
11
|
fork?(input: Readonly<{
|
|
12
|
-
session: import("../../
|
|
12
|
+
session: import("../../coordinate.js").ResumeCoordinate;
|
|
13
13
|
at: string;
|
|
14
14
|
cwd: string;
|
|
15
15
|
}>): Promise<Readonly<{
|
|
16
|
-
session: import("../../
|
|
16
|
+
session: import("../../coordinate.js").ResumeCoordinate;
|
|
17
17
|
}>>;
|
|
18
|
-
start(input: Readonly<{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
start(input: import("../../provider.js").DriveInput & Readonly<{
|
|
19
|
+
session: Readonly<{
|
|
20
|
+
kind: "fresh";
|
|
21
|
+
}>;
|
|
22
|
+
}>): Promise<Session>;
|
|
23
|
+
resume?(input: import("../../provider.js").DriveInput & Readonly<{
|
|
24
|
+
session: Readonly<{
|
|
25
|
+
kind: "resume";
|
|
26
|
+
coordinate: import("../../coordinate.js").ResumeCoordinate;
|
|
25
27
|
}>;
|
|
26
|
-
}>): Promise<
|
|
28
|
+
}>): Promise<Session>;
|
|
27
29
|
}>;
|