@selesai/code 0.8.4 → 0.8.6
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/CHANGELOG.md +22 -0
- package/README.md +7 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/defaults/models.json +46 -55
- package/dist/defaults/settings.json +7 -8
- package/dist/extensions/agent-browser.test.ts +178 -2
- package/dist/extensions/agent-browser.ts +2 -0
- package/dist/extensions/copy-turn.test.ts +229 -0
- package/dist/extensions/copy-turn.ts +11 -0
- package/dist/extensions/grep-app/index.test.ts +356 -1
- package/dist/extensions/grep-app/index.ts +6 -1
- package/dist/extensions/handoff-new.test.ts +351 -161
- package/dist/extensions/handoff-new.ts +3 -0
- package/dist/extensions/inline-skills.test.ts +93 -0
- package/dist/extensions/inline-skills.ts +3 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +26 -3
- package/dist/extensions/pi-subagents/README.md +2 -0
- package/dist/extensions/pi-subagents/agents/builder.md +5 -2
- package/dist/extensions/pi-subagents/agents/commentator.md +1 -1
- package/dist/extensions/pi-subagents/docs/configuration.md +54 -2
- package/dist/extensions/pi-subagents/docs/observability.md +1 -1
- package/dist/extensions/pi-subagents/docs/tool-reference.md +1 -1
- package/dist/extensions/pi-subagents/docs/workflows.md +1 -1
- package/dist/extensions/pi-subagents/package-lock.json +2 -2
- package/dist/extensions/pi-subagents/package.json +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +1 -1
- package/dist/extensions/pi-subagents/src/agents/agents.ts +9 -3
- package/dist/extensions/pi-subagents/src/extension/config.ts +12 -0
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +40 -0
- package/dist/extensions/pi-subagents/src/extension/index.ts +104 -14
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +5 -0
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +3 -9
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +2 -2
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +4 -1
- package/dist/extensions/pi-subagents/src/missions/lifecycle.ts +4 -7
- package/dist/extensions/pi-subagents/src/missions/store.ts +4 -4
- package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +6 -2
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +374 -0
- package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +9 -5
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +117 -29
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +12 -6
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -1
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +14 -5
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +33 -15
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +5 -2
- package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +104 -0
- package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +17 -3
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +19 -1
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +5 -2
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +12 -6
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +84 -36
- package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +37 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +135 -22
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +12 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +7 -4
- package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +171 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +653 -196
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +13 -4
- package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +286 -0
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +23 -0
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +44 -1
- package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +280 -0
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +4 -2
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +19 -3
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +17 -5
- package/dist/extensions/pi-subagents/src/shared/session-lineage.ts +71 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +108 -0
- package/dist/extensions/pi-subagents/src/shared/utils.ts +3 -1
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +7 -5
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +226 -13
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +22 -5
- package/dist/extensions/pi-subagents/src/workflows/workflow-auto-relaunch.ts +28 -0
- package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +87 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +96 -6
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +28 -5
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +8 -5
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +83 -2
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +211 -15
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +41 -3
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +314 -10
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +31 -1
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +317 -0
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +21 -2
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +16 -1
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +6 -1
- package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +75 -4
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +29 -1
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +31 -5
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +139 -1
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
- package/dist/extensions/pi-subagents/test/unit/handoff-adoption.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +22 -0
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +2 -1
- package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +171 -0
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +30 -4
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/owned-process-tree.test.ts +69 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +83 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +55 -2
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +12 -1
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +7 -7
- package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +121 -0
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +9 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +4 -3
- package/dist/extensions/pi-subagents/test/unit/session-lineage.test.ts +73 -0
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +10 -1
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +39 -0
- package/dist/extensions/pi-subagents/test/unit/timeout-defaults.test.ts +65 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-auto-relaunch.test.ts +45 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +61 -0
- package/dist/extensions/ponytail/index.js +11 -0
- package/dist/extensions/ponytail/ponytail-config.cjs +2 -0
- package/dist/extensions/ponytail/ponytail-instructions.cjs +6 -0
- package/dist/extensions/ponytail/test/extension.test.js +274 -140
- package/dist/extensions/ponytail/test/helpers.test.js +280 -92
- package/dist/extensions/question/index.ts +18 -0
- package/dist/extensions/question/question-list.ts +22 -0
- package/dist/extensions/question/tests/batch.test.ts +103 -65
- package/dist/extensions/question/tests/helpers.test.ts +68 -35
- package/dist/extensions/question/tests/question-list.test.ts +506 -204
- package/dist/extensions/question/tests/row-layout.test.ts +180 -114
- package/dist/extensions/question/tests/schemas.test.ts +42 -19
- package/dist/extensions/question/tests/shortcuts.test.ts +106 -84
- package/dist/extensions/question/tests/wizard.test.ts +771 -50
- package/dist/extensions/rtk.test.ts +180 -1
- package/dist/extensions/tokenin-onboarding.ts +3 -0
- package/dist/extensions/undo.test.ts +720 -0
- package/dist/extensions/undo.ts +6 -0
- package/dist/extensions/web-agent-onboarding.test.ts +415 -0
- package/dist/extensions/workflow/extension.ts +3 -3
- package/dist/extensions/workflow/modes.ts +41 -19
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.js +48 -1
- package/dist/skills/pi-subagents/references/execution-controls.md +1 -1
- package/docs/plans/workflow-autoloop-reference.md +1 -2
- package/docs/plans/workflow-handoff-carryover.md +108 -0
- package/docs/quickstart.md +27 -43
- package/docs/settings.md +4 -0
- package/docs/usage.md +1 -0
- package/package.json +5 -1
|
@@ -54,22 +54,25 @@ import {
|
|
|
54
54
|
import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
|
|
55
55
|
import { buildAgentMemoryInjection } from "../../agents/agent-memory.ts";
|
|
56
56
|
import { evaluateCompletionMutationGuard } from "../shared/completion-guard.ts";
|
|
57
|
+
import { arbitrateCompletionGuardRescue } from "../shared/llm-intent-arbiter.ts";
|
|
57
58
|
import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
|
|
58
59
|
import { createJsonlWriter } from "../../shared/jsonl-writer.ts";
|
|
59
60
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
60
61
|
import { resolvePermissionRules } from "../shared/permissions.ts";
|
|
61
|
-
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
|
|
62
|
+
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan, type SubagentTaskDelivery } from "../shared/pi-args.ts";
|
|
62
63
|
import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.ts";
|
|
63
64
|
import { assertAgentAllowedByCapabilityCeiling, decodeSubagentCapabilityCeiling, intersectSubagentCapabilityCeilings, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV } from "../shared/capability-ceiling.ts";
|
|
64
65
|
import { resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
65
66
|
import { MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput } from "../shared/structured-output.ts";
|
|
66
67
|
import { formatProcessSignalError, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
|
|
67
68
|
import { readChildToolDiagnosticError } from "../shared/tool-availability.ts";
|
|
68
|
-
import { captureSingleOutputSnapshot, extractChildWrittenOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, resolveSingleOutput, validateFileOnlyOutputMode, type SingleOutputSnapshot } from "../shared/single-output.ts";
|
|
69
|
+
import { captureSingleOutputSnapshot, extractChildWrittenOutput, finalizeSingleOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, resolveSingleOutput, validateFileOnlyOutputMode, type SingleOutputSnapshot } from "../shared/single-output.ts";
|
|
69
70
|
import {
|
|
70
71
|
buildModelCandidates,
|
|
71
72
|
formatModelAttemptNote,
|
|
73
|
+
formatModelRetryNote,
|
|
72
74
|
isRetryableModelFailure,
|
|
75
|
+
MODEL_RETRY_DELAYS_MS,
|
|
73
76
|
} from "../shared/model-fallback.ts";
|
|
74
77
|
import {
|
|
75
78
|
SUBAGENT_STARTUP_RETRY_DELAYS_MS,
|
|
@@ -90,6 +93,7 @@ import {
|
|
|
90
93
|
summarizeRecentMutatingFailures,
|
|
91
94
|
} from "../shared/long-running-guard.ts";
|
|
92
95
|
import { acceptanceFailureMessage, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport, validateAcceptanceInput } from "../shared/acceptance.ts";
|
|
96
|
+
import { PROMPT_REDACTED } from "../../shared/utils.ts";
|
|
93
97
|
import { attachContractProjections, isAgentContractV1 } from "../shared/agent-contract.ts";
|
|
94
98
|
import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, turnBudgetDecision, turnBudgetDeferredNote, turnBudgetDeferredState, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
|
|
95
99
|
import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
|
|
@@ -117,6 +121,12 @@ function withRunContext<T extends SingleResult>(result: T, context: RunSyncOptio
|
|
|
117
121
|
return result;
|
|
118
122
|
}
|
|
119
123
|
|
|
124
|
+
function redactResultPrompt<T extends SingleResult>(result: T): T {
|
|
125
|
+
result.task = PROMPT_REDACTED;
|
|
126
|
+
if (result.progress) result.progress.task = PROMPT_REDACTED;
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
|
|
120
130
|
function sumUsage(target: Usage, source: Usage): void {
|
|
121
131
|
target.input += source.input;
|
|
122
132
|
target.output += source.output;
|
|
@@ -139,7 +149,7 @@ function persistSingleResultMetadata(input: {
|
|
|
139
149
|
writeMetadata(input.metadataPath, {
|
|
140
150
|
runId: input.runId,
|
|
141
151
|
agent: input.agent,
|
|
142
|
-
task:
|
|
152
|
+
task: PROMPT_REDACTED,
|
|
143
153
|
exitCode: target.exitCode,
|
|
144
154
|
processSignal: target.processSignal,
|
|
145
155
|
usage: target.usage,
|
|
@@ -231,6 +241,7 @@ function stripAcceptanceReportsFromMessages(messages: Message[] | undefined): vo
|
|
|
231
241
|
function snapshotProgress(progress: AgentProgress): AgentProgress {
|
|
232
242
|
return {
|
|
233
243
|
...progress,
|
|
244
|
+
task: PROMPT_REDACTED,
|
|
234
245
|
skills: progress.skills ? [...progress.skills] : undefined,
|
|
235
246
|
recentTools: boundStreamedRecentTools(progress.recentTools),
|
|
236
247
|
recentOutput: boundStreamedRecentOutput(progress.recentOutput),
|
|
@@ -240,6 +251,7 @@ function snapshotProgress(progress: AgentProgress): AgentProgress {
|
|
|
240
251
|
function snapshotResult(result: SingleResult, progress: AgentProgress): SingleResult {
|
|
241
252
|
return {
|
|
242
253
|
...result,
|
|
254
|
+
task: PROMPT_REDACTED,
|
|
243
255
|
messages: result.outputMode === "file-only" && result.savedOutputPath ? undefined : result.messages ? [...result.messages] : undefined,
|
|
244
256
|
usage: { ...result.usage },
|
|
245
257
|
skills: result.skills ? [...result.skills] : undefined,
|
|
@@ -291,6 +303,7 @@ async function runSingleAttempt(
|
|
|
291
303
|
attemptNotes: string[];
|
|
292
304
|
outputSnapshot?: SingleOutputSnapshot;
|
|
293
305
|
originalTask?: string;
|
|
306
|
+
taskDelivery?: SubagentTaskDelivery;
|
|
294
307
|
},
|
|
295
308
|
): Promise<SingleResult> {
|
|
296
309
|
const effectiveThinking = options.thinkingOverride ?? agent.thinking;
|
|
@@ -312,6 +325,7 @@ async function runSingleAttempt(
|
|
|
312
325
|
const { args, env: sharedEnv, tempDir, toolDiagnosticPath, runtimeAcknowledgedExtensionsPath, capabilityAudit } = buildPiArgs({
|
|
313
326
|
baseArgs: ["--mode", "json", "-p"],
|
|
314
327
|
task,
|
|
328
|
+
taskDelivery: shared.taskDelivery,
|
|
315
329
|
sessionEnabled: shared.sessionEnabled,
|
|
316
330
|
sessionDir: options.sessionDir,
|
|
317
331
|
sessionFile: options.sessionFile,
|
|
@@ -337,6 +351,7 @@ async function runSingleAttempt(
|
|
|
337
351
|
parentControlInbox: options.nestedRoute?.controlInbox,
|
|
338
352
|
parentRootRunId: options.nestedRoute?.rootRunId,
|
|
339
353
|
parentCapabilityToken: options.nestedRoute?.capabilityToken,
|
|
354
|
+
runFanoutBudget: options.runFanoutBudget,
|
|
340
355
|
parentSessionId: options.parentSessionId,
|
|
341
356
|
steerInboxDir: options.steerInboxDir,
|
|
342
357
|
steerCapabilityPath: options.steerCapabilityPath,
|
|
@@ -1277,15 +1292,38 @@ async function runSingleAttempt(
|
|
|
1277
1292
|
mcpDirectTools: agent.mcpDirectTools,
|
|
1278
1293
|
})
|
|
1279
1294
|
: undefined;
|
|
1280
|
-
|
|
1295
|
+
let completionGuardTriggered = completionGuard?.triggered === true && !observedMutationAttempt;
|
|
1296
|
+
// The classifier is deliberately narrow, so a read-only review task can
|
|
1297
|
+
// still be misread as implementation. Arbitrate BEFORE any failure side
|
|
1298
|
+
// effect is published (effects, exit code, progress, notifications,
|
|
1299
|
+
// acceptance, output persistence): only a confident read-only verdict
|
|
1300
|
+
// rescues, and the task text alone is evidence — never the child's own
|
|
1301
|
+
// final message.
|
|
1302
|
+
let arbiterRescued = false;
|
|
1303
|
+
if (completionGuardTriggered) {
|
|
1304
|
+
const arbitration = await arbitrateCompletionGuardRescue({
|
|
1305
|
+
guardTriggered: true,
|
|
1306
|
+
task: shared.originalTask ?? task,
|
|
1307
|
+
arbiter: options.llmIntentArbiter,
|
|
1308
|
+
});
|
|
1309
|
+
completionGuardTriggered = arbitration.triggered;
|
|
1310
|
+
arbiterRescued = arbitration.rescued;
|
|
1311
|
+
}
|
|
1281
1312
|
if (completionGuard) {
|
|
1282
1313
|
result.effects = {
|
|
1283
1314
|
...(result.effects ?? {}),
|
|
1284
1315
|
fileMutation: {
|
|
1285
|
-
status: completionGuard.expectedMutation
|
|
1316
|
+
status: completionGuard.expectedMutation
|
|
1317
|
+
? completionGuardTriggered
|
|
1318
|
+
? "missing"
|
|
1319
|
+
: arbiterRescued
|
|
1320
|
+
? "not-applicable"
|
|
1321
|
+
: "observed"
|
|
1322
|
+
: "not-applicable",
|
|
1286
1323
|
expected: completionGuard.expectedMutation,
|
|
1287
1324
|
attempted: completionGuard.attemptedMutation || observedMutationAttempt,
|
|
1288
1325
|
...(completionGuardTriggered ? { message: "Subagent completed without making edits for an implementation task." } : {}),
|
|
1326
|
+
...(arbiterRescued ? { resolvedBy: "llm-intent-arbiter" } : {}),
|
|
1289
1327
|
},
|
|
1290
1328
|
};
|
|
1291
1329
|
}
|
|
@@ -1355,7 +1393,7 @@ async function runSyncCompletion(
|
|
|
1355
1393
|
};
|
|
1356
1394
|
const agent = agents.find((a) => a.name === agentName);
|
|
1357
1395
|
if (!agent) {
|
|
1358
|
-
return withRunContext({
|
|
1396
|
+
return redactResultPrompt(withRunContext({
|
|
1359
1397
|
index: options.index ?? 0,
|
|
1360
1398
|
agent: agentName,
|
|
1361
1399
|
task,
|
|
@@ -1363,12 +1401,12 @@ async function runSyncCompletion(
|
|
|
1363
1401
|
messages: [],
|
|
1364
1402
|
usage: emptyUsage(),
|
|
1365
1403
|
error: `Unknown agent: ${agentName}`,
|
|
1366
|
-
}, options.context);
|
|
1404
|
+
}, options.context));
|
|
1367
1405
|
}
|
|
1368
1406
|
try {
|
|
1369
1407
|
assertAgentAllowedByCapabilityCeiling(agent.name, options.capabilityCeiling);
|
|
1370
1408
|
} catch (error) {
|
|
1371
|
-
return withRunContext({
|
|
1409
|
+
return redactResultPrompt(withRunContext({
|
|
1372
1410
|
index: options.index ?? 0,
|
|
1373
1411
|
agent: agent.name,
|
|
1374
1412
|
task,
|
|
@@ -1377,11 +1415,11 @@ async function runSyncCompletion(
|
|
|
1377
1415
|
usage: emptyUsage(),
|
|
1378
1416
|
error: error instanceof Error ? error.message : String(error),
|
|
1379
1417
|
...(options.capabilityCeiling ? { capabilityCeiling: options.capabilityCeiling } : {}),
|
|
1380
|
-
}, options.context);
|
|
1418
|
+
}, options.context));
|
|
1381
1419
|
}
|
|
1382
1420
|
const acceptanceErrors = validateAcceptanceInput(options.acceptance);
|
|
1383
1421
|
if (acceptanceErrors.length > 0) {
|
|
1384
|
-
return withRunContext({
|
|
1422
|
+
return redactResultPrompt(withRunContext({
|
|
1385
1423
|
index: options.index ?? 0,
|
|
1386
1424
|
agent: agentName,
|
|
1387
1425
|
task,
|
|
@@ -1389,11 +1427,11 @@ async function runSyncCompletion(
|
|
|
1389
1427
|
messages: [],
|
|
1390
1428
|
usage: emptyUsage(),
|
|
1391
1429
|
error: acceptanceErrors.join(" "),
|
|
1392
|
-
}, options.context);
|
|
1430
|
+
}, options.context));
|
|
1393
1431
|
}
|
|
1394
1432
|
const outputModeValidationError = validateFileOnlyOutputMode(options.outputMode, options.outputPath, `Single run (${agentName})`);
|
|
1395
1433
|
if (outputModeValidationError) {
|
|
1396
|
-
return withRunContext({
|
|
1434
|
+
return redactResultPrompt(withRunContext({
|
|
1397
1435
|
index: options.index ?? 0,
|
|
1398
1436
|
agent: agentName,
|
|
1399
1437
|
task,
|
|
@@ -1402,7 +1440,7 @@ async function runSyncCompletion(
|
|
|
1402
1440
|
usage: emptyUsage(),
|
|
1403
1441
|
outputMode: options.outputMode,
|
|
1404
1442
|
error: outputModeValidationError,
|
|
1405
|
-
}, options.context);
|
|
1443
|
+
}, options.context));
|
|
1406
1444
|
}
|
|
1407
1445
|
|
|
1408
1446
|
const shareEnabled = options.share === true;
|
|
@@ -1419,6 +1457,7 @@ async function runSyncCompletion(
|
|
|
1419
1457
|
});
|
|
1420
1458
|
const acceptancePrompt = formatAcceptancePrompt(effectiveAcceptance, { reportOptional: isAgentContractV1(options.agentContract) });
|
|
1421
1459
|
const taskWithAcceptance = acceptancePrompt ? `${task}\n${acceptancePrompt}` : task;
|
|
1460
|
+
options.onEffectivePrompt?.(taskWithAcceptance);
|
|
1422
1461
|
const sessionEnabled = Boolean(options.sessionFile || options.sessionDir) || shareEnabled;
|
|
1423
1462
|
if (options.context === "fork" && options.sessionFile && existsSync(options.sessionFile)) {
|
|
1424
1463
|
alignForkedSessionCwd(options.sessionFile, options.cwd ?? runtimeCwd);
|
|
@@ -1433,7 +1472,7 @@ async function runSyncCompletion(
|
|
|
1433
1472
|
agent.filePath ? path.dirname(agent.filePath) : skillCwd,
|
|
1434
1473
|
);
|
|
1435
1474
|
if (skillNames.some((skill) => skill.trim() === "pi-subagents") && missingSkills.includes("pi-subagents")) {
|
|
1436
|
-
return withRunContext({
|
|
1475
|
+
return redactResultPrompt(withRunContext({
|
|
1437
1476
|
index: options.index ?? 0,
|
|
1438
1477
|
agent: agentName,
|
|
1439
1478
|
task,
|
|
@@ -1441,7 +1480,7 @@ async function runSyncCompletion(
|
|
|
1441
1480
|
messages: [],
|
|
1442
1481
|
usage: emptyUsage(),
|
|
1443
1482
|
error: "Skills not found: pi-subagents",
|
|
1444
|
-
}, options.context);
|
|
1483
|
+
}, options.context));
|
|
1445
1484
|
}
|
|
1446
1485
|
let systemPrompt = agent.systemPrompt?.trim() || "";
|
|
1447
1486
|
if (resolvedSkills.length > 0) {
|
|
@@ -1476,7 +1515,7 @@ async function runSyncCompletion(
|
|
|
1476
1515
|
artifactPathsResult = getArtifactPaths(options.artifactsDir, options.runId, agentName, options.index);
|
|
1477
1516
|
ensureArtifactsDir(options.artifactsDir);
|
|
1478
1517
|
if (options.artifactConfig?.includeInput !== false) {
|
|
1479
|
-
|
|
1518
|
+
writeArtifact(artifactPathsResult.inputPath, `# Task for ${agentName}\n\n${PROMPT_REDACTED}; live Prompt Audit only.\n`);
|
|
1480
1519
|
}
|
|
1481
1520
|
if (options.artifactConfig?.includeJsonl !== false) {
|
|
1482
1521
|
jsonlPath = artifactPathsResult.jsonlPath;
|
|
@@ -1490,7 +1529,7 @@ async function runSyncCompletion(
|
|
|
1490
1529
|
childIndex: options.index,
|
|
1491
1530
|
cwd: options.cwd ?? runtimeCwd,
|
|
1492
1531
|
});
|
|
1493
|
-
transcriptWriter.writeInitialUserMessage(
|
|
1532
|
+
transcriptWriter.writeInitialUserMessage(`${PROMPT_REDACTED}; live Prompt Audit only.`);
|
|
1494
1533
|
}
|
|
1495
1534
|
}
|
|
1496
1535
|
|
|
@@ -1526,6 +1565,10 @@ async function runSyncCompletion(
|
|
|
1526
1565
|
};
|
|
1527
1566
|
let lastResult: SingleResult | undefined;
|
|
1528
1567
|
const modelsToTry = candidates.length > 0 ? candidates : [undefined];
|
|
1568
|
+
let modelRetryIndex = 0;
|
|
1569
|
+
// Escalated to "file" after an unexplained zero-activity startup failure so
|
|
1570
|
+
// retries keep the task text out of argv (endpoint pre-exec scans may deny it).
|
|
1571
|
+
let taskDeliveryOverride: SubagentTaskDelivery | undefined;
|
|
1529
1572
|
modelAttemptsLoop: for (let modelIndex = 0; modelIndex < modelsToTry.length; modelIndex++) {
|
|
1530
1573
|
const candidate = modelsToTry[modelIndex];
|
|
1531
1574
|
for (let startupAttemptIndex = 0; ; startupAttemptIndex++) {
|
|
@@ -1544,6 +1587,7 @@ async function runSyncCompletion(
|
|
|
1544
1587
|
.filter((modelCandidate): modelCandidate is string => Boolean(modelCandidate)),
|
|
1545
1588
|
outputSnapshot,
|
|
1546
1589
|
originalTask: task,
|
|
1590
|
+
taskDelivery: taskDeliveryOverride,
|
|
1547
1591
|
});
|
|
1548
1592
|
lastResult = result;
|
|
1549
1593
|
if (startupAttemptIndex === 0) {
|
|
@@ -1612,6 +1656,10 @@ async function runSyncCompletion(
|
|
|
1612
1656
|
}
|
|
1613
1657
|
break modelAttemptsLoop;
|
|
1614
1658
|
}
|
|
1659
|
+
if (!taskDeliveryOverride && result.processSignal === "SIGKILL") {
|
|
1660
|
+
taskDeliveryOverride = "file";
|
|
1661
|
+
attemptNotes.push("[startup-retry] retrying with file task delivery to keep the task text out of the child process argv.");
|
|
1662
|
+
}
|
|
1615
1663
|
attempt.error = retryNote;
|
|
1616
1664
|
attemptNotes.push(retryNote);
|
|
1617
1665
|
continue;
|
|
@@ -1630,9 +1678,48 @@ async function runSyncCompletion(
|
|
|
1630
1678
|
attempt.error = startupError;
|
|
1631
1679
|
break modelAttemptsLoop;
|
|
1632
1680
|
}
|
|
1633
|
-
if (
|
|
1634
|
-
|
|
1635
|
-
|
|
1681
|
+
if (isRetryableModelFailure(result.error)) {
|
|
1682
|
+
if (modelIndex < modelsToTry.length - 1) {
|
|
1683
|
+
attemptNotes.push(formatModelAttemptNote(attempt, modelsToTry[modelIndex + 1]));
|
|
1684
|
+
modelRetryIndex = 0;
|
|
1685
|
+
break;
|
|
1686
|
+
}
|
|
1687
|
+
const modelRetryDelayMs = MODEL_RETRY_DELAYS_MS[modelRetryIndex];
|
|
1688
|
+
if (modelRetryDelayMs !== undefined) {
|
|
1689
|
+
const retryNote = formatModelRetryNote({
|
|
1690
|
+
model: attempt.model,
|
|
1691
|
+
attempt: modelRetryIndex + 1,
|
|
1692
|
+
maxAttempts: MODEL_RETRY_DELAYS_MS.length + 1,
|
|
1693
|
+
delayMs: modelRetryDelayMs,
|
|
1694
|
+
});
|
|
1695
|
+
const shouldRetry = await waitForSubagentStartupRetry(modelRetryDelayMs, [options.signal, options.interruptSignal]);
|
|
1696
|
+
if (!shouldRetry) {
|
|
1697
|
+
if (options.interruptSignal?.aborted) {
|
|
1698
|
+
result.exitCode = 0;
|
|
1699
|
+
result.interrupted = true;
|
|
1700
|
+
result.error = undefined;
|
|
1701
|
+
result.finalOutput = "Interrupted. Waiting for explicit next action.";
|
|
1702
|
+
if (result.progress) {
|
|
1703
|
+
result.progress.status = "running";
|
|
1704
|
+
result.progress.error = undefined;
|
|
1705
|
+
}
|
|
1706
|
+
} else {
|
|
1707
|
+
const cancellationError = "Subagent model retry cancelled before relaunch.";
|
|
1708
|
+
result.error = cancellationError;
|
|
1709
|
+
result.finalOutput = cancellationError;
|
|
1710
|
+
attempt.error = cancellationError;
|
|
1711
|
+
if (result.progress) result.progress.error = cancellationError;
|
|
1712
|
+
}
|
|
1713
|
+
break modelAttemptsLoop;
|
|
1714
|
+
}
|
|
1715
|
+
attempt.error = retryNote;
|
|
1716
|
+
attemptNotes.push(retryNote);
|
|
1717
|
+
modelRetryIndex += 1;
|
|
1718
|
+
startupAttemptIndex = -1;
|
|
1719
|
+
continue;
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
break modelAttemptsLoop;
|
|
1636
1723
|
}
|
|
1637
1724
|
}
|
|
1638
1725
|
|
|
@@ -1726,13 +1813,39 @@ async function runSyncCompletion(
|
|
|
1726
1813
|
stripAcceptanceReportsFromMessages(result.messages);
|
|
1727
1814
|
if (acceptanceFailure && result.acceptance.explicit && result.exitCode === 0 && !result.interrupted && !result.timedOut && !isAgentContractV1(options.agentContract)) {
|
|
1728
1815
|
result.exitCode = 1;
|
|
1816
|
+
if (result.savedOutputPath) {
|
|
1817
|
+
result.finalOutput = finalizeSingleOutput({
|
|
1818
|
+
fullOutput: result.finalOutput ?? "",
|
|
1819
|
+
outputPath: options.outputPath,
|
|
1820
|
+
outputMode: result.outputMode,
|
|
1821
|
+
exitCode: result.exitCode,
|
|
1822
|
+
preserveSavedOutput: true,
|
|
1823
|
+
savedPath: result.savedOutputPath,
|
|
1824
|
+
outputReference: result.outputReference,
|
|
1825
|
+
}).displayOutput;
|
|
1826
|
+
artifactOutputByResult.set(result, result.finalOutput);
|
|
1827
|
+
}
|
|
1729
1828
|
result.error = result.error ? `${result.error}\n${acceptanceFailure}` : acceptanceFailure;
|
|
1829
|
+
if (artifactPathsResult && options.artifactConfig?.enabled !== false && options.artifactConfig?.includeOutput !== false) {
|
|
1830
|
+
try {
|
|
1831
|
+
writeArtifact(artifactPathsResult.outputPath, formatOutputArtifactContent({
|
|
1832
|
+
output: artifactOutputByResult.get(result) ?? result.finalOutput ?? "",
|
|
1833
|
+
error: result.error,
|
|
1834
|
+
transcriptPath: result.transcriptPath,
|
|
1835
|
+
metadataPath: options.artifactConfig?.includeMetadata === false ? undefined : artifactPathsResult.metadataPath,
|
|
1836
|
+
}));
|
|
1837
|
+
} catch (error) {
|
|
1838
|
+
const message = `Artifact output post-processing failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
1839
|
+
result.outputSaveError = result.outputSaveError ? `${result.outputSaveError}\n${message}` : message;
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1730
1842
|
if (result.progress) {
|
|
1731
1843
|
result.progress.status = "failed";
|
|
1732
1844
|
result.progress.error = result.error;
|
|
1733
1845
|
}
|
|
1734
1846
|
}
|
|
1735
1847
|
if (isAgentContractV1(options.agentContract)) attachContractProjections(result);
|
|
1848
|
+
redactResultPrompt(result);
|
|
1736
1849
|
try {
|
|
1737
1850
|
persistResultMetadata(result);
|
|
1738
1851
|
} catch (error) {
|
|
@@ -1817,7 +1930,7 @@ export async function runSync(
|
|
|
1817
1930
|
durationMs: publishedReceipt.progressSummary?.durationMs ?? 0,
|
|
1818
1931
|
error: failureMessage,
|
|
1819
1932
|
};
|
|
1820
|
-
const failedResult: SingleResult = {
|
|
1933
|
+
const failedResult: SingleResult = redactResultPrompt({
|
|
1821
1934
|
...publishedReceipt,
|
|
1822
1935
|
detached: undefined,
|
|
1823
1936
|
detachedReason,
|
|
@@ -1833,7 +1946,7 @@ export async function runSync(
|
|
|
1833
1946
|
acceptance: publishedReceipt.acceptance
|
|
1834
1947
|
? buildSkippedAcceptanceLedger(publishedReceipt.acceptance.effectiveAcceptance, { id: "completion-pipeline", message: failureMessage })
|
|
1835
1948
|
: undefined,
|
|
1836
|
-
};
|
|
1949
|
+
});
|
|
1837
1950
|
if (strictContract) attachContractProjections(failedResult);
|
|
1838
1951
|
try {
|
|
1839
1952
|
// Replace the provisional detach receipt metadata with the authoritative
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { AgentProgress, ForegroundChildControl, ForegroundRunControl } from "../../shared/types.ts";
|
|
2
|
+
import { registerLivePromptAudit, removeLivePromptAudit, type PromptAuditRerunContract } from "./prompt-audit.ts";
|
|
2
3
|
|
|
3
4
|
interface BeginForegroundChildInput {
|
|
4
5
|
index: number;
|
|
5
6
|
agent: string;
|
|
6
7
|
description?: string;
|
|
8
|
+
authoredTask: string;
|
|
9
|
+
effectivePrompt: string;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
outputPath?: string;
|
|
12
|
+
rerun?: PromptAuditRerunContract;
|
|
7
13
|
model?: string;
|
|
8
14
|
thinking?: string;
|
|
9
15
|
interrupt: () => boolean;
|
|
@@ -109,6 +115,11 @@ export function beginForegroundChild(control: ForegroundRunControl, input: Begin
|
|
|
109
115
|
}
|
|
110
116
|
control.activeChildren ??= new Map();
|
|
111
117
|
control.activeChildren.set(input.index, child);
|
|
118
|
+
registerLivePromptAudit(control, input.index, input.authoredTask, input.effectivePrompt, {
|
|
119
|
+
...(input.cwd ? { cwd: input.cwd } : {}),
|
|
120
|
+
...(input.outputPath ? { outputPath: input.outputPath } : {}),
|
|
121
|
+
...(input.rerun ? { rerun: input.rerun } : {}),
|
|
122
|
+
});
|
|
112
123
|
syncCurrentChild(control, child);
|
|
113
124
|
}
|
|
114
125
|
|
|
@@ -121,6 +132,7 @@ export function updateForegroundChild(control: ForegroundRunControl, index: numb
|
|
|
121
132
|
}
|
|
122
133
|
|
|
123
134
|
export function finishForegroundChild(control: ForegroundRunControl, index: number): void {
|
|
135
|
+
removeLivePromptAudit(control, index);
|
|
124
136
|
control.activeChildren?.delete(index);
|
|
125
137
|
if (control.currentIndex === index) {
|
|
126
138
|
const next = [...(control.activeChildren?.values() ?? [])]
|
|
@@ -121,11 +121,14 @@ export function persistForegroundRunHistory(state: SubagentState, options: { res
|
|
|
121
121
|
writeAtomicJson(historyPath(resultsDir), { version: HISTORY_VERSION, runs });
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
export function restoreForegroundRunHistory(state: SubagentState, options: { resultsDir?: string; sessionId?: string | null; limit?: number } = {}): number {
|
|
125
|
-
const
|
|
126
|
-
|
|
124
|
+
export function restoreForegroundRunHistory(state: SubagentState, options: { resultsDir?: string; sessionId?: string | null; sessionIds?: string[]; limit?: number } = {}): number {
|
|
125
|
+
const sessionIds = options.sessionIds
|
|
126
|
+
?? (options.sessionId ? [options.sessionId] : state.sessionLineage)
|
|
127
|
+
?? (state.currentSessionId ? [state.currentSessionId] : []);
|
|
128
|
+
if (sessionIds.length === 0) return 0;
|
|
129
|
+
const accepted = new Set(sessionIds);
|
|
127
130
|
const index = readIndex(options.resultsDir ?? DIRS.results);
|
|
128
|
-
const runs = sortAndBound(index.runs.filter((run) => run.sessionId
|
|
131
|
+
const runs = sortAndBound(index.runs.filter((run) => run.sessionId !== undefined && accepted.has(run.sessionId)), options.limit ?? MAX_REMEMBERED_FOREGROUND_RUNS);
|
|
129
132
|
state.foregroundRuns ??= new Map();
|
|
130
133
|
let restored = 0;
|
|
131
134
|
for (const run of runs) {
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Agent, type StreamFn, type ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import { convertToLlm, type ExtensionContext } from "@selesai/code";
|
|
3
|
+
import { streamSimple } from "@earendil-works/pi-ai/compat";
|
|
4
|
+
import type { Model } from "@earendil-works/pi-ai";
|
|
5
|
+
import type { ForegroundRunControl } from "../../shared/types.ts";
|
|
6
|
+
export type PromptAuditView = "authored" | "runtime" | "effective";
|
|
7
|
+
|
|
8
|
+
export interface PromptAuditRerunContract {
|
|
9
|
+
params: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface LivePromptAudit {
|
|
13
|
+
authoredTask: string;
|
|
14
|
+
runtimeAdditions: string;
|
|
15
|
+
finalEffectivePrompt: string;
|
|
16
|
+
cwd?: string;
|
|
17
|
+
outputPath?: string;
|
|
18
|
+
rerun?: PromptAuditRerunContract;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const livePrompts = new WeakMap<ForegroundRunControl, Map<number, LivePromptAudit>>();
|
|
22
|
+
|
|
23
|
+
type RegistryModel = Model<any>;
|
|
24
|
+
|
|
25
|
+
function fullModelId(model: Pick<RegistryModel, "provider" | "id">): string {
|
|
26
|
+
return `${model.provider}/${model.id}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function textContent(value: unknown): string {
|
|
30
|
+
if (typeof value === "string") return value;
|
|
31
|
+
if (!Array.isArray(value)) return "";
|
|
32
|
+
return value.map((item) => item && typeof item === "object" && (item as { type?: unknown }).type === "text" ? String((item as { text?: unknown }).text ?? "") : "").join("");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function finalAssistantText(agent: Agent): string {
|
|
36
|
+
for (let index = agent.state.messages.length - 1; index >= 0; index--) {
|
|
37
|
+
const message = agent.state.messages[index];
|
|
38
|
+
if (message && typeof message === "object" && (message as { role?: unknown }).role === "assistant") {
|
|
39
|
+
return textContent((message as { content?: unknown }).content).trim();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return "";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function resolveRewriteAuth(ctx: ExtensionContext, model: RegistryModel): Promise<{ apiKey?: string; headers?: Record<string, string>; env?: Record<string, string> }> {
|
|
46
|
+
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
47
|
+
if (auth.ok === false) throw new Error(`Prompt redo model auth failed for ${fullModelId(model)}: ${auth.error}`);
|
|
48
|
+
return {
|
|
49
|
+
...(auth.apiKey ? { apiKey: auth.apiKey } : {}),
|
|
50
|
+
...(auth.headers ? { headers: auth.headers } : {}),
|
|
51
|
+
...(auth.env ? { env: auth.env } : {}),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function rewritePromptWithGuidance(input: {
|
|
56
|
+
ctx: ExtensionContext;
|
|
57
|
+
authoredTask: string;
|
|
58
|
+
runtimeAdditions: string;
|
|
59
|
+
finalEffectivePrompt: string;
|
|
60
|
+
guidance: string;
|
|
61
|
+
signal?: AbortSignal;
|
|
62
|
+
streamFn?: StreamFn;
|
|
63
|
+
}): Promise<string> {
|
|
64
|
+
const model = input.ctx.model;
|
|
65
|
+
if (!model) throw new Error("Prompt redo needs the current session model to rewrite the authored task.");
|
|
66
|
+
const auth = await resolveRewriteAuth(input.ctx, model);
|
|
67
|
+
const registeredProvider = (input.ctx.modelRegistry as {
|
|
68
|
+
getRegisteredProviderConfig?: (provider: string) => { api?: string; streamSimple?: StreamFn } | undefined;
|
|
69
|
+
}).getRegisteredProviderConfig?.(model.provider);
|
|
70
|
+
const baseStreamFn = input.streamFn ?? (registeredProvider?.streamSimple && registeredProvider.api === model.api
|
|
71
|
+
? registeredProvider.streamSimple
|
|
72
|
+
: streamSimple);
|
|
73
|
+
const streamFn: StreamFn = (nextModel, context, streamOptions) => baseStreamFn(nextModel, context, {
|
|
74
|
+
...streamOptions,
|
|
75
|
+
...(auth.apiKey ? { apiKey: auth.apiKey } : {}),
|
|
76
|
+
env: auth.env || streamOptions?.env ? { ...(auth.env ?? {}), ...(streamOptions?.env ?? {}) } : undefined,
|
|
77
|
+
headers: { ...(streamOptions?.headers ?? {}), ...(auth.headers ?? {}) },
|
|
78
|
+
});
|
|
79
|
+
const ctxThinking = (input.ctx as { getThinkingLevel?: () => ThinkingLevel }).getThinkingLevel?.();
|
|
80
|
+
const agent = new Agent({
|
|
81
|
+
initialState: {
|
|
82
|
+
systemPrompt: [
|
|
83
|
+
"Rewrite one subagent authored task from Prompt Audit context.",
|
|
84
|
+
"Return only the revised authored task text.",
|
|
85
|
+
"Do not add Markdown fences, explanations, labels, or commentary.",
|
|
86
|
+
"Preserve the original intent unless the guidance explicitly changes it.",
|
|
87
|
+
"Do not include runtime additions unless they are needed as ordinary task context.",
|
|
88
|
+
].join("\n"),
|
|
89
|
+
model,
|
|
90
|
+
thinkingLevel: ctxThinking ?? "off",
|
|
91
|
+
tools: [],
|
|
92
|
+
},
|
|
93
|
+
convertToLlm,
|
|
94
|
+
streamFn,
|
|
95
|
+
getApiKey: (providerName) => providerName === model.provider ? auth.apiKey : undefined,
|
|
96
|
+
toolExecution: "sequential",
|
|
97
|
+
});
|
|
98
|
+
const abort = () => agent.abort();
|
|
99
|
+
input.ctx.signal?.addEventListener("abort", abort, { once: true });
|
|
100
|
+
input.signal?.addEventListener("abort", abort, { once: true });
|
|
101
|
+
try {
|
|
102
|
+
await agent.prompt([
|
|
103
|
+
"Guidance from the human:",
|
|
104
|
+
input.guidance.trim(),
|
|
105
|
+
"",
|
|
106
|
+
"Authored task:",
|
|
107
|
+
input.authoredTask,
|
|
108
|
+
"",
|
|
109
|
+
"Runtime additions for context only:",
|
|
110
|
+
input.runtimeAdditions,
|
|
111
|
+
"",
|
|
112
|
+
"Final effective prompt for context only:",
|
|
113
|
+
input.finalEffectivePrompt,
|
|
114
|
+
].join("\n"));
|
|
115
|
+
} finally {
|
|
116
|
+
input.ctx.signal?.removeEventListener("abort", abort);
|
|
117
|
+
input.signal?.removeEventListener("abort", abort);
|
|
118
|
+
}
|
|
119
|
+
const rewritten = finalAssistantText(agent);
|
|
120
|
+
if (!rewritten) throw new Error("Prompt redo rewrite returned an empty prompt.");
|
|
121
|
+
return rewritten;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function runtimeAdditions(authoredTask: string, effectivePrompt: string): string {
|
|
125
|
+
if (!authoredTask) return effectivePrompt;
|
|
126
|
+
const authoredIndex = effectivePrompt.indexOf(authoredTask);
|
|
127
|
+
if (authoredIndex < 0) return "(runtime additions unavailable)";
|
|
128
|
+
const before = effectivePrompt.slice(0, authoredIndex).trim();
|
|
129
|
+
const after = effectivePrompt.slice(authoredIndex + authoredTask.length).trim();
|
|
130
|
+
return [before, after].filter(Boolean).join("\n\n") || "(none)";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function registerLivePromptAudit(
|
|
134
|
+
control: ForegroundRunControl,
|
|
135
|
+
index: number,
|
|
136
|
+
authoredTask: string,
|
|
137
|
+
effectivePrompt: string,
|
|
138
|
+
metadata: { cwd?: string; outputPath?: string; rerun?: PromptAuditRerunContract } = {},
|
|
139
|
+
): void {
|
|
140
|
+
let prompts = livePrompts.get(control);
|
|
141
|
+
if (!prompts) {
|
|
142
|
+
prompts = new Map();
|
|
143
|
+
livePrompts.set(control, prompts);
|
|
144
|
+
}
|
|
145
|
+
prompts.set(index, {
|
|
146
|
+
authoredTask,
|
|
147
|
+
runtimeAdditions: runtimeAdditions(authoredTask, effectivePrompt),
|
|
148
|
+
finalEffectivePrompt: effectivePrompt,
|
|
149
|
+
...(metadata.cwd ? { cwd: metadata.cwd } : {}),
|
|
150
|
+
...(metadata.outputPath ? { outputPath: metadata.outputPath } : {}),
|
|
151
|
+
...(metadata.rerun ? { rerun: metadata.rerun } : {}),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function updateLiveEffectivePrompt(control: ForegroundRunControl, index: number, effectivePrompt: string): void {
|
|
156
|
+
const prompt = livePrompts.get(control)?.get(index);
|
|
157
|
+
if (!prompt) return;
|
|
158
|
+
prompt.finalEffectivePrompt = effectivePrompt;
|
|
159
|
+
prompt.runtimeAdditions = runtimeAdditions(prompt.authoredTask, effectivePrompt);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function getLivePromptAudit(control: ForegroundRunControl, index: number): LivePromptAudit | undefined {
|
|
163
|
+
return livePrompts.get(control)?.get(index);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function removeLivePromptAudit(control: ForegroundRunControl, index: number): void {
|
|
167
|
+
const prompts = livePrompts.get(control);
|
|
168
|
+
if (!prompts) return;
|
|
169
|
+
prompts.delete(index);
|
|
170
|
+
if (prompts.size === 0) livePrompts.delete(control);
|
|
171
|
+
}
|