@astrosheep/keiyaku 2.9.2 → 2.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms.js +13 -94
- package/build/agents/harness/activity-values.js +16 -0
- package/build/agents/harness/event-persistence.js +218 -0
- package/build/agents/harness/execution-handle.js +25 -222
- package/build/agents/harness/index.js +3 -1
- package/build/agents/harness/outcome.js +47 -4
- package/build/agents/harness/projection.js +42 -59
- package/build/agents/harness/provider-adapter.js +58 -0
- package/build/agents/harness/router.js +11 -187
- package/build/agents/harness/runtime.js +17 -4
- package/build/agents/harness/session.js +15 -0
- package/build/agents/launch-snapshot/model.js +15 -236
- package/build/agents/launch-snapshot/parse-helpers.js +114 -0
- package/build/agents/launch-snapshot/resolve.js +17 -43
- package/build/agents/opencode-sdk.js +45 -12
- package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
- package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
- package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
- package/build/agents/providers/codex-app-server/adapter.js +50 -53
- package/build/agents/providers/codex-app-server/events.js +67 -11
- package/build/agents/providers/codex-app-server/identity.js +1 -0
- package/build/agents/providers/codex-app-server/policy.js +29 -0
- package/build/agents/providers/codex-app-server/registration.js +248 -0
- package/build/agents/providers/codex-app-server/session-schema.js +6 -0
- package/build/agents/providers/codex-app-server/session.js +23 -17
- package/build/agents/providers/codex-app-server/terms.js +1 -0
- package/build/agents/providers/opencode-sdk/adapter.js +94 -50
- package/build/agents/providers/opencode-sdk/events.js +8 -4
- package/build/agents/providers/opencode-sdk/registration.js +135 -0
- package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
- package/build/agents/providers/opencode-sdk/session.js +21 -14
- package/build/agents/providers/opencode-sdk/terms.js +1 -0
- package/build/agents/providers/pi/adapter.js +36 -30
- package/build/agents/providers/pi/registration.js +145 -0
- package/build/agents/providers/pi/session-schema.js +6 -0
- package/build/agents/providers/pi/terms.js +1 -0
- package/build/agents/providers/registration.js +7 -0
- package/build/agents/providers/registry.js +76 -0
- package/build/agents/selector.js +2 -29
- package/build/agents/types.js +8 -0
- package/build/artifact-directories.js +22 -0
- package/build/cli/commands/akuma/akuma/handler.js +1 -1
- package/build/cli/commands/akuma/view/handler.js +5 -4
- package/build/cli/commands/akuma.js +6 -0
- package/build/cli/commands/contract/amend/handler.js +8 -2
- package/build/cli/commands/contract/arc/handler.js +7 -1
- package/build/cli/commands/contract/bind/handler.js +4 -3
- package/build/cli/commands/contract/bind/meta.js +34 -7
- package/build/cli/commands/contract/forfeit/handler.js +4 -4
- package/build/cli/commands/contract/log/handler.js +3 -3
- package/build/cli/commands/contract/petition/handler.js +4 -6
- package/build/cli/commands/contract/renew/handler.js +20 -6
- package/build/cli/commands/contract/renew/meta.js +5 -4
- package/build/cli/commands/metadata.js +58 -0
- package/build/cli/commands/projection/call/handler.js +6 -5
- package/build/cli/commands/projection/kill/handler.js +16 -32
- package/build/cli/commands/projection/shared.js +28 -0
- package/build/cli/commands/projection/status/handler.js +1 -1
- package/build/cli/commands/projection/tell/handler.js +14 -30
- package/build/cli/commands/projection/wait/handler.js +45 -22
- package/build/cli/commands/projection/wait/meta.js +7 -2
- package/build/cli/commands/registry.js +2 -54
- package/build/cli/commands/shared.js +10 -7
- package/build/cli/commands/skills/install/handler.js +2 -5
- package/build/cli/commands/skills/skills/handler.js +1 -1
- package/build/cli/commands/task/add/handler.js +5 -13
- package/build/cli/commands/task/catalog.js +2 -2
- package/build/cli/commands/task/done/handler.js +4 -8
- package/build/cli/commands/task/drop/handler.js +3 -6
- package/build/cli/commands/task/ls/handler.js +3 -5
- package/build/cli/commands/task/shared.js +14 -4
- package/build/cli/commands/task/{view → show}/handler.js +7 -8
- package/build/cli/commands/task/show/meta.js +8 -0
- package/build/cli/commands/task/start/handler.js +3 -6
- package/build/cli/commands/task/stop/handler.js +4 -8
- package/build/cli/commands/task/task/handler.js +1 -1
- package/build/cli/commands/task/update/handler.js +4 -8
- package/build/cli/completion.js +1 -1
- package/build/cli/flags.js +19 -3
- package/build/cli/help.js +4 -11
- package/build/cli/index.js +57 -83
- package/build/cli/missing-subcommand.js +7 -0
- package/build/cli/parse-flags.js +14 -5
- package/build/cli/parse-metadata.js +3 -3
- package/build/cli/parse-selectors.js +1 -1
- package/build/cli/parse.js +21 -0
- package/build/cli/projection-address.js +7 -12
- package/build/cli/render/address.js +41 -37
- package/build/cli/render/arc.js +24 -12
- package/build/cli/render/call.js +11 -5
- package/build/cli/render/errors.js +36 -1
- package/build/cli/render/format.js +4 -0
- package/build/cli/render/kanshi.js +6 -12
- package/build/cli/render/kill.js +9 -0
- package/build/cli/render/misc.js +55 -12
- package/build/cli/render/petition.js +20 -15
- package/build/cli/render/projection-activity.js +3 -0
- package/build/cli/render/shared.js +60 -21
- package/build/cli/render/skills.js +10 -0
- package/build/cli/render/status.js +37 -14
- package/build/cli/render/success-response.js +77 -0
- package/build/cli/render/task.js +54 -14
- package/build/cli/render/tell.js +5 -0
- package/build/cli/render/terminal-failure.js +58 -0
- package/build/cli/render/types.js +1 -0
- package/build/cli/render/wait.js +38 -36
- package/build/cli/types.js +1 -1
- package/build/config/akuma-loader.js +0 -5
- package/build/config/env-keys.js +1 -1
- package/build/config/provider-policy-ownership.js +3 -32
- package/build/config/settings/disease.js +8 -1
- package/build/config/settings/loader.js +11 -3
- package/build/config/settings/provider-instance-fields.js +51 -0
- package/build/config/settings/schema.js +6 -176
- package/build/core/addressing.js +66 -16
- package/build/core/amend.js +135 -18
- package/build/core/arc.js +19 -67
- package/build/core/bind.js +82 -35
- package/build/core/call/call.js +15 -9
- package/build/core/call/context.js +6 -51
- package/build/core/call/execution.js +21 -22
- package/build/core/call/prompt.js +14 -1
- package/build/core/command-markdown.js +45 -0
- package/build/core/context.js +13 -7
- package/build/core/contract-view.js +20 -3
- package/build/core/draft.js +123 -16
- package/build/core/forfeit.js +5 -2
- package/build/core/hints.js +1 -75
- package/build/core/identifier-slug.js +66 -0
- package/build/core/ids.js +25 -11
- package/build/core/ledger.js +20 -68
- package/build/core/markdown/parser.js +0 -68
- package/build/core/markdown/render.js +68 -0
- package/build/core/markdown/sections.js +2 -1
- package/build/core/outcome-base.js +4 -0
- package/build/core/projection/generation/database.js +2 -38
- package/build/core/projection/generation/model.js +42 -1
- package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
- package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +19 -49
- package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
- package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +5 -3
- package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
- package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +18 -3
- package/build/core/projection/generation/store.js +2 -2
- package/build/core/projection/generation/transitions.js +1 -1
- package/build/core/projection/index.js +27 -0
- package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
- package/build/core/{projection-alias.js → projection/projection-alias.js} +14 -19
- package/build/core/projection/projection-coordinate.js +61 -0
- package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
- package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +2 -57
- package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
- package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
- package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +1 -1
- package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
- package/build/core/{projection-status.js → projection/projection-status.js} +98 -25
- package/build/core/projection/projection-terminal-failure.js +104 -0
- package/build/core/projection/projection-wait.js +278 -0
- package/build/core/projection/projection-wake.js +203 -0
- package/build/core/provider-loader-ports.js +4 -0
- package/build/core/ref-log.js +65 -40
- package/build/core/registry.js +63 -10
- package/build/core/renew-session.js +128 -0
- package/build/core/renew.js +426 -99
- package/build/core/scope.js +143 -66
- package/build/core/seal.js +139 -35
- package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +9 -14
- package/build/core/{claim.js → settlement/claim.js} +32 -8
- package/build/core/settlement/index.js +19 -0
- package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +22 -18
- package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
- package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
- package/build/core/settlement/petition-io.js +1 -0
- package/build/core/{petition-preview.js → settlement/petition-preview.js} +1 -1
- package/build/core/{petition.js → settlement/petition.js} +12 -10
- package/build/core/settlement/queue-read-model.js +143 -0
- package/build/core/settlement/queue-seat-allocation.js +156 -0
- package/build/core/settlement/queue.js +6 -0
- package/build/core/settlement/settlement.js +295 -0
- package/build/core/{verdict.js → settlement/verdict.js} +9 -37
- package/build/core/status/board.js +24 -23
- package/build/core/status/ledger-batch.js +158 -0
- package/build/core/status/reconciliation.js +10 -4
- package/build/core/stored-agent-event.js +3 -0
- package/build/core/task/board.js +40 -4
- package/build/core/task/commands.js +30 -21
- package/build/core/task/index.js +12 -0
- package/build/core/task/settlement-git.js +157 -65
- package/build/core/task/settlement-policy.js +54 -24
- package/build/core/task/task-contract.js +370 -0
- package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
- package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
- package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
- package/build/core/{task-git-store.js → task/task-git-store.js} +92 -29
- package/build/core/task/task-repository.js +1 -0
- package/build/core/{task-store-repository.js → task/task-store-repository.js} +5 -4
- package/build/core/task/task-store.js +1 -0
- package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
- package/build/core/task/task.js +5 -0
- package/build/core/task/tree.js +37 -0
- package/build/core/task/validation.js +5 -2
- package/build/core/transcripts.js +15 -3
- package/build/core/worktree-path.js +43 -28
- package/build/flow-error.js +85 -39
- package/build/fs/durability.js +27 -0
- package/build/fs/path-coordinate.js +16 -0
- package/build/generated/version.js +3 -2
- package/build/git/branches.js +2 -1
- package/build/git/core.js +106 -2
- package/build/git/path-coordinate.js +17 -0
- package/build/git/refs.js +57 -0
- package/build/git/streaming-batch.js +301 -0
- package/build/git/worktree.js +65 -0
- package/build/index.js +3 -3
- package/build/keiyaku.js +2 -36
- package/package.json +4 -10
- package/skills/keiyaku/SKILL.md +3 -2
- package/skills/keiyaku-akuma/SKILL.md +10 -6
- package/skills/keiyaku-task/SKILL.md +1 -1
- package/skills/keiyaku-workflow/SKILL.md +25 -4
- package/build/agents/providers/codex-sdk.js +0 -329
- package/build/cli/commands/task/view/meta.js +0 -8
- package/build/core/command-io.js +0 -174
- package/build/core/path-coordinate.js +0 -27
- package/build/core/petition-claim.js +0 -117
- package/build/core/petition-run.js +0 -83
- package/build/core/projection-coordinate.js +0 -63
- package/build/core/projection-wait.js +0 -165
- package/build/core/projection-wake.js +0 -136
- package/build/core/queue.js +0 -343
- package/build/core/task-contract.js +0 -237
- package/build/core/task.js +0 -4
- /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
- /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
- /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
- /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
- /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
|
@@ -1,185 +1,15 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
z.number(),
|
|
6
|
-
z.boolean(),
|
|
7
|
-
z.array(tomlValueSchema),
|
|
8
|
-
z.record(z.string(), tomlValueSchema),
|
|
9
|
-
]));
|
|
10
|
-
const structuredTomlValueSchema = z.record(z.string(), tomlValueSchema);
|
|
11
|
-
const executableSchema = z.string().superRefine((value, ctx) => {
|
|
12
|
-
if (value.length === 0 || /\s/.test(value) || value.includes("\"") || value.includes("'")) {
|
|
13
|
-
ctx.addIssue({
|
|
14
|
-
code: z.ZodIssueCode.custom,
|
|
15
|
-
message: "must be a single program name token with no spaces or quotes.",
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const nonblankOptionalString = z
|
|
20
|
-
.string()
|
|
21
|
-
.refine((value) => value.trim().length > 0, { message: "must not be blank." })
|
|
22
|
-
.optional();
|
|
23
|
-
const providerCommonFields = {
|
|
24
|
-
description: nonblankOptionalString,
|
|
25
|
-
};
|
|
26
|
-
const providerEnvSchema = z.record(z.string(), z.string()).optional();
|
|
27
|
-
function refinePiEnvInjection(data, ctx) {
|
|
28
|
-
if (data.env === undefined)
|
|
29
|
-
return;
|
|
30
|
-
if (Object.keys(data.env).length === 0)
|
|
31
|
-
return;
|
|
32
|
-
ctx.addIssue({
|
|
33
|
-
code: z.ZodIssueCode.custom,
|
|
34
|
-
path: ["env"],
|
|
35
|
-
message: "env injection not supported for provider pi",
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
const CODEX_SDK_FORBIDDEN_THREAD_OPTIONS_KEYS = [
|
|
39
|
-
"model",
|
|
40
|
-
"modelReasoningEffort",
|
|
41
|
-
"sandboxMode",
|
|
42
|
-
"networkAccessEnabled",
|
|
43
|
-
"webSearchMode",
|
|
44
|
-
"approvalPolicy",
|
|
45
|
-
"workingDirectory",
|
|
46
|
-
"skipGitRepoCheck",
|
|
47
|
-
];
|
|
48
|
-
const FORBIDDEN_CONFIG_KEYS = [
|
|
49
|
-
"model",
|
|
50
|
-
"model_reasoning_effort",
|
|
51
|
-
];
|
|
52
|
-
function isConfigKeyForbidden(key) {
|
|
53
|
-
return FORBIDDEN_CONFIG_KEYS.includes(key);
|
|
54
|
-
}
|
|
55
|
-
const claudeSettingSourceSchema = z.enum(CLAUDE_SETTING_SOURCES);
|
|
56
|
-
const writableRootItemSchema = z.string().superRefine((value, ctx) => {
|
|
57
|
-
if (value.length === 0) {
|
|
58
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not be empty." });
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (value.startsWith("~")) {
|
|
62
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not begin with tilde." });
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
if (value.includes("\0")) {
|
|
66
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not contain NUL byte." });
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
if (/\$[A-Za-z_]/.test(value) || /\$\{/.test(value)) {
|
|
70
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not contain environment variable references." });
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
export const providerInstanceSchema = z.discriminatedUnion("kind", [
|
|
75
|
-
z
|
|
76
|
-
.object({
|
|
77
|
-
kind: z.literal("codex-sdk"),
|
|
78
|
-
...providerCommonFields,
|
|
79
|
-
executable: executableSchema.optional(),
|
|
80
|
-
profile: z.string().optional(),
|
|
81
|
-
config: structuredTomlValueSchema.optional(),
|
|
82
|
-
threadOptions: structuredTomlValueSchema.optional(),
|
|
83
|
-
})
|
|
84
|
-
.strict()
|
|
85
|
-
.superRefine((data, ctx) => {
|
|
86
|
-
if (data.threadOptions) {
|
|
87
|
-
for (const key of CODEX_SDK_FORBIDDEN_THREAD_OPTIONS_KEYS) {
|
|
88
|
-
if (key in data.threadOptions) {
|
|
89
|
-
ctx.addIssue({
|
|
90
|
-
code: z.ZodIssueCode.custom,
|
|
91
|
-
path: ["threadOptions", key],
|
|
92
|
-
message: `"${key}" is owned by the Akuma or Keiyaku execution, not this provider instance`,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (data.config) {
|
|
98
|
-
for (const key of Object.keys(data.config)) {
|
|
99
|
-
if (isConfigKeyForbidden(key)) {
|
|
100
|
-
ctx.addIssue({
|
|
101
|
-
code: z.ZodIssueCode.custom,
|
|
102
|
-
path: ["config", key],
|
|
103
|
-
message: `"${key}" is owned by the Akuma or Keiyaku execution, not this provider instance`,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}),
|
|
109
|
-
z
|
|
110
|
-
.object({
|
|
111
|
-
kind: z.literal("codex-app-server"),
|
|
112
|
-
...providerCommonFields,
|
|
113
|
-
executable: executableSchema.optional(),
|
|
114
|
-
profile: z.string().optional(),
|
|
115
|
-
config: structuredTomlValueSchema.optional(),
|
|
116
|
-
writableRoots: z.array(writableRootItemSchema).optional(),
|
|
117
|
-
env: providerEnvSchema,
|
|
118
|
-
})
|
|
119
|
-
.strict()
|
|
120
|
-
.superRefine((data, ctx) => {
|
|
121
|
-
if (data.config) {
|
|
122
|
-
for (const key of Object.keys(data.config)) {
|
|
123
|
-
if (isConfigKeyForbidden(key)) {
|
|
124
|
-
ctx.addIssue({
|
|
125
|
-
code: z.ZodIssueCode.custom,
|
|
126
|
-
path: ["config", key],
|
|
127
|
-
message: `"${key}" is owned by the Akuma or Keiyaku execution, not this provider instance`,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}),
|
|
133
|
-
z
|
|
134
|
-
.object({
|
|
135
|
-
kind: z.literal("claude-agent-sdk"),
|
|
136
|
-
...providerCommonFields,
|
|
137
|
-
executable: executableSchema.optional(),
|
|
138
|
-
settingSources: z.array(claudeSettingSourceSchema).optional(),
|
|
139
|
-
env: providerEnvSchema,
|
|
140
|
-
})
|
|
141
|
-
.strict(),
|
|
142
|
-
z
|
|
143
|
-
.object({
|
|
144
|
-
kind: z.literal("opencode-sdk"),
|
|
145
|
-
...providerCommonFields,
|
|
146
|
-
executable: executableSchema.optional(),
|
|
147
|
-
env: providerEnvSchema,
|
|
148
|
-
})
|
|
149
|
-
.strict(),
|
|
150
|
-
z
|
|
151
|
-
.object({
|
|
152
|
-
kind: z.literal("pi"),
|
|
153
|
-
...providerCommonFields,
|
|
154
|
-
env: providerEnvSchema,
|
|
155
|
-
})
|
|
156
|
-
.strict()
|
|
157
|
-
.superRefine(refinePiEnvInjection),
|
|
158
|
-
]);
|
|
2
|
+
import { BUILTIN_PROVIDER_INSTANCE_CANDIDATES as REGISTRY_BUILTIN_PROVIDER_INSTANCE_CANDIDATES, providerInstanceSchema as registryProviderInstanceSchema, } from "../../agents/providers/registry.js";
|
|
3
|
+
export const providerInstanceSchema = registryProviderInstanceSchema;
|
|
4
|
+
export const BUILTIN_PROVIDER_INSTANCE_CANDIDATES = REGISTRY_BUILTIN_PROVIDER_INSTANCE_CANDIDATES;
|
|
159
5
|
const PROVIDER_INSTANCE_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
160
6
|
export const providerInstanceNameSchema = z
|
|
161
7
|
.string()
|
|
162
8
|
.max(64, "must contain at most 64 characters.")
|
|
163
9
|
.regex(PROVIDER_INSTANCE_NAME_PATTERN, "must match ^[a-z0-9][a-z0-9-]*$.");
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
name: "codex-app-server",
|
|
168
|
-
source: "builtin",
|
|
169
|
-
instance: { kind: "codex-app-server", executable: "codex" },
|
|
170
|
-
},
|
|
171
|
-
"claude-agent-sdk": {
|
|
172
|
-
name: "claude-agent-sdk",
|
|
173
|
-
source: "builtin",
|
|
174
|
-
instance: { kind: "claude-agent-sdk", executable: "claude", settingSources: ["project"] },
|
|
175
|
-
},
|
|
176
|
-
"opencode-sdk": {
|
|
177
|
-
name: "opencode-sdk",
|
|
178
|
-
source: "builtin",
|
|
179
|
-
instance: { kind: "opencode-sdk", executable: "opencode" },
|
|
180
|
-
},
|
|
181
|
-
pi: { name: "pi", source: "builtin", instance: { kind: "pi" } },
|
|
182
|
-
};
|
|
10
|
+
// Ensure the registry builtin map stays keyed by the closed provider vocabulary.
|
|
11
|
+
const _builtinCheck = BUILTIN_PROVIDER_INSTANCE_CANDIDATES;
|
|
12
|
+
void _builtinCheck;
|
|
183
13
|
const AGENT_NAME_PATTERN = /^[a-zA-Z0-9]+(?:[.-][a-zA-Z0-9]+)*$/;
|
|
184
14
|
export const agentNameSchema = z
|
|
185
15
|
.string()
|
package/build/core/addressing.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { FlowError } from "../flow-error.js";
|
|
3
|
+
import { errorContainsAnyPattern, NOT_GIT_REPOSITORY_PATTERNS } from "../git/core.js";
|
|
4
|
+
import { commissionSlug, formatCommissionCoordinate } from "./ids.js";
|
|
3
5
|
import { listContractIds, readLedger } from "./ledger.js";
|
|
4
6
|
import { isResponseArtifactId } from "./response-artifact-id.js";
|
|
5
|
-
import { stableRepoRoot } from "./worktree-path.js";
|
|
7
|
+
import { activeContractBoundByEngineWorktree, stableRepoRoot } from "./worktree-path.js";
|
|
8
|
+
import { assertNoRenewRecoverySession } from "./renew-session.js";
|
|
6
9
|
import { deriveContractState, isTerminalState, } from "./status/lifecycle.js";
|
|
10
|
+
const AMBIGUOUS_OBJECTIVE_MAX_CHARS = 60;
|
|
7
11
|
function normalizeAddressQuery(raw) {
|
|
8
12
|
const value = raw.startsWith("@") ? raw.slice(1) : raw;
|
|
9
13
|
if (!value.trim()) {
|
|
@@ -17,8 +21,8 @@ class AddressedFlowError extends FlowError {
|
|
|
17
21
|
constructor(error, carrier) {
|
|
18
22
|
super(error.code, error.message, {
|
|
19
23
|
cause: error,
|
|
20
|
-
hints: error.hints,
|
|
21
24
|
review: error.review,
|
|
25
|
+
facts: error.facts,
|
|
22
26
|
});
|
|
23
27
|
this.name = error.name;
|
|
24
28
|
this[ADDRESS_CARRIER] = carrier;
|
|
@@ -108,9 +112,8 @@ export class AddressResolutionError extends FlowError {
|
|
|
108
112
|
this.attempt = attempt;
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
return separator > 0 ? contractId.slice(0, separator) : contractId;
|
|
115
|
+
function candidatePlace(candidate) {
|
|
116
|
+
return candidate.bind.data.workspace === "worktree" ? candidate.bind.data.place ?? null : null;
|
|
114
117
|
}
|
|
115
118
|
async function commissionAddressCandidates(cwd) {
|
|
116
119
|
const ids = await listContractIds(cwd);
|
|
@@ -135,9 +138,9 @@ function matchCommissionAddress(query, candidates) {
|
|
|
135
138
|
const matches = [];
|
|
136
139
|
if (candidate.contractId === query)
|
|
137
140
|
matches.push({ ...candidate, spelling: "id" });
|
|
138
|
-
if (
|
|
141
|
+
if (commissionSlug(candidate.contractId) === query)
|
|
139
142
|
matches.push({ ...candidate, spelling: "slug" });
|
|
140
|
-
if (candidate.active && candidate
|
|
143
|
+
if (candidate.active && candidatePlace(candidate) === query) {
|
|
141
144
|
matches.push({ ...candidate, spelling: "place" });
|
|
142
145
|
}
|
|
143
146
|
return matches;
|
|
@@ -146,16 +149,28 @@ function matchCommissionAddress(query, candidates) {
|
|
|
146
149
|
function attemptCandidates(candidates) {
|
|
147
150
|
return candidates.map((candidate) => ({
|
|
148
151
|
commissionId: candidate.contractId,
|
|
149
|
-
place: candidate
|
|
152
|
+
place: candidatePlace(candidate),
|
|
150
153
|
name: candidate.bind.data.name,
|
|
151
154
|
objective: candidate.bind.data.objective,
|
|
152
155
|
lifecycle: candidate.lifecycle,
|
|
153
156
|
target: { branch: candidate.bind.data.target },
|
|
154
157
|
}));
|
|
155
158
|
}
|
|
156
|
-
function
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
+
function truncateObjectiveFirstLine(objective) {
|
|
160
|
+
const firstLine = objective.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
161
|
+
if (firstLine.length <= AMBIGUOUS_OBJECTIVE_MAX_CHARS)
|
|
162
|
+
return firstLine;
|
|
163
|
+
return `${firstLine.slice(0, AMBIGUOUS_OBJECTIVE_MAX_CHARS)}…`;
|
|
164
|
+
}
|
|
165
|
+
function formatAmbiguousCandidate(candidate) {
|
|
166
|
+
const coordinate = formatCommissionCoordinate({
|
|
167
|
+
commissionId: candidate.commissionId,
|
|
168
|
+
place: candidate.place,
|
|
169
|
+
});
|
|
170
|
+
const objective = truncateObjectiveFirstLine(candidate.objective);
|
|
171
|
+
return [coordinate, objective || undefined, candidate.commissionId]
|
|
172
|
+
.filter((part) => part !== undefined)
|
|
173
|
+
.join(" · ");
|
|
159
174
|
}
|
|
160
175
|
async function resolvedRepository(cwd) {
|
|
161
176
|
return { kind: "repository", stableRoot: await stableRepoRoot(cwd) };
|
|
@@ -166,7 +181,7 @@ function buildResolvedAddress(input) {
|
|
|
166
181
|
workdir: input.workdir,
|
|
167
182
|
binding: { kind: "commission", commissionId: input.candidate.contractId },
|
|
168
183
|
spelling: { asTyped: input.asTyped, source: input.source, matchedBy: input.matchedBy },
|
|
169
|
-
place: { display: input.candidate
|
|
184
|
+
place: { display: candidatePlace(input.candidate) },
|
|
170
185
|
lifecycle: input.candidate.lifecycle,
|
|
171
186
|
target: { branch: input.candidate.bind.data.target },
|
|
172
187
|
inference: input.inference,
|
|
@@ -188,8 +203,8 @@ export function buildUncommissionedRepositoryAddress(input) {
|
|
|
188
203
|
inference: input.inference,
|
|
189
204
|
});
|
|
190
205
|
}
|
|
191
|
-
export async function resolveContractAddress(cwd, raw, source = raw?.startsWith("@") ? "at-address" : "explicit-flag") {
|
|
192
|
-
const workdir = path.resolve(
|
|
206
|
+
export async function resolveContractAddress(cwd, raw, source = raw?.startsWith("@") ? "at-address" : "explicit-flag", effectiveDirectory = cwd) {
|
|
207
|
+
const workdir = path.resolve(effectiveDirectory);
|
|
193
208
|
const repo = await resolvedRepository(cwd);
|
|
194
209
|
if (raw !== undefined) {
|
|
195
210
|
const query = normalizeAddressQuery(raw);
|
|
@@ -216,7 +231,7 @@ export async function resolveContractAddress(cwd, raw, source = raw?.startsWith(
|
|
|
216
231
|
candidates: matches.map((candidate) => ({
|
|
217
232
|
commissionId: candidate.contractId,
|
|
218
233
|
matchedBy: candidate.spelling,
|
|
219
|
-
place: candidate
|
|
234
|
+
place: candidatePlace(candidate),
|
|
220
235
|
name: candidate.bind.data.name,
|
|
221
236
|
objective: candidate.bind.data.objective,
|
|
222
237
|
lifecycle: candidate.lifecycle,
|
|
@@ -238,9 +253,34 @@ export async function resolveContractAddress(cwd, raw, source = raw?.startsWith(
|
|
|
238
253
|
if (matches.length === 0) {
|
|
239
254
|
throw new AddressResolutionError("EMPTY_PARAM", `unknown contract address @${query}`, attempt);
|
|
240
255
|
}
|
|
241
|
-
throw new AddressResolutionError("CONTRACT_AMBIGUOUS",
|
|
256
|
+
throw new AddressResolutionError("CONTRACT_AMBIGUOUS", `@${query} is ambiguous:\n${attempt.candidates.map((candidate) => ` ${formatAmbiguousCandidate(candidate)}`).join("\n")}\nuse a full @commission-id`, attempt);
|
|
242
257
|
}
|
|
243
258
|
const candidates = await commissionAddressCandidates(repo.stableRoot);
|
|
259
|
+
let boundContractId;
|
|
260
|
+
try {
|
|
261
|
+
const effectiveRepo = await stableRepoRoot(workdir);
|
|
262
|
+
if (effectiveRepo === repo.stableRoot) {
|
|
263
|
+
boundContractId = await activeContractBoundByEngineWorktree(workdir);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
if (!errorContainsAnyPattern(error, NOT_GIT_REPOSITORY_PATTERNS))
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
if (boundContractId) {
|
|
271
|
+
const candidate = candidates.find((item) => item.active && item.contractId === boundContractId);
|
|
272
|
+
if (candidate) {
|
|
273
|
+
return buildResolvedAddress({
|
|
274
|
+
repo,
|
|
275
|
+
workdir,
|
|
276
|
+
candidate,
|
|
277
|
+
matchedBy: "id",
|
|
278
|
+
asTyped: `@${candidate.contractId}`,
|
|
279
|
+
source: "worktree-binding",
|
|
280
|
+
inference: ["verified active engine worktree binding"],
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
244
284
|
const operable = candidates.filter((candidate) => candidate.active);
|
|
245
285
|
const attempt = {
|
|
246
286
|
repo,
|
|
@@ -265,3 +305,13 @@ export async function resolveContractAddress(cwd, raw, source = raw?.startsWith(
|
|
|
265
305
|
? "no active commission found; pass @place, @slug, full @commission-id, or --contract <addr>"
|
|
266
306
|
: "multiple active commissions found; pass @place, @slug, full @commission-id, or --contract <addr>", attempt);
|
|
267
307
|
}
|
|
308
|
+
export async function resolveExistingContractAddress(cwd, raw, source = raw?.startsWith("@") ? "at-address" : "explicit-flag", effectiveDirectory = cwd) {
|
|
309
|
+
const address = await resolveContractAddress(cwd, raw, source, effectiveDirectory);
|
|
310
|
+
try {
|
|
311
|
+
await assertNoRenewRecoverySession(address.repo.stableRoot, address.binding.commissionId);
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
throw attachAddressCarrier(error, address);
|
|
315
|
+
}
|
|
316
|
+
return address;
|
|
317
|
+
}
|
package/build/core/amend.js
CHANGED
|
@@ -1,15 +1,137 @@
|
|
|
1
|
-
import * as fs from "node:fs/promises";
|
|
2
|
-
import * as path from "node:path";
|
|
3
1
|
import { FlowError } from "../flow-error.js";
|
|
4
2
|
import { getCurrentBranch, requireGitRepository } from "../git/branches.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { renderContractView } from "./contract-view.js";
|
|
3
|
+
import { activeLedgerRef, appendWithRetry } from "./ledger.js";
|
|
4
|
+
import { refreshContractView } from "./contract-view.js";
|
|
8
5
|
import { deriveContractState, isTerminalState } from "./status/lifecycle.js";
|
|
9
6
|
import { resolveContractAddress, withResolvedAddress } from "./addressing.js";
|
|
10
7
|
import { resolveDefaultBranch } from "./status/drift.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
8
|
+
import { isBlankScopePatternLine, normalizeScopePattern, ScopePatternError } from "./scope.js";
|
|
9
|
+
import { normalizeSectionTitle } from "./markdown/titles.js";
|
|
10
|
+
import { resolveContractDeliveryCwd } from "./worktree-path.js";
|
|
11
|
+
function amendScopeHeading(name) {
|
|
12
|
+
return `## Scope ${name[0].toUpperCase()}${name.slice(1)}`;
|
|
13
|
+
}
|
|
14
|
+
function sourceLines(markdown) {
|
|
15
|
+
const lines = [];
|
|
16
|
+
let start = 0;
|
|
17
|
+
while (start < markdown.length) {
|
|
18
|
+
const newline = markdown.indexOf("\n", start);
|
|
19
|
+
const end = newline === -1 ? markdown.length : newline;
|
|
20
|
+
const next = newline === -1 ? markdown.length : newline + 1;
|
|
21
|
+
const raw = markdown.slice(start, end);
|
|
22
|
+
lines.push({ text: raw.endsWith("\r") ? raw.slice(0, -1) : raw, start, end, next });
|
|
23
|
+
start = next;
|
|
24
|
+
}
|
|
25
|
+
return lines;
|
|
26
|
+
}
|
|
27
|
+
function amendHeading(line) {
|
|
28
|
+
const match = line.match(/^ {0,3}(#{1,2})(?!#)[ \t]+(.+)$/);
|
|
29
|
+
if (!match)
|
|
30
|
+
return null;
|
|
31
|
+
const level = match[1].length;
|
|
32
|
+
const title = normalizeSectionTitle(match[2]);
|
|
33
|
+
if (level !== 2)
|
|
34
|
+
return { level };
|
|
35
|
+
if (title === "scope add")
|
|
36
|
+
return { level, name: "add" };
|
|
37
|
+
return { level };
|
|
38
|
+
}
|
|
39
|
+
function amendFence(line) {
|
|
40
|
+
const match = line.match(/^ {0,3}(`{3,}|~{3,})/);
|
|
41
|
+
if (!match)
|
|
42
|
+
return null;
|
|
43
|
+
const marker = match[1];
|
|
44
|
+
return { delimiter: marker[0], length: marker.length };
|
|
45
|
+
}
|
|
46
|
+
function parseAmendScopeSections(markdown) {
|
|
47
|
+
const lines = sourceLines(markdown);
|
|
48
|
+
const sections = {};
|
|
49
|
+
let active;
|
|
50
|
+
let fence;
|
|
51
|
+
let frontMatterEnd = -1;
|
|
52
|
+
if (lines[0]?.text.trim() === "---") {
|
|
53
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
54
|
+
if (lines[index].text.trim() === "---") {
|
|
55
|
+
frontMatterEnd = index;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const finishActive = (end) => {
|
|
61
|
+
if (!active)
|
|
62
|
+
return;
|
|
63
|
+
sections[active.name] = { ...active, end };
|
|
64
|
+
active = undefined;
|
|
65
|
+
};
|
|
66
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
67
|
+
const line = lines[index];
|
|
68
|
+
if (index <= frontMatterEnd)
|
|
69
|
+
continue;
|
|
70
|
+
const marker = amendFence(line.text);
|
|
71
|
+
if (fence) {
|
|
72
|
+
if (marker && marker.delimiter === fence.delimiter && marker.length >= fence.length) {
|
|
73
|
+
fence = undefined;
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (marker) {
|
|
78
|
+
fence = marker;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const heading = amendHeading(line.text);
|
|
82
|
+
if (!heading)
|
|
83
|
+
continue;
|
|
84
|
+
finishActive(line.start);
|
|
85
|
+
if (!heading.name)
|
|
86
|
+
continue;
|
|
87
|
+
if (sections[heading.name]) {
|
|
88
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", `amend input may contain ${amendScopeHeading(heading.name)} at most once`);
|
|
89
|
+
}
|
|
90
|
+
active = { name: heading.name, start: line.start, contentStart: line.next };
|
|
91
|
+
}
|
|
92
|
+
finishActive(markdown.length);
|
|
93
|
+
let prose = markdown;
|
|
94
|
+
for (const section of Object.values(sections).sort((left, right) => right.start - left.start)) {
|
|
95
|
+
prose = `${prose.slice(0, section.start)}${prose.slice(section.end)}`;
|
|
96
|
+
}
|
|
97
|
+
return { sections, prose };
|
|
98
|
+
}
|
|
99
|
+
function scopePatterns(markdown, section) {
|
|
100
|
+
const patterns = markdown
|
|
101
|
+
.slice(section.contentStart, section.end)
|
|
102
|
+
.split(/\r?\n/)
|
|
103
|
+
.filter((line) => !isBlankScopePatternLine(line))
|
|
104
|
+
.map((pattern) => {
|
|
105
|
+
try {
|
|
106
|
+
// Do not trim() here: gitignore treats trailing `\ ` as a significant space.
|
|
107
|
+
return normalizeScopePattern(pattern);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (error instanceof ScopePatternError) {
|
|
111
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", error.message);
|
|
112
|
+
}
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
if (patterns.length === 0) {
|
|
117
|
+
throw new FlowError("INVALID_KEIYAKU_DRAFT", `amend input has an empty ${amendScopeHeading(section.name)} section`);
|
|
118
|
+
}
|
|
119
|
+
return patterns;
|
|
120
|
+
}
|
|
121
|
+
export function buildAmendInput(markdown, cwd, contractId, contractAddressSource) {
|
|
122
|
+
const { sections, prose } = parseAmendScopeSections(markdown);
|
|
123
|
+
const add = sections.add ? scopePatterns(markdown, sections.add) : [];
|
|
124
|
+
if (!prose.trim()) {
|
|
125
|
+
throw new FlowError("EMPTY_PARAM", "amendment cannot be empty");
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
cwd,
|
|
129
|
+
...(contractId ? { contractId } : {}),
|
|
130
|
+
...(contractAddressSource ? { contractAddressSource } : {}),
|
|
131
|
+
amendment: prose,
|
|
132
|
+
...(sections.add ? { scopeDelta: { add } } : {}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
13
135
|
function requireAmendment(value) {
|
|
14
136
|
if (!value.trim())
|
|
15
137
|
throw new FlowError("EMPTY_PARAM", "amendment cannot be empty");
|
|
@@ -24,13 +146,6 @@ function assertContractOperable(contractId, entries) {
|
|
|
24
146
|
throw new FlowError("INTERNAL_STATE", `contract ${contractId} is terminal (${state.state})`);
|
|
25
147
|
}
|
|
26
148
|
}
|
|
27
|
-
async function renderUpdatedContract(cwd, contractId) {
|
|
28
|
-
const ledger = await readLedger(cwd, contractId);
|
|
29
|
-
if (!ledger) {
|
|
30
|
-
throw new FlowError("INTERNAL_STATE", `contract ${contractId} active ledger disappeared before render`);
|
|
31
|
-
}
|
|
32
|
-
await fs.writeFile(path.join(cwd, KEIYAKU_FILE), renderContractView({ id: contractId, entries: ledger.entries }), "utf8");
|
|
33
|
-
}
|
|
34
149
|
function normalizeScopeDelta(scopeDelta) {
|
|
35
150
|
if (!scopeDelta)
|
|
36
151
|
return undefined;
|
|
@@ -43,6 +158,7 @@ function normalizeScopeDelta(scopeDelta) {
|
|
|
43
158
|
export async function amendContract(input) {
|
|
44
159
|
const amendment = requireAmendment(input.amendment);
|
|
45
160
|
const scopeDelta = normalizeScopeDelta(input.scopeDelta);
|
|
161
|
+
const renderCwd = input.renderCwd ?? input.cwd;
|
|
46
162
|
const at = new Date(input.nowMs).toISOString();
|
|
47
163
|
const ref = activeLedgerRef(input.contractId);
|
|
48
164
|
let amendmentNumber = 0;
|
|
@@ -67,20 +183,21 @@ export async function amendContract(input) {
|
|
|
67
183
|
if (amendmentNumber === 0) {
|
|
68
184
|
throw new FlowError("INTERNAL_STATE", `contract ${input.contractId} active ledger disappeared during amend`);
|
|
69
185
|
}
|
|
70
|
-
await
|
|
186
|
+
await refreshContractView({ ledgerCwd: input.cwd, renderCwd, contractId: input.contractId });
|
|
71
187
|
return { contractId: input.contractId, amendmentNumber, ledgerHead: result.head };
|
|
72
188
|
}
|
|
73
189
|
export async function amendKeiyaku(input) {
|
|
74
190
|
await requireGitRepository(input.cwd, "amend");
|
|
75
|
-
const address = await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
|
|
191
|
+
const address = input.address ?? await resolveContractAddress(input.cwd, input.contractId, input.contractAddressSource);
|
|
76
192
|
return await withResolvedAddress(address, async () => {
|
|
77
193
|
const contractId = address.binding.commissionId;
|
|
78
|
-
await
|
|
194
|
+
const renderCwd = await resolveContractDeliveryCwd(input.cwd, contractId);
|
|
79
195
|
const amendment = requireAmendment(input.amendment);
|
|
80
|
-
const currentBranch = await getCurrentBranch(
|
|
196
|
+
const currentBranch = await getCurrentBranch(renderCwd);
|
|
81
197
|
const baseBranch = (await resolveDefaultBranch(input.cwd))?.branch ?? currentBranch;
|
|
82
198
|
const amended = await amendContract({
|
|
83
199
|
cwd: input.cwd,
|
|
200
|
+
renderCwd,
|
|
84
201
|
contractId,
|
|
85
202
|
actor: "keiyaku",
|
|
86
203
|
nowMs: Date.now(),
|