@astrosheep/keiyaku 1.0.0 → 1.0.2
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 +73 -56
- package/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms_v2.js +103 -0
- package/build/agents/harness/activity-values.js +54 -0
- package/build/agents/harness/event-channel.js +55 -20
- package/build/agents/harness/events.js +47 -1
- package/build/agents/harness/execution-handle.js +292 -61
- package/build/agents/harness/index.js +103 -121
- package/build/agents/harness/pump.js +36 -47
- package/build/agents/harness/runtime.js +3 -0
- package/build/agents/launch-snapshot_v2.js +348 -0
- package/build/agents/opencode-sdk.js +42 -169
- package/build/agents/providers/claude-agent-sdk.js +240 -79
- package/build/agents/providers/codex-app-server.js +280 -72
- package/build/agents/providers/codex-sdk.js +159 -41
- package/build/agents/providers/event-type-tail.js +16 -0
- package/build/agents/providers/opencode-sdk.js +165 -59
- package/build/agents/providers/pi.js +254 -42
- package/build/agents/selector_v2.js +122 -0
- package/build/cli/commands/akuma.js +120 -42
- package/build/cli/completion.js +6 -7
- package/build/cli/flags.js +36 -10
- package/build/cli/help.js +42 -26
- package/build/cli/index.js +225 -93
- package/build/cli/parse.js +194 -75
- package/build/cli/projection-address.js +11 -0
- package/build/cli/render/address.js +88 -0
- package/build/cli/render/arc.js +10 -10
- package/build/cli/render/call.js +59 -0
- package/build/cli/render/compact-text.js +3 -0
- package/build/cli/render/errors.js +4 -2
- package/build/cli/render/format.js +6 -0
- package/build/cli/render/line-width.js +70 -0
- package/build/cli/render/misc.js +7 -4
- package/build/cli/render/petition.js +4 -3
- package/build/cli/render/projection-activity.js +201 -0
- package/build/cli/render/shared.js +46 -12
- package/build/cli/render/status.js +59 -10
- package/build/cli/render/tool-ledger-rollup.js +74 -0
- package/build/cli/render/tool-presentation.js +97 -0
- package/build/cli/render/wait.js +229 -0
- package/build/cli/skills-install.js +42 -24
- package/build/cli/subagent-guard.js +1 -1
- package/build/config/akuma-loader_v2.js +222 -0
- package/build/config/env-keys.js +0 -4
- package/build/config/env.js +0 -6
- package/build/config/settings.js +325 -12
- package/build/core/addressing.js +224 -0
- package/build/core/amend.js +30 -47
- package/build/core/arc.js +68 -60
- package/build/core/bind.js +105 -25
- package/build/core/call-persist.js +69 -0
- package/build/core/call.js +658 -0
- package/build/core/claim.js +72 -44
- package/build/core/command-io.js +19 -19
- package/build/core/context.js +11 -36
- package/build/core/draft.js +2 -3
- package/build/core/entry.js +101 -6
- package/build/core/execution-coordinate.js +62 -0
- package/build/core/execution-pact.js +141 -0
- package/build/core/forfeit.js +2 -3
- package/build/core/hints.js +10 -10
- package/build/core/ids.js +6 -0
- package/build/core/ledger.js +16 -1
- package/build/core/petition-claim-gates.js +14 -12
- package/build/core/petition-claim.js +1 -0
- package/build/core/petition-run.js +6 -2
- package/build/core/petition.js +63 -21
- package/build/core/places.js +106 -13
- package/build/core/projection/generation.js +412 -0
- package/build/core/projection/heart.js +316 -0
- package/build/core/projection/identity.js +81 -0
- package/build/core/projection/leash.js +87 -0
- package/build/core/projection/mint.js +154 -0
- package/build/core/projection-activity.js +219 -0
- package/build/core/projection-coordinate.js +35 -0
- package/build/core/projection-core.js +69 -463
- package/build/core/projection-generation-continuation.js +31 -0
- package/build/core/projection-generation-execution.js +148 -0
- package/build/core/projection-generation-identity.js +17 -0
- package/build/core/projection-generation-launcher.js +90 -0
- package/build/core/projection-generation-process.js +43 -0
- package/build/core/projection-generation-runner.js +144 -0
- package/build/core/projection-generation-runtime.js +15 -0
- package/build/core/projection-generation-store.js +707 -0
- package/build/core/projection-identity.js +11 -0
- package/build/core/projection-life-observer.js +87 -0
- package/build/core/projection-life-protocol.js +95 -0
- package/build/core/projection-mint.js +96 -24
- package/build/core/projection-runner-lock.js +230 -0
- package/build/core/projection-status.js +207 -107
- package/build/core/projection-tells.js +401 -0
- package/build/core/projection-wait.js +155 -0
- package/build/core/projection-wake.js +109 -231
- package/build/core/queue_v2.js +342 -0
- package/build/core/registry.js +6 -3
- package/build/core/render.js +63 -1
- package/build/core/renew.js +80 -53
- package/build/core/scope.js +186 -137
- package/build/core/seal.js +16 -19
- package/build/core/status.js +88 -25
- package/build/core/stored-agent-event.js +101 -0
- package/build/core/transcripts.js +214 -228
- package/build/core/verdict.js +27 -15
- package/build/core/worktree-bootstrap.js +187 -0
- package/build/core/worktree-path.js +72 -18
- package/build/flow-error.js +4 -6
- package/build/generated/version.js +1 -1
- package/build/git/branches.js +6 -1
- package/build/index.js +8 -5
- package/build/keiyaku.js +1 -3
- package/package.json +6 -5
- package/skills/keiyaku/SKILL.md +6 -47
- package/skills/keiyaku-akuma/SKILL.md +75 -0
- package/build/agents/effective-policy.js +0 -32
- package/build/agents/index.js +0 -114
- package/build/agents/selector.js +0 -28
- package/build/cli/render/summon.js +0 -17
- package/build/cli/render/tell.js +0 -11
- package/build/config/akuma-loader.js +0 -268
- package/build/core/queue.js +0 -73
- package/build/core/summon-persist.js +0 -73
- package/build/core/summon.js +0 -377
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { getConfig } from "../config/env.js";
|
|
2
|
+
function maxCaptureCharsForProvider(provider) {
|
|
3
|
+
const config = getConfig();
|
|
4
|
+
switch (provider) {
|
|
5
|
+
case "codex-sdk":
|
|
6
|
+
case "codex-app-server":
|
|
7
|
+
case "pi":
|
|
8
|
+
return config.codex.execMaxCaptureChars;
|
|
9
|
+
case "claude-agent-sdk":
|
|
10
|
+
return config.claude.execMaxCaptureChars;
|
|
11
|
+
case "opencode-sdk":
|
|
12
|
+
return config.opencode.execMaxCaptureChars;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function buildCallTermsV2(snapshot, prompt, cwd, options) {
|
|
16
|
+
const runtimeConfig = getConfig();
|
|
17
|
+
const baseTerms = {
|
|
18
|
+
workdir: cwd,
|
|
19
|
+
prompt,
|
|
20
|
+
idleTimeoutMs: options.idleTimeoutMs ?? runtimeConfig.subagent.execIdleTimeoutMs,
|
|
21
|
+
maxCaptureChars: maxCaptureCharsForProvider(snapshot.provider.kind),
|
|
22
|
+
signal: options.signal,
|
|
23
|
+
projectionDir: options.projectionDir,
|
|
24
|
+
projectionExecutionId: options.projectionExecutionId,
|
|
25
|
+
projectionTellFence: options.projectionTellFence,
|
|
26
|
+
...(options.initialTurn !== undefined ? { initialTurn: options.initialTurn } : {}),
|
|
27
|
+
};
|
|
28
|
+
const body = snapshot.akuma.body;
|
|
29
|
+
const replayPrompt = body
|
|
30
|
+
? `[Akuma system prompt]\n${body}\n\n[Operator prompt]\n${prompt}`
|
|
31
|
+
: prompt;
|
|
32
|
+
switch (snapshot.provider.kind) {
|
|
33
|
+
case "codex-sdk":
|
|
34
|
+
return {
|
|
35
|
+
...baseTerms,
|
|
36
|
+
prompt: replayPrompt,
|
|
37
|
+
provider: "codex-sdk",
|
|
38
|
+
...(snapshot.akuma.model !== undefined ? { model: snapshot.akuma.model } : {}),
|
|
39
|
+
...(snapshot.provider.profile !== undefined ? { profile: snapshot.provider.profile } : {}),
|
|
40
|
+
...(snapshot.provider.config !== undefined
|
|
41
|
+
? { config: snapshot.provider.config }
|
|
42
|
+
: {}),
|
|
43
|
+
threadOptions: snapshot.provider.threadOptions,
|
|
44
|
+
...(snapshot.provider.executable !== undefined ? { executable: snapshot.provider.executable } : {}),
|
|
45
|
+
};
|
|
46
|
+
case "codex-app-server":
|
|
47
|
+
return {
|
|
48
|
+
...baseTerms,
|
|
49
|
+
provider: "codex-app-server",
|
|
50
|
+
...(snapshot.provider.model !== undefined ? { model: snapshot.provider.model } : {}),
|
|
51
|
+
...(snapshot.provider.effort !== undefined ? { effort: snapshot.provider.effort } : {}),
|
|
52
|
+
...(snapshot.provider.profile !== undefined ? { profile: snapshot.provider.profile } : {}),
|
|
53
|
+
...(snapshot.provider.config !== undefined
|
|
54
|
+
? { config: snapshot.provider.config }
|
|
55
|
+
: {}),
|
|
56
|
+
...(snapshot.provider.executable !== undefined ? { executable: snapshot.provider.executable } : {}),
|
|
57
|
+
sandboxPolicy: snapshot.provider.sandboxPolicy,
|
|
58
|
+
approvalPolicy: snapshot.provider.approvalPolicy,
|
|
59
|
+
developerInstructions: body || undefined,
|
|
60
|
+
onCheckpoint() { },
|
|
61
|
+
};
|
|
62
|
+
case "claude-agent-sdk":
|
|
63
|
+
return {
|
|
64
|
+
...baseTerms,
|
|
65
|
+
provider: "claude-agent-sdk",
|
|
66
|
+
...(snapshot.provider.model !== undefined ? { model: snapshot.provider.model } : {}),
|
|
67
|
+
...(snapshot.provider.effort !== undefined ? { effort: snapshot.provider.effort } : {}),
|
|
68
|
+
...(snapshot.provider.executable !== undefined ? { executable: snapshot.provider.executable } : {}),
|
|
69
|
+
...(snapshot.provider.settingSources !== undefined ? { settingSources: snapshot.provider.settingSources } : {}),
|
|
70
|
+
permissionMode: snapshot.provider.permissionMode,
|
|
71
|
+
...(snapshot.provider.allowDangerouslySkipPermissions !== undefined
|
|
72
|
+
? { allowDangerouslySkipPermissions: snapshot.provider.allowDangerouslySkipPermissions }
|
|
73
|
+
: {}),
|
|
74
|
+
...(snapshot.provider.disallowedTools !== undefined
|
|
75
|
+
? { disallowedTools: snapshot.provider.disallowedTools }
|
|
76
|
+
: {}),
|
|
77
|
+
systemPrompt: body
|
|
78
|
+
? { type: "preset", preset: "claude_code", append: body }
|
|
79
|
+
: undefined,
|
|
80
|
+
onCheckpoint() { },
|
|
81
|
+
};
|
|
82
|
+
case "opencode-sdk":
|
|
83
|
+
return {
|
|
84
|
+
...baseTerms,
|
|
85
|
+
prompt: replayPrompt,
|
|
86
|
+
provider: "opencode-sdk",
|
|
87
|
+
...(snapshot.provider.model !== undefined ? { model: snapshot.provider.model } : {}),
|
|
88
|
+
...(snapshot.provider.effort !== undefined ? { effort: snapshot.provider.effort } : {}),
|
|
89
|
+
...(snapshot.provider.executable !== undefined ? { executable: snapshot.provider.executable } : {}),
|
|
90
|
+
};
|
|
91
|
+
case "pi":
|
|
92
|
+
return {
|
|
93
|
+
...baseTerms,
|
|
94
|
+
provider: "pi",
|
|
95
|
+
...(snapshot.provider.model !== undefined ? { model: snapshot.provider.model } : {}),
|
|
96
|
+
...(snapshot.provider.thinkingLevel !== undefined
|
|
97
|
+
? { thinkingLevel: snapshot.provider.thinkingLevel }
|
|
98
|
+
: {}),
|
|
99
|
+
appendSystemPromptOverride: body ? () => [body] : undefined,
|
|
100
|
+
onCheckpoint() { },
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { AGENT_EVENT_TEXT_MAX_CHARS } from "./events.js";
|
|
2
|
+
function toolKey(tool) {
|
|
3
|
+
return tool.toLowerCase().replace(/[-_\s]/g, "");
|
|
4
|
+
}
|
|
5
|
+
/** Classify already-extracted provider facts. This function never reads a provider payload. */
|
|
6
|
+
export function activityCallFromNamedTool(tool, facts) {
|
|
7
|
+
switch (toolKey(tool)) {
|
|
8
|
+
case "bash":
|
|
9
|
+
case "shell":
|
|
10
|
+
case "commandexecution":
|
|
11
|
+
return facts.command
|
|
12
|
+
? { kind: "run", command: facts.command, ...(facts.description ? { description: facts.description } : {}) }
|
|
13
|
+
: { kind: "other", display: tool };
|
|
14
|
+
case "read":
|
|
15
|
+
return facts.path
|
|
16
|
+
? {
|
|
17
|
+
kind: "read",
|
|
18
|
+
path: facts.path,
|
|
19
|
+
...(facts.offset === undefined && facts.limit === undefined
|
|
20
|
+
? {}
|
|
21
|
+
: { range: { ...(facts.offset === undefined ? {} : { offset: facts.offset }), ...(facts.limit === undefined ? {} : { limit: facts.limit }) } }),
|
|
22
|
+
}
|
|
23
|
+
: { kind: "other", display: tool };
|
|
24
|
+
case "write":
|
|
25
|
+
return facts.path
|
|
26
|
+
? { kind: "fileChange", changes: [{ op: "add", path: facts.path }] }
|
|
27
|
+
: { kind: "other", display: tool };
|
|
28
|
+
case "edit":
|
|
29
|
+
return facts.path
|
|
30
|
+
? { kind: "fileChange", changes: [{ op: "update", path: facts.path }] }
|
|
31
|
+
: { kind: "other", display: tool };
|
|
32
|
+
case "websearch":
|
|
33
|
+
case "search":
|
|
34
|
+
return facts.query
|
|
35
|
+
? { kind: "search", query: facts.query }
|
|
36
|
+
: { kind: "other", display: tool };
|
|
37
|
+
default:
|
|
38
|
+
return { kind: "other", display: tool };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function boundActivityExcerpt(value) {
|
|
42
|
+
return value.slice(-AGENT_EVENT_TEXT_MAX_CHARS);
|
|
43
|
+
}
|
|
44
|
+
export function diffstatFromUnifiedPatch(patch) {
|
|
45
|
+
let additions = 0;
|
|
46
|
+
let deletions = 0;
|
|
47
|
+
for (const line of patch.split("\n")) {
|
|
48
|
+
if (line.startsWith("+") && !line.startsWith("+++"))
|
|
49
|
+
additions += 1;
|
|
50
|
+
if (line.startsWith("-") && !line.startsWith("---"))
|
|
51
|
+
deletions += 1;
|
|
52
|
+
}
|
|
53
|
+
return additions || deletions ? { additions, deletions } : undefined;
|
|
54
|
+
}
|
|
@@ -15,7 +15,7 @@ export function isEventChannelOverflowError(error) {
|
|
|
15
15
|
/**
|
|
16
16
|
* Bounded async event channel for adapter -> runtime.
|
|
17
17
|
* Hard cap is exactly 10_000 (shared across lifecycle + coalesce slots).
|
|
18
|
-
*
|
|
18
|
+
* Consumer-lag overflow saturates observation without failing the producer or consumer.
|
|
19
19
|
*/
|
|
20
20
|
export function createEventChannel(options = {}) {
|
|
21
21
|
const queue = [];
|
|
@@ -24,6 +24,9 @@ export function createEventChannel(options = {}) {
|
|
|
24
24
|
const waiters = [];
|
|
25
25
|
let closed = false;
|
|
26
26
|
let failure;
|
|
27
|
+
let overflowed = false;
|
|
28
|
+
let overflowMarker;
|
|
29
|
+
let overflowMarkerPending = false;
|
|
27
30
|
let drained = false;
|
|
28
31
|
let resolveDrained;
|
|
29
32
|
const drainedPromise = new Promise((resolve) => {
|
|
@@ -55,8 +58,6 @@ export function createEventChannel(options = {}) {
|
|
|
55
58
|
while (waiters.length > 0) {
|
|
56
59
|
const waiter = waiters.shift();
|
|
57
60
|
if (failure !== undefined) {
|
|
58
|
-
// Rejection path marks drained in the waiter reject wrapper below when next() parks;
|
|
59
|
-
// for direct delivery, mark here after reject so whenDrained observes consumer receipt.
|
|
60
61
|
markDrained();
|
|
61
62
|
waiter.reject(failure);
|
|
62
63
|
}
|
|
@@ -67,13 +68,40 @@ export function createEventChannel(options = {}) {
|
|
|
67
68
|
}
|
|
68
69
|
};
|
|
69
70
|
const depth = () => queue.length;
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
const storeOverflowMarker = (dropped) => {
|
|
72
|
+
if (overflowMarkerPending)
|
|
73
|
+
return;
|
|
74
|
+
const marker = options.createOverflowMarker ? options.createOverflowMarker(dropped) : dropped;
|
|
75
|
+
overflowMarker = marker;
|
|
76
|
+
overflowMarkerPending = true;
|
|
77
|
+
};
|
|
78
|
+
const takeOverflowMarker = () => {
|
|
79
|
+
if (!overflowMarkerPending || overflowMarker === undefined)
|
|
80
|
+
return undefined;
|
|
81
|
+
const marker = overflowMarker;
|
|
82
|
+
overflowMarker = undefined;
|
|
83
|
+
overflowMarkerPending = false;
|
|
84
|
+
return marker;
|
|
85
|
+
};
|
|
86
|
+
const markOverflow = (dropped) => {
|
|
87
|
+
overflowed = true;
|
|
88
|
+
storeOverflowMarker(dropped);
|
|
89
|
+
const waiter = waiters.shift();
|
|
90
|
+
if (waiter && queue.length === 0) {
|
|
91
|
+
const marker = takeOverflowMarker();
|
|
92
|
+
if (marker !== undefined) {
|
|
93
|
+
waiter.resolve({ value: marker, done: false });
|
|
94
|
+
}
|
|
95
|
+
else if (closed) {
|
|
96
|
+
markDrained();
|
|
97
|
+
if (failure !== undefined)
|
|
98
|
+
waiter.reject(failure);
|
|
99
|
+
else
|
|
100
|
+
waiter.resolve({ value: undefined, done: true });
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
waiters.unshift(waiter);
|
|
104
|
+
}
|
|
77
105
|
}
|
|
78
106
|
return "overflow";
|
|
79
107
|
};
|
|
@@ -81,6 +109,8 @@ export function createEventChannel(options = {}) {
|
|
|
81
109
|
push(value, meta) {
|
|
82
110
|
if (closed)
|
|
83
111
|
return "closed";
|
|
112
|
+
if (overflowed)
|
|
113
|
+
return "overflow";
|
|
84
114
|
const coalesceKey = meta?.coalesceKey;
|
|
85
115
|
if (coalesceKey !== undefined) {
|
|
86
116
|
const existing = coalesceIndex.get(coalesceKey);
|
|
@@ -90,11 +120,10 @@ export function createEventChannel(options = {}) {
|
|
|
90
120
|
return "accepted";
|
|
91
121
|
}
|
|
92
122
|
if (depth() >= EXEC_EVENT_BUFFER_HARD_CAP) {
|
|
93
|
-
return markOverflow();
|
|
123
|
+
return markOverflow(value);
|
|
94
124
|
}
|
|
95
125
|
const waiter = waiters.shift();
|
|
96
126
|
if (waiter) {
|
|
97
|
-
// Direct delivery to a waiting consumer: nothing remains queued for this key.
|
|
98
127
|
waiter.resolve({ value, done: false });
|
|
99
128
|
return "accepted";
|
|
100
129
|
}
|
|
@@ -102,9 +131,9 @@ export function createEventChannel(options = {}) {
|
|
|
102
131
|
queue.push({ value, coalesceKey });
|
|
103
132
|
return "accepted";
|
|
104
133
|
}
|
|
105
|
-
// Lifecycle: never coalesce
|
|
134
|
+
// Lifecycle: never coalesce.
|
|
106
135
|
if (depth() >= EXEC_EVENT_BUFFER_HARD_CAP) {
|
|
107
|
-
return markOverflow();
|
|
136
|
+
return markOverflow(value);
|
|
108
137
|
}
|
|
109
138
|
const waiter = waiters.shift();
|
|
110
139
|
if (waiter) {
|
|
@@ -118,8 +147,7 @@ export function createEventChannel(options = {}) {
|
|
|
118
147
|
if (closed)
|
|
119
148
|
return;
|
|
120
149
|
closed = true;
|
|
121
|
-
|
|
122
|
-
if (queue.length === 0) {
|
|
150
|
+
if (queue.length === 0 && !overflowMarkerPending) {
|
|
123
151
|
deliverTerminalToWaiters();
|
|
124
152
|
}
|
|
125
153
|
},
|
|
@@ -128,8 +156,7 @@ export function createEventChannel(options = {}) {
|
|
|
128
156
|
return;
|
|
129
157
|
closed = true;
|
|
130
158
|
failure = error;
|
|
131
|
-
|
|
132
|
-
if (queue.length === 0) {
|
|
159
|
+
if (queue.length === 0 && !overflowMarkerPending) {
|
|
133
160
|
deliverTerminalToWaiters();
|
|
134
161
|
}
|
|
135
162
|
},
|
|
@@ -137,6 +164,12 @@ export function createEventChannel(options = {}) {
|
|
|
137
164
|
return drainedPromise;
|
|
138
165
|
},
|
|
139
166
|
depth,
|
|
167
|
+
peekCoalesced(coalesceKey) {
|
|
168
|
+
const index = coalesceIndex.get(coalesceKey);
|
|
169
|
+
if (index === undefined)
|
|
170
|
+
return undefined;
|
|
171
|
+
return queue[index]?.value;
|
|
172
|
+
},
|
|
140
173
|
iterable: {
|
|
141
174
|
[Symbol.asyncIterator]() {
|
|
142
175
|
return {
|
|
@@ -144,10 +177,12 @@ export function createEventChannel(options = {}) {
|
|
|
144
177
|
if (queue.length > 0) {
|
|
145
178
|
const entry = queue.shift();
|
|
146
179
|
reindexCoalesceKeys();
|
|
147
|
-
// After the last item leaves under a closed/failed producer, the next next()
|
|
148
|
-
// (or a parked waiter) must still receive the terminal signal.
|
|
149
180
|
return Promise.resolve({ value: entry.value, done: false });
|
|
150
181
|
}
|
|
182
|
+
const marker = takeOverflowMarker();
|
|
183
|
+
if (marker !== undefined) {
|
|
184
|
+
return Promise.resolve({ value: marker, done: false });
|
|
185
|
+
}
|
|
151
186
|
if (failure !== undefined) {
|
|
152
187
|
markDrained();
|
|
153
188
|
return Promise.reject(failure);
|
|
@@ -1 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const AGENT_EVENT_TEXT_MAX_CHARS = 4_096;
|
|
3
|
+
export const AGENT_THOUGHT_TEXT_MAX_CHARS = 4_000;
|
|
4
|
+
export const AGENT_PLAN_MAX_ITEMS = 64;
|
|
5
|
+
export const AGENT_PLAN_ITEM_TEXT_MAX_CHARS = 200;
|
|
6
|
+
export const AGENT_ACTIVITY_MAX_CHANGES = 32;
|
|
7
|
+
export const AGENT_UNKNOWN_PAYLOAD_MAX_CHARS = 4_096;
|
|
8
|
+
export const activityCallSchema = z.discriminatedUnion("kind", [
|
|
9
|
+
z.object({ kind: z.literal("run"), command: z.string(), description: z.string().optional() }).strict(),
|
|
10
|
+
z.object({
|
|
11
|
+
kind: z.literal("read"),
|
|
12
|
+
path: z.string(),
|
|
13
|
+
range: z.object({ offset: z.number().finite().optional(), limit: z.number().finite().optional() }).strict().optional(),
|
|
14
|
+
}).strict(),
|
|
15
|
+
z.object({ kind: z.literal("search"), query: z.string() }).strict(),
|
|
16
|
+
z.object({
|
|
17
|
+
kind: z.literal("fileChange"),
|
|
18
|
+
changes: z.array(z.object({ op: z.enum(["add", "update", "delete"]), path: z.string() }).strict()),
|
|
19
|
+
omittedChanges: z.number().int().nonnegative().optional(),
|
|
20
|
+
}).strict(),
|
|
21
|
+
z.object({ kind: z.literal("other"), display: z.string() }).strict(),
|
|
22
|
+
]);
|
|
23
|
+
export const activityResultSchema = z.object({
|
|
24
|
+
status: z.enum(["ok", "error"]),
|
|
25
|
+
message: z.string().optional(),
|
|
26
|
+
exitCode: z.number().finite().optional(),
|
|
27
|
+
diffstat: z.object({
|
|
28
|
+
additions: z.number().int().nonnegative(),
|
|
29
|
+
deletions: z.number().int().nonnegative(),
|
|
30
|
+
}).strict().optional(),
|
|
31
|
+
}).strict();
|
|
32
|
+
export const activityEventBodySchema = z.object({
|
|
33
|
+
type: z.literal("activity"),
|
|
34
|
+
phase: z.enum(["started", "updated", "completed"]),
|
|
35
|
+
id: z.string(),
|
|
36
|
+
tool: z.string(),
|
|
37
|
+
call: activityCallSchema,
|
|
38
|
+
result: activityResultSchema.optional(),
|
|
39
|
+
truncated: z.literal(true).optional(),
|
|
40
|
+
}).strict().superRefine((value, context) => {
|
|
41
|
+
if (value.phase === "started" && value.result !== undefined) {
|
|
42
|
+
context.addIssue({ code: "custom", path: ["result"], message: "started activity cannot carry a result" });
|
|
43
|
+
}
|
|
44
|
+
if (value.phase === "completed" && value.result === undefined) {
|
|
45
|
+
context.addIssue({ code: "custom", path: ["result"], message: "completed activity requires a result" });
|
|
46
|
+
}
|
|
47
|
+
});
|