@astrosheep/keiyaku 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -56
- package/build/.tsbuildinfo +1 -1
- package/build/agents/call-terms_v2.js +103 -0
- package/build/agents/harness/activity-values.js +54 -0
- package/build/agents/harness/event-channel.js +55 -20
- package/build/agents/harness/events.js +47 -1
- package/build/agents/harness/execution-handle.js +292 -61
- package/build/agents/harness/index.js +103 -121
- package/build/agents/harness/pump.js +36 -47
- package/build/agents/harness/runtime.js +3 -0
- package/build/agents/launch-snapshot_v2.js +348 -0
- package/build/agents/opencode-sdk.js +42 -169
- package/build/agents/providers/claude-agent-sdk.js +240 -79
- package/build/agents/providers/codex-app-server.js +280 -72
- package/build/agents/providers/codex-sdk.js +159 -41
- package/build/agents/providers/event-type-tail.js +16 -0
- package/build/agents/providers/opencode-sdk.js +165 -59
- package/build/agents/providers/pi.js +254 -42
- package/build/agents/selector_v2.js +122 -0
- package/build/cli/commands/akuma.js +120 -42
- package/build/cli/completion.js +6 -7
- package/build/cli/flags.js +36 -10
- package/build/cli/help.js +42 -26
- package/build/cli/index.js +225 -93
- package/build/cli/parse.js +194 -75
- package/build/cli/projection-address.js +11 -0
- package/build/cli/render/address.js +88 -0
- package/build/cli/render/arc.js +10 -10
- package/build/cli/render/call.js +59 -0
- package/build/cli/render/compact-text.js +3 -0
- package/build/cli/render/errors.js +4 -2
- package/build/cli/render/format.js +6 -0
- package/build/cli/render/line-width.js +70 -0
- package/build/cli/render/misc.js +7 -4
- package/build/cli/render/petition.js +4 -3
- package/build/cli/render/projection-activity.js +201 -0
- package/build/cli/render/shared.js +46 -12
- package/build/cli/render/status.js +59 -10
- package/build/cli/render/tool-ledger-rollup.js +74 -0
- package/build/cli/render/tool-presentation.js +97 -0
- package/build/cli/render/wait.js +229 -0
- package/build/cli/skills-install.js +42 -24
- package/build/cli/subagent-guard.js +1 -1
- package/build/config/akuma-loader_v2.js +222 -0
- package/build/config/env-keys.js +0 -4
- package/build/config/env.js +0 -6
- package/build/config/settings.js +325 -12
- package/build/core/addressing.js +224 -0
- package/build/core/amend.js +30 -47
- package/build/core/arc.js +68 -60
- package/build/core/bind.js +105 -25
- package/build/core/call-persist.js +69 -0
- package/build/core/call.js +658 -0
- package/build/core/claim.js +72 -44
- package/build/core/command-io.js +19 -19
- package/build/core/context.js +11 -36
- package/build/core/draft.js +2 -3
- package/build/core/entry.js +101 -6
- package/build/core/execution-coordinate.js +62 -0
- package/build/core/execution-pact.js +141 -0
- package/build/core/forfeit.js +2 -3
- package/build/core/hints.js +10 -10
- package/build/core/ids.js +6 -0
- package/build/core/ledger.js +16 -1
- package/build/core/petition-claim-gates.js +14 -12
- package/build/core/petition-claim.js +1 -0
- package/build/core/petition-run.js +6 -2
- package/build/core/petition.js +63 -21
- package/build/core/places.js +106 -13
- package/build/core/projection/generation.js +412 -0
- package/build/core/projection/heart.js +316 -0
- package/build/core/projection/identity.js +81 -0
- package/build/core/projection/leash.js +87 -0
- package/build/core/projection/mint.js +154 -0
- package/build/core/projection-activity.js +219 -0
- package/build/core/projection-coordinate.js +35 -0
- package/build/core/projection-core.js +69 -463
- package/build/core/projection-generation-continuation.js +31 -0
- package/build/core/projection-generation-execution.js +148 -0
- package/build/core/projection-generation-identity.js +17 -0
- package/build/core/projection-generation-launcher.js +90 -0
- package/build/core/projection-generation-process.js +43 -0
- package/build/core/projection-generation-runner.js +144 -0
- package/build/core/projection-generation-runtime.js +15 -0
- package/build/core/projection-generation-store.js +707 -0
- package/build/core/projection-identity.js +11 -0
- package/build/core/projection-life-observer.js +87 -0
- package/build/core/projection-life-protocol.js +95 -0
- package/build/core/projection-mint.js +96 -24
- package/build/core/projection-runner-lock.js +230 -0
- package/build/core/projection-status.js +207 -107
- package/build/core/projection-tells.js +401 -0
- package/build/core/projection-wait.js +155 -0
- package/build/core/projection-wake.js +109 -231
- package/build/core/queue_v2.js +342 -0
- package/build/core/registry.js +6 -3
- package/build/core/render.js +63 -1
- package/build/core/renew.js +80 -53
- package/build/core/scope.js +186 -137
- package/build/core/seal.js +16 -19
- package/build/core/status.js +88 -25
- package/build/core/stored-agent-event.js +101 -0
- package/build/core/transcripts.js +214 -228
- package/build/core/verdict.js +27 -15
- package/build/core/worktree-bootstrap.js +187 -0
- package/build/core/worktree-path.js +72 -18
- package/build/flow-error.js +4 -6
- package/build/generated/version.js +1 -1
- package/build/git/branches.js +6 -1
- package/build/index.js +8 -5
- package/build/keiyaku.js +1 -3
- package/package.json +6 -5
- package/skills/keiyaku/SKILL.md +6 -47
- package/skills/keiyaku-akuma/SKILL.md +75 -0
- package/build/agents/effective-policy.js +0 -32
- package/build/agents/index.js +0 -114
- package/build/agents/selector.js +0 -28
- package/build/cli/render/summon.js +0 -17
- package/build/cli/render/tell.js +0 -11
- package/build/config/akuma-loader.js +0 -268
- package/build/core/queue.js +0 -73
- package/build/core/summon-persist.js +0 -73
- package/build/core/summon.js +0 -377
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { parseToAST } from "../core/markdown/parser.js";
|
|
5
|
+
import { isGitRepo } from "../git/branches.js";
|
|
6
|
+
import { BUILTIN_AGENT_PROFILES } from "../keiyaku.js";
|
|
7
|
+
import { getKeiyakuHome } from "./env.js";
|
|
8
|
+
import { agentNameSchema, providerInstanceNameSchema } from "./settings.js";
|
|
9
|
+
const nonblankString = z.string().refine((value) => value.trim().length > 0, { message: "must not be blank" });
|
|
10
|
+
const effortOptionsSchema = z.array(nonblankString).superRefine((values, ctx) => {
|
|
11
|
+
if (new Set(values).size !== values.length) {
|
|
12
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must not contain duplicate values" });
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
const profileSchema = z
|
|
16
|
+
.object({
|
|
17
|
+
provider: providerInstanceNameSchema,
|
|
18
|
+
description: nonblankString.optional(),
|
|
19
|
+
model: nonblankString.optional(),
|
|
20
|
+
effort: nonblankString.optional(),
|
|
21
|
+
effortOptions: effortOptionsSchema.optional(),
|
|
22
|
+
access: z.enum(["read", "write", "auto"]).optional(),
|
|
23
|
+
network: z.enum(["disabled", "enabled"]).optional(),
|
|
24
|
+
webSearch: z.enum(["disabled", "cached", "live"]).optional(),
|
|
25
|
+
})
|
|
26
|
+
.strict();
|
|
27
|
+
function formatIssues(error) {
|
|
28
|
+
return error.issues.map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`).join("; ");
|
|
29
|
+
}
|
|
30
|
+
function stripFrontMatterQuote(rawValue) {
|
|
31
|
+
const value = rawValue.trim();
|
|
32
|
+
if (value.length < 2)
|
|
33
|
+
return value;
|
|
34
|
+
const quote = value[0];
|
|
35
|
+
return (quote === "'" || quote === '"') && value.at(-1) === quote ? value.slice(1, -1) : value;
|
|
36
|
+
}
|
|
37
|
+
function splitFrontMatter(content) {
|
|
38
|
+
const ast = parseToAST(content, { allowSections: false });
|
|
39
|
+
if (ast.frontmatter === undefined) {
|
|
40
|
+
throw new Error("missing leading YAML frontmatter");
|
|
41
|
+
}
|
|
42
|
+
const lines = content.split(/\r?\n/);
|
|
43
|
+
let closingIndex = -1;
|
|
44
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
45
|
+
if ((lines[index] ?? "").trim() === "---") {
|
|
46
|
+
closingIndex = index;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (closingIndex === -1)
|
|
51
|
+
throw new Error("frontmatter is not closed");
|
|
52
|
+
const entries = [];
|
|
53
|
+
for (let index = 1; index < closingIndex; index += 1) {
|
|
54
|
+
const line = lines[index] ?? "";
|
|
55
|
+
const match = line.trim().match(/^([A-Za-z0-9_.-]+)\s*:\s*(.*)$/);
|
|
56
|
+
if (!match)
|
|
57
|
+
continue;
|
|
58
|
+
const key = match[1] ?? "";
|
|
59
|
+
const value = match[2] ?? "";
|
|
60
|
+
if (key === "effortOptions" && value.trim() === "") {
|
|
61
|
+
const options = [];
|
|
62
|
+
while (index + 1 < closingIndex) {
|
|
63
|
+
const item = lines[index + 1] ?? "";
|
|
64
|
+
if (item.trim().match(/^([A-Za-z0-9_.-]+)\s*:/))
|
|
65
|
+
break;
|
|
66
|
+
const itemMatch = item.match(/^\s*-\s*(.*)$/);
|
|
67
|
+
if (!itemMatch)
|
|
68
|
+
break;
|
|
69
|
+
options.push(stripFrontMatterQuote(itemMatch[1] ?? ""));
|
|
70
|
+
index += 1;
|
|
71
|
+
}
|
|
72
|
+
entries.push([key, options]);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
entries.push([key, stripFrontMatterQuote(value)]);
|
|
76
|
+
}
|
|
77
|
+
return { entries, body: lines.slice(closingIndex + 1).join("\n") };
|
|
78
|
+
}
|
|
79
|
+
function freezeProfile(profile) {
|
|
80
|
+
if (profile.effortOptions === undefined)
|
|
81
|
+
return Object.freeze({ ...profile });
|
|
82
|
+
return Object.freeze({
|
|
83
|
+
...profile,
|
|
84
|
+
effortOptions: Object.freeze([...profile.effortOptions]),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function freezeCandidate(candidate) {
|
|
88
|
+
if ("reason" in candidate && candidate.reason !== undefined) {
|
|
89
|
+
return Object.freeze({ ...candidate });
|
|
90
|
+
}
|
|
91
|
+
return Object.freeze({
|
|
92
|
+
...candidate,
|
|
93
|
+
profile: freezeProfile(candidate.profile),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function decodeProfile(entries) {
|
|
97
|
+
const raw = {};
|
|
98
|
+
for (const [key, value] of entries) {
|
|
99
|
+
if (key === "effortOptions") {
|
|
100
|
+
raw[key] = value;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (typeof value !== "string")
|
|
104
|
+
throw new Error(`${key} must be a scalar value`);
|
|
105
|
+
raw[key] = value;
|
|
106
|
+
}
|
|
107
|
+
const parsed = profileSchema.safeParse(raw);
|
|
108
|
+
if (!parsed.success)
|
|
109
|
+
throw new Error(formatIssues(parsed.error));
|
|
110
|
+
if (parsed.data.effort !== undefined && parsed.data.effortOptions !== undefined && !parsed.data.effortOptions.includes(parsed.data.effort)) {
|
|
111
|
+
throw new Error("effort must be an exact member of effortOptions");
|
|
112
|
+
}
|
|
113
|
+
return freezeProfile(parsed.data);
|
|
114
|
+
}
|
|
115
|
+
async function readLayer(directory, source) {
|
|
116
|
+
let entries;
|
|
117
|
+
try {
|
|
118
|
+
entries = await fs.readdir(directory, { withFileTypes: true });
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
if (error.code === "ENOENT")
|
|
122
|
+
return { candidates: [] };
|
|
123
|
+
return {
|
|
124
|
+
candidates: [],
|
|
125
|
+
directoryFailure: {
|
|
126
|
+
path: directory,
|
|
127
|
+
reason: `unable to read akuma directory (${error instanceof Error ? error.message : String(error)})`,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const candidates = [];
|
|
132
|
+
for (const entry of entries.filter((candidate) => candidate.isFile() && candidate.name.endsWith(".md")).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
133
|
+
const file = path.join(directory, entry.name);
|
|
134
|
+
const name = path.basename(entry.name, ".md");
|
|
135
|
+
const nameResult = agentNameSchema.safeParse(name);
|
|
136
|
+
if (!nameResult.success) {
|
|
137
|
+
candidates.push(freezeCandidate({
|
|
138
|
+
name,
|
|
139
|
+
source,
|
|
140
|
+
path: file,
|
|
141
|
+
reason: `invalid akuma name: ${formatIssues(nameResult.error)}`,
|
|
142
|
+
}));
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const content = await fs.readFile(file, "utf-8");
|
|
147
|
+
const { entries: frontmatter, body } = splitFrontMatter(content);
|
|
148
|
+
candidates.push(freezeCandidate({
|
|
149
|
+
name,
|
|
150
|
+
source,
|
|
151
|
+
path: file,
|
|
152
|
+
body,
|
|
153
|
+
profile: decodeProfile(frontmatter),
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
candidates.push(freezeCandidate({
|
|
158
|
+
name,
|
|
159
|
+
source,
|
|
160
|
+
path: file,
|
|
161
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return { candidates };
|
|
166
|
+
}
|
|
167
|
+
function foldLayer(selected, shadows, allCandidates, source, layer) {
|
|
168
|
+
if (layer.directoryFailure !== undefined) {
|
|
169
|
+
allCandidates.push(freezeCandidate({
|
|
170
|
+
name: `${source}-akuma-directory`,
|
|
171
|
+
source,
|
|
172
|
+
path: layer.directoryFailure.path,
|
|
173
|
+
reason: layer.directoryFailure.reason,
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
for (const candidate of layer.candidates) {
|
|
177
|
+
allCandidates.push(candidate);
|
|
178
|
+
const prior = selected[candidate.name];
|
|
179
|
+
if (prior !== undefined) {
|
|
180
|
+
shadows.push(Object.freeze({
|
|
181
|
+
name: prior.name,
|
|
182
|
+
source: prior.source,
|
|
183
|
+
path: prior.path,
|
|
184
|
+
shadowedBy: candidate.source,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
selected[candidate.name] = candidate;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
export async function loadAkumaCatalogV2(cwd) {
|
|
191
|
+
const candidates = [];
|
|
192
|
+
const selected = {};
|
|
193
|
+
const shadows = [];
|
|
194
|
+
for (const [name, profile] of Object.entries(BUILTIN_AGENT_PROFILES)) {
|
|
195
|
+
const candidate = freezeCandidate({
|
|
196
|
+
name,
|
|
197
|
+
source: "builtin",
|
|
198
|
+
path: null,
|
|
199
|
+
body: "",
|
|
200
|
+
profile: freezeProfile({
|
|
201
|
+
provider: profile.provider,
|
|
202
|
+
...(profile.description !== undefined ? { description: profile.description } : {}),
|
|
203
|
+
...("model" in profile && profile.model !== undefined ? { model: profile.model } : {}),
|
|
204
|
+
...("effort" in profile && profile.effort !== undefined ? { effort: profile.effort } : {}),
|
|
205
|
+
...("effortOptions" in profile && profile.effortOptions !== undefined
|
|
206
|
+
? { effortOptions: Object.freeze([...profile.effortOptions]) }
|
|
207
|
+
: {}),
|
|
208
|
+
}),
|
|
209
|
+
});
|
|
210
|
+
candidates.push(candidate);
|
|
211
|
+
selected[name] = candidate;
|
|
212
|
+
}
|
|
213
|
+
foldLayer(selected, shadows, candidates, "user", await readLayer(path.join(getKeiyakuHome(), "akuma"), "user"));
|
|
214
|
+
if (await isGitRepo(cwd)) {
|
|
215
|
+
foldLayer(selected, shadows, candidates, "project", await readLayer(path.join(cwd, ".keiyaku", "akuma"), "project"));
|
|
216
|
+
}
|
|
217
|
+
return Object.freeze({
|
|
218
|
+
candidates: Object.freeze(candidates),
|
|
219
|
+
selected: Object.freeze(selected),
|
|
220
|
+
shadows: Object.freeze(shadows),
|
|
221
|
+
});
|
|
222
|
+
}
|
package/build/config/env-keys.js
CHANGED
|
@@ -9,9 +9,7 @@ export const DISABLE_SUBAGENT_SPAWN_ENV_KEY = "KEIYAKU_DISABLE_SUBAGENT_SPAWN";
|
|
|
9
9
|
export const ENV_KEYS = {
|
|
10
10
|
AGENT_OVERRIDE: "KEIYAKU_AGENT_OVERRIDE",
|
|
11
11
|
DISABLE_SUBAGENT_SPAWN: DISABLE_SUBAGENT_SPAWN_ENV_KEY,
|
|
12
|
-
SUBAGENT_EXEC_TIMEOUT_MS: "KEIYAKU_SUBAGENT_EXEC_TIMEOUT_MS",
|
|
13
12
|
SUBAGENT_EXEC_IDLE_TIMEOUT_MS: "KEIYAKU_SUBAGENT_EXEC_IDLE_TIMEOUT_MS",
|
|
14
|
-
SUBAGENT_PROGRESS_INTERVAL_MIN: "KEIYAKU_SUBAGENT_PROGRESS_INTERVAL_MIN",
|
|
15
13
|
CODEX_EXEC_MAX_CAPTURE_CHARS: "KEIYAKU_CODEX_EXEC_MAX_CAPTURE_CHARS",
|
|
16
14
|
CLAUDE_EXEC_MAX_CAPTURE_CHARS: "KEIYAKU_CLAUDE_EXEC_MAX_CAPTURE_CHARS",
|
|
17
15
|
OPENCODE_EXEC_MAX_CAPTURE_CHARS: "KEIYAKU_OPENCODE_EXEC_MAX_CAPTURE_CHARS",
|
|
@@ -27,9 +25,7 @@ export const ENV_KEYS = {
|
|
|
27
25
|
const ENV_KEY_ENTRIES = [
|
|
28
26
|
{ key: ENV_KEYS.AGENT_OVERRIDE, defaultValue: "", description: "Override default agent name", category: "subagent" },
|
|
29
27
|
{ key: ENV_KEYS.DISABLE_SUBAGENT_SPAWN, defaultValue: "0", description: "Disable subprocess subagent spawning when set to 1", category: "subagent" },
|
|
30
|
-
{ key: ENV_KEYS.SUBAGENT_EXEC_TIMEOUT_MS, defaultValue: "2700000", description: "Subagent execution timeout in milliseconds", category: "subagent" },
|
|
31
28
|
{ key: ENV_KEYS.SUBAGENT_EXEC_IDLE_TIMEOUT_MS, defaultValue: "600000", description: "Subagent idle timeout in milliseconds", category: "subagent" },
|
|
32
|
-
{ key: ENV_KEYS.SUBAGENT_PROGRESS_INTERVAL_MIN, defaultValue: "0", description: "Print subagent tool/activity summaries every N minutes when greater than 0", category: "subagent" },
|
|
33
29
|
{ key: ENV_KEYS.CODEX_EXEC_MAX_CAPTURE_CHARS, defaultValue: "200000", description: "Codex runtime output/diagnostics capture cap", category: "subagent" },
|
|
34
30
|
{ key: ENV_KEYS.CLAUDE_EXEC_MAX_CAPTURE_CHARS, defaultValue: "200000", description: "Claude runtime output/diagnostics capture cap", category: "subagent" },
|
|
35
31
|
{ key: ENV_KEYS.OPENCODE_EXEC_MAX_CAPTURE_CHARS, defaultValue: "200000", description: "OpenCode runtime output/diagnostics capture cap", category: "subagent" },
|
package/build/config/env.js
CHANGED
|
@@ -138,9 +138,7 @@ function booleanFlagEnv(key) {
|
|
|
138
138
|
const subagentSchema = z.object({
|
|
139
139
|
nameOverride: z.string().default(getEnvDefaultValue(ENV_KEYS.AGENT_OVERRIDE)).transform((value) => value.trim()),
|
|
140
140
|
disableSpawn: booleanFlagEnv(ENV_KEYS.DISABLE_SUBAGENT_SPAWN),
|
|
141
|
-
execTimeoutMs: positiveIntEnv(ENV_KEYS.SUBAGENT_EXEC_TIMEOUT_MS),
|
|
142
141
|
execIdleTimeoutMs: positiveIntEnv(ENV_KEYS.SUBAGENT_EXEC_IDLE_TIMEOUT_MS),
|
|
143
|
-
progressIntervalMin: nonNegativeIntEnv(ENV_KEYS.SUBAGENT_PROGRESS_INTERVAL_MIN),
|
|
144
142
|
});
|
|
145
143
|
const codexSchema = z.object({
|
|
146
144
|
execMaxCaptureChars: positiveIntEnv(ENV_KEYS.CODEX_EXEC_MAX_CAPTURE_CHARS),
|
|
@@ -174,9 +172,7 @@ const envSchema = z
|
|
|
174
172
|
.object({
|
|
175
173
|
[ENV_KEYS.AGENT_OVERRIDE]: z.string().optional(),
|
|
176
174
|
[ENV_KEYS.DISABLE_SUBAGENT_SPAWN]: z.string().optional(),
|
|
177
|
-
[ENV_KEYS.SUBAGENT_EXEC_TIMEOUT_MS]: z.string().optional(),
|
|
178
175
|
[ENV_KEYS.SUBAGENT_EXEC_IDLE_TIMEOUT_MS]: z.string().optional(),
|
|
179
|
-
[ENV_KEYS.SUBAGENT_PROGRESS_INTERVAL_MIN]: z.string().optional(),
|
|
180
176
|
[ENV_KEYS.CODEX_EXEC_MAX_CAPTURE_CHARS]: z.string().optional(),
|
|
181
177
|
[ENV_KEYS.CLAUDE_EXEC_MAX_CAPTURE_CHARS]: z.string().optional(),
|
|
182
178
|
[ENV_KEYS.OPENCODE_EXEC_MAX_CAPTURE_CHARS]: z.string().optional(),
|
|
@@ -196,9 +192,7 @@ const envSchema = z
|
|
|
196
192
|
subagent: subagentSchema.parse({
|
|
197
193
|
nameOverride: rawEnv[ENV_KEYS.AGENT_OVERRIDE],
|
|
198
194
|
disableSpawn: rawEnv[ENV_KEYS.DISABLE_SUBAGENT_SPAWN],
|
|
199
|
-
execTimeoutMs: rawEnv[ENV_KEYS.SUBAGENT_EXEC_TIMEOUT_MS],
|
|
200
195
|
execIdleTimeoutMs: rawEnv[ENV_KEYS.SUBAGENT_EXEC_IDLE_TIMEOUT_MS],
|
|
201
|
-
progressIntervalMin: rawEnv[ENV_KEYS.SUBAGENT_PROGRESS_INTERVAL_MIN],
|
|
202
196
|
}),
|
|
203
197
|
codex: codexSchema.parse({
|
|
204
198
|
execMaxCaptureChars: rawEnv[ENV_KEYS.CODEX_EXEC_MAX_CAPTURE_CHARS],
|