@mrciphersmith/keryx 0.3.75 → 0.3.76
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/dist/cli.js +544 -437
- package/dist/core.js +6 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -20145,7 +20145,7 @@ var package_default;
|
|
|
20145
20145
|
var init_package = __esm(() => {
|
|
20146
20146
|
package_default = {
|
|
20147
20147
|
name: "@mrciphersmith/keryx",
|
|
20148
|
-
version: "0.3.
|
|
20148
|
+
version: "0.3.76",
|
|
20149
20149
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
20150
20150
|
private: false,
|
|
20151
20151
|
publishConfig: {
|
|
@@ -97077,109 +97077,6 @@ function createSpawnSubagentTool(deps) {
|
|
|
97077
97077
|
outcome
|
|
97078
97078
|
});
|
|
97079
97079
|
};
|
|
97080
|
-
const parent = deps.getParentModel();
|
|
97081
|
-
const detected = deps.getDetectedProviders();
|
|
97082
|
-
const session = { providerId: parent.providerId, modelId: parent.modelId };
|
|
97083
|
-
const catalog = detected.map((p) => ({
|
|
97084
|
-
name: p.name,
|
|
97085
|
-
models: p.models ?? []
|
|
97086
|
-
}));
|
|
97087
|
-
const requestedTier = parseModelTier(typeof input.model_tier === "string" ? input.model_tier : undefined);
|
|
97088
|
-
let categoryModelRequest;
|
|
97089
|
-
if (requestedTier === undefined) {
|
|
97090
|
-
const routingLocation = { cwd: deps.cwd };
|
|
97091
|
-
const [projectRouting, userRouting] = await Promise.all([
|
|
97092
|
-
loadRoutingConfig("project", routingLocation),
|
|
97093
|
-
loadRoutingConfig("user", routingLocation)
|
|
97094
|
-
]);
|
|
97095
|
-
for (const layer of [projectRouting, userRouting]) {
|
|
97096
|
-
if (layer.error !== undefined) {
|
|
97097
|
-
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "system", text: `routing: ${layer.error}` } });
|
|
97098
|
-
}
|
|
97099
|
-
}
|
|
97100
|
-
const external = await resolveExternalSetting({ cwd: deps.cwd });
|
|
97101
|
-
const { config: externalConfig } = loadExternalProvidersConfig();
|
|
97102
|
-
const connected = externalAllowedConnectedPredicate(connectedPredicateFrom(catalog), external.value === "on", externalConfig);
|
|
97103
|
-
const resolved = resolveCategoryDetailed("subagents", { project: projectRouting.table, user: userRouting.table }, connected);
|
|
97104
|
-
if (resolved.rejected !== undefined) {
|
|
97105
|
-
emitFleetEvent({
|
|
97106
|
-
kind: "log",
|
|
97107
|
-
id: workerId,
|
|
97108
|
-
entry: { kind: "system", text: `routing: ${describeFallbackNotice(resolved.rejected.assignment, resolved.assignment)}` }
|
|
97109
|
-
});
|
|
97110
|
-
}
|
|
97111
|
-
categoryModelRequest = categoryAssignmentToChildModelRequest(resolved.assignment);
|
|
97112
|
-
}
|
|
97113
|
-
const dispatchModelRequest = requestedTier !== undefined ? { kind: "tier", tier: requestedTier } : categoryModelRequest;
|
|
97114
|
-
let tierMap = buildTierMap(session, catalog);
|
|
97115
|
-
const tierPrices = deps.tierRank?.prices?.(session.providerId);
|
|
97116
|
-
let tierResolution = requestedTier === undefined ? undefined : resolveTierModel(session, requestedTier, catalog, undefined, tierPrices);
|
|
97117
|
-
if (requestedTier !== undefined && deps.tierRank !== undefined) {
|
|
97118
|
-
tierResolution = await resolveTierWithAgent(session, requestedTier, rankDiscoveredModels(session, catalog), {
|
|
97119
|
-
agent: deps.tierRank.agent,
|
|
97120
|
-
...deps.tierRank.cache !== undefined ? { cache: deps.tierRank.cache } : {},
|
|
97121
|
-
...tierPrices !== undefined ? { prices: tierPrices } : {},
|
|
97122
|
-
...parent.baseUrl !== undefined ? { baseUrl: parent.baseUrl } : {}
|
|
97123
|
-
});
|
|
97124
|
-
if (tierResolution.source === "agent-ranked") {
|
|
97125
|
-
tierMap = applyTierResolution(tierMap, tierResolution);
|
|
97126
|
-
}
|
|
97127
|
-
}
|
|
97128
|
-
const ctx = {
|
|
97129
|
-
parentRunId,
|
|
97130
|
-
parentSessionId,
|
|
97131
|
-
parentProvenance,
|
|
97132
|
-
contextManifestHash: sha2569(`${parentRunId}:${parentSessionId}`),
|
|
97133
|
-
canonicalContractVersion: "1.0.0",
|
|
97134
|
-
parentModel: session,
|
|
97135
|
-
parentPolicy: parentShellPolicy(),
|
|
97136
|
-
ledger,
|
|
97137
|
-
detected: detected.length > 0 ? detected : [{ name: parent.providerId }],
|
|
97138
|
-
config: {
|
|
97139
|
-
maxTreeDepth: 2,
|
|
97140
|
-
maxChildren: DEFAULT_MAX_CHILDREN,
|
|
97141
|
-
tiers: tierMap
|
|
97142
|
-
}
|
|
97143
|
-
};
|
|
97144
|
-
const attemptId = idSeq();
|
|
97145
|
-
const branchId = idSeq();
|
|
97146
|
-
const reservationId = idSeq();
|
|
97147
|
-
const artifactHash = sha2569(task);
|
|
97148
|
-
const spawned = spawnSubagent({
|
|
97149
|
-
attempt: { attemptId, number: childSeq },
|
|
97150
|
-
branchId,
|
|
97151
|
-
budgetRequest: {
|
|
97152
|
-
reservationId,
|
|
97153
|
-
maxRuntimeMs: 5 * 60000
|
|
97154
|
-
},
|
|
97155
|
-
policyRequest: childReadOnlyPolicy(),
|
|
97156
|
-
durableResultArtifact: {
|
|
97157
|
-
artifactId: idSeq(),
|
|
97158
|
-
kind: "final-report",
|
|
97159
|
-
hash: artifactHash
|
|
97160
|
-
},
|
|
97161
|
-
...dispatchModelRequest !== undefined ? { modelRequest: dispatchModelRequest } : {}
|
|
97162
|
-
}, ctx, { idSeq, clock });
|
|
97163
|
-
if (!spawned.ok) {
|
|
97164
|
-
emitFleetEvent({
|
|
97165
|
-
id: workerId,
|
|
97166
|
-
kind: "upsert",
|
|
97167
|
-
label,
|
|
97168
|
-
status: "failed",
|
|
97169
|
-
detail: "denied",
|
|
97170
|
-
task
|
|
97171
|
-
});
|
|
97172
|
-
return {
|
|
97173
|
-
status: "Denied",
|
|
97174
|
-
output: `spawn_subagent denied by MAE: ${spawned.reason}`,
|
|
97175
|
-
isError: true
|
|
97176
|
-
};
|
|
97177
|
-
}
|
|
97178
|
-
const runModel = spawned.runModel ?? {
|
|
97179
|
-
provider: parent.providerId,
|
|
97180
|
-
model: parent.modelId
|
|
97181
|
-
};
|
|
97182
|
-
const tierRecord = tierResolution === undefined ? undefined : `model tier ${tierResolution.tier} \u2192 ${runModel.provider}/${runModel.model} ` + `[${tierResolution.source}] ${tierResolution.reason}` + (tierResolution.agent === undefined ? "" : ` (agent ${tierResolution.agent.trigger}, ran on ${tierResolution.agent.runOn.providerId}/${tierResolution.agent.runOn.modelId}, ` + `${tierResolution.agent.cacheHit ? "cache hit" : "asked"}${tierResolution.agent.failure === null ? "" : `, failed: ${tierResolution.agent.failure}`})`);
|
|
97183
97080
|
const externalRuntime = readExternalRuntimeRequest(input);
|
|
97184
97081
|
const externalAgentId = externalRuntime === undefined || typeof externalRuntime.agent !== "string" ? undefined : externalRuntime.agent;
|
|
97185
97082
|
const externalMark = externalRuntime !== undefined && deps.runExternal !== undefined ? { runtime: "external", ...externalAgentId === undefined ? {} : { agentId: externalAgentId } } : {};
|
|
@@ -97188,29 +97085,190 @@ function createSpawnSubagentTool(deps) {
|
|
|
97188
97085
|
id: workerId,
|
|
97189
97086
|
label,
|
|
97190
97087
|
status: "running",
|
|
97191
|
-
detail:
|
|
97192
|
-
model: `${runModel.provider}/${runModel.model}`,
|
|
97088
|
+
detail: "preparing",
|
|
97193
97089
|
task,
|
|
97194
97090
|
...externalMark
|
|
97195
97091
|
});
|
|
97196
|
-
|
|
97197
|
-
|
|
97198
|
-
|
|
97199
|
-
|
|
97200
|
-
const
|
|
97201
|
-
|
|
97202
|
-
|
|
97092
|
+
try {
|
|
97093
|
+
const parent = deps.getParentModel();
|
|
97094
|
+
const detected = deps.getDetectedProviders();
|
|
97095
|
+
const session = { providerId: parent.providerId, modelId: parent.modelId };
|
|
97096
|
+
const catalog = detected.map((p) => ({
|
|
97097
|
+
name: p.name,
|
|
97098
|
+
models: p.models ?? []
|
|
97099
|
+
}));
|
|
97100
|
+
const requestedTier = parseModelTier(typeof input.model_tier === "string" ? input.model_tier : undefined);
|
|
97101
|
+
let categoryModelRequest;
|
|
97102
|
+
if (requestedTier === undefined) {
|
|
97103
|
+
const routingLocation = { cwd: deps.cwd };
|
|
97104
|
+
const [projectRouting, userRouting] = await Promise.all([
|
|
97105
|
+
loadRoutingConfig("project", routingLocation),
|
|
97106
|
+
loadRoutingConfig("user", routingLocation)
|
|
97107
|
+
]);
|
|
97108
|
+
for (const layer of [projectRouting, userRouting]) {
|
|
97109
|
+
if (layer.error !== undefined) {
|
|
97110
|
+
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "system", text: `routing: ${layer.error}` } });
|
|
97111
|
+
}
|
|
97112
|
+
}
|
|
97113
|
+
const external = await resolveExternalSetting({ cwd: deps.cwd });
|
|
97114
|
+
const { config: externalConfig } = loadExternalProvidersConfig();
|
|
97115
|
+
const connected = externalAllowedConnectedPredicate(connectedPredicateFrom(catalog), external.value === "on", externalConfig);
|
|
97116
|
+
const resolved = resolveCategoryDetailed("subagents", { project: projectRouting.table, user: userRouting.table }, connected);
|
|
97117
|
+
if (resolved.rejected !== undefined) {
|
|
97118
|
+
emitFleetEvent({
|
|
97119
|
+
kind: "log",
|
|
97120
|
+
id: workerId,
|
|
97121
|
+
entry: { kind: "system", text: `routing: ${describeFallbackNotice(resolved.rejected.assignment, resolved.assignment)}` }
|
|
97122
|
+
});
|
|
97123
|
+
}
|
|
97124
|
+
categoryModelRequest = categoryAssignmentToChildModelRequest(resolved.assignment);
|
|
97125
|
+
}
|
|
97126
|
+
const dispatchModelRequest = requestedTier !== undefined ? { kind: "tier", tier: requestedTier } : categoryModelRequest;
|
|
97127
|
+
let tierMap = buildTierMap(session, catalog);
|
|
97128
|
+
const tierPrices = deps.tierRank?.prices?.(session.providerId);
|
|
97129
|
+
let tierResolution = requestedTier === undefined ? undefined : resolveTierModel(session, requestedTier, catalog, undefined, tierPrices);
|
|
97130
|
+
if (requestedTier !== undefined && deps.tierRank !== undefined) {
|
|
97131
|
+
tierResolution = await resolveTierWithAgent(session, requestedTier, rankDiscoveredModels(session, catalog), {
|
|
97132
|
+
agent: deps.tierRank.agent,
|
|
97133
|
+
...deps.tierRank.cache !== undefined ? { cache: deps.tierRank.cache } : {},
|
|
97134
|
+
...tierPrices !== undefined ? { prices: tierPrices } : {},
|
|
97135
|
+
...parent.baseUrl !== undefined ? { baseUrl: parent.baseUrl } : {}
|
|
97136
|
+
});
|
|
97137
|
+
if (tierResolution.source === "agent-ranked") {
|
|
97138
|
+
tierMap = applyTierResolution(tierMap, tierResolution);
|
|
97139
|
+
}
|
|
97140
|
+
}
|
|
97141
|
+
const ctx = {
|
|
97142
|
+
parentRunId,
|
|
97143
|
+
parentSessionId,
|
|
97144
|
+
parentProvenance,
|
|
97145
|
+
contextManifestHash: sha2569(`${parentRunId}:${parentSessionId}`),
|
|
97146
|
+
canonicalContractVersion: "1.0.0",
|
|
97147
|
+
parentModel: session,
|
|
97148
|
+
parentPolicy: parentShellPolicy(),
|
|
97149
|
+
ledger,
|
|
97150
|
+
detected: detected.length > 0 ? detected : [{ name: parent.providerId }],
|
|
97151
|
+
config: {
|
|
97152
|
+
maxTreeDepth: 2,
|
|
97153
|
+
maxChildren: DEFAULT_MAX_CHILDREN,
|
|
97154
|
+
tiers: tierMap
|
|
97155
|
+
}
|
|
97156
|
+
};
|
|
97157
|
+
const attemptId = idSeq();
|
|
97158
|
+
const branchId = idSeq();
|
|
97159
|
+
const reservationId = idSeq();
|
|
97160
|
+
const artifactHash = sha2569(task);
|
|
97161
|
+
const spawned = spawnSubagent({
|
|
97162
|
+
attempt: { attemptId, number: childSeq },
|
|
97163
|
+
branchId,
|
|
97164
|
+
budgetRequest: {
|
|
97165
|
+
reservationId,
|
|
97166
|
+
maxRuntimeMs: 5 * 60000
|
|
97167
|
+
},
|
|
97168
|
+
policyRequest: childReadOnlyPolicy(),
|
|
97169
|
+
durableResultArtifact: {
|
|
97170
|
+
artifactId: idSeq(),
|
|
97171
|
+
kind: "final-report",
|
|
97172
|
+
hash: artifactHash
|
|
97173
|
+
},
|
|
97174
|
+
...dispatchModelRequest !== undefined ? { modelRequest: dispatchModelRequest } : {}
|
|
97175
|
+
}, ctx, { idSeq, clock });
|
|
97176
|
+
if (!spawned.ok) {
|
|
97203
97177
|
emitFleetEvent({
|
|
97204
|
-
kind: "upsert",
|
|
97205
97178
|
id: workerId,
|
|
97179
|
+
kind: "upsert",
|
|
97206
97180
|
label,
|
|
97207
97181
|
status: "failed",
|
|
97208
|
-
detail: "
|
|
97209
|
-
task
|
|
97210
|
-
...externalMark
|
|
97182
|
+
detail: "denied",
|
|
97183
|
+
task
|
|
97211
97184
|
});
|
|
97185
|
+
return {
|
|
97186
|
+
status: "Denied",
|
|
97187
|
+
output: `spawn_subagent denied by MAE: ${spawned.reason}`,
|
|
97188
|
+
isError: true
|
|
97189
|
+
};
|
|
97190
|
+
}
|
|
97191
|
+
const runModel = spawned.runModel ?? {
|
|
97192
|
+
provider: parent.providerId,
|
|
97193
|
+
model: parent.modelId
|
|
97194
|
+
};
|
|
97195
|
+
const tierRecord = tierResolution === undefined ? undefined : `model tier ${tierResolution.tier} \u2192 ${runModel.provider}/${runModel.model} ` + `[${tierResolution.source}] ${tierResolution.reason}` + (tierResolution.agent === undefined ? "" : ` (agent ${tierResolution.agent.trigger}, ran on ${tierResolution.agent.runOn.providerId}/${tierResolution.agent.runOn.modelId}, ` + `${tierResolution.agent.cacheHit ? "cache hit" : "asked"}${tierResolution.agent.failure === null ? "" : `, failed: ${tierResolution.agent.failure}`})`);
|
|
97196
|
+
emitFleetEvent({
|
|
97197
|
+
kind: "upsert",
|
|
97198
|
+
id: workerId,
|
|
97199
|
+
label,
|
|
97200
|
+
status: "running",
|
|
97201
|
+
detail: mode === "read_only" ? "read-only" : "general",
|
|
97202
|
+
model: `${runModel.provider}/${runModel.model}`,
|
|
97203
|
+
task,
|
|
97204
|
+
...externalMark
|
|
97205
|
+
});
|
|
97206
|
+
if (tierRecord !== undefined) {
|
|
97207
|
+
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "system", text: tierRecord } });
|
|
97208
|
+
}
|
|
97209
|
+
if (externalRuntime !== undefined && deps.runExternal !== undefined) {
|
|
97210
|
+
const externalStartedAt = performance.now();
|
|
97211
|
+
const startOutcome = await fireSubagentStart("external");
|
|
97212
|
+
if (startOutcome === "deny" || startOutcome === "ask") {
|
|
97213
|
+
emitFleetEvent({
|
|
97214
|
+
kind: "upsert",
|
|
97215
|
+
id: workerId,
|
|
97216
|
+
label,
|
|
97217
|
+
status: "failed",
|
|
97218
|
+
detail: "hook-denied",
|
|
97219
|
+
task,
|
|
97220
|
+
...externalMark
|
|
97221
|
+
});
|
|
97222
|
+
ledger.release(spawned.reservation.reservationId, {
|
|
97223
|
+
maxRuntimeMs: Math.round(performance.now() - externalStartedAt)
|
|
97224
|
+
});
|
|
97225
|
+
return {
|
|
97226
|
+
status: "Denied",
|
|
97227
|
+
output: `spawn_subagent denied by a SubagentStart hook for ${workerId}`,
|
|
97228
|
+
isError: true
|
|
97229
|
+
};
|
|
97230
|
+
}
|
|
97231
|
+
try {
|
|
97232
|
+
const external = await deps.runExternal({ runtime: externalRuntime, task, mode, workerId, label });
|
|
97233
|
+
emitFleetEvent({
|
|
97234
|
+
kind: "upsert",
|
|
97235
|
+
id: workerId,
|
|
97236
|
+
label,
|
|
97237
|
+
status: external.isError ? "failed" : "done",
|
|
97238
|
+
detail: external.status,
|
|
97239
|
+
task,
|
|
97240
|
+
...externalMark
|
|
97241
|
+
});
|
|
97242
|
+
await fireSubagentStop(external.status);
|
|
97243
|
+
return external;
|
|
97244
|
+
} catch (err) {
|
|
97245
|
+
emitFleetEvent({
|
|
97246
|
+
kind: "upsert",
|
|
97247
|
+
id: workerId,
|
|
97248
|
+
label,
|
|
97249
|
+
status: "failed",
|
|
97250
|
+
detail: "error",
|
|
97251
|
+
task,
|
|
97252
|
+
...externalMark
|
|
97253
|
+
});
|
|
97254
|
+
await fireSubagentStop("Error");
|
|
97255
|
+
return {
|
|
97256
|
+
status: "Error",
|
|
97257
|
+
output: `external runtime failed before the agent could report: ${err.message}`,
|
|
97258
|
+
isError: true
|
|
97259
|
+
};
|
|
97260
|
+
} finally {
|
|
97261
|
+
ledger.release(spawned.reservation.reservationId, {
|
|
97262
|
+
maxRuntimeMs: Math.round(performance.now() - externalStartedAt)
|
|
97263
|
+
});
|
|
97264
|
+
}
|
|
97265
|
+
}
|
|
97266
|
+
const nativeStartedAt = performance.now();
|
|
97267
|
+
const nativeStartOutcome = await fireSubagentStart("internal");
|
|
97268
|
+
if (nativeStartOutcome === "deny" || nativeStartOutcome === "ask") {
|
|
97269
|
+
emitFleetEvent({ kind: "upsert", id: workerId, label, status: "failed", detail: "hook-denied", task });
|
|
97212
97270
|
ledger.release(spawned.reservation.reservationId, {
|
|
97213
|
-
maxRuntimeMs: Math.round(performance.now() -
|
|
97271
|
+
maxRuntimeMs: Math.round(performance.now() - nativeStartedAt)
|
|
97214
97272
|
});
|
|
97215
97273
|
return {
|
|
97216
97274
|
status: "Denied",
|
|
@@ -97218,333 +97276,289 @@ function createSpawnSubagentTool(deps) {
|
|
|
97218
97276
|
isError: true
|
|
97219
97277
|
};
|
|
97220
97278
|
}
|
|
97279
|
+
const cwd = childCwd;
|
|
97280
|
+
const tools = mode === "read_only" ? [
|
|
97281
|
+
...builtinReadOnlyTools(cwd),
|
|
97282
|
+
...builtinMetaprojectTools(cwd, makeKeryxRunner(cwd), createMetaprojectAdapter(cwd))
|
|
97283
|
+
] : [
|
|
97284
|
+
...builtinReadOnlyTools(cwd),
|
|
97285
|
+
...builtinMetaprojectTools(cwd, makeKeryxRunner(cwd), createMetaprojectAdapter(cwd))
|
|
97286
|
+
];
|
|
97287
|
+
let ephemeralDir;
|
|
97288
|
+
let openedChildSlate;
|
|
97289
|
+
let dispatchId = "";
|
|
97290
|
+
let closing = false;
|
|
97221
97291
|
try {
|
|
97222
|
-
|
|
97223
|
-
|
|
97224
|
-
|
|
97225
|
-
|
|
97226
|
-
|
|
97227
|
-
|
|
97228
|
-
|
|
97229
|
-
task,
|
|
97230
|
-
...externalMark
|
|
97292
|
+
ephemeralDir = await mkdtemp2(path220.join(tmpdir6(), "keryx-subagent-slate-"));
|
|
97293
|
+
dispatchId = path220.basename(ephemeralDir);
|
|
97294
|
+
openedChildSlate = await openSlate({
|
|
97295
|
+
dir: ephemeralDir,
|
|
97296
|
+
cwd,
|
|
97297
|
+
mintAttemptId: () => idSeq(),
|
|
97298
|
+
runtime: { provider: runModel.provider, model: runModel.model }
|
|
97231
97299
|
});
|
|
97232
|
-
|
|
97233
|
-
|
|
97234
|
-
|
|
97235
|
-
|
|
97236
|
-
|
|
97237
|
-
|
|
97238
|
-
|
|
97239
|
-
|
|
97240
|
-
|
|
97241
|
-
|
|
97242
|
-
|
|
97243
|
-
});
|
|
97244
|
-
await fireSubagentStop("Error");
|
|
97245
|
-
return {
|
|
97246
|
-
status: "Error",
|
|
97247
|
-
output: `external runtime failed before the agent could report: ${err.message}`,
|
|
97248
|
-
isError: true
|
|
97249
|
-
};
|
|
97250
|
-
} finally {
|
|
97300
|
+
tools.push(slateWriteSeedTool(() => closing ? undefined : ephemeralDir, idSeq, clock));
|
|
97301
|
+
} catch {
|
|
97302
|
+
openedChildSlate = undefined;
|
|
97303
|
+
}
|
|
97304
|
+
let provider;
|
|
97305
|
+
try {
|
|
97306
|
+
provider = deps.makeProvider(runModel.provider, runModel.model, parent.baseUrl);
|
|
97307
|
+
} catch (cause) {
|
|
97308
|
+
if (ephemeralDir !== undefined) {
|
|
97309
|
+
await rm15(ephemeralDir, { recursive: true, force: true }).catch(() => {});
|
|
97310
|
+
}
|
|
97311
|
+
await fireSubagentStop("Error").catch(() => {});
|
|
97251
97312
|
ledger.release(spawned.reservation.reservationId, {
|
|
97252
|
-
maxRuntimeMs: Math.round(performance.now() -
|
|
97313
|
+
maxRuntimeMs: Math.round(performance.now() - nativeStartedAt)
|
|
97253
97314
|
});
|
|
97315
|
+
throw cause;
|
|
97254
97316
|
}
|
|
97255
|
-
|
|
97256
|
-
|
|
97257
|
-
|
|
97258
|
-
|
|
97259
|
-
|
|
97260
|
-
|
|
97261
|
-
|
|
97262
|
-
|
|
97263
|
-
|
|
97264
|
-
|
|
97265
|
-
|
|
97266
|
-
|
|
97317
|
+
const childHooks = deps.hooks === undefined ? undefined : (() => {
|
|
97318
|
+
const childRunId = idSeq();
|
|
97319
|
+
return { runtime: deps.hooks.forChild({ sessionId: workerId, runId: childRunId }), sessionId: workerId, runId: childRunId };
|
|
97320
|
+
})();
|
|
97321
|
+
const childDeps = {
|
|
97322
|
+
provider,
|
|
97323
|
+
providerId: runModel.provider,
|
|
97324
|
+
modelId: runModel.model,
|
|
97325
|
+
tools,
|
|
97326
|
+
...childHooks !== undefined ? { hooks: childHooks } : {},
|
|
97327
|
+
systemInstruction: "You are a keryx subagent. Complete ONLY the assigned task. " + "Be concise. Use tools when needed. Do not spawn further subagents. " + (configuredMaxToolCalls === undefined ? "" : `You may invoke at most ${configuredMaxToolCalls} tools in total (a hard limit). `) + (advisoryToolCalls === undefined ? "" : `Aim to finish within about ${advisoryToolCalls} tool calls \u2014 a target, not a hard stop; ` + "tool results will tell you when you are close. ") + `You have up to ${maxRounds} model turns (rounds) to complete this task \u2014 each round ` + "may include several tool calls; an identical call repeated does not start a new round " + "but is still capped at a few attempts, so do not retry the same query hoping for a " + "different answer. If a graph/symbol/wiki lookup returns empty or 'not found', that tool " + "has no index for this \u2014 do not re-run it with a slightly reworded query; switch tool " + "(e.g. a direct file read or a plain text/code search) or report the gap instead of " + "spending rounds probing the same dead end. When a tool result says your budget is nearly " + "spent, stop exploring and return your result. If a limit is reached you get one final round " + "in which the only tool is submit_result \u2014 use it to hand back a partial result. " + "End with a short factual summary the parent can use.",
|
|
97328
|
+
idSeq: () => idSeq(),
|
|
97329
|
+
controlNonce: generateControlNonce(),
|
|
97330
|
+
maxRounds,
|
|
97331
|
+
...configuredMaxToolCalls === undefined ? {} : { maxToolCalls: configuredMaxToolCalls },
|
|
97332
|
+
subagentBudget: advisoryToolCalls === undefined ? {} : { advisoryToolCalls }
|
|
97267
97333
|
};
|
|
97268
|
-
|
|
97269
|
-
|
|
97270
|
-
|
|
97271
|
-
|
|
97272
|
-
|
|
97273
|
-
|
|
97274
|
-
|
|
97275
|
-
|
|
97276
|
-
|
|
97277
|
-
|
|
97278
|
-
|
|
97279
|
-
|
|
97280
|
-
|
|
97281
|
-
|
|
97282
|
-
|
|
97283
|
-
|
|
97284
|
-
|
|
97285
|
-
|
|
97286
|
-
|
|
97287
|
-
|
|
97288
|
-
|
|
97289
|
-
|
|
97290
|
-
|
|
97291
|
-
|
|
97292
|
-
|
|
97293
|
-
|
|
97294
|
-
|
|
97295
|
-
|
|
97296
|
-
|
|
97297
|
-
|
|
97298
|
-
|
|
97299
|
-
|
|
97300
|
-
|
|
97301
|
-
|
|
97302
|
-
|
|
97303
|
-
|
|
97304
|
-
|
|
97305
|
-
|
|
97306
|
-
|
|
97307
|
-
|
|
97308
|
-
|
|
97309
|
-
|
|
97310
|
-
|
|
97311
|
-
|
|
97312
|
-
|
|
97313
|
-
|
|
97314
|
-
|
|
97315
|
-
|
|
97316
|
-
|
|
97317
|
-
|
|
97318
|
-
|
|
97319
|
-
|
|
97320
|
-
|
|
97321
|
-
|
|
97322
|
-
|
|
97323
|
-
|
|
97324
|
-
|
|
97325
|
-
|
|
97326
|
-
|
|
97327
|
-
|
|
97328
|
-
const io = {
|
|
97329
|
-
write: (s) => {
|
|
97330
|
-
assistant += s;
|
|
97331
|
-
},
|
|
97332
|
-
onAssistantText: (text) => {
|
|
97333
|
-
assistant = text;
|
|
97334
|
-
if (closed) {
|
|
97335
|
-
return;
|
|
97336
|
-
}
|
|
97337
|
-
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "text", text } });
|
|
97338
|
-
},
|
|
97339
|
-
onReasoning: (text) => {
|
|
97340
|
-
if (closed) {
|
|
97341
|
-
return;
|
|
97342
|
-
}
|
|
97343
|
-
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "reasoning", text } });
|
|
97344
|
-
},
|
|
97345
|
-
onToolCall: (name) => {
|
|
97346
|
-
if (closed) {
|
|
97347
|
-
return;
|
|
97348
|
-
}
|
|
97349
|
-
emitFleetEvent({
|
|
97350
|
-
kind: "upsert",
|
|
97351
|
-
id: workerId,
|
|
97352
|
-
label,
|
|
97353
|
-
status: "running",
|
|
97354
|
-
detail: name.length > 14 ? `${name.slice(0, 12)}\u2026` : name,
|
|
97355
|
-
model: `${runModel.provider}/${runModel.model}`,
|
|
97356
|
-
task
|
|
97357
|
-
});
|
|
97358
|
-
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "tool", text: name } });
|
|
97359
|
-
},
|
|
97360
|
-
onToolResult: (name, result) => {
|
|
97361
|
-
if (closed) {
|
|
97362
|
-
return;
|
|
97363
|
-
}
|
|
97364
|
-
const preview = result.output.trim().slice(0, 400);
|
|
97365
|
-
emitFleetEvent({
|
|
97366
|
-
kind: "log",
|
|
97367
|
-
id: workerId,
|
|
97368
|
-
entry: { kind: "result", text: `${name}${result.isError ? " (error)" : ""} ${preview}` }
|
|
97334
|
+
let assistant = "";
|
|
97335
|
+
let closed = false;
|
|
97336
|
+
const internalAbort = new AbortController;
|
|
97337
|
+
const composed = composeAbortSignals(toolCtx?.signal, internalAbort.signal);
|
|
97338
|
+
const io = {
|
|
97339
|
+
write: (s) => {
|
|
97340
|
+
assistant += s;
|
|
97341
|
+
},
|
|
97342
|
+
onAssistantText: (text) => {
|
|
97343
|
+
assistant = text;
|
|
97344
|
+
if (closed) {
|
|
97345
|
+
return;
|
|
97346
|
+
}
|
|
97347
|
+
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "text", text } });
|
|
97348
|
+
},
|
|
97349
|
+
onReasoning: (text) => {
|
|
97350
|
+
if (closed) {
|
|
97351
|
+
return;
|
|
97352
|
+
}
|
|
97353
|
+
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "reasoning", text } });
|
|
97354
|
+
},
|
|
97355
|
+
onToolCall: (name) => {
|
|
97356
|
+
if (closed) {
|
|
97357
|
+
return;
|
|
97358
|
+
}
|
|
97359
|
+
emitFleetEvent({
|
|
97360
|
+
kind: "upsert",
|
|
97361
|
+
id: workerId,
|
|
97362
|
+
label,
|
|
97363
|
+
status: "running",
|
|
97364
|
+
detail: name.length > 14 ? `${name.slice(0, 12)}\u2026` : name,
|
|
97365
|
+
model: `${runModel.provider}/${runModel.model}`,
|
|
97366
|
+
task
|
|
97367
|
+
});
|
|
97368
|
+
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "tool", text: name } });
|
|
97369
|
+
},
|
|
97370
|
+
onToolResult: (name, result) => {
|
|
97371
|
+
if (closed) {
|
|
97372
|
+
return;
|
|
97373
|
+
}
|
|
97374
|
+
const preview = result.output.trim().slice(0, 400);
|
|
97375
|
+
emitFleetEvent({
|
|
97376
|
+
kind: "log",
|
|
97377
|
+
id: workerId,
|
|
97378
|
+
entry: { kind: "result", text: `${name}${result.isError ? " (error)" : ""} ${preview}` }
|
|
97379
|
+
});
|
|
97380
|
+
},
|
|
97381
|
+
onSystem: (text) => {
|
|
97382
|
+
if (closed) {
|
|
97383
|
+
return;
|
|
97384
|
+
}
|
|
97385
|
+
emitFleetEvent({ kind: "log", id: workerId, entry: { kind: "system", text } });
|
|
97386
|
+
},
|
|
97387
|
+
requestApproval: async () => false
|
|
97388
|
+
};
|
|
97389
|
+
const deadlineMs = resolveSubagentTimeoutMs(spawned.reservation.maxRuntimeMs);
|
|
97390
|
+
const startedAt = performance.now();
|
|
97391
|
+
const releaseBudget = () => {
|
|
97392
|
+
ledger.release(spawned.reservation.reservationId, {
|
|
97393
|
+
maxRuntimeMs: Math.round(performance.now() - startedAt)
|
|
97369
97394
|
});
|
|
97370
|
-
}
|
|
97371
|
-
|
|
97372
|
-
|
|
97395
|
+
};
|
|
97396
|
+
const foldChildSlateAndCleanup = async (status) => {
|
|
97397
|
+
closing = true;
|
|
97398
|
+
if (ephemeralDir === undefined) {
|
|
97373
97399
|
return;
|
|
97374
97400
|
}
|
|
97375
|
-
|
|
97376
|
-
|
|
97377
|
-
|
|
97378
|
-
|
|
97379
|
-
|
|
97380
|
-
|
|
97381
|
-
|
|
97382
|
-
|
|
97383
|
-
|
|
97384
|
-
|
|
97385
|
-
|
|
97386
|
-
|
|
97387
|
-
|
|
97388
|
-
if (ephemeralDir === undefined) {
|
|
97389
|
-
return;
|
|
97390
|
-
}
|
|
97391
|
-
const dirToClean = ephemeralDir;
|
|
97392
|
-
try {
|
|
97393
|
-
await withFileLock(slateLockPath(dirToClean), async () => {
|
|
97394
|
-
try {
|
|
97395
|
-
const slateSession = deps.getSlateSession?.();
|
|
97396
|
-
if (openedChildSlate !== undefined && slateSession !== undefined) {
|
|
97397
|
-
try {
|
|
97398
|
-
const childSlate = await readSlate(dirToClean);
|
|
97399
|
-
const dispatch = {
|
|
97400
|
-
anchors: childSlate?.anchors ?? openedChildSlate.anchors,
|
|
97401
|
-
course: childSlate?.course ?? openedChildSlate.course,
|
|
97402
|
-
seeds: childSlate?.seeds ?? [],
|
|
97403
|
-
status
|
|
97404
|
-
};
|
|
97405
|
-
const parentDir = slateSession.dir;
|
|
97406
|
-
await writeSlate(parentDir, (prev) => {
|
|
97407
|
-
if (prev === undefined) {
|
|
97408
|
-
throw new Error(`foldChildSlateAndCleanup: no open parent slate in ${parentDir}`);
|
|
97409
|
-
}
|
|
97410
|
-
return {
|
|
97411
|
-
...prev,
|
|
97412
|
-
childDispatches: { ...prev.childDispatches ?? {}, [dispatchId]: dispatch }
|
|
97401
|
+
const dirToClean = ephemeralDir;
|
|
97402
|
+
try {
|
|
97403
|
+
await withFileLock(slateLockPath(dirToClean), async () => {
|
|
97404
|
+
try {
|
|
97405
|
+
const slateSession = deps.getSlateSession?.();
|
|
97406
|
+
if (openedChildSlate !== undefined && slateSession !== undefined) {
|
|
97407
|
+
try {
|
|
97408
|
+
const childSlate = await readSlate(dirToClean);
|
|
97409
|
+
const dispatch = {
|
|
97410
|
+
anchors: childSlate?.anchors ?? openedChildSlate.anchors,
|
|
97411
|
+
course: childSlate?.course ?? openedChildSlate.course,
|
|
97412
|
+
seeds: childSlate?.seeds ?? [],
|
|
97413
|
+
status
|
|
97413
97414
|
};
|
|
97414
|
-
|
|
97415
|
-
|
|
97416
|
-
|
|
97417
|
-
|
|
97418
|
-
|
|
97419
|
-
|
|
97420
|
-
|
|
97421
|
-
|
|
97415
|
+
const parentDir = slateSession.dir;
|
|
97416
|
+
await writeSlate(parentDir, (prev) => {
|
|
97417
|
+
if (prev === undefined) {
|
|
97418
|
+
throw new Error(`foldChildSlateAndCleanup: no open parent slate in ${parentDir}`);
|
|
97419
|
+
}
|
|
97420
|
+
return {
|
|
97421
|
+
...prev,
|
|
97422
|
+
childDispatches: { ...prev.childDispatches ?? {}, [dispatchId]: dispatch }
|
|
97423
|
+
};
|
|
97424
|
+
});
|
|
97425
|
+
} catch (foldCause) {
|
|
97426
|
+
const foldMsg = foldCause instanceof Error ? foldCause.message : String(foldCause);
|
|
97427
|
+
emitFleetEvent({
|
|
97428
|
+
kind: "log",
|
|
97429
|
+
id: workerId,
|
|
97430
|
+
entry: { kind: "system", text: `slate fold failed (ignored): ${foldMsg}` }
|
|
97431
|
+
});
|
|
97432
|
+
}
|
|
97422
97433
|
}
|
|
97434
|
+
} finally {
|
|
97435
|
+
await rm15(dirToClean, { recursive: true, force: true }).catch(() => {});
|
|
97423
97436
|
}
|
|
97424
|
-
}
|
|
97425
|
-
|
|
97426
|
-
|
|
97427
|
-
|
|
97428
|
-
|
|
97429
|
-
|
|
97430
|
-
|
|
97431
|
-
|
|
97432
|
-
|
|
97433
|
-
|
|
97434
|
-
|
|
97435
|
-
|
|
97436
|
-
|
|
97437
|
-
|
|
97438
|
-
|
|
97439
|
-
|
|
97440
|
-
|
|
97441
|
-
history.push({ role: "user", content: renderAnchorsBlock(openedChildSlate.anchors), provenance: "project", injected: true });
|
|
97442
|
-
}
|
|
97443
|
-
const userLine = `## Subagent task (${mode})
|
|
97437
|
+
});
|
|
97438
|
+
} catch (lockCause) {
|
|
97439
|
+
const lockMsg = lockCause instanceof Error ? lockCause.message : String(lockCause);
|
|
97440
|
+
emitFleetEvent({
|
|
97441
|
+
kind: "log",
|
|
97442
|
+
id: workerId,
|
|
97443
|
+
entry: { kind: "system", text: `slate cleanup lock failed (ignored): ${lockMsg}` }
|
|
97444
|
+
});
|
|
97445
|
+
await rm15(dirToClean, { recursive: true, force: true }).catch(() => {});
|
|
97446
|
+
}
|
|
97447
|
+
};
|
|
97448
|
+
try {
|
|
97449
|
+
const history = [];
|
|
97450
|
+
if (openedChildSlate !== undefined) {
|
|
97451
|
+
history.push({ role: "user", content: renderAnchorsBlock(openedChildSlate.anchors), provenance: "project", injected: true });
|
|
97452
|
+
}
|
|
97453
|
+
const userLine = `## Subagent task (${mode})
|
|
97444
97454
|
` + `${task}
|
|
97445
97455
|
|
|
97446
97456
|
` + `Project root: ${childCwd}
|
|
97447
97457
|
` + `Round budget: ${maxRounds} rounds \u2014 plan which tools to try before spending them; prefer a ` + "direct, targeted lookup (exact file path, exact symbol) over a broad/guessed one, and fall " + `back to a different tool rather than repeating a failed call.
|
|
97448
97458
|
|
|
97449
97459
|
` + "Return a concise summary of findings and any recommended next steps for the parent agent.";
|
|
97450
|
-
|
|
97451
|
-
|
|
97452
|
-
|
|
97453
|
-
|
|
97454
|
-
|
|
97455
|
-
|
|
97456
|
-
|
|
97457
|
-
|
|
97458
|
-
|
|
97459
|
-
|
|
97460
|
-
|
|
97461
|
-
|
|
97462
|
-
|
|
97463
|
-
|
|
97464
|
-
|
|
97465
|
-
|
|
97466
|
-
|
|
97467
|
-
|
|
97468
|
-
|
|
97469
|
-
|
|
97470
|
-
|
|
97471
|
-
|
|
97472
|
-
|
|
97473
|
-
|
|
97474
|
-
|
|
97475
|
-
|
|
97476
|
-
|
|
97477
|
-
|
|
97460
|
+
const turn = runAgentTurn(io, childDeps, history, userLine, { signal: composed.signal });
|
|
97461
|
+
let turnResult;
|
|
97462
|
+
if (deadlineMs > 0) {
|
|
97463
|
+
let timer;
|
|
97464
|
+
const expired = new Promise((resolve) => {
|
|
97465
|
+
timer = setTimeout(() => resolve("timeout"), deadlineMs);
|
|
97466
|
+
});
|
|
97467
|
+
let outcome;
|
|
97468
|
+
try {
|
|
97469
|
+
outcome = await Promise.race([turn.then(() => "done"), expired]);
|
|
97470
|
+
} finally {
|
|
97471
|
+
if (timer !== undefined)
|
|
97472
|
+
clearTimeout(timer);
|
|
97473
|
+
}
|
|
97474
|
+
if (outcome === "timeout") {
|
|
97475
|
+
closed = true;
|
|
97476
|
+
internalAbort.abort();
|
|
97477
|
+
turn.catch(() => {});
|
|
97478
|
+
composed.dispose();
|
|
97479
|
+
releaseBudget();
|
|
97480
|
+
emitFleetEvent({ kind: "upsert", id: workerId, label, status: "failed", detail: "timeout", task });
|
|
97481
|
+
await foldChildSlateAndCleanup("incomplete");
|
|
97482
|
+
await fireSubagentStop("Timeout");
|
|
97483
|
+
const partial = assistant.trim();
|
|
97484
|
+
const foldedPartial = partial.length > 0 ? foldChildSummary(partial).text : "";
|
|
97485
|
+
return {
|
|
97486
|
+
status: "Timeout",
|
|
97487
|
+
output: `subagent ${label} (${workerId}) timed out after ${deadlineMs}ms and was abandoned ` + `(tighten or disable with ${ENV_SUBAGENT_TIMEOUT_MS})` + (foldedPartial.length > 0 ? `
|
|
97478
97488
|
--- partial output ---
|
|
97479
97489
|
${boundSummary(foldedPartial)}` : ""),
|
|
97480
|
-
|
|
97481
|
-
|
|
97482
|
-
|
|
97490
|
+
isError: true,
|
|
97491
|
+
...foldedPartial.length > 0 ? { partial: boundSummary(foldedPartial) } : {}
|
|
97492
|
+
};
|
|
97493
|
+
}
|
|
97494
|
+
turnResult = await turn;
|
|
97495
|
+
} else {
|
|
97496
|
+
turnResult = await turn;
|
|
97483
97497
|
}
|
|
97484
|
-
|
|
97485
|
-
|
|
97486
|
-
|
|
97487
|
-
|
|
97488
|
-
closed = true;
|
|
97489
|
-
composed.dispose();
|
|
97490
|
-
releaseBudget();
|
|
97491
|
-
const raw = assistant.trim().length > 0 ? assistant.trim() : history.filter((m) => m.role === "assistant").map((m) => m.content).join(`
|
|
97498
|
+
closed = true;
|
|
97499
|
+
composed.dispose();
|
|
97500
|
+
releaseBudget();
|
|
97501
|
+
const raw = assistant.trim().length > 0 ? assistant.trim() : history.filter((m) => m.role === "assistant").map((m) => m.content).join(`
|
|
97492
97502
|
`).trim() || "(subagent produced no text)";
|
|
97493
|
-
|
|
97494
|
-
|
|
97495
|
-
|
|
97496
|
-
|
|
97497
|
-
|
|
97498
|
-
|
|
97499
|
-
|
|
97500
|
-
|
|
97501
|
-
|
|
97502
|
-
|
|
97503
|
-
|
|
97504
|
-
|
|
97505
|
-
|
|
97506
|
-
|
|
97507
|
-
|
|
97503
|
+
const folded = foldChildSummary(raw);
|
|
97504
|
+
const status = subagentStatusForFinishReason(turnResult?.finishReason);
|
|
97505
|
+
const isError = status !== "Completed";
|
|
97506
|
+
emitFleetEvent({
|
|
97507
|
+
kind: "upsert",
|
|
97508
|
+
id: workerId,
|
|
97509
|
+
label,
|
|
97510
|
+
status: isError ? "failed" : "done",
|
|
97511
|
+
detail: subagentFleetDetail(status),
|
|
97512
|
+
model: `${runModel.provider}/${runModel.model}`,
|
|
97513
|
+
task
|
|
97514
|
+
});
|
|
97515
|
+
await foldChildSlateAndCleanup(isError ? "incomplete" : "completed");
|
|
97516
|
+
await fireSubagentStop(status);
|
|
97517
|
+
const header = `subagent ${label} (${workerId}) ${mode} via ${runModel.provider}/${runModel.model}
|
|
97508
97518
|
` + `MAE reservation: rounds\u2264${maxRounds} ` + (configuredMaxToolCalls === undefined ? "" : `calls\u2264${configuredMaxToolCalls} `) + (advisoryToolCalls === undefined ? "" : `calls~${advisoryToolCalls}(advisory) `) + `runtime\u2264${spawned.reservation.maxRuntimeMs}ms children=${ledger.childCount}
|
|
97509
97519
|
` + (tierRecord === undefined ? "" : `${tierRecord}
|
|
97510
97520
|
`);
|
|
97511
|
-
|
|
97512
|
-
|
|
97521
|
+
if (status === "Completed") {
|
|
97522
|
+
return { status, isError, output: `${header}--- summary ---
|
|
97513
97523
|
${boundSummary(folded.text)}` };
|
|
97514
|
-
|
|
97515
|
-
|
|
97516
|
-
|
|
97517
|
-
|
|
97524
|
+
}
|
|
97525
|
+
const statusLine = formatStoppedStatusLine(status, turnResult);
|
|
97526
|
+
const submitted = turnResult?.submittedResult;
|
|
97527
|
+
const resultBlock = submitted !== undefined ? foldChildSummary(`--- submitted result (${submitted.status}) ---
|
|
97518
97528
|
` + `summary: ${submitted.summary}
|
|
97519
97529
|
` + `result:
|
|
97520
97530
|
${typeof submitted.result === "string" ? submitted.result : JSON.stringify(submitted.result, null, 2)}`).text : foldChildSummary(`no result submitted${turnResult?.submitResultError !== undefined ? ` (${turnResult.submitResultError})` : ""}
|
|
97521
97531
|
` + `--- last output ---
|
|
97522
97532
|
${raw}`).text;
|
|
97523
|
-
|
|
97524
|
-
|
|
97525
|
-
|
|
97526
|
-
|
|
97527
|
-
|
|
97533
|
+
const boundedResult = boundSummary(resultBlock);
|
|
97534
|
+
return {
|
|
97535
|
+
status,
|
|
97536
|
+
isError,
|
|
97537
|
+
output: `${statusLine}
|
|
97528
97538
|
${header}${boundedResult}`,
|
|
97529
|
-
|
|
97530
|
-
|
|
97539
|
+
partial: boundedResult
|
|
97540
|
+
};
|
|
97541
|
+
} catch (cause) {
|
|
97542
|
+
closed = true;
|
|
97543
|
+
internalAbort.abort();
|
|
97544
|
+
composed.dispose();
|
|
97545
|
+
releaseBudget();
|
|
97546
|
+
const msg = cause instanceof Error ? cause.message : String(cause);
|
|
97547
|
+
emitFleetEvent({
|
|
97548
|
+
kind: "upsert",
|
|
97549
|
+
id: workerId,
|
|
97550
|
+
label,
|
|
97551
|
+
status: "failed",
|
|
97552
|
+
detail: "error",
|
|
97553
|
+
task
|
|
97554
|
+
});
|
|
97555
|
+
await foldChildSlateAndCleanup("incomplete");
|
|
97556
|
+
await fireSubagentStop("Error");
|
|
97557
|
+
return { status: "Error", output: `subagent ${label} failed: ${msg}`, isError: true };
|
|
97558
|
+
}
|
|
97531
97559
|
} catch (cause) {
|
|
97532
|
-
|
|
97533
|
-
|
|
97534
|
-
composed.dispose();
|
|
97535
|
-
releaseBudget();
|
|
97536
|
-
const msg = cause instanceof Error ? cause.message : String(cause);
|
|
97537
|
-
emitFleetEvent({
|
|
97538
|
-
kind: "upsert",
|
|
97539
|
-
id: workerId,
|
|
97540
|
-
label,
|
|
97541
|
-
status: "failed",
|
|
97542
|
-
detail: "error",
|
|
97543
|
-
task
|
|
97544
|
-
});
|
|
97545
|
-
await foldChildSlateAndCleanup("incomplete");
|
|
97546
|
-
await fireSubagentStop("Error");
|
|
97547
|
-
return { status: "Error", output: `subagent ${label} failed: ${msg}`, isError: true };
|
|
97560
|
+
emitFleetEvent({ kind: "upsert", id: workerId, label, status: "failed", detail: "setup-error", task });
|
|
97561
|
+
throw cause;
|
|
97548
97562
|
}
|
|
97549
97563
|
}
|
|
97550
97564
|
};
|
|
@@ -107425,6 +107439,12 @@ var init_help_groups = __esm(() => {
|
|
|
107425
107439
|
group: "Working in keryx shell",
|
|
107426
107440
|
summary: "Manage the main queue \u2014 /queue <remove|edit|force> [N] (N = qN position, default 1)."
|
|
107427
107441
|
},
|
|
107442
|
+
{
|
|
107443
|
+
kind: "slash",
|
|
107444
|
+
name: "/tasks",
|
|
107445
|
+
group: "Working in keryx shell",
|
|
107446
|
+
summary: "List supervised shell tasks \u2014 /tasks [output <task_id> [cursor] | kill <task_id>]."
|
|
107447
|
+
},
|
|
107428
107448
|
{
|
|
107429
107449
|
kind: "slash",
|
|
107430
107450
|
name: "/interrupt",
|
|
@@ -109761,6 +109781,10 @@ function createBlockView(otui, renderer, parent, block, options = {}) {
|
|
|
109761
109781
|
render: (state, opts = {}) => {
|
|
109762
109782
|
paintHeader(state, opts.focused === true);
|
|
109763
109783
|
if (state.collapsed) {
|
|
109784
|
+
if (options.collapsedPreview !== undefined) {
|
|
109785
|
+
showBody(options.collapsedPreview);
|
|
109786
|
+
return;
|
|
109787
|
+
}
|
|
109764
109788
|
dropBody();
|
|
109765
109789
|
return;
|
|
109766
109790
|
}
|
|
@@ -123085,6 +123109,11 @@ var init_agent_commands = __esm(() => {
|
|
|
123085
123109
|
description: "Hand a task to an external agent CLI \u2014 /delegate <agent> <task>",
|
|
123086
123110
|
modes: AGENT_ONLY
|
|
123087
123111
|
},
|
|
123112
|
+
{
|
|
123113
|
+
name: "/tasks",
|
|
123114
|
+
description: "Shell tasks \u2014 /tasks, /tasks output <task_id> [cursor], /tasks kill <task_id>",
|
|
123115
|
+
modes: AGENT_ONLY
|
|
123116
|
+
},
|
|
123088
123117
|
{
|
|
123089
123118
|
name: "/demote",
|
|
123090
123119
|
description: "Move a running foreground task to the background \u2014 /demote <task_id>",
|
|
@@ -144030,15 +144059,18 @@ function classifyDeterministic(line) {
|
|
|
144030
144059
|
return;
|
|
144031
144060
|
if (REVIEW_RE.test(trimmed))
|
|
144032
144061
|
return "review";
|
|
144062
|
+
if (RUSSIAN_CHITCHAT_RE.test(trimmed))
|
|
144063
|
+
return "quick";
|
|
144033
144064
|
const words = trimmed.split(/\s+/).filter((w) => w.length > 0);
|
|
144034
144065
|
if (trimmed.length <= CHITCHAT_MAX_CHARS && words.length <= CHITCHAT_MAX_WORDS && CHITCHAT_RE.test(trimmed)) {
|
|
144035
144066
|
return "quick";
|
|
144036
144067
|
}
|
|
144037
144068
|
return;
|
|
144038
144069
|
}
|
|
144039
|
-
var CHITCHAT_RE, CHITCHAT_MAX_CHARS = 24, CHITCHAT_MAX_WORDS = 4, REVIEW_RE;
|
|
144070
|
+
var CHITCHAT_RE, CHITCHAT_MAX_CHARS = 24, CHITCHAT_MAX_WORDS = 4, RUSSIAN_CHITCHAT_RE, REVIEW_RE;
|
|
144040
144071
|
var init_deterministic_shortcuts = __esm(() => {
|
|
144041
144072
|
CHITCHAT_RE = /^(?:hi|hello|hey|yo|thanks|thank you|thx|ty|ok|okay|k|cool|nice|great|awesome|sounds good|got it|sure|yes|no|yep|yup|nope|nah|good morning|good night|gm|lol|haha|np|no problem|welcome|you're welcome)[.!?]*$/i;
|
|
144073
|
+
RUSSIAN_CHITCHAT_RE = /^(?:\u043F\u0440\u0438\u0432\u0435\u0442|\u0437\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439|\u0437\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435|\u0441\u043F\u0430\u0441\u0438\u0431\u043E|\u043E\u043A|\u0434\u0430|\u043D\u0435\u0442)[.!?]*(?:\s+\u043E\u0442\u0432\u0435\u0442\u044C \u043E\u0434\u043D\u0438\u043C \u0441\u043B\u043E\u0432\u043E\u043C[.!?]*)?$/i;
|
|
144042
144074
|
REVIEW_RE = /\b(?:code\s+review|review(?:s|ed|ing)?|PRs?|pull\s+requests?)\b/i;
|
|
144043
144075
|
});
|
|
144044
144076
|
|
|
@@ -144298,6 +144330,11 @@ async function runRoutingClassifierForTurn(line, opts) {
|
|
|
144298
144330
|
}
|
|
144299
144331
|
return { classification, category, assignment: resolved.assignment };
|
|
144300
144332
|
}
|
|
144333
|
+
function renderRoutingFallbackLine(result) {
|
|
144334
|
+
if (result === undefined)
|
|
144335
|
+
return "[route fallback: no classifier category; using session model]";
|
|
144336
|
+
return `[route fallback: ${result.category} -> ${describeAssignment(result.assignment)}; using session model]`;
|
|
144337
|
+
}
|
|
144301
144338
|
function pct6(n) {
|
|
144302
144339
|
return `${Math.round(n * 100)}%`;
|
|
144303
144340
|
}
|
|
@@ -147101,6 +147138,71 @@ var init_help_first_run = __esm(() => {
|
|
|
147101
147138
|
init_config_dir();
|
|
147102
147139
|
});
|
|
147103
147140
|
|
|
147141
|
+
// src/tui/tasks-command.ts
|
|
147142
|
+
async function runTasksCommand(args, registry) {
|
|
147143
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
147144
|
+
const usage = `Usage: /tasks [output <task_id> [cursor] | kill <task_id>]
|
|
147145
|
+
`;
|
|
147146
|
+
if (registry === undefined)
|
|
147147
|
+
return `This session tracks no shell tasks.
|
|
147148
|
+
`;
|
|
147149
|
+
if (parts.length === 0) {
|
|
147150
|
+
const tasks = registry.list();
|
|
147151
|
+
return tasks.length === 0 ? `No shell tasks.
|
|
147152
|
+
` : tasks.map((task) => `${task.jobId} \xB7 ${task.status} \xB7 ${task.phase} \xB7 ${task.description ?? task.command}`).join(`
|
|
147153
|
+
`) + `
|
|
147154
|
+
`;
|
|
147155
|
+
}
|
|
147156
|
+
const [action, id, rawCursor] = parts;
|
|
147157
|
+
if (id === undefined)
|
|
147158
|
+
return usage;
|
|
147159
|
+
if (action === "output" && parts.length <= 3) {
|
|
147160
|
+
if (rawCursor !== undefined && !/^\d+$/.test(rawCursor))
|
|
147161
|
+
return usage;
|
|
147162
|
+
const cursor = Number(rawCursor ?? 0);
|
|
147163
|
+
if (!Number.isSafeInteger(cursor))
|
|
147164
|
+
return usage;
|
|
147165
|
+
const result = registry.readOutputSince(id, cursor);
|
|
147166
|
+
if (!result.ok)
|
|
147167
|
+
return `${result.error}
|
|
147168
|
+
`;
|
|
147169
|
+
return `${id} \xB7 ${result.status} \xB7 next_cursor=${result.nextCursor}${result.missed > 0 ? ` \xB7 missed=${result.missed}` : ""}
|
|
147170
|
+
${result.output}
|
|
147171
|
+
`;
|
|
147172
|
+
}
|
|
147173
|
+
if (action === "kill" && parts.length === 2) {
|
|
147174
|
+
const result = await registry.kill(id, "operator");
|
|
147175
|
+
if (!result.ok)
|
|
147176
|
+
return `${result.error}
|
|
147177
|
+
`;
|
|
147178
|
+
return `${id} \xB7 ${registry.get(id)?.status ?? "unknown"}
|
|
147179
|
+
`;
|
|
147180
|
+
}
|
|
147181
|
+
return usage;
|
|
147182
|
+
}
|
|
147183
|
+
|
|
147184
|
+
// src/tui/usage-format.ts
|
|
147185
|
+
function formatUsageLine(usage) {
|
|
147186
|
+
const parts = [];
|
|
147187
|
+
if (usage.inputTokens !== undefined)
|
|
147188
|
+
parts.push(`\u2191${usage.inputTokens}`);
|
|
147189
|
+
if (usage.outputTokens !== undefined)
|
|
147190
|
+
parts.push(`\u2193${usage.outputTokens}`);
|
|
147191
|
+
if (parts.length === 0)
|
|
147192
|
+
return;
|
|
147193
|
+
const cache = [];
|
|
147194
|
+
if (usage.cacheReadTokens !== undefined)
|
|
147195
|
+
cache.push(`cache-read ${usage.cacheReadTokens}`);
|
|
147196
|
+
if (usage.cacheWriteTokens !== undefined)
|
|
147197
|
+
cache.push(`cache-write ${usage.cacheWriteTokens}`);
|
|
147198
|
+
if (usage.inputTokens !== undefined && usage.cacheReadTokens !== undefined && usage.cacheWriteTokens !== undefined) {
|
|
147199
|
+
const uncached = usage.inputTokens - usage.cacheReadTokens - usage.cacheWriteTokens;
|
|
147200
|
+
if (uncached >= 0)
|
|
147201
|
+
cache.push(`uncached ${uncached}`);
|
|
147202
|
+
}
|
|
147203
|
+
return `${parts.join(" ")} tokens${cache.length > 0 ? ` \xB7 ${cache.join(" \xB7 ")}` : " \xB7 cache not reported"}`;
|
|
147204
|
+
}
|
|
147205
|
+
|
|
147104
147206
|
// src/tui/settings-actions.ts
|
|
147105
147207
|
async function runSettingsCommand(command, handlers) {
|
|
147106
147208
|
const [name = "", ...rest] = command.trim().split(/\s+/);
|
|
@@ -157575,16 +157677,9 @@ function createTuiAgentIo(otui, renderer, transcript) {
|
|
|
157575
157677
|
}))}`);
|
|
157576
157678
|
},
|
|
157577
157679
|
onUsage: (usage) => {
|
|
157578
|
-
const
|
|
157579
|
-
if (
|
|
157580
|
-
|
|
157581
|
-
}
|
|
157582
|
-
if (usage.outputTokens !== undefined) {
|
|
157583
|
-
parts.push(`\u2193${usage.outputTokens}`);
|
|
157584
|
-
}
|
|
157585
|
-
if (parts.length > 0) {
|
|
157586
|
-
append(otui.t`${dimChunk(otui, `${parts.join(" ")} tokens`)}`);
|
|
157587
|
-
}
|
|
157680
|
+
const line = formatUsageLine(usage);
|
|
157681
|
+
if (line !== undefined)
|
|
157682
|
+
append(otui.t`${dimChunk(otui, line)}`);
|
|
157588
157683
|
},
|
|
157589
157684
|
onToolCall: (name, input) => {
|
|
157590
157685
|
const args = summarizeToolArgs(input);
|
|
@@ -162453,6 +162548,10 @@ ${formatThemeList(getThemeId())}`);
|
|
|
162453
162548
|
}
|
|
162454
162549
|
return;
|
|
162455
162550
|
}
|
|
162551
|
+
if (command.name === "/tasks") {
|
|
162552
|
+
trackCommandWork(() => runTasksCommand(line.slice(command.name.length), deps.jobRegistry).then((text) => io.onSystem?.(text)));
|
|
162553
|
+
return;
|
|
162554
|
+
}
|
|
162456
162555
|
if (command.name === "/clear" || command.name === "/new") {
|
|
162457
162556
|
(async () => {
|
|
162458
162557
|
await closeSlateSession(slateSession, mintTimestampAttemptId);
|
|
@@ -163022,6 +163121,15 @@ ${formatThemeList(getThemeId())}`);
|
|
|
163022
163121
|
if (line.startsWith("/")) {
|
|
163023
163122
|
io.onSystem?.(describeUnavailableCommand(line, "agent") ?? `Unknown command: ${line}
|
|
163024
163123
|
`);
|
|
163124
|
+
const help = renderCommandHelp("agent");
|
|
163125
|
+
addBlock({ kind: "output", fullText: help, summary: "Available commands", lineCount: help.trimEnd().split(`
|
|
163126
|
+
`).length }, {
|
|
163127
|
+
hint: "ctrl+o \xB7 Enter to expand",
|
|
163128
|
+
collapsedPreview: help.trimEnd().split(`
|
|
163129
|
+
`).slice(0, 8).join(`
|
|
163130
|
+
`),
|
|
163131
|
+
maxLines: 500
|
|
163132
|
+
});
|
|
163025
163133
|
io.onSystem?.(helpText());
|
|
163026
163134
|
return;
|
|
163027
163135
|
}
|
|
@@ -163258,6 +163366,10 @@ ${formatThemeList(getThemeId())}`);
|
|
|
163258
163366
|
(async () => {
|
|
163259
163367
|
let deps = sessionDeps;
|
|
163260
163368
|
let routingOutcome;
|
|
163369
|
+
if (routingEnabled && sessionModelExplicit && origin === "operator") {
|
|
163370
|
+
io.onSystem?.(`[route skipped: manual /model selection pins this session]
|
|
163371
|
+
`);
|
|
163372
|
+
}
|
|
163261
163373
|
if (routingEnabled && !sessionModelExplicit && origin === "operator" && line.trim().length > 0) {
|
|
163262
163374
|
try {
|
|
163263
163375
|
routingOutcome = await runRoutingClassifierForTurn(line, {
|
|
@@ -163287,7 +163399,12 @@ ${formatThemeList(getThemeId())}`);
|
|
|
163287
163399
|
`);
|
|
163288
163400
|
} catch {
|
|
163289
163401
|
deps = sessionDeps;
|
|
163402
|
+
io.onSystem?.(`[route fallback: selected model could not be prepared; check availability and external policy; using session model]
|
|
163403
|
+
`);
|
|
163290
163404
|
}
|
|
163405
|
+
} else {
|
|
163406
|
+
io.onSystem?.(`${renderRoutingFallbackLine(routingOutcome)}
|
|
163407
|
+
`);
|
|
163291
163408
|
}
|
|
163292
163409
|
}
|
|
163293
163410
|
const turnCategory = routingOutcome?.category;
|
|
@@ -165563,20 +165680,8 @@ ${rows.length > 0 ? rows.join(`
|
|
|
165563
165680
|
`;
|
|
165564
165681
|
}
|
|
165565
165682
|
function formatUsage(usage) {
|
|
165566
|
-
|
|
165567
|
-
|
|
165568
|
-
}
|
|
165569
|
-
const parts = [];
|
|
165570
|
-
if (usage.inputTokens !== undefined) {
|
|
165571
|
-
parts.push(`\u2191${usage.inputTokens}`);
|
|
165572
|
-
}
|
|
165573
|
-
if (usage.outputTokens !== undefined) {
|
|
165574
|
-
parts.push(`\u2193${usage.outputTokens}`);
|
|
165575
|
-
}
|
|
165576
|
-
if (parts.length === 0) {
|
|
165577
|
-
return "";
|
|
165578
|
-
}
|
|
165579
|
-
return style.dim(`${parts.join(" ")} tokens`);
|
|
165683
|
+
const line = usage === undefined ? undefined : formatUsageLine(usage);
|
|
165684
|
+
return line === undefined ? "" : style.dim(line);
|
|
165580
165685
|
}
|
|
165581
165686
|
async function runAgentRepl(lines, rich, deps, metaprojectPort, sessionOpts, initialPermissionMode, slateSessionBox = { current: undefined }, events, configDir, orient) {
|
|
165582
165687
|
const out = rich.write ?? ((s) => {
|
|
@@ -166413,6 +166518,8 @@ ${GUTTER}${turnSeparator()}
|
|
|
166413
166518
|
`);
|
|
166414
166519
|
}
|
|
166415
166520
|
}
|
|
166521
|
+
} else if (command === "/tasks") {
|
|
166522
|
+
agentIo.onSystem?.(await runTasksCommand(rest, deps.jobRegistry));
|
|
166416
166523
|
} else if (command === "/demote") {
|
|
166417
166524
|
const parsed = parseDemoteCommand(rest);
|
|
166418
166525
|
if (!parsed.ok) {
|
package/dist/core.js
CHANGED
|
@@ -41212,6 +41212,12 @@ var HELP_GROUPS = [
|
|
|
41212
41212
|
group: "Working in keryx shell",
|
|
41213
41213
|
summary: "Manage the main queue \u2014 /queue <remove|edit|force> [N] (N = qN position, default 1)."
|
|
41214
41214
|
},
|
|
41215
|
+
{
|
|
41216
|
+
kind: "slash",
|
|
41217
|
+
name: "/tasks",
|
|
41218
|
+
group: "Working in keryx shell",
|
|
41219
|
+
summary: "List supervised shell tasks \u2014 /tasks [output <task_id> [cursor] | kill <task_id>]."
|
|
41220
|
+
},
|
|
41215
41221
|
{
|
|
41216
41222
|
kind: "slash",
|
|
41217
41223
|
name: "/interrupt",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.76",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|