@astrosheep/keiyaku 2.8.4 → 2.9.0
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 +35 -15
- package/build/.tsbuildinfo +1 -1
- package/build/agents/{call-terms_v2.js → call-terms.js} +12 -8
- package/build/agents/harness/control-types.js +1 -0
- package/build/agents/harness/execution-handle.js +23 -3
- package/build/agents/harness/index.js +6 -607
- package/build/agents/harness/outcome.js +141 -0
- package/build/agents/harness/projection.js +310 -0
- package/build/agents/harness/router.js +201 -0
- package/build/agents/harness/runtime.js +2 -1
- package/build/agents/{launch-snapshot_v2.js → launch-snapshot/model.js} +69 -74
- package/build/agents/launch-snapshot/resolve.js +72 -0
- package/build/agents/opencode-sdk.js +24 -3
- package/build/agents/providers/{claude-agent-sdk.js → claude-agent-sdk/adapter.js} +46 -368
- package/build/agents/providers/claude-agent-sdk/events.js +218 -0
- package/build/agents/providers/claude-agent-sdk/session.js +158 -0
- package/build/agents/providers/codex-app-server/adapter.js +347 -0
- package/build/agents/providers/codex-app-server/events.js +352 -0
- package/build/agents/providers/codex-app-server/session.js +266 -0
- package/build/agents/providers/codex-sdk.js +23 -5
- package/build/agents/providers/opencode-sdk/adapter.js +344 -0
- package/build/agents/providers/opencode-sdk/events.js +354 -0
- package/build/agents/providers/opencode-sdk/session.js +180 -0
- package/build/agents/providers/pi/adapter.js +269 -0
- package/build/agents/providers/pi/checkpoint.js +41 -0
- package/build/agents/providers/pi/events.js +282 -0
- package/build/agents/{selector_v2.js → selector.js} +8 -6
- package/build/cli/commands/akuma/akuma/handler.js +4 -0
- package/build/cli/commands/akuma/akuma/meta.js +16 -0
- package/build/cli/commands/akuma/catalog.js +8 -0
- package/build/cli/commands/akuma/list/handler.js +15 -0
- package/build/cli/commands/akuma/list/meta-ls.js +9 -0
- package/build/cli/commands/akuma/view/handler.js +34 -0
- package/build/cli/commands/akuma/view/meta.js +8 -0
- package/build/cli/commands/akuma.js +1 -1
- package/build/cli/commands/contract/amend/handler.js +10 -0
- package/build/cli/commands/contract/amend/meta.js +12 -0
- package/build/cli/commands/contract/arc/handler.js +9 -0
- package/build/cli/commands/contract/arc/meta.js +26 -0
- package/build/cli/commands/contract/bind/handler.js +23 -0
- package/build/cli/commands/contract/bind/meta.js +30 -0
- package/build/cli/commands/contract/catalog.js +16 -0
- package/build/cli/commands/contract/forfeit/handler.js +13 -0
- package/build/cli/commands/contract/forfeit/meta.js +12 -0
- package/build/cli/commands/contract/log/handler.js +12 -0
- package/build/cli/commands/contract/log/meta.js +12 -0
- package/build/cli/commands/contract/petition/handler.js +26 -0
- package/build/cli/commands/contract/petition/meta.js +23 -0
- package/build/cli/commands/contract/renew/handler.js +10 -0
- package/build/cli/commands/contract/renew/meta.js +17 -0
- package/build/cli/commands/projection/call/handler.js +39 -0
- package/build/cli/commands/projection/call/meta.js +9 -0
- package/build/cli/commands/projection/catalog.js +14 -0
- package/build/cli/commands/projection/kill/handler.js +35 -0
- package/build/cli/commands/projection/kill/meta.js +11 -0
- package/build/cli/commands/projection/revive/handler.js +53 -0
- package/build/cli/commands/projection/revive/meta.js +9 -0
- package/build/cli/commands/projection/status/handler.js +23 -0
- package/build/cli/commands/projection/status/meta.js +9 -0
- package/build/cli/commands/projection/tell/handler.js +34 -0
- package/build/cli/commands/projection/tell/meta.js +9 -0
- package/build/cli/commands/projection/wait/handler.js +21 -0
- package/build/cli/commands/projection/wait/meta.js +11 -0
- package/build/cli/commands/registry.js +100 -0
- package/build/cli/commands/shared.js +71 -0
- package/build/cli/commands/skills/catalog.js +6 -0
- package/build/cli/commands/skills/install/handler.js +10 -0
- package/build/cli/commands/skills/install/meta.js +9 -0
- package/build/cli/commands/skills/skills/handler.js +4 -0
- package/build/cli/commands/skills/skills/meta.js +10 -0
- package/build/cli/commands/system/catalog.js +8 -0
- package/build/cli/commands/system/completion/handler.js +10 -0
- package/build/cli/commands/system/completion/meta.js +9 -0
- package/build/cli/commands/system/dump-env/handler.js +3 -0
- package/build/cli/commands/system/dump-env/meta.js +10 -0
- package/build/cli/commands/system/guide/handler.js +4 -0
- package/build/cli/commands/system/guide/meta.js +9 -0
- package/build/cli/commands/task/add/handler.js +21 -0
- package/build/cli/commands/task/add/meta.js +8 -0
- package/build/cli/commands/task/catalog.js +22 -0
- package/build/cli/commands/task/doctor/handler.js +4 -0
- package/build/cli/commands/task/doctor/meta.js +8 -0
- package/build/cli/commands/task/done/handler.js +17 -0
- package/build/cli/commands/task/done/meta.js +8 -0
- package/build/cli/commands/task/drop/handler.js +6 -0
- package/build/cli/commands/task/drop/meta.js +8 -0
- package/build/cli/commands/task/ls/handler.js +13 -0
- package/build/cli/commands/task/ls/meta.js +8 -0
- package/build/cli/commands/task/shared.js +131 -0
- package/build/cli/commands/task/start/handler.js +6 -0
- package/build/cli/commands/task/start/meta.js +8 -0
- package/build/cli/commands/task/stop/handler.js +17 -0
- package/build/cli/commands/task/stop/meta.js +8 -0
- package/build/cli/commands/task/task/handler.js +5 -0
- package/build/cli/commands/task/task/meta.js +11 -0
- package/build/cli/commands/task/update/handler.js +18 -0
- package/build/cli/commands/task/update/meta.js +8 -0
- package/build/cli/commands/task/view/handler.js +14 -0
- package/build/cli/commands/task/view/meta.js +8 -0
- package/build/cli/completion.js +26 -27
- package/build/cli/flags.js +79 -2
- package/build/cli/help.js +27 -49
- package/build/cli/index.js +121 -374
- package/build/cli/output-stream-error-policy.js +17 -0
- package/build/cli/parse.js +159 -72
- package/build/cli/projection-address.js +5 -0
- package/build/cli/render/arc.js +1 -1
- package/build/cli/render/errors.js +4 -3
- package/build/cli/render/format.js +14 -0
- package/build/cli/render/kanshi.js +106 -0
- package/build/cli/render/petition.js +24 -1
- package/build/cli/render/projection-activity.js +5 -1
- package/build/cli/render/shared.js +2 -2
- package/build/cli/render/status.js +79 -13
- package/build/cli/render/task.js +113 -0
- package/build/cli/render/wait.js +23 -3
- package/build/cli/types.js +1 -1
- package/build/config/{akuma-loader_v2.js → akuma-loader.js} +2 -2
- package/build/config/env.js +9 -4
- package/build/config/settings/disease.js +26 -0
- package/build/config/settings/knobs.js +8 -0
- package/build/config/settings/loader.js +244 -0
- package/build/config/settings/schema.js +276 -0
- package/build/core/addressing.js +1 -1
- package/build/core/amend.js +3 -3
- package/build/core/arc.js +5 -4
- package/build/core/bind-workspace.js +123 -0
- package/build/core/bind.js +75 -155
- package/build/core/call/call.js +224 -0
- package/build/core/call/context.js +238 -0
- package/build/core/call/execution.js +217 -0
- package/build/core/call/prompt.js +42 -0
- package/build/core/call/reference.js +24 -0
- package/build/core/call-persist.js +1 -1
- package/build/core/claim-delivery.js +247 -0
- package/build/core/claim.js +39 -277
- package/build/core/context.js +2 -1
- package/build/core/{render.js → contract-view.js} +12 -140
- package/build/core/draft.js +107 -9
- package/build/core/entry.js +9 -1
- package/build/core/execution-coordinate.js +4 -20
- package/build/core/execution-pact.js +16 -31
- package/build/core/forfeit.js +35 -22
- package/build/core/hints.js +2 -2
- package/build/core/log.js +2 -2
- package/build/core/petition-claim-gates.js +8 -6
- package/build/core/petition-preview.js +97 -0
- package/build/core/petition-run.js +3 -2
- package/build/core/petition.js +39 -26
- package/build/core/projection/generation/database.js +306 -0
- package/build/core/projection/generation/identity.js +84 -0
- package/build/core/projection/generation/model.js +201 -0
- package/build/core/projection/generation/store.js +73 -0
- package/build/core/projection/generation/transitions.js +258 -0
- package/build/core/projection/heart.js +0 -307
- package/build/core/projection/tell/database.js +109 -0
- package/build/core/projection/tell/model.js +97 -0
- package/build/core/{projection-tells.js → projection/tell/store.js} +3 -158
- package/build/core/projection-activity.js +23 -2
- package/build/core/projection-core.js +2 -1
- package/build/core/projection-execution-observer.js +259 -0
- package/build/core/projection-generation-continuation.js +1 -1
- package/build/core/projection-generation-execution.js +90 -20
- package/build/core/projection-generation-launcher.js +1 -1
- package/build/core/projection-generation-runner.js +198 -4
- package/build/core/projection-identity.js +1 -1
- package/build/core/projection-kill.js +50 -17
- package/build/core/projection-life-observer.js +1 -1
- package/build/core/projection-life-protocol.js +10 -0
- package/build/core/projection-mint.js +1 -1
- package/build/core/projection-status.js +45 -32
- package/build/core/projection-wait.js +12 -2
- package/build/core/projection-wake.js +5 -2
- package/build/core/{queue_v2.js → queue.js} +2 -1
- package/build/core/registry.js +1 -1
- package/build/core/renew.js +7 -7
- package/build/core/response-artifact-catalog-sqlite.js +112 -0
- package/build/core/response-artifact-catalog.js +7 -0
- package/build/core/seal.js +44 -16
- package/build/core/status/board.js +286 -0
- package/build/core/status/drift.js +99 -0
- package/build/core/status/lifecycle.js +84 -0
- package/build/core/status/reconciliation.js +131 -0
- package/build/core/stored-agent-event.js +28 -4
- package/build/core/target-ref.js +10 -0
- package/build/core/task/board.js +175 -0
- package/build/core/task/commands.js +211 -0
- package/build/core/task/document.js +189 -0
- package/build/core/task/model.js +1 -0
- package/build/core/task/settlement-git.js +207 -0
- package/build/core/task/settlement-policy.js +82 -0
- package/build/core/task/source-board.js +84 -0
- package/build/core/task/source-model.js +1 -0
- package/build/core/task/validation.js +44 -0
- package/build/core/task-contract.js +224 -0
- package/build/core/task-doctor.js +14 -0
- package/build/core/task-git-actor.js +38 -0
- package/build/core/task-git-runtime.js +34 -0
- package/build/core/task-git-store.js +375 -0
- package/build/core/task-repository.js +1 -0
- package/build/core/task-store-repository.js +86 -0
- package/build/core/task-store.js +1 -0
- package/build/core/task-worktree.js +51 -0
- package/build/core/task.js +4 -0
- package/build/core/transcripts.js +138 -56
- package/build/core/validation.js +17 -0
- package/build/core/verdict.js +2 -2
- package/build/core/worktree-path.js +24 -6
- package/build/flow-error.js +3 -2
- package/build/generated/version.js +1 -1
- package/build/git/commits.js +3 -0
- package/build/git/diff/parsers.js +0 -94
- package/build/index.js +2 -0
- package/build/keiyaku-constants.js +2 -0
- package/build/keiyaku.js +4 -3
- package/package.json +3 -2
- package/skills/keiyaku/SKILL.md +1 -1
- package/skills/keiyaku-akuma/SKILL.md +11 -6
- package/build/agents/harness/pump.js +0 -158
- package/build/agents/providers/codex-app-server.js +0 -864
- package/build/agents/providers/opencode-sdk.js +0 -363
- package/build/agents/providers/pi.js +0 -557
- package/build/config/settings.js +0 -533
- package/build/core/call.js +0 -686
- package/build/core/projection/generation.js +0 -412
- package/build/core/projection/identity.js +0 -81
- package/build/core/projection/mint.js +0 -174
- package/build/core/projection-generation-store.js +0 -707
- package/build/core/status.js +0 -539
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import { FlowError } from "../../flow-error.js";
|
|
3
|
+
import { isGitRepo } from "../../git/branches.js";
|
|
4
|
+
import { createGit, wrapGitError } from "../../git/core.js";
|
|
5
|
+
import { AddressResolutionError, buildResolutionAttempt, buildUncommissionedAddress, buildUncommissionedRepositoryAddress, resolveContractAddress, withResolvedAddress, } from "../addressing.js";
|
|
6
|
+
import { findOpenArcView } from "../arc.js";
|
|
7
|
+
import { readLedger } from "../ledger.js";
|
|
8
|
+
import { deriveContractState, isTerminalState } from "../status/lifecycle.js";
|
|
9
|
+
import { contractPresentedByWorktree, contractWorktreePathFromBind, stableRepoRoot } from "../worktree-path.js";
|
|
10
|
+
async function findWorktreePathForContract(cwd, contractId) {
|
|
11
|
+
const git = createGit(cwd);
|
|
12
|
+
let output;
|
|
13
|
+
try {
|
|
14
|
+
output = await git.raw(["worktree", "list", "--porcelain"]);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw wrapGitError("worktree list --porcelain", error, cwd);
|
|
18
|
+
}
|
|
19
|
+
let currentPath;
|
|
20
|
+
for (const line of output.split(/\r?\n/)) {
|
|
21
|
+
if (line.startsWith("worktree ")) {
|
|
22
|
+
currentPath = line.slice("worktree ".length);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (line === `branch refs/heads/keiyaku/${contractId}`) {
|
|
26
|
+
return currentPath;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
async function resolveWorkspaceCwd(cwd, contractId, bind) {
|
|
32
|
+
const repoRoot = cwd;
|
|
33
|
+
if (bind.data.workspace === "here")
|
|
34
|
+
return repoRoot;
|
|
35
|
+
const listedWorktreePath = await findWorktreePathForContract(cwd, contractId);
|
|
36
|
+
const worktreePath = listedWorktreePath ?? await contractWorktreePathFromBind(repoRoot, contractId, bind);
|
|
37
|
+
let stat;
|
|
38
|
+
try {
|
|
39
|
+
stat = await fs.stat(worktreePath);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new FlowError("INTERNAL_STATE", `contract ${contractId} worktree not found at ${worktreePath}`, { cause: error });
|
|
43
|
+
}
|
|
44
|
+
if (!stat.isDirectory()) {
|
|
45
|
+
throw new FlowError("INTERNAL_STATE", `contract ${contractId} worktree path is not a directory: ${worktreePath}`);
|
|
46
|
+
}
|
|
47
|
+
return worktreePath;
|
|
48
|
+
}
|
|
49
|
+
export async function readCallKeiyakuContext(executionCwd, input) {
|
|
50
|
+
const ledgerCandidate = input.repoCwd ?? executionCwd;
|
|
51
|
+
const isRepo = await isGitRepo(ledgerCandidate);
|
|
52
|
+
if (!isRepo) {
|
|
53
|
+
if (input.bare && input.contractId) {
|
|
54
|
+
const asTyped = input.contractAddressSource === "at-address"
|
|
55
|
+
? `@${input.contractId}`
|
|
56
|
+
: `--contract ${input.contractId}`;
|
|
57
|
+
throw new AddressResolutionError("EMPTY_PARAM", `commission address ${asTyped} cannot be combined with --bare`, buildResolutionAttempt({
|
|
58
|
+
repo: { kind: "user" },
|
|
59
|
+
workdir: executionCwd,
|
|
60
|
+
spelling: {
|
|
61
|
+
asTyped,
|
|
62
|
+
source: input.contractAddressSource ?? "explicit-flag",
|
|
63
|
+
},
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
if (input.contractId) {
|
|
67
|
+
const asTyped = input.contractAddressSource === "at-address"
|
|
68
|
+
? `@${input.contractId}`
|
|
69
|
+
: `--contract ${input.contractId}`;
|
|
70
|
+
throw new AddressResolutionError("EMPTY_PARAM", `${asTyped} is a commission address, but ${ledgerCandidate} has no repository ledger; contract addressing requires a ledger`, buildResolutionAttempt({
|
|
71
|
+
repo: { kind: "user" },
|
|
72
|
+
workdir: executionCwd,
|
|
73
|
+
spelling: {
|
|
74
|
+
asTyped,
|
|
75
|
+
source: input.contractAddressSource ?? "explicit-flag",
|
|
76
|
+
},
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
activeKeiyaku: false,
|
|
81
|
+
effectiveCwd: executionCwd,
|
|
82
|
+
historyCwd: executionCwd,
|
|
83
|
+
profileCwd: executionCwd,
|
|
84
|
+
projectionCwd: executionCwd,
|
|
85
|
+
address: buildUncommissionedAddress({
|
|
86
|
+
repo: { kind: "user" },
|
|
87
|
+
workdir: executionCwd,
|
|
88
|
+
binding: "bare",
|
|
89
|
+
}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const ledgerCwd = await stableRepoRoot(ledgerCandidate);
|
|
93
|
+
if (input.reviveBinding) {
|
|
94
|
+
if (input.reviveBinding.kind === "commission") {
|
|
95
|
+
input.contractId = input.reviveBinding.commissionId;
|
|
96
|
+
input.contractAddressSource = "artifact-provenance";
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
return {
|
|
100
|
+
activeKeiyaku: false,
|
|
101
|
+
effectiveCwd: executionCwd,
|
|
102
|
+
historyCwd: ledgerCwd,
|
|
103
|
+
profileCwd: ledgerCwd,
|
|
104
|
+
projectionCwd: ledgerCwd,
|
|
105
|
+
address: buildUncommissionedRepositoryAddress({
|
|
106
|
+
stableRoot: ledgerCwd,
|
|
107
|
+
workdir: executionCwd,
|
|
108
|
+
binding: input.reviveBinding.kind,
|
|
109
|
+
}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (input.bare && input.contractId) {
|
|
114
|
+
const repositoryAddress = buildUncommissionedRepositoryAddress({
|
|
115
|
+
stableRoot: ledgerCwd,
|
|
116
|
+
workdir: executionCwd,
|
|
117
|
+
binding: "bare",
|
|
118
|
+
});
|
|
119
|
+
const asTyped = input.contractAddressSource === "at-address"
|
|
120
|
+
? `@${input.contractId}`
|
|
121
|
+
: `--contract ${input.contractId}`;
|
|
122
|
+
throw new AddressResolutionError("EMPTY_PARAM", `commission address ${asTyped} cannot be combined with --bare`, buildResolutionAttempt({
|
|
123
|
+
repo: repositoryAddress.repo,
|
|
124
|
+
workdir: repositoryAddress.workdir,
|
|
125
|
+
spelling: {
|
|
126
|
+
asTyped,
|
|
127
|
+
source: input.contractAddressSource ?? "explicit-flag",
|
|
128
|
+
},
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
if (input.bare) {
|
|
132
|
+
return {
|
|
133
|
+
activeKeiyaku: false,
|
|
134
|
+
effectiveCwd: executionCwd,
|
|
135
|
+
historyCwd: ledgerCwd,
|
|
136
|
+
profileCwd: ledgerCwd,
|
|
137
|
+
projectionCwd: ledgerCwd,
|
|
138
|
+
address: buildUncommissionedRepositoryAddress({
|
|
139
|
+
stableRoot: ledgerCwd,
|
|
140
|
+
workdir: executionCwd,
|
|
141
|
+
binding: "bare",
|
|
142
|
+
}),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
let address;
|
|
146
|
+
if (input.contractId) {
|
|
147
|
+
address = await resolveContractAddress(ledgerCwd, input.contractId, input.contractAddressSource);
|
|
148
|
+
}
|
|
149
|
+
else if (await isGitRepo(executionCwd)) {
|
|
150
|
+
const executionRepo = await stableRepoRoot(executionCwd);
|
|
151
|
+
if (input.repoCwd && executionRepo !== ledgerCwd) {
|
|
152
|
+
const presented = await contractPresentedByWorktree(executionCwd);
|
|
153
|
+
if (presented) {
|
|
154
|
+
throw new FlowError("EMPTY_PARAM", `cross-repository contract-worktree addressing is pending: -C presents @${presented} from ${executionRepo}, but --repo selects ${ledgerCwd}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
const presented = await contractPresentedByWorktree(executionCwd);
|
|
159
|
+
if (presented) {
|
|
160
|
+
address = await resolveContractAddress(ledgerCwd, presented, "worktree-presented");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (!address) {
|
|
165
|
+
try {
|
|
166
|
+
address = await resolveContractAddress(ledgerCwd);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (error instanceof AddressResolutionError
|
|
170
|
+
&& error.code === "EMPTY_PARAM"
|
|
171
|
+
&& error.attempt.expected === "commission"
|
|
172
|
+
&& error.attempt.candidates.length === 0) {
|
|
173
|
+
return {
|
|
174
|
+
activeKeiyaku: false,
|
|
175
|
+
effectiveCwd: executionCwd,
|
|
176
|
+
historyCwd: ledgerCwd,
|
|
177
|
+
profileCwd: ledgerCwd,
|
|
178
|
+
projectionCwd: ledgerCwd,
|
|
179
|
+
address: buildUncommissionedRepositoryAddress({
|
|
180
|
+
stableRoot: ledgerCwd,
|
|
181
|
+
workdir: executionCwd,
|
|
182
|
+
binding: "unbound",
|
|
183
|
+
}),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return await withResolvedAddress(address, async () => {
|
|
190
|
+
const contractId = address.binding.commissionId;
|
|
191
|
+
const ledger = await readLedger(ledgerCwd, contractId);
|
|
192
|
+
if (!ledger) {
|
|
193
|
+
throw new FlowError("INTERNAL_STATE", `contract ${contractId} not found or not active`);
|
|
194
|
+
}
|
|
195
|
+
const state = deriveContractState(ledger.entries);
|
|
196
|
+
if (state.state === "corrupt") {
|
|
197
|
+
throw new FlowError("INTERNAL_STATE", `contract ${contractId} is corrupt at entry ${state.at}: ${state.reason}`);
|
|
198
|
+
}
|
|
199
|
+
if (isTerminalState(state)) {
|
|
200
|
+
throw new FlowError("EMPTY_PARAM", `commission ${contractId} is terminal and cannot launch an Akuma`);
|
|
201
|
+
}
|
|
202
|
+
const bind = ledger.entries.find((entry) => entry.kind === "bind");
|
|
203
|
+
if (!bind) {
|
|
204
|
+
throw new FlowError("INTERNAL_STATE", `contract ${contractId} active ledger is missing bind entry`);
|
|
205
|
+
}
|
|
206
|
+
const effectiveCwd = await resolveWorkspaceCwd(ledgerCwd, contractId, bind);
|
|
207
|
+
const executionAddress = { ...address, workdir: effectiveCwd };
|
|
208
|
+
const openArc = findOpenArcView(ledger.entries);
|
|
209
|
+
const currentIntent = openArc
|
|
210
|
+
? {
|
|
211
|
+
source: "arc",
|
|
212
|
+
arc: openArc.arc,
|
|
213
|
+
title: openArc.title,
|
|
214
|
+
objective: openArc.objective,
|
|
215
|
+
brief: openArc.brief,
|
|
216
|
+
}
|
|
217
|
+
: ledger.entries.some((entry) => entry.kind === "arc")
|
|
218
|
+
? undefined
|
|
219
|
+
: {
|
|
220
|
+
source: "bind",
|
|
221
|
+
arc: 0,
|
|
222
|
+
name: bind.data.name,
|
|
223
|
+
objective: bind.data.objective,
|
|
224
|
+
scope: bind.data.scope,
|
|
225
|
+
checks: bind.data.checks,
|
|
226
|
+
extensions: bind.data.extensions,
|
|
227
|
+
};
|
|
228
|
+
return {
|
|
229
|
+
activeKeiyaku: true,
|
|
230
|
+
effectiveCwd,
|
|
231
|
+
historyCwd: ledgerCwd,
|
|
232
|
+
profileCwd: effectiveCwd,
|
|
233
|
+
projectionCwd: ledgerCwd,
|
|
234
|
+
currentIntent,
|
|
235
|
+
address: executionAddress,
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { buildCallTerms } from "../../agents/call-terms.js";
|
|
2
|
+
import { createAbortError, restoreOutcome, SubagentFailure, } from "../../agents/harness/index.js";
|
|
3
|
+
import { resolveAkumaLaunchSnapshot } from "../../agents/launch-snapshot/resolve.js";
|
|
4
|
+
import { selectSubagent } from "../../agents/selector.js";
|
|
5
|
+
import { FlowError } from "../../flow-error.js";
|
|
6
|
+
import { assertProjectionAlias, moveProjectionAlias } from "../projection-alias.js";
|
|
7
|
+
import { projectionDir } from "../projection-core.js";
|
|
8
|
+
import { createProjectionExecutionId } from "../projection-generation-identity.js";
|
|
9
|
+
import { PROJECTION_ADOPTION_TIMEOUT_MS, startProjectionGeneration } from "../projection-generation-launcher.js";
|
|
10
|
+
import { openProjectionGenerationStore, openProjectionGenerationStoreReadOnly, } from "../projection/generation/store.js";
|
|
11
|
+
import { observeProjectionLife } from "../projection-life-observer.js";
|
|
12
|
+
import { mintProjection, mintRepositoryProjection } from "../projection-mint.js";
|
|
13
|
+
import { waitForProjection } from "../projection-wait.js";
|
|
14
|
+
export function readCurrentGenerationOrThrow(projectionDirectory) {
|
|
15
|
+
const store = openProjectionGenerationStoreReadOnly(projectionDirectory);
|
|
16
|
+
try {
|
|
17
|
+
const current = store.readCurrentGeneration();
|
|
18
|
+
if (!current)
|
|
19
|
+
throw new FlowError("INTERNAL_STATE", "projection has no current generation");
|
|
20
|
+
return current;
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
store.close();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function outcomeFromGeneration(current) {
|
|
27
|
+
const verdict = current.verdict;
|
|
28
|
+
if (!verdict)
|
|
29
|
+
throw new FlowError("INTERNAL_STATE", "projection generation has no terminal verdict");
|
|
30
|
+
const facts = verdict.facts;
|
|
31
|
+
const finalMessage = typeof facts.finalMessage === "string"
|
|
32
|
+
? facts.finalMessage
|
|
33
|
+
: typeof facts.detail === "string"
|
|
34
|
+
? facts.detail
|
|
35
|
+
: "";
|
|
36
|
+
if (facts.state === "failed" && typeof facts.detail === "string") {
|
|
37
|
+
throw new FlowError("SUBAGENT_EXEC_ERROR", facts.detail);
|
|
38
|
+
}
|
|
39
|
+
const session = facts.session;
|
|
40
|
+
if (session === null || typeof session !== "object" || Array.isArray(session)) {
|
|
41
|
+
throw new FlowError("INTERNAL_STATE", "projection verdict is missing its session envelope");
|
|
42
|
+
}
|
|
43
|
+
const record = {
|
|
44
|
+
status: facts.state === "completed"
|
|
45
|
+
? "completed"
|
|
46
|
+
: facts.state === "dismissed"
|
|
47
|
+
? "dismissed"
|
|
48
|
+
: "failed",
|
|
49
|
+
finalMessage,
|
|
50
|
+
output: typeof facts.output === "string" ? facts.output : "",
|
|
51
|
+
diagnostics: typeof facts.diagnostics === "string" ? facts.diagnostics : "",
|
|
52
|
+
session: session,
|
|
53
|
+
warnings: Array.isArray(facts.warnings)
|
|
54
|
+
? facts.warnings
|
|
55
|
+
: [],
|
|
56
|
+
...(facts.error && typeof facts.error === "object" && !Array.isArray(facts.error)
|
|
57
|
+
? { error: facts.error }
|
|
58
|
+
: {}),
|
|
59
|
+
};
|
|
60
|
+
return restoreOutcome(record);
|
|
61
|
+
}
|
|
62
|
+
export async function executeSubagent(agentName, prompt, cwd, options) {
|
|
63
|
+
const { projection: projectionCoordinate, launchSnapshot } = await buildCallConfig(agentName, prompt, cwd, options);
|
|
64
|
+
if (!projectionCoordinate) {
|
|
65
|
+
throw new FlowError("INTERNAL_STATE", "durable execution requires a projection coordinate");
|
|
66
|
+
}
|
|
67
|
+
const launched = await startProjectionGeneration(projectionCoordinate.dir, projectionCoordinate.executionId);
|
|
68
|
+
if (launched.status === "failed") {
|
|
69
|
+
throw new FlowError("SUBAGENT_EXEC_ERROR", launched.detail);
|
|
70
|
+
}
|
|
71
|
+
const joined = await waitForProjection({
|
|
72
|
+
projectionDirectory: projectionCoordinate.dir,
|
|
73
|
+
signal: options.signal,
|
|
74
|
+
});
|
|
75
|
+
if (joined.state !== "terminal") {
|
|
76
|
+
throw new FlowError("INTERNAL_STATE", "durable execution ended without a terminal generation");
|
|
77
|
+
}
|
|
78
|
+
const current = readCurrentGenerationOrThrow(projectionCoordinate.dir);
|
|
79
|
+
const providerOutcome = outcomeFromGeneration(current);
|
|
80
|
+
const outcome = {
|
|
81
|
+
status: providerOutcome.status,
|
|
82
|
+
finalMessage: providerOutcome.finalMessage,
|
|
83
|
+
output: providerOutcome.output,
|
|
84
|
+
diagnostics: providerOutcome.diagnostics,
|
|
85
|
+
session: providerOutcome.session,
|
|
86
|
+
warnings: providerOutcome.warnings,
|
|
87
|
+
...(providerOutcome.error ? { error: providerOutcome.error } : {}),
|
|
88
|
+
launchSnapshot,
|
|
89
|
+
};
|
|
90
|
+
const completionFacts = current.verdict?.facts;
|
|
91
|
+
switch (outcome.status) {
|
|
92
|
+
case "completed":
|
|
93
|
+
return { outcome, projection: projectionCoordinate, ...(completionFacts ? { completionFacts } : {}) };
|
|
94
|
+
case "dismissed":
|
|
95
|
+
throw createAbortError("subagent exec cancelled by client");
|
|
96
|
+
case "failed": {
|
|
97
|
+
const error = outcome.error;
|
|
98
|
+
if (!error) {
|
|
99
|
+
throw new FlowError("SUBAGENT_EXEC_ERROR", "Subagent exec failed without an error payload.");
|
|
100
|
+
}
|
|
101
|
+
throw new FlowError(error.code, error.message, {
|
|
102
|
+
cause: new SubagentFailure(error.code, error.message, {
|
|
103
|
+
timeoutMs: error.timeoutMs,
|
|
104
|
+
exitCode: error.exitCode,
|
|
105
|
+
output: outcome.output,
|
|
106
|
+
diagnostics: outcome.diagnostics,
|
|
107
|
+
}),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
throw new FlowError("INTERNAL_STATE", "Unhandled subagent outcome state.");
|
|
112
|
+
}
|
|
113
|
+
export async function launchSubagentGeneration(agentName, prompt, cwd, options) {
|
|
114
|
+
const { projection, launchSnapshot } = await buildCallConfig(agentName, prompt, cwd, options);
|
|
115
|
+
if (!projection) {
|
|
116
|
+
throw new FlowError("INTERNAL_STATE", "durable launch requires a projection coordinate");
|
|
117
|
+
}
|
|
118
|
+
const launched = await startProjectionGeneration(projection.dir, projection.executionId);
|
|
119
|
+
if (launched.status === "failed") {
|
|
120
|
+
throw new FlowError("SUBAGENT_EXEC_ERROR", launched.detail);
|
|
121
|
+
}
|
|
122
|
+
return { projection, launchSnapshot };
|
|
123
|
+
}
|
|
124
|
+
export async function buildCallConfig(agentName, prompt, cwd, options) {
|
|
125
|
+
const launchSnapshot = options.launchSnapshot ?? resolveAkumaLaunchSnapshot(await selectSubagent(agentName, cwd), {
|
|
126
|
+
executionCwd: cwd,
|
|
127
|
+
projectRoot: cwd,
|
|
128
|
+
...(options.model !== undefined ? { model: options.model } : {}),
|
|
129
|
+
...(options.effort !== undefined ? { effort: options.effort } : {}),
|
|
130
|
+
});
|
|
131
|
+
const resolvedTerms = buildCallTerms(launchSnapshot, prompt, cwd, {
|
|
132
|
+
signal: options.signal,
|
|
133
|
+
idleTimeoutMs: options.idleTimeoutMs,
|
|
134
|
+
});
|
|
135
|
+
// Mint projection directory for supervisor pump.
|
|
136
|
+
const slug = launchSnapshot.akuma.name;
|
|
137
|
+
const publishProjection = async () => {
|
|
138
|
+
const mintInput = {
|
|
139
|
+
cwd: options.projectionCwd ?? cwd,
|
|
140
|
+
workspaceRoot: cwd,
|
|
141
|
+
slug,
|
|
142
|
+
pid: process.pid,
|
|
143
|
+
akuma: launchSnapshot.akuma.name,
|
|
144
|
+
provider: launchSnapshot.provider.kind,
|
|
145
|
+
binding: options.binding,
|
|
146
|
+
effectivePolicy: launchSnapshot.akuma.policy,
|
|
147
|
+
nowMs: Date.now(),
|
|
148
|
+
};
|
|
149
|
+
const minted = options.authority.kind === "repository"
|
|
150
|
+
? await mintRepositoryProjection({ ...mintInput, authority: { kind: "repository" } })
|
|
151
|
+
: mintProjection({ ...mintInput, authority: { kind: "user" } });
|
|
152
|
+
const executionId = createProjectionExecutionId();
|
|
153
|
+
const launchFacts = JSON.parse(JSON.stringify({
|
|
154
|
+
executionId,
|
|
155
|
+
createdAt: new Date().toISOString(),
|
|
156
|
+
launchedBy: "call",
|
|
157
|
+
inputs: {
|
|
158
|
+
prompt,
|
|
159
|
+
task: options.task ?? prompt,
|
|
160
|
+
launchSnapshot,
|
|
161
|
+
idleTimeoutMs: resolvedTerms.idleTimeoutMs,
|
|
162
|
+
cwd,
|
|
163
|
+
historyCwd: options.historyStorageCwd ?? cwd,
|
|
164
|
+
...(options.evidenceCwd !== undefined ? { evidenceCwd: options.evidenceCwd } : {}),
|
|
165
|
+
...(options.title !== undefined ? { title: options.title } : {}),
|
|
166
|
+
...(options.context !== undefined ? { context: options.context } : {}),
|
|
167
|
+
persistProjectionResponse: options.persistProjectionResponse ?? false,
|
|
168
|
+
...(options.continuation ? {
|
|
169
|
+
session: options.continuation.session,
|
|
170
|
+
resumePath: options.continuation.resumePath,
|
|
171
|
+
sourceArtifactId: options.continuation.sourceArtifactId,
|
|
172
|
+
} : {}),
|
|
173
|
+
},
|
|
174
|
+
}));
|
|
175
|
+
const store = openProjectionGenerationStore(minted.dir);
|
|
176
|
+
try {
|
|
177
|
+
const launch = store.launchIfSettled({ executionId, facts: launchFacts });
|
|
178
|
+
if (launch.status !== "committed") {
|
|
179
|
+
throw new FlowError("INTERNAL_STATE", `initial generation launch rejected: ${launch.reason}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
store.close();
|
|
184
|
+
}
|
|
185
|
+
const previousAliasTarget = options.alias === undefined
|
|
186
|
+
? undefined
|
|
187
|
+
: moveProjectionAlias(options.projectionCwd ?? cwd, assertProjectionAlias(options.alias), minted.id);
|
|
188
|
+
const previousAliasTargetStillRunning = previousAliasTarget === undefined
|
|
189
|
+
? undefined
|
|
190
|
+
: (() => {
|
|
191
|
+
try {
|
|
192
|
+
const phase = observeProjectionLife(projectionDir(options.projectionCwd ?? cwd, previousAliasTarget), { nowMs: Date.now(), startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS }).phase;
|
|
193
|
+
return phase === "minting" || phase === "active" || phase === "quiescent"
|
|
194
|
+
? previousAliasTarget
|
|
195
|
+
: undefined;
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
})();
|
|
201
|
+
return {
|
|
202
|
+
id: minted.id,
|
|
203
|
+
dir: minted.dir,
|
|
204
|
+
executionId,
|
|
205
|
+
...(options.alias ? { alias: options.alias } : {}),
|
|
206
|
+
...(previousAliasTargetStillRunning ? { previousAliasTarget: previousAliasTargetStillRunning } : {}),
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
// Every public launch has one durable projection object. Repository-free
|
|
210
|
+
// authority changes the storage owner, not whether the object exists; mint
|
|
211
|
+
// failure is therefore a launch failure rather than an in-process fallback.
|
|
212
|
+
const projectionCoordinate = await publishProjection();
|
|
213
|
+
return {
|
|
214
|
+
projection: projectionCoordinate,
|
|
215
|
+
launchSnapshot,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ACTOR_IDENTITY } from "../../keiyaku.js";
|
|
2
|
+
export function buildCallPrompt(input) {
|
|
3
|
+
const references = [...new Set((input.referenceFiles ?? []).map((file) => file.trim()).filter(Boolean))];
|
|
4
|
+
if (input.currentIntent?.source === "arc") {
|
|
5
|
+
const arc = input.currentIntent;
|
|
6
|
+
return [
|
|
7
|
+
`You are a called ${ACTOR_IDENTITY} working inside open arc a${arc.arc}.`,
|
|
8
|
+
"Stay within the arc scope and do the requested work directly.",
|
|
9
|
+
`Title: ${arc.title}`,
|
|
10
|
+
`Objective: ${arc.objective}`,
|
|
11
|
+
`Brief:\n${arc.brief}`,
|
|
12
|
+
"",
|
|
13
|
+
`Task:\n${input.task}`,
|
|
14
|
+
`Context:\n${input.context?.trim() || "(none provided)"}`,
|
|
15
|
+
references.length > 0 ? `Reference files:\n${references.map((file) => `- ${file}`).join("\n")}` : "",
|
|
16
|
+
"Provide the final result for the caller/main agent.",
|
|
17
|
+
].filter(Boolean).join("\n\n");
|
|
18
|
+
}
|
|
19
|
+
if (input.currentIntent?.source === "bind") {
|
|
20
|
+
const bind = input.currentIntent;
|
|
21
|
+
const trimmedContext = input.context?.trim() ?? "";
|
|
22
|
+
const extensionsBlock = bind.extensions.length > 0
|
|
23
|
+
? `Extensions:\n${bind.extensions.map((extension) => `## ${extension.title}\n${extension.content}`).join("\n\n")}`
|
|
24
|
+
: "";
|
|
25
|
+
return [
|
|
26
|
+
`You are a called ${ACTOR_IDENTITY} working inside derived default arc a0.`,
|
|
27
|
+
"Stay within the contract scope and do the requested work directly.",
|
|
28
|
+
`Contract: ${bind.name}`,
|
|
29
|
+
`Objective:\n${bind.objective}`,
|
|
30
|
+
`Scope:\n${bind.scope.map((value) => `- ${value}`).join("\n")}`,
|
|
31
|
+
`Checks:\n${bind.checks.map((value) => `- ${value}`).join("\n")}`,
|
|
32
|
+
extensionsBlock,
|
|
33
|
+
`Task:\n${input.task}`,
|
|
34
|
+
trimmedContext ? `Context:\n${trimmedContext}` : "",
|
|
35
|
+
references.length > 0 ? `Reference files:\n${references.map((file) => `- ${file}`).join("\n")}` : "",
|
|
36
|
+
"Provide the final result for the caller/main agent.",
|
|
37
|
+
].filter(Boolean).join("\n\n");
|
|
38
|
+
}
|
|
39
|
+
return [input.task, input.context?.trim() ?? "", references.length > 0 ? `Reference files:\n${references.map((file) => `- ${file}`).join("\n")}` : ""]
|
|
40
|
+
.filter(Boolean)
|
|
41
|
+
.join("\n\n");
|
|
42
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { isErrnoException } from "../../errno.js";
|
|
4
|
+
import { BASE_RULES_FILE, KEIYAKU_FILE } from "../../keiyaku.js";
|
|
5
|
+
async function fileExists(cwd, relativePath) {
|
|
6
|
+
try {
|
|
7
|
+
await fs.access(path.join(cwd, relativePath));
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
if (isErrnoException(error) && error.code === "ENOENT") {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export async function collectCallReferenceFiles(cwd, input) {
|
|
18
|
+
const candidates = [
|
|
19
|
+
...(input.activeKeiyaku ? [KEIYAKU_FILE] : []),
|
|
20
|
+
BASE_RULES_FILE,
|
|
21
|
+
];
|
|
22
|
+
const existing = await Promise.all(candidates.map(async (file) => ({ file, exists: await fileExists(cwd, file) })));
|
|
23
|
+
return existing.filter((entry) => entry.exists).map((entry) => entry.file);
|
|
24
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { appendDebugLog } from "../telemetry/debug-log.js";
|
|
2
2
|
import { logWarn } from "../telemetry/logger.js";
|
|
3
|
-
import { runCall } from "./call.js";
|
|
3
|
+
import { runCall } from "./call/call.js";
|
|
4
4
|
import { persistResponseHistory } from "./transcripts.js";
|
|
5
5
|
import { isGitRepo } from "../git/branches.js";
|
|
6
6
|
import * as path from "node:path";
|