@astrosheep/keiyaku 4.5.20 → 4.5.21
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 +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +22 -8
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/references/automation.md +237 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +6 -7
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +2 -3
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -3
- package/build/src/akuma/akuma-handle.d.ts +5 -1
- package/build/src/akuma/akuma-handle.js +4 -1
- package/build/src/akuma/akuma-instance.d.ts +7 -2
- package/build/src/akuma/akuma-instance.js +14 -7
- package/build/src/akuma/akuma-observe.d.ts +11 -0
- package/build/src/akuma/akuma-observe.js +22 -0
- package/build/src/akuma/akuma-product.d.ts +1 -0
- package/build/src/akuma/akuma-product.js +3 -0
- package/build/src/akuma/akuma.d.ts +1 -0
- package/build/src/akuma/body.d.ts +25 -5
- package/build/src/akuma/body.js +65 -8
- package/build/src/akuma/call-request.d.ts +2 -0
- package/build/src/akuma/call-request.js +2 -0
- package/build/src/akuma/fleet-execution.d.ts +28 -0
- package/build/src/akuma/fleet-execution.js +36 -4
- package/build/src/akuma/fleet-request.d.ts +10 -0
- package/build/src/akuma/fleet-request.js +11 -2
- package/build/src/akuma/heart/facts.d.ts +2 -0
- package/build/src/akuma/heart/index.d.ts +1 -0
- package/build/src/akuma/heart/index.js +4 -1
- package/build/src/akuma/heart/rows.d.ts +2 -0
- package/build/src/akuma/heart/rows.js +7 -5
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +3 -1
- package/build/src/akuma/heart/tells.js +6 -5
- package/build/src/akuma/heart/timeline.js +1 -1
- package/build/src/akuma/provider.d.ts +1 -1
- package/build/src/akuma/provider.js +1 -1
- package/build/src/akuma/providers/acp/core.js +3 -6
- package/build/src/akuma/providers/claude/index.js +9 -12
- package/build/src/akuma/providers/codex-app-server/index.js +4 -11
- package/build/src/akuma/providers/execution-environment.d.ts +6 -0
- package/build/src/akuma/providers/execution-environment.js +24 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +30 -23
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +8 -1
- package/build/src/akuma/providers/opencode-sdk/session.js +6 -5
- package/build/src/akuma/providers/pi/events.js +7 -2
- package/build/src/akuma/providers/pi/index.js +3 -2
- package/build/src/akuma/request-rendezvous.js +8 -3
- package/build/src/akuma/turn-drive.d.ts +1 -0
- package/build/src/akuma/turn-drive.js +2 -0
- package/build/src/akuma-body.js +2 -0
- package/build/src/body/amend.js +6 -4
- package/build/src/body/decode.d.ts +3 -1
- package/build/src/body/decode.js +53 -17
- package/build/src/body/region.d.ts +9 -1
- package/build/src/body/region.js +87 -12
- package/build/src/body/render.js +1 -1
- package/build/src/body/verification.d.ts +3 -1
- package/build/src/body/verification.js +4 -1
- package/build/src/cli/accepted.js +19 -2
- package/build/src/cli/commands/akuma-invoke.d.ts +2 -0
- package/build/src/cli/commands/akuma-invoke.js +133 -13
- package/build/src/cli/commands/akuma.js +11 -4
- package/build/src/cli/commands/contract-help.js +17 -4
- package/build/src/cli/commands/contract.js +6 -4
- package/build/src/cli/commands/status-set.js +15 -24
- package/build/src/cli/main.js +5 -0
- package/build/src/cli/parse.d.ts +2 -0
- package/build/src/cli/parse.js +5 -0
- package/build/src/cli/render/akuma-activity.d.ts +99 -2
- package/build/src/cli/render/akuma-activity.js +484 -40
- package/build/src/cli/render/akuma.d.ts +10 -0
- package/build/src/cli/render/akuma.js +28 -21
- package/build/src/cli/render/audit.js +1 -1
- package/build/src/cli/render/board.js +1 -1
- package/build/src/cli/render/catalog.js +16 -13
- package/build/src/cli/render/contract-history.js +39 -10
- package/build/src/cli/render/contract-observation.js +10 -6
- package/build/src/cli/render/contract.js +109 -106
- package/build/src/cli/render/execution-progress.d.ts +23 -1
- package/build/src/cli/render/execution-progress.js +151 -28
- package/build/src/cli/render/kanshi-akuma.js +27 -39
- package/build/src/cli/render/kanshi.js +33 -26
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/render/receipt.d.ts +1 -1
- package/build/src/cli/render/receipt.js +5 -5
- package/build/src/cli/render/refusal.js +10 -7
- package/build/src/cli/render/region.js +1 -1
- package/build/src/cli/render/settings.js +12 -2
- package/build/src/cli/render/status-line.d.ts +30 -0
- package/build/src/cli/render/status-line.js +58 -0
- package/build/src/cli/render/status-set.js +1 -1
- package/build/src/cli/render/task.d.ts +2 -0
- package/build/src/cli/render/task.js +11 -7
- package/build/src/cli/render/terminal.d.ts +0 -1
- package/build/src/cli/render/terminal.js +47 -15
- package/build/src/cli/result.d.ts +1 -0
- package/build/src/cli/runtime.d.ts +2 -0
- package/build/src/cli/runtime.js +13 -7
- package/build/src/cli/usage.js +2 -2
- package/build/src/cli/version.d.ts +1 -0
- package/build/src/cli/version.js +25 -0
- package/build/src/git/workspace.d.ts +1 -1
- package/build/src/git/workspace.js +1 -1
- package/build/src/identity/mint.d.ts +13 -0
- package/build/src/identity/mint.js +26 -0
- package/build/src/identity/normalize.d.ts +4 -0
- package/build/src/identity/normalize.js +30 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +1 -0
- package/build/src/kanshi/read.js +17 -4
- package/build/src/kanshi/report.d.ts +1 -0
- package/build/src/library/akuma-creation.d.ts +2 -0
- package/build/src/library/akuma-creation.js +33 -17
- package/build/src/library/bind.js +18 -16
- package/build/src/library/contract-bind.d.ts +3 -1
- package/build/src/library/contract-bind.js +5 -3
- package/build/src/library/contract-operations.d.ts +2 -2
- package/build/src/library/contract-operations.js +1 -1
- package/build/src/library/contract-types.d.ts +1 -0
- package/build/src/library/fleet.d.ts +4 -1
- package/build/src/library/fleet.js +32 -8
- package/build/src/plugin/akuma-signals.d.ts +6 -0
- package/build/src/plugin/akuma-signals.js +8 -0
- package/build/src/plugin/public.d.ts +4 -0
- package/build/src/plugin/runtime.js +4 -1
- package/build/src/protocol/amend.js +4 -3
- package/build/src/protocol/attempt.d.ts +2 -0
- package/build/src/protocol/bind.js +41 -14
- package/build/src/protocol/completion.d.ts +3 -0
- package/build/src/protocol/completion.js +7 -1
- package/build/src/protocol/deliver.js +165 -92
- package/build/src/protocol/execution-observation.d.ts +0 -4
- package/build/src/protocol/intent.d.ts +15 -20
- package/build/src/protocol/intent.js +29 -17
- package/build/src/protocol/operations.d.ts +2 -0
- package/build/src/protocol/placement.js +5 -1
- package/build/src/protocol/read/status.d.ts +1 -0
- package/build/src/protocol/read/status.js +10 -2
- package/build/src/protocol/reintegrate.d.ts +1 -1
- package/build/src/protocol/reintegrate.js +70 -43
- package/build/src/protocol/result-codec.js +9 -7
- package/build/src/protocol/review.js +53 -30
- package/build/src/protocol/run.d.ts +83 -36
- package/build/src/protocol/run.js +90 -75
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settings.js +5 -14
- package/build/src/task/document.d.ts +5 -1
- package/build/src/task/document.js +6 -1
- package/build/src/verification/execution.d.ts +0 -1
- package/build/src/verification/execution.js +0 -24
- package/build/src/verification/observation.d.ts +0 -4
- package/build/src/verification/observation.js +1 -2
- package/package.json +3 -1
- package/build/src/git/verification-environment.d.ts +0 -10
- package/build/src/git/verification-environment.js +0 -281
|
@@ -57,7 +57,7 @@ function decodeTimelineRows(database, rows) {
|
|
|
57
57
|
const facts = new Map();
|
|
58
58
|
const turns = database
|
|
59
59
|
.prepare(`SELECT sequence, body_sequence, started_at, end_sequence, outcome,
|
|
60
|
-
history_id, session_json, answer, answer_json, schema_json, diagnostic, completed_at FROM turns
|
|
60
|
+
history_id, session_json, answer, answer_json, schema_json, initiator, diagnostic, completed_at FROM turns
|
|
61
61
|
WHERE sequence IN (SELECT value FROM json_each(?)) OR end_sequence IN (SELECT value FROM json_each(?))`)
|
|
62
62
|
.all(sequences("turn-start"), sequences("turn-end"));
|
|
63
63
|
for (const row of turns) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { decodeResumeCoordinate, encodeResumeCoordinate, type ResumeCoordinate } from "./coordinate.js";
|
|
2
2
|
import type { ProviderOptions, ReadonlyRestraint } from "./provider-recipe.js";
|
|
3
3
|
export type { ResumeCoordinate } from "./coordinate.js";
|
|
4
|
-
export
|
|
4
|
+
export { AKUMA_REQUESTS_ENV } from "./providers/execution-environment.js";
|
|
5
5
|
export declare const AGENT_EVENT_TEXT_LIMIT = 16384;
|
|
6
6
|
export declare const AGENT_THOUGHT_TEXT_LIMIT = 4000;
|
|
7
7
|
export declare const AGENT_EVENT_QUEUE_LIMIT = 256;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { decodeResumeCoordinate, encodeResumeCoordinate } from "./coordinate.js";
|
|
2
|
-
export
|
|
2
|
+
export { AKUMA_REQUESTS_ENV } from "./providers/execution-environment.js";
|
|
3
3
|
export const AGENT_EVENT_TEXT_LIMIT = 16_384;
|
|
4
4
|
export const AGENT_THOUGHT_TEXT_LIMIT = 4_000;
|
|
5
5
|
export const AGENT_EVENT_QUEUE_LIMIT = 256;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Readable, Writable } from "node:stream";
|
|
2
2
|
import { spawnStdioProcess } from "../../../runtime/proc/stdio.js";
|
|
3
3
|
import { abortable } from "../../abort.js";
|
|
4
|
-
import {
|
|
4
|
+
import { AgentEventChannel, } from "../../provider.js";
|
|
5
|
+
import { akumaExecutionEnvironment } from "../execution-environment.js";
|
|
5
6
|
import { EMPTY_ACP_EVENT_STATE, flushAcpEvents, mapAcpUpdate, } from "./events.js";
|
|
6
7
|
function diagnostic(acp, error) {
|
|
7
8
|
if (!(error instanceof Error))
|
|
@@ -156,11 +157,7 @@ export async function startAcpSession(launch, input, dependencies = {}, custody)
|
|
|
156
157
|
const child = (dependencies.spawnProcess ?? spawnStdioProcess)({
|
|
157
158
|
argv: launch.argv,
|
|
158
159
|
cwd: input.cwd,
|
|
159
|
-
env:
|
|
160
|
-
...globalThis.process.env,
|
|
161
|
-
...launch.env,
|
|
162
|
-
...(input.requests === undefined ? {} : { [AKUMA_REQUESTS_ENV]: input.requests.dir }),
|
|
163
|
-
},
|
|
160
|
+
env: akumaExecutionEnvironment(globalThis.process.env, launch.env, input.requests?.dir),
|
|
164
161
|
});
|
|
165
162
|
custody?.own({
|
|
166
163
|
closed: child.exited.then(() => undefined),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { abortable } from "../../abort.js";
|
|
3
|
-
import {
|
|
3
|
+
import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
|
|
4
|
+
import { akumaExecutionEnvironment } from "../execution-environment.js";
|
|
4
5
|
import { emitClaudeMessage } from "./events.js";
|
|
5
6
|
import { claudeUserMessage, createClaudeInput, isClaudeTurnEnded } from "./input.js";
|
|
6
7
|
export { CLAUDE_MESSAGE_DISPOSITIONS, CLAUDE_SYSTEM_DISPOSITIONS } from "./events.js";
|
|
@@ -38,8 +39,11 @@ class ReceiptChannel {
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
function admitClaudeOptions(options) {
|
|
41
|
-
if (options.sandbox
|
|
42
|
-
return { kind: "refused", diagnostic: "Claude
|
|
42
|
+
if (options.sandbox === "full-access" && options.readonly === true) {
|
|
43
|
+
return { kind: "refused", diagnostic: "Claude full-access sandbox cannot combine with readonly" };
|
|
44
|
+
}
|
|
45
|
+
if (options.sandbox === "full-access" && options.network === "disabled") {
|
|
46
|
+
return { kind: "refused", diagnostic: "Claude full-access sandbox cannot combine with disabled network" };
|
|
43
47
|
}
|
|
44
48
|
if (options.network !== undefined) {
|
|
45
49
|
return { kind: "refused", diagnostic: "Claude provider does not support the network option" };
|
|
@@ -67,18 +71,11 @@ function claudeQueryOptions(input, execution, abortController) {
|
|
|
67
71
|
abortController,
|
|
68
72
|
...(input.requests === undefined ? {} : { additionalDirectories: [input.requests.dir] }),
|
|
69
73
|
...(execution.executable === undefined ? {} : { pathToClaudeCodeExecutable: execution.executable }),
|
|
70
|
-
|
|
71
|
-
? {}
|
|
72
|
-
: {
|
|
73
|
-
env: {
|
|
74
|
-
...process.env,
|
|
75
|
-
...execution.env,
|
|
76
|
-
...(input.requests === undefined ? {} : { [AKUMA_REQUESTS_ENV]: input.requests.dir }),
|
|
77
|
-
},
|
|
78
|
-
}),
|
|
74
|
+
env: akumaExecutionEnvironment(process.env, execution.env, input.requests?.dir),
|
|
79
75
|
permissionMode: mode,
|
|
80
76
|
...(mode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {}),
|
|
81
77
|
settingSources: ["user", "project", "local"],
|
|
78
|
+
...(input.options.sandbox === "full-access" ? { sandbox: { enabled: false } } : {}),
|
|
82
79
|
...(input.options.model === undefined ? {} : { model: input.options.model }),
|
|
83
80
|
...(input.options.effort === undefined ? {} : { effort: input.options.effort }),
|
|
84
81
|
...(input.options.systemPrompt === undefined || input.options.systemPrompt.length === 0
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LineRpcProcess } from "../../../runtime/proc/line-rpc.js";
|
|
2
|
-
import { AgentEventChannel,
|
|
2
|
+
import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
|
|
3
|
+
import { akumaExecutionEnvironment } from "../execution-environment.js";
|
|
3
4
|
import { codexNotificationResult, codexObject, codexText } from "./events.js";
|
|
4
5
|
export { CODEX_ITEM_DISPOSITIONS, CODEX_NOTIFICATION_DISPOSITIONS } from "./events.js";
|
|
5
6
|
function diagnostic(error) {
|
|
@@ -106,7 +107,7 @@ async function forkCodex(execution, input, custody) {
|
|
|
106
107
|
const server = new LineRpcProcess({
|
|
107
108
|
argv: [execution.executable ?? "codex", "app-server", "--listen", "stdio://"],
|
|
108
109
|
cwd: input.cwd,
|
|
109
|
-
|
|
110
|
+
env: akumaExecutionEnvironment(process.env, execution.env),
|
|
110
111
|
});
|
|
111
112
|
const closed = new Promise((resolve) => server.onExit(() => resolve()));
|
|
112
113
|
custody.own({
|
|
@@ -137,15 +138,7 @@ function codexServer(execution, input) {
|
|
|
137
138
|
return new LineRpcProcess({
|
|
138
139
|
argv: [execution.executable ?? "codex", "app-server", "--listen", "stdio://"],
|
|
139
140
|
cwd: input.cwd,
|
|
140
|
-
|
|
141
|
-
? {}
|
|
142
|
-
: {
|
|
143
|
-
env: {
|
|
144
|
-
...process.env,
|
|
145
|
-
...execution.env,
|
|
146
|
-
...(input.requests === undefined ? {} : { [AKUMA_REQUESTS_ENV]: input.requests.dir }),
|
|
147
|
-
},
|
|
148
|
-
}),
|
|
141
|
+
env: akumaExecutionEnvironment(process.env, execution.env, input.requests?.dir),
|
|
149
142
|
});
|
|
150
143
|
}
|
|
151
144
|
async function startCodex(execution, input, custody) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const AKUMA_REQUESTS_ENV = "AKUMA_REQUESTS";
|
|
2
|
+
declare const PARENT_HARNESS_IDENTITY_KEYS: readonly ["CLAUDE_CODE_SESSION_ID", "CLAUDE_CODE_CHILD_SESSION", "CLAUDECODE", "CODEX_THREAD_ID", "OPENCODE_SESSION_ID", "PI_SESSION_ID", "PI_SESSION_FILE", "PASEO_AGENT_ID", "SQUARE_PARTICIPANT_NAME"];
|
|
3
|
+
type Environment = Readonly<Record<string, string | undefined>>;
|
|
4
|
+
/** Construct the environment for one isolated Akuma execution or native child. */
|
|
5
|
+
export declare function akumaExecutionEnvironment(inherited: Environment, overrides?: Environment, requests?: string, nativeIdentity?: readonly (typeof PARENT_HARNESS_IDENTITY_KEYS)[number][]): Record<string, string>;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const AKUMA_REQUESTS_ENV = "AKUMA_REQUESTS";
|
|
2
|
+
const PARENT_HARNESS_IDENTITY_KEYS = [
|
|
3
|
+
"CLAUDE_CODE_SESSION_ID",
|
|
4
|
+
"CLAUDE_CODE_CHILD_SESSION",
|
|
5
|
+
"CLAUDECODE",
|
|
6
|
+
"CODEX_THREAD_ID",
|
|
7
|
+
"OPENCODE_SESSION_ID",
|
|
8
|
+
"PI_SESSION_ID",
|
|
9
|
+
"PI_SESSION_FILE",
|
|
10
|
+
"PASEO_AGENT_ID",
|
|
11
|
+
"SQUARE_PARTICIPANT_NAME",
|
|
12
|
+
];
|
|
13
|
+
/** Construct the environment for one isolated Akuma execution or native child. */
|
|
14
|
+
export function akumaExecutionEnvironment(inherited, overrides = {}, requests, nativeIdentity = []) {
|
|
15
|
+
const preserved = Object.fromEntries(nativeIdentity.flatMap((key) => (inherited[key] === undefined ? [] : [[key, inherited[key]]])));
|
|
16
|
+
const environment = Object.fromEntries(Object.entries({ ...inherited, ...overrides }).flatMap(([key, value]) => value === undefined ? [] : [[key, value]]));
|
|
17
|
+
for (const key of PARENT_HARNESS_IDENTITY_KEYS)
|
|
18
|
+
delete environment[key];
|
|
19
|
+
Object.assign(environment, preserved);
|
|
20
|
+
delete environment[AKUMA_REQUESTS_ENV];
|
|
21
|
+
if (requests !== undefined)
|
|
22
|
+
environment[AKUMA_REQUESTS_ENV] = requests;
|
|
23
|
+
return environment;
|
|
24
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
|
|
3
3
|
import { createEventState, mapEvent } from "./events.js";
|
|
4
4
|
import { coordinate, loadOpencode, OPENCODE_SDK_PROVIDER, parseModel } from "./session.js";
|
|
5
5
|
function object(value) {
|
|
@@ -204,12 +204,13 @@ async function forceDisposeOpencode(abortController, close, finish) {
|
|
|
204
204
|
}
|
|
205
205
|
async function loadDriveRuntime(execution, input, signal, loader, onRuntime) {
|
|
206
206
|
const runtime = await loadOpencode({
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
},
|
|
212
|
-
|
|
207
|
+
execution,
|
|
208
|
+
cwd: input.cwd,
|
|
209
|
+
signal,
|
|
210
|
+
...(loader === undefined ? {} : { loader }),
|
|
211
|
+
...(onRuntime === undefined ? {} : { onRuntime }),
|
|
212
|
+
...(input.requests === undefined ? {} : { requests: input.requests.dir }),
|
|
213
|
+
});
|
|
213
214
|
if (signal.aborted) {
|
|
214
215
|
await runtime.close();
|
|
215
216
|
signal.throwIfAborted();
|
|
@@ -343,22 +344,28 @@ export function createOpencodeProvider(input = { name: OPENCODE_SDK_PROVIDER, ki
|
|
|
343
344
|
fork: (input) => createProviderAttempt(new AbortController().signal, async (custody) => {
|
|
344
345
|
const sessionId = opencodeSessionId(input.session);
|
|
345
346
|
let close;
|
|
346
|
-
const runtime = await loadOpencode(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
347
|
+
const runtime = await loadOpencode({
|
|
348
|
+
execution,
|
|
349
|
+
cwd: input.cwd,
|
|
350
|
+
signal: custody.signal,
|
|
351
|
+
...(loader === undefined ? {} : { loader }),
|
|
352
|
+
onRuntime: (ready) => {
|
|
353
|
+
let closing;
|
|
354
|
+
let settleRuntimeClosed;
|
|
355
|
+
let rejectRuntimeClosed;
|
|
356
|
+
const runtimeClosed = new Promise((resolve, reject) => {
|
|
357
|
+
settleRuntimeClosed = resolve;
|
|
358
|
+
rejectRuntimeClosed = reject;
|
|
359
|
+
});
|
|
360
|
+
close = () => {
|
|
361
|
+
if (closing === undefined) {
|
|
362
|
+
closing = ready.close();
|
|
363
|
+
void closing.then(settleRuntimeClosed, rejectRuntimeClosed);
|
|
364
|
+
}
|
|
365
|
+
return closing;
|
|
366
|
+
};
|
|
367
|
+
custody.own({ closed: runtimeClosed, abort: close, forceDispose: close });
|
|
368
|
+
},
|
|
362
369
|
});
|
|
363
370
|
try {
|
|
364
371
|
const result = await runtime.client.session.fork({
|
|
@@ -23,5 +23,12 @@ export type OpencodeRuntime = Readonly<{
|
|
|
23
23
|
};
|
|
24
24
|
close: () => Promise<void>;
|
|
25
25
|
}>;
|
|
26
|
-
export declare function loadOpencode(
|
|
26
|
+
export declare function loadOpencode(input: Readonly<{
|
|
27
|
+
execution: ProviderExecution;
|
|
28
|
+
cwd: string;
|
|
29
|
+
signal: AbortSignal;
|
|
30
|
+
loader?: OpencodeSdkLoader;
|
|
31
|
+
onRuntime?: (runtime: OpencodeRuntime) => void;
|
|
32
|
+
requests?: string;
|
|
33
|
+
}>): Promise<OpencodeRuntime>;
|
|
27
34
|
export declare function coordinate(sessionId: string): ResumeCoordinate;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import net from "node:net";
|
|
2
2
|
import { abortable } from "../../abort.js";
|
|
3
|
+
import { akumaExecutionEnvironment } from "../execution-environment.js";
|
|
3
4
|
import { spawnDetachedProcess } from "../../../runtime/proc/run.js";
|
|
4
5
|
export const OPENCODE_SDK_PROVIDER = "opencode-sdk";
|
|
5
6
|
export function parseModel(model) {
|
|
@@ -37,9 +38,10 @@ async function availablePort() {
|
|
|
37
38
|
});
|
|
38
39
|
});
|
|
39
40
|
}
|
|
40
|
-
export async function loadOpencode(
|
|
41
|
+
export async function loadOpencode(input) {
|
|
42
|
+
const { execution, cwd, signal, loader, onRuntime, requests } = input;
|
|
41
43
|
if (loader) {
|
|
42
|
-
const loaded = await abortable(loader(cwd, execution, signal), signal);
|
|
44
|
+
const loaded = await abortable(loader(cwd, { ...execution, env: akumaExecutionEnvironment(process.env, execution.env, requests) }, signal), signal);
|
|
43
45
|
let closing;
|
|
44
46
|
const runtime = {
|
|
45
47
|
client: loaded.client,
|
|
@@ -64,11 +66,10 @@ export async function loadOpencode(execution, cwd, signal, loader, onRuntime) {
|
|
|
64
66
|
const owned = await spawnDetachedProcess({
|
|
65
67
|
argv: [execution.executable ?? "opencode", "serve", "--hostname", "127.0.0.1", "--port", String(port)],
|
|
66
68
|
cwd,
|
|
67
|
-
env: {
|
|
68
|
-
...process.env,
|
|
69
|
+
env: akumaExecutionEnvironment(process.env, {
|
|
69
70
|
...(execution.config === undefined ? {} : { OPENCODE_CONFIG_CONTENT: JSON.stringify(execution.config) }),
|
|
70
71
|
...execution.env,
|
|
71
|
-
},
|
|
72
|
+
}, requests),
|
|
72
73
|
log: `${cwd}/.opencode.log`,
|
|
73
74
|
});
|
|
74
75
|
const { createOpencodeClient } = await import("@opencode-ai/sdk");
|
|
@@ -89,7 +89,9 @@ function searchCall(name, value) {
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
function fileChangeCall(name, value) {
|
|
92
|
-
|
|
92
|
+
// Native write cannot prove creation versus overwrite and reports no patch, so
|
|
93
|
+
// it joins the conservative update operation with unknown diffstat.
|
|
94
|
+
if ((name !== "edit" && name !== "write") || typeof value.path !== "string")
|
|
93
95
|
return undefined;
|
|
94
96
|
return { kind: "fileChange", changes: [{ op: "update", path: value.path }] };
|
|
95
97
|
}
|
|
@@ -158,7 +160,10 @@ function translateMessage(event, state) {
|
|
|
158
160
|
}
|
|
159
161
|
const text = textContent(message.content);
|
|
160
162
|
state.answer = text;
|
|
161
|
-
|
|
163
|
+
// Gemini emits an empty text block alongside every tool-use message. It is
|
|
164
|
+
// transport scaffolding, not narration; an ordinary terminal empty answer
|
|
165
|
+
// remains public evidence.
|
|
166
|
+
if (hasTextContent(message.content) && !(message.stopReason === "toolUse" && text.length === 0)) {
|
|
162
167
|
translated.push({ type: "assistant", text });
|
|
163
168
|
}
|
|
164
169
|
return translated;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { abortable } from "../../abort.js";
|
|
2
|
-
import {
|
|
2
|
+
import { akumaExecutionEnvironment } from "../execution-environment.js";
|
|
3
|
+
import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
|
|
3
4
|
import { piTerminalFailure, translatePiEvent } from "./events.js";
|
|
4
5
|
const PI_THINKING_LEVELS = new Set(["minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
5
6
|
const MODEL_PATTERN = /^[^/\s]+\/[^\s]+$/u;
|
|
@@ -56,7 +57,7 @@ async function piCreateOptions(sdk, input) {
|
|
|
56
57
|
(await import("@earendil-works/pi-coding-agent")).createBashToolDefinition(input.cwd, {
|
|
57
58
|
spawnHook: (context) => ({
|
|
58
59
|
...context,
|
|
59
|
-
env:
|
|
60
|
+
env: akumaExecutionEnvironment(context.env, {}, input.requests.dir, ["PI_SESSION_ID", "PI_SESSION_FILE"]),
|
|
60
61
|
}),
|
|
61
62
|
}),
|
|
62
63
|
];
|
|
@@ -135,9 +135,14 @@ async function observePublishedRequest(input, id, transportId, path) {
|
|
|
135
135
|
}
|
|
136
136
|
try {
|
|
137
137
|
for (;;) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
let response;
|
|
139
|
+
try {
|
|
140
|
+
response = await readRequestReceipt(input, path, id);
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
// A visible receipt guarantees its final progress was already published, even on failure.
|
|
144
|
+
await consumeProgress();
|
|
145
|
+
}
|
|
141
146
|
if (response !== undefined)
|
|
142
147
|
return response;
|
|
143
148
|
if (!(await access(input.directory).then(() => true, () => false))) {
|
|
@@ -25,6 +25,7 @@ export type DriveTurnInput = Readonly<{
|
|
|
25
25
|
body: string;
|
|
26
26
|
call?: string;
|
|
27
27
|
launchTells: readonly TellFact[];
|
|
28
|
+
initiator?: string;
|
|
28
29
|
schemaJson?: string;
|
|
29
30
|
supervisor: BodySupervisor;
|
|
30
31
|
runtimeSpawn(launch: AkumaCallRequestChildLaunch): Promise<OwnedProcess | void>;
|
|
@@ -72,7 +72,9 @@ async function startTurnDrive(input) {
|
|
|
72
72
|
return { kind: "resume-unsupported" };
|
|
73
73
|
const boundTells = drainPendingTells(input.launchTells);
|
|
74
74
|
const schemaJson = input.schemaJson ?? boundTells.find((tell) => tell.schemaJson !== undefined)?.schemaJson;
|
|
75
|
+
const initiator = input.call === undefined ? boundTells[0]?.initiator : input.initiator;
|
|
75
76
|
const turn = await beginTurn(input.paths, {
|
|
77
|
+
...(initiator === undefined ? {} : { initiator }),
|
|
76
78
|
bodySequence: input.bodySequence,
|
|
77
79
|
startedAt: input.now(),
|
|
78
80
|
...(input.call === undefined ? {} : { call: input.call }),
|
package/build/src/akuma-body.js
CHANGED
|
@@ -86,11 +86,13 @@ function fleetRequestPort(world) {
|
|
|
86
86
|
body: input.body,
|
|
87
87
|
tellId: input.tellId,
|
|
88
88
|
recordedAt: input.recordedAt,
|
|
89
|
+
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
89
90
|
signal: input.signal,
|
|
90
91
|
}),
|
|
91
92
|
tellAnswer: async (input) => await PublicAkuma.select(world, input.target).tell(input.body, {
|
|
92
93
|
schema: Schema.json(JSON.parse(input.schemaJson), (value) => value),
|
|
93
94
|
...(input.interrupt === undefined ? {} : { interrupt: input.interrupt }),
|
|
95
|
+
...(input.initiator === undefined ? {} : { initiator: input.initiator }),
|
|
94
96
|
}),
|
|
95
97
|
kill: async (input) => {
|
|
96
98
|
const result = await executeKillAkuma({ path: world, ids: input.targets, signal: input.signal });
|
package/build/src/body/amend.js
CHANGED
|
@@ -16,11 +16,13 @@ function sections(document) {
|
|
|
16
16
|
function operationSections(document) {
|
|
17
17
|
if (document.frontmatter !== undefined)
|
|
18
18
|
refusal("amend operations may not contain frontmatter");
|
|
19
|
-
|
|
19
|
+
const openedBy = document.children.find((node) => nonblank(document, node));
|
|
20
|
+
const heading = openedBy?.type === "section" && openedBy.level === 1 ? openedBy : undefined;
|
|
21
|
+
if (indexedHeadings(indexDocument(document), { level: 1 }).length > (heading === undefined ? 0 : 1))
|
|
20
22
|
refusal("amend operations may contain H2 sections only");
|
|
21
|
-
|
|
23
|
+
const outside = [...document.children, ...(heading?.children ?? [])];
|
|
24
|
+
if (outside.some((node) => node.type !== "section" && nonblank(document, node)))
|
|
22
25
|
refusal("amend operations contain bytes outside H2 sections");
|
|
23
|
-
}
|
|
24
26
|
return sections(document).map((section) => {
|
|
25
27
|
const title = section.title.trim();
|
|
26
28
|
const match = /^(Add|Update|Replace|Append|Remove):[ ]+(.+)$/.exec(title);
|
|
@@ -70,7 +72,7 @@ function criteria(document, section) {
|
|
|
70
72
|
}
|
|
71
73
|
function verification(document, section) {
|
|
72
74
|
try {
|
|
73
|
-
return decodeVerificationDeclarations(document, section);
|
|
75
|
+
return decodeVerificationDeclarations(document, section, { requireTimeout: true });
|
|
74
76
|
}
|
|
75
77
|
catch (error) {
|
|
76
78
|
if (error instanceof VerificationDocumentError)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { DecodedContractDocument } from "./types.js";
|
|
2
2
|
import type { VerificationDefinition } from "../verification/declaration.js";
|
|
3
|
-
export declare function decodeContractDocument(source: string
|
|
3
|
+
export declare function decodeContractDocument(source: string, options?: Readonly<{
|
|
4
|
+
requireTimeout?: boolean;
|
|
5
|
+
}>): DecodedContractDocument;
|
|
4
6
|
export declare function verificationDefinition(document: DecodedContractDocument): VerificationDefinition | null;
|
package/build/src/body/decode.js
CHANGED
|
@@ -2,20 +2,60 @@ import { mintDocumentKey, mintDocumentSegmentKey } from "./keys.js";
|
|
|
2
2
|
import { decodeDocumentEnvelope } from "./envelope.js";
|
|
3
3
|
import { directChildren, normalizeTitle, rawSlice, sectionContent } from "../markdown/query.js";
|
|
4
4
|
import { CONTRACT_SECTIONS, RESERVED_SECTIONS } from "./shape.js";
|
|
5
|
-
import { decodeRegion, RegionDocumentError } from "./region.js";
|
|
5
|
+
import { decodeRegion, regionStructure, RegionDocumentError } from "./region.js";
|
|
6
6
|
import { decodeVerificationDeclarations, VerificationDocumentError } from "./verification.js";
|
|
7
7
|
function refusal(message) {
|
|
8
8
|
throw new TypeError(message);
|
|
9
9
|
}
|
|
10
10
|
function requireSections(sections) {
|
|
11
|
+
const diagnostics = [];
|
|
11
12
|
for (const [name, spec] of Object.entries(CONTRACT_SECTIONS)) {
|
|
12
13
|
if (spec.required && !sections.has(name))
|
|
13
|
-
|
|
14
|
+
diagnostics.push(`contract document is missing ## ${spec.title}`);
|
|
14
15
|
}
|
|
16
|
+
return diagnostics;
|
|
15
17
|
}
|
|
16
18
|
function requiredSection(sections, name) {
|
|
17
19
|
return sections.get(name);
|
|
18
20
|
}
|
|
21
|
+
function criteriaStructure(document, section) {
|
|
22
|
+
const headings = directChildren(section, "heading").filter((heading) => heading.level === 3);
|
|
23
|
+
if (headings.length === 0)
|
|
24
|
+
return "Criteria must contain one or more H3 entries";
|
|
25
|
+
const before = rawSlice(document, { start: section.contentStart, end: headings[0].span.start });
|
|
26
|
+
return before.trim().length === 0 ? null : "Criteria may contain only H3 entries";
|
|
27
|
+
}
|
|
28
|
+
function verificationStructure(document, section) {
|
|
29
|
+
const blocks = directChildren(section, "code_block");
|
|
30
|
+
if (blocks.length === 0)
|
|
31
|
+
return "Verification must contain one or more fenced executor declarations";
|
|
32
|
+
const other = section.children.filter((node) => node.type !== "code_block" && rawSlice(document, node.span).trim().length > 0);
|
|
33
|
+
return other.length === 0 ? null : "Verification may contain only fenced executor declarations";
|
|
34
|
+
}
|
|
35
|
+
// Independent structural rules collect together; each predicate mirrors the
|
|
36
|
+
// fence, heading, or reserved-name check its decoder already enforces so a
|
|
37
|
+
// document with several violations is refused once with every diagnostic.
|
|
38
|
+
function structuralDiagnostics(document, sections) {
|
|
39
|
+
const diagnostics = requireSections(sections);
|
|
40
|
+
for (const name of RESERVED_SECTIONS) {
|
|
41
|
+
if (sections.has(name))
|
|
42
|
+
diagnostics.push(`${name} is not a contract Markdown section`);
|
|
43
|
+
}
|
|
44
|
+
const checks = [
|
|
45
|
+
["region", (_document, section) => regionStructure(section)],
|
|
46
|
+
["criteria", criteriaStructure],
|
|
47
|
+
["verification", verificationStructure],
|
|
48
|
+
];
|
|
49
|
+
for (const [name, check] of checks) {
|
|
50
|
+
const section = sections.get(name);
|
|
51
|
+
if (section === undefined)
|
|
52
|
+
continue;
|
|
53
|
+
const diagnostic = check(document, section);
|
|
54
|
+
if (diagnostic !== null)
|
|
55
|
+
diagnostics.push(diagnostic);
|
|
56
|
+
}
|
|
57
|
+
return diagnostics;
|
|
58
|
+
}
|
|
19
59
|
function prose(document, section) {
|
|
20
60
|
const value = sectionContent(document, section);
|
|
21
61
|
if (value.trim().length === 0)
|
|
@@ -33,12 +73,10 @@ function region(document, section) {
|
|
|
33
73
|
}
|
|
34
74
|
}
|
|
35
75
|
function criteria(document, section) {
|
|
76
|
+
const structural = criteriaStructure(document, section);
|
|
77
|
+
if (structural !== null)
|
|
78
|
+
refusal(structural);
|
|
36
79
|
const headings = directChildren(section, "heading").filter((heading) => heading.level === 3);
|
|
37
|
-
if (headings.length === 0)
|
|
38
|
-
refusal("Criteria must contain one or more H3 entries");
|
|
39
|
-
const before = rawSlice(document, { start: section.contentStart, end: headings[0].span.start });
|
|
40
|
-
if (before.trim().length > 0)
|
|
41
|
-
refusal("Criteria may contain only H3 entries");
|
|
42
80
|
const seen = new Set();
|
|
43
81
|
return headings.map((heading, index) => {
|
|
44
82
|
const title = heading.text.trim();
|
|
@@ -55,9 +93,9 @@ function criteria(document, section) {
|
|
|
55
93
|
return { title, body };
|
|
56
94
|
});
|
|
57
95
|
}
|
|
58
|
-
function verification(document, section) {
|
|
96
|
+
function verification(document, section, options) {
|
|
59
97
|
try {
|
|
60
|
-
return decodeVerificationDeclarations(document, section);
|
|
98
|
+
return decodeVerificationDeclarations(document, section, options);
|
|
61
99
|
}
|
|
62
100
|
catch (error) {
|
|
63
101
|
if (error instanceof VerificationDocumentError)
|
|
@@ -65,7 +103,7 @@ function verification(document, section) {
|
|
|
65
103
|
throw error;
|
|
66
104
|
}
|
|
67
105
|
}
|
|
68
|
-
export function decodeContractDocument(source) {
|
|
106
|
+
export function decodeContractDocument(source, options = {}) {
|
|
69
107
|
let envelope;
|
|
70
108
|
try {
|
|
71
109
|
envelope = decodeDocumentEnvelope(source, "contract");
|
|
@@ -74,11 +112,10 @@ export function decodeContractDocument(source) {
|
|
|
74
112
|
refusal(error instanceof Error ? error.message : String(error));
|
|
75
113
|
}
|
|
76
114
|
const { document, title, sections, sectionNodes } = envelope;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
115
|
+
const structural = structuralDiagnostics(document, sections);
|
|
116
|
+
if (structural.length > 0)
|
|
117
|
+
refusal(structural.join("\n"));
|
|
118
|
+
const verificationSection = sections.get("verification");
|
|
82
119
|
const extensions = [...sections.entries()]
|
|
83
120
|
.filter(([name]) => !Object.hasOwn(CONTRACT_SECTIONS, name))
|
|
84
121
|
.map(([, section]) => {
|
|
@@ -87,7 +124,6 @@ export function decodeContractDocument(source) {
|
|
|
87
124
|
refusal(`extension '${section.title}' is empty`);
|
|
88
125
|
return { title: section.title, content };
|
|
89
126
|
});
|
|
90
|
-
const verificationSection = sections.get("verification");
|
|
91
127
|
const body = {
|
|
92
128
|
title: title.title,
|
|
93
129
|
context: prose(document, requiredSection(sections, "context")),
|
|
@@ -95,7 +131,7 @@ export function decodeContractDocument(source) {
|
|
|
95
131
|
design: prose(document, requiredSection(sections, "design")),
|
|
96
132
|
region: region(document, requiredSection(sections, "region")),
|
|
97
133
|
criteria: criteria(document, requiredSection(sections, "criteria")),
|
|
98
|
-
verification: verificationSection === undefined ? [] : verification(document, verificationSection),
|
|
134
|
+
verification: verificationSection === undefined ? [] : verification(document, verificationSection, options),
|
|
99
135
|
extensions,
|
|
100
136
|
};
|
|
101
137
|
const segments = sectionNodes.map((section) => mintDocumentSegmentKey(document.source, section.span));
|
|
@@ -3,5 +3,13 @@ export declare class RegionDocumentError extends Error {
|
|
|
3
3
|
constructor(message: string);
|
|
4
4
|
}
|
|
5
5
|
export declare function assertRegionPattern(pattern: string): string;
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Structural refusals are separate from pattern compilation so a caller may aggregate every independent failure.
|
|
8
|
+
* The three authoring forms — fenced lines, list items, and bare paragraph lines — union freely. Blank lines never
|
|
9
|
+
* count, and an info string beyond the exact `txt` still implies executable content that belongs to Verification.
|
|
10
|
+
*/
|
|
11
|
+
export declare function regionStructure(section: SectionNode): string | null;
|
|
12
|
+
/** A whitespace-bearing pattern is almost certainly strayed prose; bind warns and proceeds rather than rejecting. */
|
|
13
|
+
export declare function regionWarnings(patterns: readonly string[]): readonly string[];
|
|
14
|
+
export declare function decodeRegion(_document: DocumentNode, section: SectionNode): readonly string[];
|
|
7
15
|
export declare function regionsOverlap(mine: readonly string[], theirs: readonly string[]): readonly [string, string][];
|