@ordewell/core 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{IFileSystem-DgpX0BU7.d.mts → IFileSystem-B5asBRDa.d.mts} +1 -1
- package/dist/{IFileSystem-D4ADfTrX.d.ts → IFileSystem-CbCmUDBn.d.ts} +1 -1
- package/dist/{ModeResolver-Cv01ZDd9.d.mts → ModeResolver-DcqAho4y.d.mts} +1 -1
- package/dist/{ModeResolver-BEcRAz1c.d.ts → ModeResolver-DtfhWeVL.d.ts} +1 -1
- package/dist/{Task-CoKhvBa1.d.mts → Task-BpzIbunq.d.mts} +146 -22
- package/dist/{Task-CoKhvBa1.d.ts → Task-BpzIbunq.d.ts} +146 -22
- package/dist/{chunk-LSGY7AIZ.mjs → chunk-AJ5KDO6V.mjs} +219 -77
- package/dist/chunk-AJ5KDO6V.mjs.map +1 -0
- package/dist/chunk-H5O74L77.mjs +185 -0
- package/dist/chunk-H5O74L77.mjs.map +1 -0
- package/dist/{chunk-YU4UKKKI.mjs → chunk-MZYZS7B3.mjs} +14 -186
- package/dist/chunk-MZYZS7B3.mjs.map +1 -0
- package/dist/{chunk-J3YSTPCE.mjs → chunk-OUIQWNS3.mjs} +8 -5
- package/dist/chunk-OUIQWNS3.mjs.map +1 -0
- package/dist/{chunk-N66ZHFGN.mjs → chunk-OYUSADFM.mjs} +11 -1
- package/dist/chunk-OYUSADFM.mjs.map +1 -0
- package/dist/{chunk-HPNUFBIT.mjs → chunk-V3JHS7AX.mjs} +9 -1
- package/dist/chunk-V3JHS7AX.mjs.map +1 -0
- package/dist/index.d.mts +909 -459
- package/dist/index.d.ts +909 -459
- package/dist/index.js +5671 -3776
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5548 -3795
- package/dist/index.mjs.map +1 -1
- package/dist/order-labels.d.mts +15 -2
- package/dist/order-labels.d.ts +15 -2
- package/dist/order-labels.js +12 -2
- package/dist/order-labels.js.map +1 -1
- package/dist/order-labels.mjs +7 -3
- package/dist/{parsing-DMdOq-BV.d.ts → parsing-COFGUEWx.d.ts} +2 -2
- package/dist/{parsing-B4OCHH1_.d.mts → parsing-D0uo-Icd.d.mts} +2 -2
- package/dist/parsing.d.mts +3 -3
- package/dist/parsing.d.ts +3 -3
- package/dist/parsing.js +6 -3
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +4 -3
- package/dist/{plan-utils-CD1Xu65s.d.mts → plan-utils-CdW3mxt5.d.mts} +226 -9
- package/dist/{plan-utils-BdYPRBno.d.ts → plan-utils-D4Z8UyLL.d.ts} +226 -9
- package/dist/plan-utils.d.mts +4 -3
- package/dist/plan-utils.d.ts +4 -3
- package/dist/plan-utils.js +210 -3
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +44 -3
- package/dist/testing.d.mts +17 -5
- package/dist/testing.d.ts +17 -5
- package/dist/testing.js +50 -3
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +50 -5
- package/dist/testing.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-HPNUFBIT.mjs.map +0 -1
- package/dist/chunk-J3YSTPCE.mjs.map +0 -1
- package/dist/chunk-LSGY7AIZ.mjs.map +0 -1
- package/dist/chunk-N66ZHFGN.mjs.map +0 -1
- package/dist/chunk-YU4UKKKI.mjs.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { d as AgentAdapterFactory, i as AllProviderModels, l as ApprovalKind, o as ApprovalPolicyOptions, q as ApprovalSource, B as BlockingPrompt, C as CMD_EXE_MAX_COMMAND_LINE, s as CatalogModel, u as CheckpointArgs, v as CommandLineTooLongError, D as
|
|
3
|
-
import {
|
|
4
|
-
export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DiffRow, e as DiffRowKind, f as DiffStat, g as DisplayBlock, E as EMPTY_CONVERSATION, h as EMPTY_HOLD, i as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry,
|
|
5
|
-
import { I as IFileSystem, R as ReadFileOpts, T as ToolOutcome, b as GrepOptions, a as GlobOptions, F as FindSymbolOptions } from './IFileSystem-
|
|
6
|
-
export { G as GREP_DEFAULT_HEAD_LIMIT, c as GrepOutputMode, S as SEARCH_EXCLUSIONS } from './IFileSystem-
|
|
7
|
-
import { R as RunnerModeInfo } from './ModeResolver-
|
|
8
|
-
export { M as ManifestLookup, a as autonomyLevelLabel, b as buildModeGuide, f as filteredBuildModes, p as parseAutonomyLevel, r as resolveDefaultMode, c as resolveTaskMode, d as runnerModesFrom } from './ModeResolver-
|
|
1
|
+
import { b0 as RunnerId, ay as PlanStatus, ac as LegacyPlanState, M as IApproval, p as ApprovalRequest, k as ApprovalDecision, j as ApprovalAnswer, P as ITerminalRunner, N as IConfig, h as AiProvider, aN as ProviderModelLists, m as ApprovalMode, $ as IsolationMergeResult, X as IsolationLandedTask, R as IWorktreeIsolation, a8 as IsolationTaskStatus, av as PlanIsolation, b5 as RunnerTransport, aV as RepoGroupLayout, Q as ITerminalSession, z as DiscoveredModel, bi as Task, f as AgentProcessDeps, c as AgentAdapter, as as OrdewellMcpServer, aX as ResearchProgress, aW as ResearchLogEntry, w as ConversationMessage, aB as PlannerToolHandler, bF as UsageRecord, bu as TaskSnapshot, r as AwaitingReason, U as IsolationHandoff, a4 as IsolationRun, a5 as IsolationTaskRecord, bk as TaskIsolation, a9 as IsolationView, a0 as IsolationOutcome, aU as RepairEvidence, bD as TreeSnapshot, bM as Verdict, b3 as RunnerRegistry, aS as QueuedTaskMessage, aR as QueuedMessage, b as ActiveTaskSession, ar as OrchestratorOption, bn as TaskModeAgentAdapter, g as AgentStartOptions, e as AgentEvent, a_ as ResearchToolType, aC as PlannerUsage, n as ApprovalPolicy, ax as PlanState, bj as TaskCompleteArgs, t as CheckpointAnswer, b1 as RunnerInvocation, A as AbstractRunner, a as AbstractTerminalSession, b6 as RunnerVersionProbe, bb as StructuredSessionCapability, bv as TaskStartOptions, bx as TaskTokenScope, bc as StructuredTurnEnd, ba as StructuredEvent, b4 as RunnerSpawnOptions, O as IPluginStore, b2 as RunnerPluginManifest, a$ as ResolveContext, bt as TaskRunnerFlags } from './Task-BpzIbunq.js';
|
|
2
|
+
export { d as AgentAdapterFactory, i as AllProviderModels, l as ApprovalKind, o as ApprovalPolicyOptions, q as ApprovalSource, B as BlockingPrompt, C as CMD_EXE_MAX_COMMAND_LINE, s as CatalogModel, u as CheckpointArgs, v as CommandLineTooLongError, D as DEFAULT_RUNNERS, x as DENY_ALL, y as DiscoveredMode, E as DiscoveryCommand, F as EditPlanArgs, G as EmbeddedNewlineError, H as ExecutableNotFoundError, I as FetchAllProviderModelsOptions, J as HeadlessRunner, K as HeadlessRunnerDeps, L as HeadlessSession, S as IntegrationDisposal, T as IsolationAvailability, V as IsolationHandoffRepo, W as IsolationInactiveReason, Y as IsolationLanding, Z as IsolationMergeBlock, _ as IsolationMergeBlockReason, a1 as IsolationPruneResult, a2 as IsolationRemoval, a3 as IsolationRepo, a6 as IsolationTaskRef, a7 as IsolationTaskRepo, aa as LaunchDeps, ab as LaunchPlan, ad as LineBuffer, ae as ListModelsArgs, af as ListRunnersArgs, ag as McpClientConfig, ah as McpCredential, ai as McpTool, aj as McpToolContext, ak as McpToolReply, al as Message, am as ModelCatalog, an as ModelShortcut, ao as ORCHESTRATOR_SHORTCUTS, ap as ORDEWELL_MCP_PATH, aq as ORDEWELL_MCP_SERVER_NAME, at as OwnerOnlyFile, au as PLANNER_TOOLS, aw as PlanModificationWarnings, az as PlannerStartOptions, aA as PlannerTokenScope, aD as PluginCloneFn, aE as PluginEntry, aF as PluginFeatures, aG as PluginMode, aH as PluginModelDiscovery, aI as PluginRunnerDef, aJ as PreparedLaunch, aK as PreparedTask, aL as PreservedWork, aM as ProviderCredentialSource, aO as ProviderModelsResult, aP as PtySize, aQ as PtyWrapOptions, aT as RefusedRemoval, aY as ResearchStep, aZ as ResearchStepOutcome, b7 as StreamEvent, b8 as StreamStepEvent, b9 as StreamThinkingEvent, bd as SubagentLogEntry, be as SubagentOutcome, bf as SubmitPlanArgs, bg as TASK_COMPLETE_TOOL, bh as TASK_TOOLS, bl as TaskIsolationState, bm as TaskMode, bo as TaskModeUnsupportedError, bp as TaskModelAssignment, bq as TaskOutputArgs, br as TaskOutputSummary, bs as TaskQueryArgs, bw as TaskStatus, by as TaskToolHandler, bz as TaskTransport, bA as TaskType, bB as TaskWithParent, bC as ThinkingBlock, bE as UsageLine, bG as UsageTotals, bH as UserPromptEntry, bI as UserStep, bJ as ValidationCheck, bK as ValidationContext, bL as ValidationResult, bN as VerificationCheck, bO as WINDOWS_MAX_COMMAND_LINE, bP as addPlannerUsage, bQ as addTaskToPlan, bR as addUsage, bS as approvalScopes, bT as buildShellInvocation, bU as collectProviderCredentials, bV as createEmptyPlan, bW as createTask, bX as emptyWarnings, bY as enabledRunners, bZ as fetchAllProviderModels, b_ as flattenTasks, b$ as flattenTasksWithParents, c0 as inheritedOps, c1 as isAwaitingReason, c2 as isExecutableResolved, c3 as isGranted, c4 as isMeasured, c5 as isReservedRunnerName, c6 as isRunnerApproval, c7 as isRunnerTransport, c8 as isStructuredSession, c9 as keepExecutionState, ca as knownModelId, cb as mcpClientConfig, cc as migrateLegacyPlan, cd as migratePlanState, ce as migrateTask, cf as opsFlag, cg as ownerOnlyConfigFile, ch as partedPromptUsage, ci as planDirectLaunch, cj as planShellLaunch, ck as plannerContextFill, cl as posixShellQuote, cm as removeTaskFromPlan, cn as renumberTasks, co as resolveModelShortcut, cp as resolveProvider, cq as sharedMcpServer, cr as stripAnsi, cs as toApprovalDecision, ct as toOrchestratorOptions, cu as updateTaskInPlan, cv as usageLine, cw as validateModifiedPlan, cx as warningsText, cy as windowsCommandLine, cz as wrapWithPty } from './Task-BpzIbunq.js';
|
|
3
|
+
import { B as TaskOp, M as MergeGateView, j as EditCatalog, s as SessionBroadcaster, A as ApplyTaskOpsResult, t as SessionMessage, u as SessionNotice, y as TaskLogEvent } from './plan-utils-D4Z8UyLL.js';
|
|
4
|
+
export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DiffRow, e as DiffRowKind, f as DiffStat, g as DisplayBlock, E as EMPTY_CONVERSATION, h as EMPTY_HOLD, i as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry, k as MessageBlock, l as MessageRole, N as NOT_STARTED, m as NO_TURN, n as NewTaskFields, O as OutputPreview, P as PlanBlock, o as PlanMarkerStatus, p as PromptHold, S as SerializedPlan, q as SerializedTask, r as SerializedTaskStatus, v as SubagentBlock, w as SubagentChild, x as SubagentStatus, T as TakenPrompt, z as TaskLogView, F as TaskRef, H as TaskRowAction, I as TaskRowContext, J as TaskRowIsolation, K as TaskRowKind, Q as TaskRowPlacement, R as TaskRowSubject, U as TaskRowView, V as TaskStatusKind, W as ThinkingDisplayBlock, X as ToolBlock, Y as ToolHeadline, Z as ToolStatus, _ as TurnGate, $ as UsageBlock, a0 as aheadOfDraft, a1 as applyTaskOps, a2 as approvalLabel, a3 as awaitingLabel, a4 as canMergeTasks, a5 as canSetDependencies, a6 as canSplitTask, a7 as capConflictFiles, a8 as classifyOutcome, a9 as coalesceTaskLog, aa as dependencyCandidates, ab as dependentsNotice, ac as dependentsOf, ad as diffRows, ae as diffStat, af as diffSummary, ag as digestTaskLog, ah as drainNext, ai as executionSummary, aj as followTurn, ak as fromTranscript, al as hasHiddenDetail, am as holdPrompt, an as isTaskRunning, ao as markAction, ap as markRequestFor, aq as namedRepos, ar as newTaskFields, as as opsEditable, at as outputLines, au as outputPreview, av as parseTaskOpsJson, aw as pastGateConfirmation, ax as reduceConversation, ay as reduceTaskLog, az as replayTaskLog, aA as runnerToolSubject, aB as serializePlan, aC as serializeTask, aD as serializeTaskStatus, aE as stopTurn, aF as summarizeToolCall, aG as taskRowActions, aH as taskRowView, aI as taskStartedNotice, aJ as taskStatusKind, aK as textHasTaskOps, aL as titledRefs, aM as toTaskLogEvent, aN as toolHeadline, aO as trimToolOutput, aP as truncateCheckpointSummary, aQ as unsendAll, aR as unsendLatest } from './plan-utils-D4Z8UyLL.js';
|
|
5
|
+
import { I as IFileSystem, R as ReadFileOpts, T as ToolOutcome, b as GrepOptions, a as GlobOptions, F as FindSymbolOptions } from './IFileSystem-CbCmUDBn.js';
|
|
6
|
+
export { G as GREP_DEFAULT_HEAD_LIMIT, c as GrepOutputMode, S as SEARCH_EXCLUSIONS } from './IFileSystem-CbCmUDBn.js';
|
|
7
|
+
import { R as RunnerModeInfo } from './ModeResolver-DtfhWeVL.js';
|
|
8
|
+
export { M as ManifestLookup, a as autonomyLevelLabel, b as buildModeGuide, f as filteredBuildModes, p as parseAutonomyLevel, r as resolveDefaultMode, c as resolveTaskMode, d as runnerModesFrom } from './ModeResolver-DtfhWeVL.js';
|
|
9
9
|
import { ChildProcess } from 'child_process';
|
|
10
|
-
import { b as PlanParseError } from './parsing-
|
|
11
|
-
export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, c as PlanTaskError, d as PlanTasksResult, T as TASK_OPS_ENVELOPE_KEY, e as TASK_QUERY_ENVELOPE_KEY, f as checkDepsResolve, g as checkImmutableLog, h as checkInProgress, i as checkNoCycles, j as checkUniqueIds, k as escapeControlCharsInStrings, l as extractJsonObject, m as extractObjectWithBalance, n as extractObjectsWithKey, o as looksLikePlanAttempt, p as opensWithJsonObject, q as parsePartialPlan, r as parsePlanJson, s as stripModelNoise, t as stripTrailingCommas, v as validatePlanModification, u as validatePlanTasks } from './parsing-
|
|
12
|
-
export { resolveOrderLabel, taskOrderLabel } from './order-labels.js';
|
|
10
|
+
import { b as PlanParseError } from './parsing-COFGUEWx.js';
|
|
11
|
+
export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, c as PlanTaskError, d as PlanTasksResult, T as TASK_OPS_ENVELOPE_KEY, e as TASK_QUERY_ENVELOPE_KEY, f as checkDepsResolve, g as checkImmutableLog, h as checkInProgress, i as checkNoCycles, j as checkUniqueIds, k as escapeControlCharsInStrings, l as extractJsonObject, m as extractObjectWithBalance, n as extractObjectsWithKey, o as looksLikePlanAttempt, p as opensWithJsonObject, q as parsePartialPlan, r as parsePlanJson, s as stripModelNoise, t as stripTrailingCommas, v as validatePlanModification, u as validatePlanTasks } from './parsing-COFGUEWx.js';
|
|
12
|
+
export { resolveOrderLabel, taskOrderLabel, taskRef, titledTaskRef } from './order-labels.js';
|
|
13
13
|
import 'events';
|
|
14
14
|
import 'zod/v4';
|
|
15
15
|
|
|
@@ -650,6 +650,7 @@ type GitExecFn = (file: string, args: string[], opts: {
|
|
|
650
650
|
stdout: string;
|
|
651
651
|
stderr: string;
|
|
652
652
|
}>;
|
|
653
|
+
|
|
653
654
|
interface WorktreeIsolationDeps {
|
|
654
655
|
config: Pick<IConfig, 'worktreeIsolation' | 'worktreeSetupCommand' | 'workspaceRepos' | 'worktreeLinks'>;
|
|
655
656
|
/** Test seam: every git invocation goes through this. */
|
|
@@ -1106,10 +1107,13 @@ interface ConversationRequest {
|
|
|
1106
1107
|
* atomically and answers queries out of its own state; the AI service only
|
|
1107
1108
|
* parses them.
|
|
1108
1109
|
*/
|
|
1109
|
-
type ConversationTurn =
|
|
1110
|
+
type ConversationTurn =
|
|
1111
|
+
/** `aborted`: the call was stopped, and `text` is only what it had by then. */
|
|
1112
|
+
{
|
|
1110
1113
|
kind: 'message';
|
|
1111
1114
|
text: string;
|
|
1112
1115
|
researchLog: ResearchLogEntry[];
|
|
1116
|
+
aborted?: boolean;
|
|
1113
1117
|
} | {
|
|
1114
1118
|
kind: 'plan';
|
|
1115
1119
|
tasks: Task[];
|
|
@@ -1464,15 +1468,6 @@ declare class PlanStore {
|
|
|
1464
1468
|
setTaskVerdict(id: string, verdict: Task['verdict']): void;
|
|
1465
1469
|
setTaskOutputSummary(id: string, summary: Task['outputSummary']): void;
|
|
1466
1470
|
setTaskTransport(id: string, transport: Task['transport']): void;
|
|
1467
|
-
getPlanVisualization(): {
|
|
1468
|
-
tasks: {
|
|
1469
|
-
id: string;
|
|
1470
|
-
title: string;
|
|
1471
|
-
dependencies: string[];
|
|
1472
|
-
parallelGroups: number[][];
|
|
1473
|
-
}[];
|
|
1474
|
-
parallelGroups: number[][];
|
|
1475
|
-
};
|
|
1476
1471
|
/**
|
|
1477
1472
|
* Widen the plan's runner set. Retargeting a task onto a runner the plan has
|
|
1478
1473
|
* not used before has to land here as well as on the plan state, or
|
|
@@ -1517,6 +1512,12 @@ interface IsolationRunControllerDeps {
|
|
|
1517
1512
|
notifications: INotification;
|
|
1518
1513
|
workspaceRoot: () => string;
|
|
1519
1514
|
listener: IsolationRunListener;
|
|
1515
|
+
/**
|
|
1516
|
+
* The tasks no clean-up of the whole run may take a worktree from: an
|
|
1517
|
+
* attempt is running them, or the plan has them in progress or waiting on
|
|
1518
|
+
* the user mid-attempt.
|
|
1519
|
+
*/
|
|
1520
|
+
liveTasks: () => ReadonlySet<string>;
|
|
1520
1521
|
}
|
|
1521
1522
|
/**
|
|
1522
1523
|
* The lifecycle of a plan's isolation run (ADR-0013, ADR-0014, ADR-0020),
|
|
@@ -1533,6 +1534,7 @@ declare class IsolationRunController {
|
|
|
1533
1534
|
private readonly notifications;
|
|
1534
1535
|
private readonly workspaceRoot;
|
|
1535
1536
|
private readonly listener;
|
|
1537
|
+
private readonly liveTasks;
|
|
1536
1538
|
private run;
|
|
1537
1539
|
/** Copied paths already reported for the current run: every task gets the same copies. */
|
|
1538
1540
|
private reportedCopies;
|
|
@@ -1545,6 +1547,8 @@ declare class IsolationRunController {
|
|
|
1545
1547
|
/** Resolver task id → the conflicted task it resolves; see {@link linkResolver}. */
|
|
1546
1548
|
private resolvers;
|
|
1547
1549
|
private opening;
|
|
1550
|
+
/** Bumped by an interrupt, so an activation in flight across it does not open the run it ended. */
|
|
1551
|
+
private activations;
|
|
1548
1552
|
/** The start a dirty tree turned away, handed back once the user chooses how to go on. */
|
|
1549
1553
|
private blockedStart;
|
|
1550
1554
|
/** The dirty repos behind {@link blockedStart}, for the stash notice. */
|
|
@@ -1561,6 +1565,7 @@ declare class IsolationRunController {
|
|
|
1561
1565
|
get blocked(): boolean;
|
|
1562
1566
|
/** What the plan persists of isolated execution; null when no run ever isolated. */
|
|
1563
1567
|
get planIsolation(): PlanIsolation | null;
|
|
1568
|
+
/** The one guard of every action on the run: a plan that never isolated is a request refused, not a fault. */
|
|
1564
1569
|
requireRun(): IsolationRun;
|
|
1565
1570
|
/** A task's record in the open run, only while that run isolates. */
|
|
1566
1571
|
openRecord(taskId: string): IsolationTaskRecord | undefined;
|
|
@@ -1604,20 +1609,27 @@ declare class IsolationRunController {
|
|
|
1604
1609
|
*/
|
|
1605
1610
|
continueBlocked(how: 'stash' | 'shared'): Promise<(() => Promise<void>) | null>;
|
|
1606
1611
|
/**
|
|
1607
|
-
* The
|
|
1608
|
-
*
|
|
1609
|
-
*
|
|
1610
|
-
*
|
|
1611
|
-
*
|
|
1612
|
-
* is
|
|
1612
|
+
* The working directory of an attempt that may run in a worktree — which
|
|
1613
|
+
* attempts do is the attempt kind's to say (see `attemptKind.attemptCwd`):
|
|
1614
|
+
* the worktree prepared for it in an isolated run, the kept one for a
|
|
1615
|
+
* conflict repair, else the workspace root. `worktree` says which. Does not
|
|
1616
|
+
* itself report a worktree it creates as a change — the caller does once
|
|
1617
|
+
* the attempt is committed as running, so a spawn abandoned or failed after
|
|
1618
|
+
* this settles is not misreported as a change that stuck.
|
|
1613
1619
|
*/
|
|
1614
1620
|
attemptCwd(task: Task, opts: {
|
|
1615
1621
|
repair: boolean;
|
|
1616
|
-
ops?: boolean;
|
|
1617
1622
|
}): Promise<{
|
|
1618
1623
|
cwd: string;
|
|
1619
1624
|
worktree: boolean;
|
|
1620
1625
|
}>;
|
|
1626
|
+
/** The workspace root, for an attempt that runs outside any worktree. */
|
|
1627
|
+
workspaceCwd(task: Task): Promise<{
|
|
1628
|
+
cwd: string;
|
|
1629
|
+
worktree: boolean;
|
|
1630
|
+
}>;
|
|
1631
|
+
private reopenCwd;
|
|
1632
|
+
private prepareCwd;
|
|
1621
1633
|
/**
|
|
1622
1634
|
* Land a task's work on the run's integration branches. The record is
|
|
1623
1635
|
* reported changed once the landing is set and before the first merge, so
|
|
@@ -1654,10 +1666,11 @@ declare class IsolationRunController {
|
|
|
1654
1666
|
*/
|
|
1655
1667
|
refreshInHead(): Promise<boolean>;
|
|
1656
1668
|
/**
|
|
1657
|
-
* The tracked state of the workspace as an
|
|
1658
|
-
* {@link filesChangedSince}
|
|
1659
|
-
*
|
|
1660
|
-
* it, or a workspace git
|
|
1669
|
+
* The tracked state of the workspace as an attempt whose tree is checked
|
|
1670
|
+
* starts (see `attemptKind.checksTree`), for {@link filesChangedSince}
|
|
1671
|
+
* (ADR-0020). Null where the check does not run: a run that shares the
|
|
1672
|
+
* workspace root, where every task's edits land in it, or a workspace git
|
|
1673
|
+
* cannot isolate at all.
|
|
1661
1674
|
*/
|
|
1662
1675
|
snapshotWorkspace(): Promise<TreeSnapshot | null>;
|
|
1663
1676
|
/** Tracked files changed since `snapshot`; none when the run has since gone on in the workspace root. */
|
|
@@ -1672,7 +1685,9 @@ declare class IsolationRunController {
|
|
|
1672
1685
|
/**
|
|
1673
1686
|
* Mark which added task resolves which conflict. The resolver merges the
|
|
1674
1687
|
* conflicted task's branch by hand in its own worktree; once that lands, the
|
|
1675
|
-
* conflicted task can land in turn
|
|
1688
|
+
* conflicted task can land in turn — through the same merge, so a resolver
|
|
1689
|
+
* that did not really bring it along conflicts again instead of being taken
|
|
1690
|
+
* at its word.
|
|
1676
1691
|
*/
|
|
1677
1692
|
linkResolver(resolverId: string, conflictedId: string): void;
|
|
1678
1693
|
/** The conflicted task a landed resolver was added for, forgotten as it is returned. */
|
|
@@ -1687,11 +1702,28 @@ declare class IsolationRunController {
|
|
|
1687
1702
|
* HEAD somehow does not contain stays for the next run's sweep.
|
|
1688
1703
|
*/
|
|
1689
1704
|
merge(): Promise<IsolationMergeResult>;
|
|
1690
|
-
/**
|
|
1705
|
+
/**
|
|
1706
|
+
* Worktrees and task branches go; the integration branch and the record stay
|
|
1707
|
+
* for review and merge. Refused while a task of the run is still live.
|
|
1708
|
+
*/
|
|
1691
1709
|
cleanup(): Promise<void>;
|
|
1692
|
-
/**
|
|
1710
|
+
/**
|
|
1711
|
+
* The run and everything it made go, and the plan forgets it; the next run
|
|
1712
|
+
* starts afresh. Refused while a task of the run is still live.
|
|
1713
|
+
*/
|
|
1693
1714
|
discard(): Promise<void>;
|
|
1715
|
+
/** The records of tasks still live, whose worktrees no clean-up of the whole run may take. */
|
|
1716
|
+
private liveRecords;
|
|
1717
|
+
private refuseWhileLive;
|
|
1718
|
+
/**
|
|
1719
|
+
* Clear a settled run up once everything it landed is merged — and only
|
|
1720
|
+
* when nothing else is left in it: a live task, or a worktree holding work
|
|
1721
|
+
* that never landed, keeps the whole run, worktrees and branches, rather
|
|
1722
|
+
* than leaving that work to a deletion.
|
|
1723
|
+
*/
|
|
1694
1724
|
private clearMerged;
|
|
1725
|
+
/** Say what a removal kept back instead of deleting: where the work went, or which worktree stayed. */
|
|
1726
|
+
private report;
|
|
1695
1727
|
private forget;
|
|
1696
1728
|
private assess;
|
|
1697
1729
|
private activate;
|
|
@@ -1711,6 +1743,10 @@ declare class IsolationRunController {
|
|
|
1711
1743
|
* whole. One that cannot be continued for another reason — it ran from a
|
|
1712
1744
|
* different workspace path — keeps its integration branch in each repo that
|
|
1713
1745
|
* has not merged it: only the user gives landed work up.
|
|
1746
|
+
*
|
|
1747
|
+
* False when `interrupted` came while git was minting: a newer activation
|
|
1748
|
+
* may be minting its own run, so this one is never installed over it, and
|
|
1749
|
+
* is discarded rather than left as branches no record names.
|
|
1714
1750
|
*/
|
|
1715
1751
|
private mint;
|
|
1716
1752
|
private reportCopies;
|
|
@@ -1862,7 +1898,7 @@ interface OrchestratorObserver {
|
|
|
1862
1898
|
}): void;
|
|
1863
1899
|
onTick?(): void;
|
|
1864
1900
|
onExecutionComplete?(): void;
|
|
1865
|
-
/**
|
|
1901
|
+
/** The run is parked behind queued user messages, with nothing live, until they are drained. */
|
|
1866
1902
|
onQueueReady?(): void;
|
|
1867
1903
|
onReviewNeeded?(data: {
|
|
1868
1904
|
tasks: Task[];
|
|
@@ -1916,9 +1952,9 @@ interface TaskAttemptSnapshot {
|
|
|
1916
1952
|
}
|
|
1917
1953
|
/**
|
|
1918
1954
|
* The wiring a {@link TaskOrchestrator} runs on, every collaborator resolved.
|
|
1919
|
-
* {@link
|
|
1920
|
-
* through
|
|
1921
|
-
*
|
|
1955
|
+
* {@link TaskOrchestrator.compose} is the only production caller; tests build
|
|
1956
|
+
* one through it too. The constructor makes nothing itself, so there is exactly
|
|
1957
|
+
* one place defaults live.
|
|
1922
1958
|
*/
|
|
1923
1959
|
interface TaskOrchestratorDeps {
|
|
1924
1960
|
config: IConfig;
|
|
@@ -1943,9 +1979,9 @@ interface TaskOrchestratorDeps {
|
|
|
1943
1979
|
previousAttemptFromLog: (taskId: string) => string | null;
|
|
1944
1980
|
}
|
|
1945
1981
|
/**
|
|
1946
|
-
* What a caller supplies to {@link
|
|
1947
|
-
* gets its default there. This is what a host or test chooses, not the
|
|
1948
|
-
* wiring the orchestrator itself runs on.
|
|
1982
|
+
* What a caller supplies to {@link TaskOrchestrator.compose}; every optional
|
|
1983
|
+
* one gets its default there. This is what a host or test chooses, not the
|
|
1984
|
+
* resolved wiring the orchestrator itself runs on.
|
|
1949
1985
|
*/
|
|
1950
1986
|
interface TaskOrchestratorOptions {
|
|
1951
1987
|
config: IConfig;
|
|
@@ -2008,8 +2044,18 @@ declare class TaskOrchestrator {
|
|
|
2008
2044
|
* task whose spawn always throws.
|
|
2009
2045
|
*/
|
|
2010
2046
|
private onHold;
|
|
2011
|
-
/**
|
|
2012
|
-
|
|
2047
|
+
/**
|
|
2048
|
+
* Tasks Mark complete is landing after it ended their attempt: in progress
|
|
2049
|
+
* with no attempt for as long as that takes, and not orphans for it.
|
|
2050
|
+
*/
|
|
2051
|
+
private completing;
|
|
2052
|
+
/**
|
|
2053
|
+
* The plan's isolation run and the open run's lifecycle (ADR-0013); see
|
|
2054
|
+
* {@link IsolationRunController}. Read and acted on there directly, except
|
|
2055
|
+
* Merge all: that goes through {@link mergeRun}, which keeps it apart from
|
|
2056
|
+
* ops tasks and starts the tasks its merge lets through.
|
|
2057
|
+
*/
|
|
2058
|
+
readonly runs: IsolationRunController;
|
|
2013
2059
|
/** A passed attempt's work onto the integration branch, and the conflict repair a landing may need. */
|
|
2014
2060
|
private landing;
|
|
2015
2061
|
private registry;
|
|
@@ -2054,13 +2100,24 @@ declare class TaskOrchestrator {
|
|
|
2054
2100
|
private envForTask;
|
|
2055
2101
|
approveCheckpoint(taskId: string): void;
|
|
2056
2102
|
rejectCheckpoint(taskId: string, reason?: string): void;
|
|
2057
|
-
|
|
2103
|
+
/** What the task's waiting checkpoint asks, whole; undefined once it settles or when none waits. */
|
|
2104
|
+
getCheckpointQuestion(taskId: string): string | undefined;
|
|
2105
|
+
awaitsCheckpoint(taskId: string): boolean;
|
|
2058
2106
|
/**
|
|
2059
2107
|
* Send a structured task a user message (ADR-0018, M1). Mid-turn it queues
|
|
2060
2108
|
* behind the turn; a task waiting for input takes it at once and is back in
|
|
2061
2109
|
* progress. Returns the message's id, for {@link removeQueuedTaskMessage}.
|
|
2062
2110
|
*/
|
|
2063
2111
|
sendTaskMessage(taskId: string, text: string): string;
|
|
2112
|
+
/**
|
|
2113
|
+
* Force send (ADR-0023, F1–F3): interrupt the running turn and deliver the
|
|
2114
|
+
* message as the next one, ahead of anything queued, without the task
|
|
2115
|
+
* waiting for input in between. A task already waiting for input just takes it.
|
|
2116
|
+
*/
|
|
2117
|
+
forceSendTaskMessage(taskId: string, text: string): string;
|
|
2118
|
+
private messageTask;
|
|
2119
|
+
/** Force send a message still queued behind the running turn; false once the runner has it. */
|
|
2120
|
+
forceSendQueuedTaskMessage(taskId: string, id: string): boolean;
|
|
2064
2121
|
/** Take back a message still queued behind a turn; false once it was delivered. */
|
|
2065
2122
|
removeQueuedTaskMessage(taskId: string, id: string): boolean;
|
|
2066
2123
|
/** Stop a structured task's running turn; it then waits for input like any turn that ends without its marker. */
|
|
@@ -2095,30 +2152,12 @@ declare class TaskOrchestrator {
|
|
|
2095
2152
|
/** Task id → session id of every attempt whose runner is up; a spawn in flight has no session yet. */
|
|
2096
2153
|
get activeSessionMap(): Map<string, string>;
|
|
2097
2154
|
getAttempt(taskId: string): TaskAttemptSnapshot | undefined;
|
|
2098
|
-
/** Where a task's isolated work stands; null when the plan has no isolation run to speak of. */
|
|
2099
|
-
getTaskIsolation(taskId: string): TaskIsolation | null;
|
|
2100
|
-
/**
|
|
2101
|
-
* The plan's isolation as a surface shows it, for one with no stream to have
|
|
2102
|
-
* told it — a reconnected webview, a session just loaded. Null without a run.
|
|
2103
|
-
*/
|
|
2104
|
-
isolationView(): IsolationView | null;
|
|
2105
|
-
getAttemptSession(taskId: string): ITerminalSession | undefined;
|
|
2106
2155
|
get queuedCount(): number;
|
|
2107
|
-
/** A run is waiting on the user to stash or to go on without isolation. */
|
|
2108
|
-
get awaitingIsolationChoice(): boolean;
|
|
2109
|
-
/**
|
|
2110
|
-
* Take over a plan's persisted isolation, or none for a plan that has not
|
|
2111
|
-
* isolated yet, pruning what a crashed process left behind. Silent on the
|
|
2112
|
-
* observer: adopting is not a change to persist.
|
|
2113
|
-
*/
|
|
2114
|
-
adoptIsolation(state: PlanIsolation | null): Promise<void>;
|
|
2115
|
-
reviewRunDiff(): Promise<string>;
|
|
2116
2156
|
/**
|
|
2117
2157
|
* "Merge all"; a settled run that merged everything is cleared up and
|
|
2118
2158
|
* forgotten. During a run it merges what has landed and the run goes on:
|
|
2119
2159
|
* the tasks waiting at a merge gate for that work then start (ADR-0020).
|
|
2120
|
-
* Never
|
|
2121
|
-
* one overlap the plan cannot order, because the merge is the user's.
|
|
2160
|
+
* Never alongside ops work, either way round ({@link mergeExcludes}).
|
|
2122
2161
|
*/
|
|
2123
2162
|
mergeRun(): Promise<IsolationMergeResult>;
|
|
2124
2163
|
/**
|
|
@@ -2133,13 +2172,7 @@ declare class TaskOrchestrator {
|
|
|
2133
2172
|
* the task has started, and for every other task.
|
|
2134
2173
|
*/
|
|
2135
2174
|
getMergeGate(taskId: string): string[];
|
|
2136
|
-
/** Worktrees and task branches go; the integration branch and the record stay for review and merge. */
|
|
2137
|
-
cleanupRun(): Promise<void>;
|
|
2138
|
-
/** The run and everything it made go, and the plan forgets it; the next run starts afresh. */
|
|
2139
|
-
discardRun(): Promise<void>;
|
|
2140
2175
|
private watchBlockingPrompts;
|
|
2141
|
-
/** What the plan persists of isolated execution; null when no run ever isolated. */
|
|
2142
|
-
get isolationRecord(): PlanIsolation | null;
|
|
2143
2176
|
/** The transport the plan's latest run copied from the setting; null before its first run. */
|
|
2144
2177
|
get runnerTransport(): RunnerTransport | null;
|
|
2145
2178
|
/** Take over a saved plan's copied transport. The next run copies the setting afresh. */
|
|
@@ -2150,7 +2183,6 @@ declare class TaskOrchestrator {
|
|
|
2150
2183
|
removeQueuedMessage(id: string): boolean;
|
|
2151
2184
|
setQueuedMessages(messages: QueuedMessage[]): void;
|
|
2152
2185
|
clearQueuedMessages(): void;
|
|
2153
|
-
processNextQueuedMessage(): QueuedMessage | null;
|
|
2154
2186
|
loadPlan(tasks: readonly Task[], planRunners?: RunnerId[]): void;
|
|
2155
2187
|
/**
|
|
2156
2188
|
* Adopt an edited plan without letting go of the run in progress. Everything
|
|
@@ -2167,7 +2199,40 @@ declare class TaskOrchestrator {
|
|
|
2167
2199
|
start(): Promise<void>;
|
|
2168
2200
|
private haltOnFailure;
|
|
2169
2201
|
stop(): void;
|
|
2170
|
-
|
|
2202
|
+
/** Name the tasks a stop took down, so none is mistaken for one still at work. */
|
|
2203
|
+
private sayStopped;
|
|
2204
|
+
/**
|
|
2205
|
+
* A task in progress with no attempt has nothing running it: a stop, a plan
|
|
2206
|
+
* load or anything else that ended its attempt left its status behind. It
|
|
2207
|
+
* is put back to not started, and said, so it can be retried rather than
|
|
2208
|
+
* read as running — or, in an isolated run, count as live work forever.
|
|
2209
|
+
*/
|
|
2210
|
+
private recoverOrphans;
|
|
2211
|
+
/**
|
|
2212
|
+
* Task ids still live, whose worktrees no clean-up of the whole run may
|
|
2213
|
+
* take: an attempt is running them, or the plan has them in progress or
|
|
2214
|
+
* waiting on the user mid-attempt — at a checkpoint, or for input. One
|
|
2215
|
+
* waiting on the user's decision instead (a conflict, a usage limit, files
|
|
2216
|
+
* an ops task changed) is not: no runner is at work on it, and a clean-up
|
|
2217
|
+
* keeps what it holds on a branch before its worktree goes.
|
|
2218
|
+
*/
|
|
2219
|
+
private liveTaskIds;
|
|
2220
|
+
/**
|
|
2221
|
+
* Whether the run may close with its handoff: no task is live. A handoff
|
|
2222
|
+
* tells the user the run has finished, and a Merge all after it clears the
|
|
2223
|
+
* run up, so neither may happen under a task the plan still shows at work.
|
|
2224
|
+
*/
|
|
2225
|
+
private get settled();
|
|
2226
|
+
/**
|
|
2227
|
+
* The boundary a verdict crosses: nothing awaits the verifier's listener, so
|
|
2228
|
+
* a throw from reading the output, landing, releasing a worktree or the tick
|
|
2229
|
+
* after would be an unhandled rejection — and an attempt left integrating is
|
|
2230
|
+
* live work forever. One that never settled fails (a repair waits on the
|
|
2231
|
+
* user, as its conflict did); either way the run halts and says why.
|
|
2232
|
+
*/
|
|
2233
|
+
private deliverVerdict;
|
|
2234
|
+
/** Work nothing awaits: a rejection is said, not left unhandled. */
|
|
2235
|
+
private unawaited;
|
|
2171
2236
|
private onVerdict;
|
|
2172
2237
|
private afterVerdict;
|
|
2173
2238
|
/**
|
|
@@ -2192,24 +2257,17 @@ declare class TaskOrchestrator {
|
|
|
2192
2257
|
* the ending attempt freed and never one more than the run allows.
|
|
2193
2258
|
*/
|
|
2194
2259
|
private settleUnlanded;
|
|
2195
|
-
/**
|
|
2196
|
-
* Mark which added task resolves which conflict. The resolver merges the
|
|
2197
|
-
* conflicted task's branch by hand in its own worktree; once that lands, the
|
|
2198
|
-
* conflicted task's branch is already on the integration branch and it can
|
|
2199
|
-
* land in turn — through the same merge, so a resolver that did not really
|
|
2200
|
-
* bring it along conflicts again instead of being taken at its word.
|
|
2201
|
-
*/
|
|
2202
|
-
linkConflictResolver(resolverId: string, conflictedId: string): void;
|
|
2203
2260
|
private landResolved;
|
|
2204
2261
|
getReadyTasks(): Task[];
|
|
2205
2262
|
private readiness;
|
|
2206
2263
|
/**
|
|
2207
|
-
* Open the run a task starts in, and
|
|
2208
|
-
*
|
|
2209
|
-
*
|
|
2210
|
-
* their choice replays.
|
|
2264
|
+
* Open the run a task starts in, and decide whether it isolates if the
|
|
2265
|
+
* task's next attempt needs that ({@link decidesIsolation}). False while a
|
|
2266
|
+
* dirty tree waits on the user; `resume` is what their choice replays.
|
|
2211
2267
|
*/
|
|
2212
2268
|
private openFor;
|
|
2269
|
+
/** The kind a task's next attempt starts as, short of a repair or a continue: what is weighed before one exists. */
|
|
2270
|
+
private nextAttemptKind;
|
|
2213
2271
|
/**
|
|
2214
2272
|
* Cancel a running (or scheduled) task: kill its session and return it to
|
|
2215
2273
|
* 'pending' — "not executed". The task is put on hold so the scheduler
|
|
@@ -2231,7 +2289,6 @@ declare class TaskOrchestrator {
|
|
|
2231
2289
|
*/
|
|
2232
2290
|
releaseTask(taskId: string): Promise<void>;
|
|
2233
2291
|
markTaskComplete(taskId: string): Promise<void>;
|
|
2234
|
-
markAiTaskComplete(taskId: string): Promise<void>;
|
|
2235
2292
|
/**
|
|
2236
2293
|
* Undo a completion: return the task to "not executed" — pending, verdict and
|
|
2237
2294
|
* summary dropped, archive entry removed. It is put on hold like a cancel, so
|
|
@@ -2278,16 +2335,9 @@ declare class TaskOrchestrator {
|
|
|
2278
2335
|
isAllComplete(): boolean;
|
|
2279
2336
|
isAnyFailed(): boolean;
|
|
2280
2337
|
approveReview(): Promise<void>;
|
|
2281
|
-
getPlanVisualization(): {
|
|
2282
|
-
tasks: {
|
|
2283
|
-
id: string;
|
|
2284
|
-
title: string;
|
|
2285
|
-
dependencies: string[];
|
|
2286
|
-
parallelGroups: number[][];
|
|
2287
|
-
}[];
|
|
2288
|
-
parallelGroups: number[][];
|
|
2289
|
-
};
|
|
2290
2338
|
tick(): Promise<void>;
|
|
2339
|
+
/** Whether the scheduler may start `id` now: it passes every readiness gate and a slot is free. */
|
|
2340
|
+
private stillReady;
|
|
2291
2341
|
/**
|
|
2292
2342
|
* A run paused at merge gates says so, as plainly as a task that waits on
|
|
2293
2343
|
* the user: which tasks wait, and that Merge all lets them go on (ADR-0020).
|
|
@@ -2321,11 +2371,6 @@ declare class TaskOrchestrator {
|
|
|
2321
2371
|
private abandonSpawn;
|
|
2322
2372
|
private tell;
|
|
2323
2373
|
private say;
|
|
2324
|
-
/**
|
|
2325
|
-
* Whether the run in force, or else the next one, gives each task its own
|
|
2326
|
-
* worktrees, and of which repo group — what the planner is told.
|
|
2327
|
-
*/
|
|
2328
|
-
plannerIsolation(): Promise<IsolatedExecution>;
|
|
2329
2374
|
/**
|
|
2330
2375
|
* Replay the start a dirty tree turned away. `stash` puts the user's tracked
|
|
2331
2376
|
* changes on the git stash first, so the run isolates; `shared` runs this one
|
|
@@ -2350,12 +2395,6 @@ declare class TaskOrchestrator {
|
|
|
2350
2395
|
private saveNativeSession;
|
|
2351
2396
|
private endAllAttempts;
|
|
2352
2397
|
}
|
|
2353
|
-
/**
|
|
2354
|
-
* Build a {@link TaskOrchestrator}, filling in every collaborator a caller did
|
|
2355
|
-
* not inject. The one entry point for hosts, bench harnesses and tests alike;
|
|
2356
|
-
* {@link TaskOrchestrator} itself constructs nothing.
|
|
2357
|
-
*/
|
|
2358
|
-
declare function createTaskOrchestrator(options: TaskOrchestratorOptions): TaskOrchestrator;
|
|
2359
2398
|
|
|
2360
2399
|
/**
|
|
2361
2400
|
* Everything needed to produce a plan from a goal. Carries the planning context
|
|
@@ -2518,7 +2557,9 @@ declare class RunnerInstallation {
|
|
|
2518
2557
|
* typing a real goal is the failure this exists to prevent.
|
|
2519
2558
|
*
|
|
2520
2559
|
* "Usable" is deliberately shallow: the binary answers `--version`, and the
|
|
2521
|
-
* runner
|
|
2560
|
+
* runner has a connector to plan over. Plugin runners have none yet: a
|
|
2561
|
+
* manifest-level planner capability, so a plugin can declare itself
|
|
2562
|
+
* plannable, is a follow-up. Whether the user's subscription is
|
|
2522
2563
|
* live cannot be known without spending a turn on it, so an expired login
|
|
2523
2564
|
* surfaces where it actually bites — as the agent's own error text on the
|
|
2524
2565
|
* first turn.
|
|
@@ -2594,6 +2635,37 @@ declare function isCliProvider(id: AiProvider): boolean;
|
|
|
2594
2635
|
declare function runnerForProvider(id: AiProvider): string | null;
|
|
2595
2636
|
/** The harness planner that wraps a given runner, or null when none does. */
|
|
2596
2637
|
declare function providerForRunner(runner: string): AiProvider | null;
|
|
2638
|
+
/** One runner's planner usability, as `RunnerInstallation.plannerUsability` reports it. */
|
|
2639
|
+
interface PlannerUsability {
|
|
2640
|
+
usable: boolean;
|
|
2641
|
+
reason?: string;
|
|
2642
|
+
}
|
|
2643
|
+
/**
|
|
2644
|
+
* One entry of the planner backend list (ADR-0009). `id` is the `AiProvider`
|
|
2645
|
+
* either way; `runner` is set only for a harness planner, whose model catalog
|
|
2646
|
+
* comes from that runner, and `reason` is the second line a surface renders —
|
|
2647
|
+
* the block detail for a harness planner, the API-key variable for a vendor.
|
|
2648
|
+
*/
|
|
2649
|
+
interface PlannerBackendEntry {
|
|
2650
|
+
id: AiProvider;
|
|
2651
|
+
label: string;
|
|
2652
|
+
kind: 'harness' | 'vendor';
|
|
2653
|
+
runner?: string;
|
|
2654
|
+
usable: boolean;
|
|
2655
|
+
reason?: string;
|
|
2656
|
+
}
|
|
2657
|
+
/** The detail a usable harness planner is always shown with. */
|
|
2658
|
+
declare const HARNESS_PLANNER_REASON = "coding agent \u00B7 no API key needed";
|
|
2659
|
+
/**
|
|
2660
|
+
* The planner backends every surface offers, in order: the harness planners
|
|
2661
|
+
* first, always listed so a missing CLI is greyed with its reason rather than
|
|
2662
|
+
* hidden, then the configured vendors in `PROVIDER_PRIORITY` order. Pure: the
|
|
2663
|
+
* caller supplies what it knows of each runner (VS Code its `plannerUsability`
|
|
2664
|
+
* results, the TUI its installed set) and maps the entries to its own item
|
|
2665
|
+
* type, keeping surface-specific affordances — e.g. the CLI's empty-vendor
|
|
2666
|
+
* placeholder — to itself.
|
|
2667
|
+
*/
|
|
2668
|
+
declare function plannerBackendEntries(usability: Readonly<Record<string, PlannerUsability>>, configured: readonly AiProvider[]): PlannerBackendEntry[];
|
|
2597
2669
|
/**
|
|
2598
2670
|
* The single definition of which providers count as "configured" — one API
|
|
2599
2671
|
* key each, or (for `openai_compatible`) an explicit base URL. Every surface
|
|
@@ -2672,7 +2744,7 @@ interface EnvAdmission {
|
|
|
2672
2744
|
*/
|
|
2673
2745
|
declare function admitSettingsEnv(env: Record<string, unknown>): EnvAdmission;
|
|
2674
2746
|
|
|
2675
|
-
/** Whether a runner's tasks can run on the structured transport. */
|
|
2747
|
+
/** Whether a runner's tasks can run on the structured transport (ADR-0018, S3). */
|
|
2676
2748
|
declare function supportsTaskMode(runner: string): boolean;
|
|
2677
2749
|
/** The adapter that drives one task. Throws {@link TaskModeUnsupportedError} for a runner without a connector. */
|
|
2678
2750
|
declare function createTaskAdapter(runner: string, deps: AgentProcessDeps): TaskModeAgentAdapter;
|
|
@@ -2693,8 +2765,8 @@ interface SpawnSpec {
|
|
|
2693
2765
|
*
|
|
2694
2766
|
* Subclasses own their agent's protocol: what to spawn, how to phrase a user
|
|
2695
2767
|
* turn, and how to read one protocol line. Everything below — line framing,
|
|
2696
|
-
* turn lifecycle, abort
|
|
2697
|
-
*
|
|
2768
|
+
* turn lifecycle, abort — is the same for all of them, and the process itself
|
|
2769
|
+
* is a {@link RunnerProcess}.
|
|
2698
2770
|
*/
|
|
2699
2771
|
declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
2700
2772
|
protected deps: AgentProcessDeps;
|
|
@@ -2702,8 +2774,7 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2702
2774
|
protected process: ChildProcess | null;
|
|
2703
2775
|
protected sessionId: string | null;
|
|
2704
2776
|
private readonly stdout;
|
|
2705
|
-
private
|
|
2706
|
-
private exited;
|
|
2777
|
+
private readonly runner;
|
|
2707
2778
|
/** Set for the duration of a turn. Outside one, events are buffered rather than dropped. */
|
|
2708
2779
|
private turnEmit;
|
|
2709
2780
|
/** Set for the duration of a turn. Pinged on every raw line, whether or not `handleLine` turns it into an event. */
|
|
@@ -2725,11 +2796,6 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2725
2796
|
/** A task's session, which wants what the agent says on its own after a turn closed; a planner registers none and drops it. */
|
|
2726
2797
|
private outOfTurnListener;
|
|
2727
2798
|
private disposed;
|
|
2728
|
-
/** Resolves when the process ends, so a handshake can lose the race instead of waiting out its timeout. */
|
|
2729
|
-
protected processEnded: Promise<void>;
|
|
2730
|
-
/** The environment the agent was spawned under, for any side process a handshake needs. */
|
|
2731
|
-
protected spawnEnv: NodeJS.ProcessEnv;
|
|
2732
|
-
private markEnded;
|
|
2733
2799
|
/** What this process is to the user — a planner or a task's runner — for the words a failure is reported in. */
|
|
2734
2800
|
protected role: 'planner' | 'task';
|
|
2735
2801
|
constructor(deps: AgentProcessDeps);
|
|
@@ -2745,6 +2811,17 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2745
2811
|
/** Protocol handshake, if the agent needs one before it accepts a turn. */
|
|
2746
2812
|
protected handshake(_opts: AgentStartOptions): Promise<void>;
|
|
2747
2813
|
start(opts: AgentStartOptions): Promise<void>;
|
|
2814
|
+
/**
|
|
2815
|
+
* Every protocol line goes to `handleLine`, turn or no turn: an agent's
|
|
2816
|
+
* handshake and its session-id announcement both arrive before the first
|
|
2817
|
+
* message is sent, and dropping them left the handshake waiting on a reply
|
|
2818
|
+
* that had already come and gone.
|
|
2819
|
+
*/
|
|
2820
|
+
private readProtocol;
|
|
2821
|
+
/** Resolves when the process ends, so a handshake can lose the race instead of waiting out its timeout. */
|
|
2822
|
+
protected get processEnded(): Promise<void>;
|
|
2823
|
+
/** The environment the agent was spawned under, for any side process a handshake needs. */
|
|
2824
|
+
protected get spawnEnv(): NodeJS.ProcessEnv;
|
|
2748
2825
|
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
2749
2826
|
onOutOfTurn(listener: (event: AgentEvent) => void): void;
|
|
2750
2827
|
nativeSessionId(): string | null;
|
|
@@ -2802,8 +2879,12 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
2802
2879
|
private pendingResume;
|
|
2803
2880
|
/** The `--mcp-config` file of the running process, which holds its token; removed with the process. */
|
|
2804
2881
|
private mcpConfig;
|
|
2805
|
-
/**
|
|
2806
|
-
private
|
|
2882
|
+
/** Whether this process was given the server, so its tools' requests are Ordewell's own. */
|
|
2883
|
+
private givenOrdewell;
|
|
2884
|
+
/** Messages written into a running task turn, by the `uuid` their echo will carry, until it does (ADR-0023). */
|
|
2885
|
+
private readonly steers;
|
|
2886
|
+
/** The last turn's `result` ended it, so a steer's echo now opens a turn the CLI started for that message. */
|
|
2887
|
+
private turnClosed;
|
|
2807
2888
|
protected spawnSpec(opts: AgentStartOptions): SpawnSpec;
|
|
2808
2889
|
/**
|
|
2809
2890
|
* A task's run: the manifest decides what its mode and effort mean
|
|
@@ -2814,16 +2895,9 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
2814
2895
|
* without it `-p` refuses them silently and nothing can ever surface one.
|
|
2815
2896
|
*/
|
|
2816
2897
|
private taskSpawnSpec;
|
|
2817
|
-
/**
|
|
2818
|
-
* `--mcp-config` takes a path as well as inline JSON; the path keeps the
|
|
2819
|
-
* token out of the argv every local user can list (ADR-0022, A5). The file
|
|
2820
|
-
* lives exactly as long as the process that reads it. `alwaysLoad` because
|
|
2821
|
-
* the CLI otherwise defers MCP tools behind its tool search, and a model
|
|
2822
|
-
* that has to look an Ordewell tool up first tends to go on without it.
|
|
2823
|
-
*/
|
|
2898
|
+
/** The file holding the token lives exactly as long as the process that reads it. */
|
|
2824
2899
|
private ordewellServerArgs;
|
|
2825
2900
|
private removeMcpConfig;
|
|
2826
|
-
start(opts: AgentStartOptions): Promise<void>;
|
|
2827
2901
|
/** Asks the CLI itself, which reports `pending` until its connection attempt settles. */
|
|
2828
2902
|
mcpAttached(): Promise<boolean>;
|
|
2829
2903
|
/**
|
|
@@ -2833,6 +2907,15 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
2833
2907
|
* as an interrupted `turn_end`.
|
|
2834
2908
|
*/
|
|
2835
2909
|
interrupt(timeoutMs: number): Promise<boolean>;
|
|
2910
|
+
/**
|
|
2911
|
+
* A `user` line written mid-turn is Claude Code's own queue (ADR-0023): the
|
|
2912
|
+
* CLI attaches it to the next tool result, or runs it as a turn of its own
|
|
2913
|
+
* after `result` — an interrupted one included — so it never lets go of one,
|
|
2914
|
+
* and nothing is ever reported dropped. Refused while an interrupt is in
|
|
2915
|
+
* flight, and before a `--resume` is taken up: a refused resume closes stdin
|
|
2916
|
+
* with the message unread.
|
|
2917
|
+
*/
|
|
2918
|
+
steer(id: string, text: string): Promise<boolean>;
|
|
2836
2919
|
/** Send a control request and wait for its answer; null when none came in time or the process ended. */
|
|
2837
2920
|
private control;
|
|
2838
2921
|
/**
|
|
@@ -2852,6 +2935,13 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
2852
2935
|
dispose(): void;
|
|
2853
2936
|
private clearFollowOnTimer;
|
|
2854
2937
|
protected turnPayload(message: string): string;
|
|
2938
|
+
private openTurnState;
|
|
2939
|
+
/**
|
|
2940
|
+
* The echo of a steered message: the model has it. After a closed turn it
|
|
2941
|
+
* opens the CLI's own turn for the message, which then runs like one Ordewell
|
|
2942
|
+
* sent. The first prompt is echoed too, and is no steer.
|
|
2943
|
+
*/
|
|
2944
|
+
private steerDelivered;
|
|
2855
2945
|
protected handleLine(line: string, emit: (event: AgentEvent) => void): void;
|
|
2856
2946
|
/**
|
|
2857
2947
|
* `--permission-mode auto` on a model or account without auto mode is not
|
|
@@ -2913,25 +3003,22 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
2913
3003
|
private threadId;
|
|
2914
3004
|
/** The model Codex opened the thread with — usage records name it. */
|
|
2915
3005
|
private threadModel;
|
|
2916
|
-
private
|
|
2917
|
-
private settleHandshake;
|
|
2918
|
-
private handshakeError;
|
|
3006
|
+
private readonly rpc;
|
|
2919
3007
|
private startOpts;
|
|
2920
3008
|
/** Whether this turn has already emitted prose — see the `agentMessage` case. */
|
|
2921
3009
|
private turnHasText;
|
|
2922
|
-
/**
|
|
2923
|
-
* The turn in flight. Its id arrives with `turn/started` or the `turn/start`
|
|
2924
|
-
* response, whichever lands first; `turn/interrupt` cannot be sent without it.
|
|
2925
|
-
*/
|
|
3010
|
+
/** The turn in flight. `turn/interrupt` and `turn/steer` cannot be sent before it has an id. */
|
|
2926
3011
|
private turn;
|
|
2927
|
-
/** The JSON-RPC id of the `turn/start` that opened {@link turn}. */
|
|
2928
|
-
private turnRequestId;
|
|
2929
3012
|
/** The last turn this adapter ended — so its second end signal, landing late, ends nothing. */
|
|
2930
3013
|
private endedTurnId;
|
|
2931
3014
|
/** An interrupt was asked for during this turn, so however it ends, it was cut short. */
|
|
2932
3015
|
private interruptRequested;
|
|
2933
|
-
/**
|
|
2934
|
-
|
|
3016
|
+
/**
|
|
3017
|
+
* Turns an interrupt cut short. Codex leaves their command running and
|
|
3018
|
+
* reports it when it ends, inside whatever turn is live by then — a report
|
|
3019
|
+
* that belongs to no turn of the agent's any more (ADR-0023, F4).
|
|
3020
|
+
*/
|
|
3021
|
+
private readonly interruptedTurnIds;
|
|
2935
3022
|
/** A task's approval requests still waiting for an answer, by the request id as a string. */
|
|
2936
3023
|
private readonly openPermissions;
|
|
2937
3024
|
/**
|
|
@@ -2941,10 +3028,6 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
2941
3028
|
private readonly fileChangePaths;
|
|
2942
3029
|
/** The row each announced file of an in-flight `fileChange` item is shown under, by the file's shown path. */
|
|
2943
3030
|
private readonly fileChangeRows;
|
|
2944
|
-
/** Requests this adapter sent and awaits an answer to, by JSON-RPC id. */
|
|
2945
|
-
private readonly pendingRequests;
|
|
2946
|
-
private resumeAttempted;
|
|
2947
|
-
private resumeFallbackSent;
|
|
2948
3031
|
private sandbox;
|
|
2949
3032
|
/** The Ordewell server's startup state, as Codex last reported it for this thread. */
|
|
2950
3033
|
private mcpStartup;
|
|
@@ -2955,6 +3038,7 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
2955
3038
|
* one stream; the thread id is what tells them apart (see {@link subagentOf}).
|
|
2956
3039
|
*/
|
|
2957
3040
|
private readonly subagents;
|
|
3041
|
+
constructor(deps: AgentProcessDeps);
|
|
2958
3042
|
protected spawnSpec(opts: AgentStartOptions): SpawnSpec;
|
|
2959
3043
|
/**
|
|
2960
3044
|
* `initialize`, then `thread/start`, both before the first user message. A
|
|
@@ -2964,16 +3048,18 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
2964
3048
|
* construction. A task's runs as its mode says (see {@link threadParams}).
|
|
2965
3049
|
*/
|
|
2966
3050
|
protected handshake(opts: AgentStartOptions): Promise<void>;
|
|
3051
|
+
private handshakeIncomplete;
|
|
2967
3052
|
/**
|
|
2968
3053
|
* Open this session's thread. A resume id means the previous
|
|
2969
3054
|
* process died mid-session: `thread/resume` puts the agent back in front of
|
|
2970
3055
|
* the context it already paid to read. A planner's failed resume is not an
|
|
2971
|
-
* error —
|
|
2972
|
-
*
|
|
2973
|
-
*
|
|
2974
|
-
*
|
|
3056
|
+
* error — it falls back to a fresh thread, which is the same degradation
|
|
3057
|
+
* `restoreChat` performs on every surface (T4). A task's is: Continue (K1)
|
|
3058
|
+
* offers the session that did the work, and a fresh thread in its place
|
|
3059
|
+
* would pretend it was resumed.
|
|
2975
3060
|
*/
|
|
2976
|
-
private
|
|
3061
|
+
private openThread;
|
|
3062
|
+
private requestThread;
|
|
2977
3063
|
private threadParams;
|
|
2978
3064
|
/**
|
|
2979
3065
|
* Codex's own startup report for the server, which it sends once the thread
|
|
@@ -2984,10 +3070,23 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
2984
3070
|
private effort;
|
|
2985
3071
|
/**
|
|
2986
3072
|
* `turn/interrupt` names the turn as well as the thread, so an interrupt
|
|
2987
|
-
* asked for before Codex has named the turn waits for it
|
|
2988
|
-
* with an empty result, then ends the turn as `interrupted`.
|
|
3073
|
+
* asked for before Codex has named the turn waits for it, as a steer does.
|
|
3074
|
+
* Codex acknowledges with an empty result, then ends the turn as `interrupted`.
|
|
2989
3075
|
*/
|
|
2990
3076
|
interrupt(timeoutMs: number): Promise<boolean>;
|
|
3077
|
+
/** Run `send` now if Codex has named the turn, and once it does if not. */
|
|
3078
|
+
private whenNamed;
|
|
3079
|
+
/**
|
|
3080
|
+
* `turn/steer` into the running turn (ADR-0023). Codex answers with the
|
|
3081
|
+
* turn's id at once — acceptance, not delivery — and shows the input to the
|
|
3082
|
+
* model after the item in flight, as a `userMessage` item carrying the
|
|
3083
|
+
* `clientUserMessageId` sent; that item is the delivery. The request needs
|
|
3084
|
+
* the turn's id, so a steer asked for before Codex named the turn waits for
|
|
3085
|
+
* it, as an interrupt does. Refused when the turn has ended or is another one.
|
|
3086
|
+
*/
|
|
3087
|
+
steer(id: string, text: string): Promise<boolean>;
|
|
3088
|
+
/** The one way input reaches a running turn: a task message, or a deny note. */
|
|
3089
|
+
private requestSteer;
|
|
2991
3090
|
/**
|
|
2992
3091
|
* Answer an open approval in its own result schema. Codex's decline carries
|
|
2993
3092
|
* no message, so a deny note reaches the agent as input steered into the
|
|
@@ -2995,9 +3094,19 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
2995
3094
|
*/
|
|
2996
3095
|
answerPermission(id: string, decision: ApprovalDecision): boolean;
|
|
2997
3096
|
protected turnPayload(message: string): string;
|
|
3097
|
+
/** `turn/start`'s answer. One for a turn that has since closed or been replaced names and closes nothing. */
|
|
3098
|
+
private turnAnswered;
|
|
2998
3099
|
protected handleLine(line: string, emit: (event: AgentEvent) => void): void;
|
|
2999
3100
|
private turnStarted;
|
|
3101
|
+
/**
|
|
3102
|
+
* Ahead of the event that ends the turn: a steer Codex accepted and the turn
|
|
3103
|
+
* never consumed is gone — Codex keeps no queue across turns — and one not
|
|
3104
|
+
* yet accepted never will be (ADR-0023, D4).
|
|
3105
|
+
*/
|
|
3000
3106
|
private closeTurn;
|
|
3107
|
+
private fromInterruptedTurn;
|
|
3108
|
+
/** The `userMessage` item a steer turns into once the item before it completes: the model has it. */
|
|
3109
|
+
private steerDelivered;
|
|
3001
3110
|
/**
|
|
3002
3111
|
* The child thread id when `threadId` names a subagent's thread, or undefined
|
|
3003
3112
|
* for the planner's own. Codex replays both threads on one stream and only
|
|
@@ -3065,8 +3174,8 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
3065
3174
|
* (ADR-0009, ADR-0018).
|
|
3066
3175
|
*
|
|
3067
3176
|
* The odd one out: `opencode serve` is a real server rather than a stdio
|
|
3068
|
-
* protocol, so this adapter owns both halves of the boundary — it
|
|
3069
|
-
* process
|
|
3177
|
+
* protocol, so this adapter owns both halves of the boundary — it starts the
|
|
3178
|
+
* process as the same {@link RunnerProcess} every other adapter uses, then
|
|
3070
3179
|
* talks to it through the injected `fetch`. Both are part of the one seam the
|
|
3071
3180
|
* tests drive.
|
|
3072
3181
|
*
|
|
@@ -3086,29 +3195,36 @@ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
|
|
|
3086
3195
|
/** Sent on every request to a task's server, which a per-task password secures. */
|
|
3087
3196
|
private authorization;
|
|
3088
3197
|
private sessionId;
|
|
3089
|
-
private
|
|
3090
|
-
private exited;
|
|
3091
|
-
private exitCode;
|
|
3198
|
+
private readonly runner;
|
|
3092
3199
|
private disposed;
|
|
3093
|
-
private markEnded;
|
|
3094
|
-
private readonly processEnded;
|
|
3095
3200
|
private planner;
|
|
3096
3201
|
private task;
|
|
3097
|
-
/** Whether this turn has already emitted reply text — see {@link emitPart}. */
|
|
3098
|
-
private turnHasText;
|
|
3099
3202
|
/** The last assistant message already settled — the baseline {@link recoverReply} measures a new reply against. */
|
|
3100
3203
|
private lastAssistantId;
|
|
3101
3204
|
private taskTurn;
|
|
3102
3205
|
/** An abort was posted during the current task turn, so the idle that follows ends it as interrupted. */
|
|
3103
3206
|
private interruptRequested;
|
|
3104
|
-
|
|
3105
|
-
|
|
3207
|
+
private readonly permissions;
|
|
3208
|
+
/** Messages handed into the running task turn, until the model reads them (ADR-0023). Kept across turns: the server keeps the message too. */
|
|
3209
|
+
private readonly steers;
|
|
3106
3210
|
/** Set once the server turns out to speak the 2.x API, which then owns the session. */
|
|
3107
3211
|
private v2;
|
|
3108
3212
|
/** The Ordewell server this process was configured with; null when none was given or its config could not be merged. */
|
|
3109
3213
|
private ordewell;
|
|
3110
3214
|
constructor(deps: AgentProcessDeps);
|
|
3215
|
+
private get processEnded();
|
|
3216
|
+
private get exited();
|
|
3111
3217
|
start(opts: AgentStartOptions): Promise<void>;
|
|
3218
|
+
private launch;
|
|
3219
|
+
/**
|
|
3220
|
+
* Where `serve` listens, or null once it ends or gives up. Stdout only: that
|
|
3221
|
+
* is where `serve` prints its address, and stderr can carry another URL — a
|
|
3222
|
+
* warning about a provider it could not reach. Read a line at a time, and
|
|
3223
|
+
* only until the address is known.
|
|
3224
|
+
*/
|
|
3225
|
+
private serverAddress;
|
|
3226
|
+
/** From the server's address to an open session — the 2.x API's, or a 1.x one created or resumed. */
|
|
3227
|
+
private connect;
|
|
3112
3228
|
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
3113
3229
|
/**
|
|
3114
3230
|
* One task turn. `prompt_async` only queues the work, so the turn is over
|
|
@@ -3120,6 +3236,20 @@ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
|
|
|
3120
3236
|
* {@link recoverReply}, never applies.
|
|
3121
3237
|
*/
|
|
3122
3238
|
private sendTask;
|
|
3239
|
+
/**
|
|
3240
|
+
* The prompt that carries a task message: the mode as the agent, the task
|
|
3241
|
+
* model and effort, and only `question` withheld. A steer names its own
|
|
3242
|
+
* `messageID` so the frames can be told apart from the first prompt's.
|
|
3243
|
+
*/
|
|
3244
|
+
private taskPromptBody;
|
|
3245
|
+
/** Hand a message into the running task turn (ADR-0023, D2), naming it so its delivery is observable. */
|
|
3246
|
+
steer(id: string, text: string): Promise<boolean>;
|
|
3247
|
+
/**
|
|
3248
|
+
* Messages handed over but unread when the turn ended. Each is deleted from
|
|
3249
|
+
* the session — so the next turn's re-send is not a duplicate — and reported
|
|
3250
|
+
* dropped, which is what puts it back in Ordewell's queue.
|
|
3251
|
+
*/
|
|
3252
|
+
private dropUnreadSteers;
|
|
3123
3253
|
/**
|
|
3124
3254
|
* Whatever of the turn's own messages the stream missed. Each part is
|
|
3125
3255
|
* emitted once, so a turn the stream saw whole adds nothing here; one that
|
|
@@ -3207,48 +3337,15 @@ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
|
|
|
3207
3337
|
* none of this turn's business.
|
|
3208
3338
|
*/
|
|
3209
3339
|
private onFrame;
|
|
3210
|
-
/**
|
|
3211
|
-
|
|
3212
|
-
* with its first visible delta, so the deltas add up to exactly the text the
|
|
3213
|
-
* completed part then re-sends; a part that is only whitespace so far is
|
|
3214
|
-
* held back, for the reason {@link emitPart} drops one.
|
|
3215
|
-
*/
|
|
3216
|
-
private onTextDelta;
|
|
3217
|
-
/**
|
|
3218
|
-
* Deny one permission request (T1). OpenCode blocks the turn until the
|
|
3219
|
-
* request is answered, so this must answer — `reject` rather than a silent
|
|
3220
|
-
* drop, which is the same "absent answer is a denial" invariant ADR-0008
|
|
3221
|
-
* states for Ordewell's own tools. The refusal is announced so the timeline
|
|
3222
|
-
* shows the planner reaching for something it may not have.
|
|
3223
|
-
*/
|
|
3224
|
-
private denyPermission;
|
|
3225
|
-
/**
|
|
3226
|
-
* A task's request. Under a mode whose manifest sets `approvals: auto` —
|
|
3227
|
-
* `build`, which the terminal transport runs with `--auto` — it is answered
|
|
3228
|
-
* at once with what `run --auto` answers, so the same plan behaves the same
|
|
3229
|
-
* on both transports (ADR-0001), and announced already decided so the log
|
|
3230
|
-
* still shows it. Any other mode leaves it open for an approval card.
|
|
3231
|
-
*/
|
|
3232
|
-
private askPermission;
|
|
3340
|
+
/** A planner's request is refused (T1); a task's is answered at once or left open for a card. */
|
|
3341
|
+
private onPermissionAsked;
|
|
3233
3342
|
/**
|
|
3234
3343
|
* `POST /permission/:id/reply` is the current answer. The per-session path
|
|
3235
3344
|
* it replaced is tried only when a server too old to know the new one 404s.
|
|
3236
3345
|
*/
|
|
3237
3346
|
private replyPermission;
|
|
3238
|
-
/**
|
|
3239
|
-
* Open `/event` for one turn and wait until it is connected. The stream
|
|
3240
|
-
* stopped being best-effort the moment permission answers moved onto it: a
|
|
3241
|
-
* request raised before we connect is one nobody answers, and the turn
|
|
3242
|
-
* hangs on it. Waiting is bounded so a server that never opens `/event`
|
|
3243
|
-
* still gets its turn.
|
|
3244
|
-
*/
|
|
3347
|
+
/** `/event` for one turn — see {@link openEventStream}. Load-bearing for {@link onPermissionAsked}. */
|
|
3245
3348
|
private openStream;
|
|
3246
|
-
/**
|
|
3247
|
-
* Server-sent events from `/event`: the turn's live text, reasoning, tool
|
|
3248
|
-
* activity and usage, and the only channel permission requests arrive on —
|
|
3249
|
-
* so the stream is load-bearing for {@link denyPermission}.
|
|
3250
|
-
*/
|
|
3251
|
-
private streamEvents;
|
|
3252
3349
|
private json;
|
|
3253
3350
|
private request;
|
|
3254
3351
|
private headers;
|
|
@@ -3277,12 +3374,155 @@ declare function mapAgentTool(name: string): MappedTool;
|
|
|
3277
3374
|
*/
|
|
3278
3375
|
declare function normalizeAgentArgs(tool: ResearchToolType, args: Record<string, unknown>): Record<string, unknown>;
|
|
3279
3376
|
|
|
3377
|
+
/** What a runner offers a task: the models discovered for it and the modes its manifest declares. */
|
|
3378
|
+
interface RunnerCatalog {
|
|
3379
|
+
models: DiscoveredModel[];
|
|
3380
|
+
modes: RunnerModeInfo[];
|
|
3381
|
+
/**
|
|
3382
|
+
* The mode a task lands on when it carries none this runner offers: the
|
|
3383
|
+
* manifest's `autonomous`/`safe`-tagged mode under the user's toggle
|
|
3384
|
+
* (ADR-0001). Absent, `modes[0]` stands in — which for Codex is its
|
|
3385
|
+
* workspace-write sandbox, not the full access an unattended run needs.
|
|
3386
|
+
*/
|
|
3387
|
+
defaultMode?: string;
|
|
3388
|
+
}
|
|
3389
|
+
/**
|
|
3390
|
+
* The model, thinking effort and mode a runner offers for a task.
|
|
3391
|
+
*
|
|
3392
|
+
* A task's model, effort and mode are all scoped to its runner:
|
|
3393
|
+
* `claude-sonnet-4-5` on Codex, or `acceptEdits` on OpenCode, are not degraded
|
|
3394
|
+
* choices but unspawnable ones. So this is where any task acquires a runnable
|
|
3395
|
+
* assignment — a runner change (below) and a hand-added task derive it the same
|
|
3396
|
+
* way. Each field in `current` is preserved when the runner also offers it, and
|
|
3397
|
+
* otherwise snapped to that runner's preferred entry (discovery already sorts
|
|
3398
|
+
* models by the manifest's `preferredPatterns`; the mode is the catalog's
|
|
3399
|
+
* `defaultMode`).
|
|
3400
|
+
*
|
|
3401
|
+
* An empty catalog means discovery failed or the runner is a plugin we have no
|
|
3402
|
+
* list for — not that the runner offers nothing. That field is left out of the
|
|
3403
|
+
* patch and the runner validates last, matching `coerceAssignments`.
|
|
3404
|
+
*/
|
|
3405
|
+
declare function runnerAssignment(catalog: RunnerCatalog, current?: Pick<Task, 'assignedModel' | 'taskMode'>): Partial<Task>;
|
|
3406
|
+
/**
|
|
3407
|
+
* Move a task onto a different runner, carrying its model, thinking effort and
|
|
3408
|
+
* mode over to values that runner actually offers. A runner change is never a
|
|
3409
|
+
* single-field edit — it either brings the other three with it or leaves the
|
|
3410
|
+
* task unrunnable.
|
|
3411
|
+
*
|
|
3412
|
+
* Returns the patch to apply, or `{}` when there is nothing to change.
|
|
3413
|
+
*/
|
|
3414
|
+
declare function retargetTaskRunner(task: Task, runner: RunnerId, catalog: RunnerCatalog): Partial<Task>;
|
|
3415
|
+
|
|
3416
|
+
type ModelsByRunner = Partial<Record<RunnerId, DiscoveredModel[]>>;
|
|
3417
|
+
interface SessionCatalogDeps {
|
|
3418
|
+
config: Pick<IConfig, 'enabledRunners' | 'autonomousMode'>;
|
|
3419
|
+
registry: Pick<RunnerRegistry, 'getManifest'>;
|
|
3420
|
+
modelResolver: Pick<ModelResolver, 'modelsForRunners' | 'getCachedRunnerModels'>;
|
|
3421
|
+
/** Read at each call: a toggle or allowlist edit made since the session was built counts (#69). */
|
|
3422
|
+
settings: () => {
|
|
3423
|
+
enabledRunners?: RunnerId[];
|
|
3424
|
+
modelAllowlist?: Record<string, string[]>;
|
|
3425
|
+
};
|
|
3426
|
+
/** The runners of the plan being edited; empty while the session has none. */
|
|
3427
|
+
planRunners: () => RunnerId[];
|
|
3428
|
+
}
|
|
3429
|
+
/**
|
|
3430
|
+
* What a session may assign: the enabled runners, their modes, the models
|
|
3431
|
+
* discovery found for them and the allowlist narrowing those. Every view of
|
|
3432
|
+
* it — the planner's per-turn block, its tools, a user's direct edit — reads
|
|
3433
|
+
* it here, so none can be shown or checked against something the others are not.
|
|
3434
|
+
*
|
|
3435
|
+
* The discovered models are remembered per runner and only ever merged into:
|
|
3436
|
+
* discovering one runner must not forget another's, since coercion later clamps
|
|
3437
|
+
* thinking efforts against whatever was last found.
|
|
3438
|
+
*/
|
|
3439
|
+
declare class SessionCatalog {
|
|
3440
|
+
private readonly deps;
|
|
3441
|
+
private discovered;
|
|
3442
|
+
constructor(deps: SessionCatalogDeps);
|
|
3443
|
+
/** The runners enabled right now. */
|
|
3444
|
+
enabledRunners(): RunnerId[];
|
|
3445
|
+
/**
|
|
3446
|
+
* The allowlist in force right now. Unset means no restriction — falling
|
|
3447
|
+
* back to the one planning started under would keep a restriction the user
|
|
3448
|
+
* has since cleared.
|
|
3449
|
+
*/
|
|
3450
|
+
allowlist(): Record<string, string[]>;
|
|
3451
|
+
/** The models the user allows on one runner; unset means no restriction. */
|
|
3452
|
+
allowlistFor(runner: RunnerId): string[] | undefined;
|
|
3453
|
+
/**
|
|
3454
|
+
* The discovered catalog as the resolver holds it now, per runner, with this
|
|
3455
|
+
* session's own discovery as the fallback where the resolver has nothing
|
|
3456
|
+
* cached. The resolver's cache outlives this session's snapshot in both
|
|
3457
|
+
* directions — an allowlist picker re-discovers into it mid-session — and a
|
|
3458
|
+
* model allowed after that must reach the planner with its real label and
|
|
3459
|
+
* variants, not as an id-only stub. Never triggers discovery itself.
|
|
3460
|
+
*/
|
|
3461
|
+
models(): ModelsByRunner;
|
|
3462
|
+
/** What this session's own discovery found for a runner; empty when it never ran there. */
|
|
3463
|
+
known(runner: RunnerId): DiscoveredModel[];
|
|
3464
|
+
/** Discover the runners' models, spawning their CLIs where the resolver has none cached, and remember them. */
|
|
3465
|
+
discover(runners: RunnerId[]): Promise<ModelsByRunner>;
|
|
3466
|
+
/**
|
|
3467
|
+
* Keep what an admitted runner was found to offer, for the next coercion's
|
|
3468
|
+
* effort clamping. An empty list is discovery having found nothing, not a
|
|
3469
|
+
* runner offering nothing, so it never displaces what is known.
|
|
3470
|
+
*/
|
|
3471
|
+
admit(runner: RunnerId, models: DiscoveredModel[]): void;
|
|
3472
|
+
/** Session boundaries are hard: nothing discovered for one goal informs the next. */
|
|
3473
|
+
reset(): void;
|
|
3474
|
+
modes(runners: RunnerId[]): Record<RunnerId, RunnerModeInfo[]>;
|
|
3475
|
+
/**
|
|
3476
|
+
* What a planner may assign right now: every enabled runner, its modes, and
|
|
3477
|
+
* its allowlisted models. Discovers a runner's models the first time it is
|
|
3478
|
+
* asked for.
|
|
3479
|
+
*/
|
|
3480
|
+
live(): Promise<TaskQueryCatalog>;
|
|
3481
|
+
queryCatalog(runners: RunnerId[]): TaskQueryCatalog;
|
|
3482
|
+
/**
|
|
3483
|
+
* The catalog a model/task-mode edit is checked against — the same
|
|
3484
|
+
* discovered models and manifest modes the per-turn catalog block shows the
|
|
3485
|
+
* planner, so a refusal here can never name something invalid that the
|
|
3486
|
+
* planner was never told about. The catalog is not filtered by the
|
|
3487
|
+
* allowlist here — `checkModelAndModeValidity` narrows by allowlist itself,
|
|
3488
|
+
* the same way `coerceAssignments` does.
|
|
3489
|
+
*/
|
|
3490
|
+
edit(runners?: RunnerId[]): EditCatalog;
|
|
3491
|
+
/** What a runner offers, as `runnerAssignment` needs it. Spawns the runner's CLI to list models. */
|
|
3492
|
+
runner(runner: RunnerId): Promise<RunnerCatalog>;
|
|
3493
|
+
/**
|
|
3494
|
+
* The one place planning discovers what it may draw from: the runners'
|
|
3495
|
+
* models and their modes. `filteredModels` is the allowlisted view a prompt
|
|
3496
|
+
* may show; `modelsByRunner` stays whole because coercion needs real labels
|
|
3497
|
+
* and variants.
|
|
3498
|
+
*/
|
|
3499
|
+
planning(runners: RunnerId[]): Promise<{
|
|
3500
|
+
modelsByRunner: Partial<Record<string, DiscoveredModel[]>>;
|
|
3501
|
+
filteredModels: Partial<Record<string, DiscoveredModel[]>>;
|
|
3502
|
+
runnerModes: Record<string, RunnerModeInfo[]>;
|
|
3503
|
+
}>;
|
|
3504
|
+
}
|
|
3505
|
+
|
|
3280
3506
|
/** The dialogue record a fork carries — what {@link PlannerConversation.clone} returns. */
|
|
3281
3507
|
interface ForkedDialogue {
|
|
3282
3508
|
conversationHistory: ConversationMessage[];
|
|
3283
3509
|
researchLog: ResearchLogEntry[];
|
|
3284
3510
|
}
|
|
3285
3511
|
|
|
3512
|
+
/**
|
|
3513
|
+
* The planner turn (see CONTEXT.md): the one piece of planner work that holds
|
|
3514
|
+
* the conversation, from its claim to its settled outcome. Its signal is what a
|
|
3515
|
+
* stop aborts.
|
|
3516
|
+
*/
|
|
3517
|
+
declare class PlannerTurn {
|
|
3518
|
+
private readonly controller;
|
|
3519
|
+
private dropped;
|
|
3520
|
+
get signal(): AbortSignal;
|
|
3521
|
+
/** The plan it was answering was dropped under it, so nothing it settles may land. */
|
|
3522
|
+
get abandoned(): boolean;
|
|
3523
|
+
stop(): void;
|
|
3524
|
+
abandon(): void;
|
|
3525
|
+
}
|
|
3286
3526
|
/** A read made through a planner tool: refused once the turn's budget is gone, else answered, told to land when the budget asks it to. */
|
|
3287
3527
|
type ToolRead<T> = {
|
|
3288
3528
|
status: 'refused';
|
|
@@ -3323,7 +3563,7 @@ interface PlannerConversationHost {
|
|
|
3323
3563
|
* conversation never reaches into execution state directly.
|
|
3324
3564
|
*/
|
|
3325
3565
|
liveOutput: LiveOutputLookup;
|
|
3326
|
-
|
|
3566
|
+
isExecuting(): boolean;
|
|
3327
3567
|
/** The session's single mutation ritual: op → persist → notify (default: the plan). */
|
|
3328
3568
|
mutate(op: () => boolean, notify?: () => void): LegacyPlanState | null;
|
|
3329
3569
|
broadcast: SessionBroadcaster;
|
|
@@ -3338,6 +3578,8 @@ interface PlannerConversationHost {
|
|
|
3338
3578
|
queueEdit(userMessage: string): number;
|
|
3339
3579
|
/** Wake a scheduler an applied edit may have unblocked. */
|
|
3340
3580
|
afterEdit(): Promise<void>;
|
|
3581
|
+
/** The planner turn was stopped or abandoned: whatever it is waiting on (a parked approval) will never be answered. */
|
|
3582
|
+
turnAborted(): void;
|
|
3341
3583
|
}
|
|
3342
3584
|
/**
|
|
3343
3585
|
* A conversation edit (rewind, fork) the conversation refused because the
|
|
@@ -3356,6 +3598,25 @@ declare class ConversationEditError extends Error {
|
|
|
3356
3598
|
declare class ConversationBusyError extends ConversationEditError {
|
|
3357
3599
|
constructor(operation: string);
|
|
3358
3600
|
}
|
|
3601
|
+
/**
|
|
3602
|
+
* A planner turn that settled after the plan it was answering was dropped (a
|
|
3603
|
+
* new plan, another session adopted, the session closed), or after its call
|
|
3604
|
+
* was cut off by something other than its own stop. Nothing it produced was
|
|
3605
|
+
* committed: landing it would write one session's reply into another's
|
|
3606
|
+
* transcript.
|
|
3607
|
+
*/
|
|
3608
|
+
declare class PlannerTurnDiscardedError extends Error {
|
|
3609
|
+
constructor(options?: ErrorOptions);
|
|
3610
|
+
}
|
|
3611
|
+
/**
|
|
3612
|
+
* The user stopped the turn and the backend reported that as a thrown error
|
|
3613
|
+
* rather than a settled reply. Typed so a surface can stay quiet for it without
|
|
3614
|
+
* reading the message: some SDKs' abort errors are plain `Error`s by name, and
|
|
3615
|
+
* a real failure can mention "aborted" too.
|
|
3616
|
+
*/
|
|
3617
|
+
declare class PlannerTurnStoppedError extends Error {
|
|
3618
|
+
constructor(options?: ErrorOptions);
|
|
3619
|
+
}
|
|
3359
3620
|
/** A user message a rewind can fork the conversation from just before. */
|
|
3360
3621
|
interface RewindTarget {
|
|
3361
3622
|
/** Position in the transcript — what {@link PlannerConversation.cloneBefore} takes. */
|
|
@@ -3411,13 +3672,32 @@ declare class PlannerConversation {
|
|
|
3411
3672
|
private persisted;
|
|
3412
3673
|
/** Saves an execution event made while a turn may be in flight; see {@link restore}. */
|
|
3413
3674
|
private savedInBackground;
|
|
3414
|
-
private
|
|
3415
|
-
private compacting;
|
|
3675
|
+
private live;
|
|
3416
3676
|
private openTurn;
|
|
3417
3677
|
constructor(host: PlannerConversationHost);
|
|
3418
3678
|
get transcript(): readonly ConversationMessage[];
|
|
3419
|
-
/** Whether a
|
|
3679
|
+
/** Whether a planner turn holds the conversation. */
|
|
3420
3680
|
get isTurnInFlight(): boolean;
|
|
3681
|
+
/** Stop the planner turn in flight; it settles as stopped. False when none is. */
|
|
3682
|
+
stopTurn(): boolean;
|
|
3683
|
+
/**
|
|
3684
|
+
* Drop the planner turn in flight together with the plan it was answering:
|
|
3685
|
+
* it is stopped, whatever it settles is discarded, and the conversation is
|
|
3686
|
+
* free at once rather than when the abandoned turn finishes unwinding.
|
|
3687
|
+
*/
|
|
3688
|
+
abandonTurn(): void;
|
|
3689
|
+
/**
|
|
3690
|
+
* Run planner work that is not a conversation turn — one-shot plan
|
|
3691
|
+
* generation — as the planner turn, so it is stopped, refused and superseded
|
|
3692
|
+
* like one. It starts a fresh plan, so it supersedes the turn in flight.
|
|
3693
|
+
*/
|
|
3694
|
+
hold<T>(signal: AbortSignal | undefined, body: (turn: PlannerTurn) => Promise<T>): Promise<T>;
|
|
3695
|
+
/**
|
|
3696
|
+
* Take the conversation for a new planner turn. A caller's own signal stops
|
|
3697
|
+
* the turn too; the relay is detached on release because a caller may reuse
|
|
3698
|
+
* that signal, and a stale listener would stop the next turn with it.
|
|
3699
|
+
*/
|
|
3700
|
+
private claim;
|
|
3421
3701
|
/** The user turn being answered, for what the host raises during it — an approval the turn's research asks for. */
|
|
3422
3702
|
get currentTurnId(): string | undefined;
|
|
3423
3703
|
/**
|
|
@@ -3526,8 +3806,11 @@ declare class PlannerConversation {
|
|
|
3526
3806
|
* inside the host's mutation ritual.
|
|
3527
3807
|
*/
|
|
3528
3808
|
recordQueuedEditsFailed(messages: string[], reason: string): void;
|
|
3529
|
-
/**
|
|
3530
|
-
|
|
3809
|
+
/**
|
|
3810
|
+
* Open the conversation on the host's fresh plan: the goal is its first
|
|
3811
|
+
* message. `prepare` (discovery) runs inside the turn, so a stop reaches it.
|
|
3812
|
+
*/
|
|
3813
|
+
start(goal: string, prepare: () => Promise<ConversationOpening>, signal?: AbortSignal): Promise<LegacyPlanState>;
|
|
3531
3814
|
/**
|
|
3532
3815
|
* Every later user message, from the transcript append to a persisted
|
|
3533
3816
|
* outcome. A turn that throws before anything was persisted takes its own
|
|
@@ -3544,7 +3827,20 @@ declare class PlannerConversation {
|
|
|
3544
3827
|
*/
|
|
3545
3828
|
private editTouchesLiveWork;
|
|
3546
3829
|
private assertIdle;
|
|
3547
|
-
|
|
3830
|
+
/**
|
|
3831
|
+
* Refuse to land a turn that no longer belongs here: it was abandoned, its
|
|
3832
|
+
* plan is no longer the host's, or its call was cut off by something other
|
|
3833
|
+
* than its own stop (`IAiService.reset` under a plan change) — what such a
|
|
3834
|
+
* call hands back is a fragment of an answer to a dialogue that is gone.
|
|
3835
|
+
*/
|
|
3836
|
+
private assertCurrent;
|
|
3837
|
+
/**
|
|
3838
|
+
* A live conversation is only safe to continue in-place when it also
|
|
3839
|
+
* matches the model/effort configured right now — a harness planner's
|
|
3840
|
+
* running process was spawned with the old one baked in and cannot pick up
|
|
3841
|
+
* a switch (ADR-0009). Otherwise the turn resumes from the transcript.
|
|
3842
|
+
*/
|
|
3843
|
+
private canContinueLive;
|
|
3548
3844
|
/**
|
|
3549
3845
|
* Bracket one user turn with its start and end, under an id minted here:
|
|
3550
3846
|
* the turn is where the stream a surface draws begins and ends, and only the
|
|
@@ -3589,10 +3885,11 @@ declare class PlannerConversation {
|
|
|
3589
3885
|
*/
|
|
3590
3886
|
private taskQueryAnswer;
|
|
3591
3887
|
/**
|
|
3592
|
-
* Drive a planner turn to a persisted, broadcast
|
|
3593
|
-
* atomically; validation failures are fed back to
|
|
3594
|
-
* silent retries, then surfaced as a message with the
|
|
3595
|
-
* first turn and every later turn route through here —
|
|
3888
|
+
* Drive a planner turn, its reads already drained, to a persisted, broadcast
|
|
3889
|
+
* outcome. Task edits apply atomically; validation failures are fed back to
|
|
3890
|
+
* the model for up to 2 silent retries, then surfaced as a message with the
|
|
3891
|
+
* plan untouched. The first turn and every later turn route through here —
|
|
3892
|
+
* one path, not two.
|
|
3596
3893
|
*/
|
|
3597
3894
|
private settle;
|
|
3598
3895
|
/** Validate + commit a task_ops turn atomically. Returns the errors on rejection (plan untouched). */
|
|
@@ -3694,14 +3991,21 @@ interface SessionEventRelayDeps {
|
|
|
3694
3991
|
/** Where isolation notices go, for a host whose notifications are not seen by the user. */
|
|
3695
3992
|
onNotice?: (notice: SessionNotice) => void;
|
|
3696
3993
|
store: Pick<PlanStore, 'allTasks' | 'snapshot'>;
|
|
3697
|
-
orchestrator: Pick<TaskOrchestrator, 'getIdleSince' | '
|
|
3994
|
+
orchestrator: Pick<TaskOrchestrator, 'getIdleSince' | 'getQueuedTaskMessages' | 'getMergeGate' | 'mergeGateView'>;
|
|
3995
|
+
runs: Pick<IsolationRunController, 'taskIsolation'>;
|
|
3698
3996
|
/** Shared with the Session, which snapshots, restores and clears it. */
|
|
3699
3997
|
usage: PlannerUsageLedger;
|
|
3700
3998
|
/** How many of a task's runner requests wait for an answer (ADR-0018, A1). */
|
|
3701
3999
|
awaitingApproval?: (taskId: string) => number;
|
|
4000
|
+
/** What a task's waiting checkpoint asks, whole. */
|
|
4001
|
+
checkpointQuestion?: (taskId: string) => string | undefined;
|
|
3702
4002
|
}
|
|
3703
|
-
/**
|
|
3704
|
-
|
|
4003
|
+
/**
|
|
4004
|
+
* Every orchestrator event the relay announces. `onTaskSettled` is persistence
|
|
4005
|
+
* only and `onQueueReady` is the Session's cue to drain its queue, so both are
|
|
4006
|
+
* the Session's alone.
|
|
4007
|
+
*/
|
|
4008
|
+
type RelayObserver = Required<Omit<OrchestratorObserver, 'onTaskSettled' | 'onQueueReady'>>;
|
|
3705
4009
|
/**
|
|
3706
4010
|
* Turns orchestrator and planner events into {@link SessionMessage}
|
|
3707
4011
|
* broadcasts — the one place a surface's view of a Session is produced. It
|
|
@@ -3713,8 +4017,10 @@ declare class SessionEventRelay {
|
|
|
3713
4017
|
private readonly onNotice?;
|
|
3714
4018
|
private readonly store;
|
|
3715
4019
|
private readonly orchestrator;
|
|
4020
|
+
private readonly runs;
|
|
3716
4021
|
private readonly usage;
|
|
3717
4022
|
private readonly awaitingApproval;
|
|
4023
|
+
private readonly checkpointQuestion;
|
|
3718
4024
|
/**
|
|
3719
4025
|
* The in-flight turn's subagent activity, grouped one run per subagent so a
|
|
3720
4026
|
* replay nests each step under its own brief/result. Folded into the plan's
|
|
@@ -3780,16 +4086,6 @@ declare function openTaskLog(location: TaskLogLocation, taskId: string): TaskLog
|
|
|
3780
4086
|
*/
|
|
3781
4087
|
declare function readTaskLog(location: TaskLogLocation, taskId: string, attempt: number): TaskLogEvent[];
|
|
3782
4088
|
|
|
3783
|
-
/**
|
|
3784
|
-
* A direct (non-planner) plan edit the session refused. Distinct from a plain
|
|
3785
|
-
* Error so a surface can tell "you asked for something invalid" from "something
|
|
3786
|
-
* broke" and say which — the HTTP routes used to collapse both into 404/500,
|
|
3787
|
-
* which read to the TUI and VS Code as the edit silently doing nothing. Carries
|
|
3788
|
-
* no status code: core is transport-agnostic, the route maps it.
|
|
3789
|
-
*/
|
|
3790
|
-
declare class PlanEditError extends Error {
|
|
3791
|
-
constructor(message: string);
|
|
3792
|
-
}
|
|
3793
4089
|
/**
|
|
3794
4090
|
* Options for plan generation. Progress is not overridable: every planner
|
|
3795
4091
|
* progress event is translated to a SessionMessage inside the Session and
|
|
@@ -3909,7 +4205,7 @@ declare function createSession(deps: SessionDeps): Session;
|
|
|
3909
4205
|
/** What {@link createSession} hands a Session: every collaborator, already built and wired. */
|
|
3910
4206
|
interface SessionParts {
|
|
3911
4207
|
config: IConfig;
|
|
3912
|
-
|
|
4208
|
+
catalog: SessionCatalog;
|
|
3913
4209
|
workspace: string;
|
|
3914
4210
|
fsAdapter: IFileSystem;
|
|
3915
4211
|
broadcast: SessionBroadcaster;
|
|
@@ -3921,6 +4217,8 @@ interface SessionParts {
|
|
|
3921
4217
|
planner: SessionPlanner;
|
|
3922
4218
|
store: PlanStore;
|
|
3923
4219
|
orchestrator: TaskOrchestrator;
|
|
4220
|
+
/** The orchestrator's own: Session reads the run and acts on it there, Merge all aside. */
|
|
4221
|
+
runs: IsolationRunController;
|
|
3924
4222
|
events: SessionEventRelay;
|
|
3925
4223
|
usage: PlannerUsageLedger;
|
|
3926
4224
|
approvals: PendingApprovals;
|
|
@@ -3949,9 +4247,10 @@ declare class Session {
|
|
|
3949
4247
|
private readonly events;
|
|
3950
4248
|
private readonly planner;
|
|
3951
4249
|
private readonly orchestrator;
|
|
4250
|
+
private readonly runs;
|
|
3952
4251
|
private readonly store;
|
|
3953
4252
|
private readonly config;
|
|
3954
|
-
private readonly
|
|
4253
|
+
private readonly catalog;
|
|
3955
4254
|
private plan;
|
|
3956
4255
|
private goal;
|
|
3957
4256
|
private workspace;
|
|
@@ -3964,13 +4263,18 @@ declare class Session {
|
|
|
3964
4263
|
private readonly fetcher;
|
|
3965
4264
|
private readonly settingsFn;
|
|
3966
4265
|
private readonly save;
|
|
3967
|
-
/**
|
|
3968
|
-
private
|
|
4266
|
+
/** The queue drain in flight, which a second call joins; see {@link processQueuedMessages}. */
|
|
4267
|
+
private queueDrain;
|
|
4268
|
+
/** The queued messages the planner has been given, no longer the user's to take back. */
|
|
4269
|
+
private drainingIds;
|
|
4270
|
+
/** User controls in flight; see {@link withSave}. */
|
|
4271
|
+
private controlsInFlight;
|
|
3969
4272
|
private unsubObserver;
|
|
3970
4273
|
private readonly hostSessionId?;
|
|
3971
4274
|
private currentSessionId;
|
|
3972
4275
|
private readonly skillsService;
|
|
3973
4276
|
private readonly conversation;
|
|
4277
|
+
private readonly editor;
|
|
3974
4278
|
private readonly plannerTools;
|
|
3975
4279
|
constructor(parts: SessionParts);
|
|
3976
4280
|
/**
|
|
@@ -3997,7 +4301,7 @@ declare class Session {
|
|
|
3997
4301
|
/**
|
|
3998
4302
|
* The relay announces every orchestrator event; this adds the saves some of
|
|
3999
4303
|
* them owe, each made before the announcement so no surface sees state the
|
|
4000
|
-
* disk lacks.
|
|
4304
|
+
* disk lacks, and drains the queue the scheduler parked behind.
|
|
4001
4305
|
*/
|
|
4002
4306
|
private observer;
|
|
4003
4307
|
/**
|
|
@@ -4032,41 +4336,8 @@ declare class Session {
|
|
|
4032
4336
|
* session.
|
|
4033
4337
|
*/
|
|
4034
4338
|
reset(): void;
|
|
4035
|
-
/**
|
|
4036
|
-
* What a planner may assign right now: every enabled runner, its modes, and
|
|
4037
|
-
* its allowlisted models — read as of this call, so a runner enabled or an
|
|
4038
|
-
* allowlist edited since planning started is in it (#69). Discovers a
|
|
4039
|
-
* runner's models the first time it is asked for.
|
|
4040
|
-
*/
|
|
4339
|
+
/** What a planner may assign right now; see {@link SessionCatalog.live}. */
|
|
4041
4340
|
liveCatalog(): Promise<TaskQueryCatalog>;
|
|
4042
|
-
private catalogOf;
|
|
4043
|
-
private runnerModesFor;
|
|
4044
|
-
/**
|
|
4045
|
-
* The catalog a model/task-mode edit is checked against — the same
|
|
4046
|
-
* discovered models and manifest modes the per-turn catalog block shows the
|
|
4047
|
-
* planner, so a refusal here can never name something invalid that the
|
|
4048
|
-
* planner was never told about. The catalog is not filtered by the
|
|
4049
|
-
* allowlist here — {@link checkModelAndModeValidity} narrows by
|
|
4050
|
-
* allowlist itself, the same way `coerceAssignments` does.
|
|
4051
|
-
*/
|
|
4052
|
-
private editCatalog;
|
|
4053
|
-
/** The runners enabled right now — a toggle made since the session was built counts (#69). */
|
|
4054
|
-
private enabledRunners;
|
|
4055
|
-
/**
|
|
4056
|
-
* The allowlist in force right now. Unset means no restriction — falling
|
|
4057
|
-
* back to the one planning started under would keep a restriction the user
|
|
4058
|
-
* has since cleared.
|
|
4059
|
-
*/
|
|
4060
|
-
private allowlist;
|
|
4061
|
-
/**
|
|
4062
|
-
* The discovered catalog as the resolver holds it now, per runner, with this
|
|
4063
|
-
* session's own discovery as the fallback where the resolver has nothing
|
|
4064
|
-
* cached. The resolver's cache outlives this session's snapshot in both
|
|
4065
|
-
* directions — an allowlist picker re-discovers into it mid-session — and a
|
|
4066
|
-
* model allowed after that must reach the planner with its real label and
|
|
4067
|
-
* variants, not as an id-only stub. Never triggers discovery itself.
|
|
4068
|
-
*/
|
|
4069
|
-
private models;
|
|
4070
4341
|
get planState(): LegacyPlanState | null;
|
|
4071
4342
|
/**
|
|
4072
4343
|
* The live plan in the shape a saved session is read back as. The disk
|
|
@@ -4082,24 +4353,16 @@ declare class Session {
|
|
|
4082
4353
|
* nothing executing, and reporting it as executing is what left the plan
|
|
4083
4354
|
* unstartable after its last live task was cancelled.
|
|
4084
4355
|
*/
|
|
4085
|
-
get isExecuting(): boolean;
|
|
4086
4356
|
/** See {@link TaskOrchestrator.hasLiveWork} — a spawned runner, not merely an armed scheduler. */
|
|
4087
|
-
get
|
|
4357
|
+
get isExecuting(): boolean;
|
|
4088
4358
|
get status(): 'approved' | 'running' | 'completed';
|
|
4359
|
+
/** Whether a planner turn — a reply, a compaction, plan generation — holds the conversation. */
|
|
4360
|
+
get isPlannerBusy(): boolean;
|
|
4089
4361
|
/**
|
|
4090
|
-
*
|
|
4091
|
-
*
|
|
4092
|
-
* waiting on has no one left to serve, and denying it unblocks the research
|
|
4093
|
-
* loop instead of stranding it. Without this the request sat out its
|
|
4094
|
-
* five-minute timeout and the loop then carried on as if nothing had
|
|
4095
|
-
* happened — the abort was real, but invisible until long after the user
|
|
4096
|
-
* pressed stop.
|
|
4097
|
-
*
|
|
4098
|
-
* The listener is returned as a disposer rather than left attached: callers
|
|
4099
|
-
* own the signal and may reuse it, and a leaked listener would deny the
|
|
4100
|
-
* *next* turn's prompts the moment that stale signal aborted.
|
|
4362
|
+
* Stop the planner turn in flight. It still settles — a backend hands back
|
|
4363
|
+
* what it had — and ends as stopped. False when no turn is in flight.
|
|
4101
4364
|
*/
|
|
4102
|
-
|
|
4365
|
+
abortPlannerTurn(): boolean;
|
|
4103
4366
|
generatePlan(goal: string, runners: RunnerId[], options?: GeneratePlanOptions): Promise<LegacyPlanState>;
|
|
4104
4367
|
/**
|
|
4105
4368
|
* Kick off the planner conversation (ADR-0002): research + the first planner
|
|
@@ -4169,13 +4432,6 @@ declare class Session {
|
|
|
4169
4432
|
* bare /unknown through to be mis-resolved.
|
|
4170
4433
|
*/
|
|
4171
4434
|
private resolveSkillInvocation;
|
|
4172
|
-
/**
|
|
4173
|
-
* The one place planning discovers what it may draw from: the runners'
|
|
4174
|
-
* models (cached for later effort clamping), their modes, and the settings
|
|
4175
|
-
* in force. `filteredModels` is the allowlisted view a prompt may show;
|
|
4176
|
-
* `modelsByRunner` stays whole because coercion needs real labels and variants.
|
|
4177
|
-
*/
|
|
4178
|
-
private plannerCatalog;
|
|
4179
4435
|
private conversationOpening;
|
|
4180
4436
|
/**
|
|
4181
4437
|
* Load planner-produced tasks, coerced to the allowlist read live — it may
|
|
@@ -4212,7 +4468,17 @@ declare class Session {
|
|
|
4212
4468
|
cancelTask(taskId: string): Promise<void>;
|
|
4213
4469
|
markTaskComplete(taskId: string): Promise<void>;
|
|
4214
4470
|
markTaskIncomplete(taskId: string): Promise<void>;
|
|
4471
|
+
/**
|
|
4472
|
+
* Hand the queued edits to the planner. The Session does this itself each
|
|
4473
|
+
* time the scheduler parks behind the queue, so no surface has to; a caller
|
|
4474
|
+
* only needs it to await the drain. The messages stay queued until the
|
|
4475
|
+
* planner's answer is applied, so the scheduler stays paused behind them
|
|
4476
|
+
* meanwhile; one drain runs at a time, and a call made during it joins it.
|
|
4477
|
+
* Whatever was queued while it ran is drained after, before the run goes on.
|
|
4478
|
+
*/
|
|
4215
4479
|
processQueuedMessages(): Promise<void>;
|
|
4480
|
+
private drainQueue;
|
|
4481
|
+
private applyQueuedEdits;
|
|
4216
4482
|
/**
|
|
4217
4483
|
* Every finished task as the log records it: this run's own entries, plus
|
|
4218
4484
|
* the tasks earlier runs completed, which the log dropped when this run
|
|
@@ -4221,16 +4487,25 @@ declare class Session {
|
|
|
4221
4487
|
private finishedWork;
|
|
4222
4488
|
approveCheckpoint(taskId: string): void;
|
|
4223
4489
|
rejectCheckpoint(taskId: string, reason?: string): void;
|
|
4490
|
+
/** Whether an answer would reach the task: it waits at a checkpoint and a runner is left to hear it. */
|
|
4491
|
+
awaitsCheckpoint(taskId: string): boolean;
|
|
4224
4492
|
/**
|
|
4225
4493
|
* A user message to a structured task (ADR-0018, M1); throws
|
|
4226
4494
|
* `TaskControlError` for one that cannot take it. A task waiting for input
|
|
4227
4495
|
* is back in progress, and saved so before any surface is told.
|
|
4228
4496
|
*/
|
|
4229
4497
|
sendTaskMessage(taskId: string, text: string): string;
|
|
4498
|
+
/**
|
|
4499
|
+
* Force send (ADR-0023, F1): interrupt the task's running turn and deliver
|
|
4500
|
+
* this message next. Throws `TaskControlError` where a plain message would,
|
|
4501
|
+
* and for a task on the terminal transport.
|
|
4502
|
+
*/
|
|
4503
|
+
forceSendTaskMessage(taskId: string, text: string): string;
|
|
4504
|
+
forceSendQueuedTaskMessage(taskId: string, id: string): boolean;
|
|
4230
4505
|
removeQueuedTaskMessage(taskId: string, id: string): boolean;
|
|
4231
4506
|
interruptTask(taskId: string): Promise<void>;
|
|
4232
4507
|
getQueuedMessages(): QueuedMessage[];
|
|
4233
|
-
/** Take back one unsent message; the plan's persisted queue follows so a reload cannot resurrect it. */
|
|
4508
|
+
/** Take back one unsent message — false once the planner has it; the plan's persisted queue follows so a reload cannot resurrect it. */
|
|
4234
4509
|
removeQueuedMessage(id: string): boolean;
|
|
4235
4510
|
setQueuedMessages(msgs: QueuedMessage[]): void;
|
|
4236
4511
|
/** Replay a run a dirty tree blocked, after stashing the tracked changes. */
|
|
@@ -4267,104 +4542,43 @@ declare class Session {
|
|
|
4267
4542
|
*/
|
|
4268
4543
|
discardRun(): Promise<void>;
|
|
4269
4544
|
private requireSettledRun;
|
|
4270
|
-
/**
|
|
4271
|
-
* The opt-in way through a merge conflict: add an AI task, on the conflicted
|
|
4272
|
-
* task's own runner and model, that merges its branch by hand in a worktree
|
|
4273
|
-
* of its own. When that task lands, the conflicted one lands through it (see
|
|
4274
|
-
* {@link TaskOrchestrator.linkConflictResolver}). The automatic answer to a
|
|
4275
|
-
* conflict is a repair, a new attempt of the same task (ADR-0015); a task is
|
|
4276
|
-
* only ever added to the plan by this call.
|
|
4277
|
-
*/
|
|
4545
|
+
/** Add the task that merges a conflicted task's branch by hand; see {@link PlanEditor.addConflictResolver}. */
|
|
4278
4546
|
resolveConflictAsTask(taskId: string): Promise<LegacyPlanState | null>;
|
|
4279
4547
|
stopExecution(): void;
|
|
4548
|
+
/**
|
|
4549
|
+
* Run a user control and save what it changed before any surface hears of
|
|
4550
|
+
* it. Not a status hold, as {@link saved} is: these await spawns and git, so
|
|
4551
|
+
* a hold would stall every task's status for as long, and an
|
|
4552
|
+
* `execution_complete` the control triggers would overtake the status held
|
|
4553
|
+
* back — which a surface treats as the end of the stream. Instead each status
|
|
4554
|
+
* announced while one runs is saved first (see {@link observer}), as the
|
|
4555
|
+
* background save of an execution event: it may land mid planner turn. So
|
|
4556
|
+
* is the last one where the control is itself execution, not the user's
|
|
4557
|
+
* word on the plan (`background`).
|
|
4558
|
+
*/
|
|
4559
|
+
private withSave;
|
|
4560
|
+
private saveForControl;
|
|
4561
|
+
/** A control that finishes synchronously: its status is held until it is saved. */
|
|
4562
|
+
private saved;
|
|
4280
4563
|
/**
|
|
4281
4564
|
* The one mutation seam: every structural plan mutation runs the same
|
|
4282
4565
|
* ritual — store op → persist (which snapshots tasks from PlanStore) →
|
|
4283
4566
|
* broadcast — in that order, once. A store op returning false aborts
|
|
4284
4567
|
* before anything is persisted. PlanStore is the single authority for
|
|
4285
4568
|
* task state; LegacyPlanState.tasks is populated only at persist time.
|
|
4569
|
+
* Direct edits reach it through the {@link PlanEditor}, which adds the
|
|
4570
|
+
* reschedule they owe.
|
|
4286
4571
|
*/
|
|
4287
4572
|
private mutatePlan;
|
|
4288
|
-
/**
|
|
4289
|
-
* The direct-edit seam: {@link mutatePlan} plus the reschedule every
|
|
4290
|
-
* structural edit owes an armed scheduler. Nothing else wakes one after a
|
|
4291
|
-
* hand edit — the queue-drain path never runs, because a direct edit never
|
|
4292
|
-
* queues — so a task the edit just unblocked would sit ready and never
|
|
4293
|
-
* start. `tick()` no-ops while the scheduler is idle, so this costs nothing
|
|
4294
|
-
* during plain planning. The planner-driven path re-ticks in
|
|
4295
|
-
* {@link PlannerConversation} instead (`afterEdit`); it must not tick twice.
|
|
4296
|
-
*/
|
|
4297
|
-
private editPlan;
|
|
4298
|
-
/**
|
|
4299
|
-
* Patch one task's fields. A hand-set dependency list, or a type flip
|
|
4300
|
-
* between AI and MAN, are the patches that can leave a task incoherent
|
|
4301
|
-
* (unschedulable, or carrying fields that mean nothing for its new type),
|
|
4302
|
-
* so both go through the same {@link validateTaskEdit} guard the planner's
|
|
4303
|
-
* task-ops applier uses (as the 'direct' actor, which skips the lock rule)
|
|
4304
|
-
* rather than a second copy of the rules — and throws, so the surface can
|
|
4305
|
-
* say why. Gated on the task existing so an edit to an unknown id still
|
|
4306
|
-
* falls through to the no-op `store.update` below instead of throwing.
|
|
4307
|
-
*/
|
|
4573
|
+
/** Patch one task's fields, checked as the planner's task ops are; see {@link PlanEditor.updateTask}. */
|
|
4308
4574
|
updateTask(taskId: string, changes: Partial<Task>): Promise<LegacyPlanState | null>;
|
|
4309
|
-
/**
|
|
4310
|
-
* Move one task onto a different runner. Distinct from {@link updateTask}
|
|
4311
|
-
* because a runner change is never a single-field edit: the task's model,
|
|
4312
|
-
* thinking effort and mode are all scoped to its runner, so they are
|
|
4313
|
-
* re-derived from the new runner's catalog (see {@link retargetTaskRunner}).
|
|
4314
|
-
* That needs discovery, which is why it is not a branch inside `updateTask`.
|
|
4315
|
-
*
|
|
4316
|
-
* The runner is also admitted into `plan.runners` — see {@link admitRunner}.
|
|
4317
|
-
*/
|
|
4575
|
+
/** Move one task onto a different runner, re-deriving what is scoped to it; see {@link PlanEditor.setTaskRunner}. */
|
|
4318
4576
|
setTaskRunner(taskId: string, runner: RunnerId): Promise<LegacyPlanState | null>;
|
|
4319
|
-
/**
|
|
4320
|
-
private catalogFor;
|
|
4321
|
-
/**
|
|
4322
|
-
* What a *derived* assignment may draw from: the runner's catalog narrowed to
|
|
4323
|
-
* the user's allowlist. Deriving from the full catalog would hand a task the
|
|
4324
|
-
* runner's first model regardless of a restriction the user set — the next
|
|
4325
|
-
* planner turn's `coerceAssignments` would snap it back anyway, so the user
|
|
4326
|
-
* would see their pick silently change instead of never being offered.
|
|
4327
|
-
*
|
|
4328
|
-
* `catalogFor` stays unnarrowed because {@link admitRunner} caches it as what
|
|
4329
|
-
* the runner really offers, which is what effort clamping needs.
|
|
4330
|
-
*/
|
|
4331
|
-
private allowedCatalog;
|
|
4332
|
-
/**
|
|
4333
|
-
* Make a runner a first-class member of this plan. Without this, the next
|
|
4334
|
-
* planner turn's `coerceAssignments` would treat it as disallowed and snap
|
|
4335
|
-
* every task on it back, silently undoing the user's choice; and that same
|
|
4336
|
-
* pass clamps efforts against `modelsCache`, so a catalog missing from there
|
|
4337
|
-
* makes the effort we just derived read as unverifiable.
|
|
4338
|
-
*/
|
|
4339
|
-
private admitRunner;
|
|
4340
|
-
/**
|
|
4341
|
-
* Replace one task's dependency list — the named entry point the surfaces'
|
|
4342
|
-
* dependency pickers call. The guard itself lives in {@link updateTask}, so
|
|
4343
|
-
* a dependency list arriving as a plain field patch is rejected by the same
|
|
4344
|
-
* rule instead of slipping past it.
|
|
4345
|
-
*/
|
|
4577
|
+
/** Replace one task's dependency list, under the same guard as a field patch; see {@link PlanEditor.setTaskDependencies}. */
|
|
4346
4578
|
setTaskDependencies(taskId: string, dependencies: string[]): Promise<LegacyPlanState | null>;
|
|
4347
|
-
/**
|
|
4348
|
-
* Delete one task. A running task is cancelled first: the plan can drop it
|
|
4349
|
-
* either way, but nothing can reach its runner afterwards — the tmux session
|
|
4350
|
-
* outlives the plan and the orchestrator keeps counting it as active. The
|
|
4351
|
-
* planner-driven path refuses instead (see {@link applyTaskOps}); a user
|
|
4352
|
-
* deleting their own task means it.
|
|
4353
|
-
*/
|
|
4579
|
+
/** Delete one task, cancelling its runner first if it runs; see {@link PlanEditor.removeTask}. */
|
|
4354
4580
|
removeTask(taskId: string): Promise<LegacyPlanState | null>;
|
|
4355
|
-
/**
|
|
4356
|
-
* Add one task, filling in whatever the caller left unset. A task with no
|
|
4357
|
-
* runnable assignment is not a lighter task but an unspawnable one, so the
|
|
4358
|
-
* runner falls back to the plan's first and the model, effort and mode are
|
|
4359
|
-
* derived from that runner's catalog — the same derivation a runner change
|
|
4360
|
-
* uses ({@link runnerAssignment}), which is why this is async like
|
|
4361
|
-
* {@link setTaskRunner}. Anything the caller did choose survives when the
|
|
4362
|
-
* runner offers it.
|
|
4363
|
-
*
|
|
4364
|
-
* Dependencies naming tasks that don't exist are dropped rather than rejected:
|
|
4365
|
-
* the caller is a picker over the current plan, so a stale id means the plan
|
|
4366
|
-
* moved on, not that the whole task should be refused.
|
|
4367
|
-
*/
|
|
4581
|
+
/** Add one task, deriving what the caller left unset; see {@link PlanEditor.addTask}. */
|
|
4368
4582
|
addTask(draft: Partial<Task>): Promise<LegacyPlanState | null>;
|
|
4369
4583
|
/**
|
|
4370
4584
|
* Planner-driven merge: validate compatibility up front, then ask the planner
|
|
@@ -4389,6 +4603,274 @@ declare class Session {
|
|
|
4389
4603
|
get aiServiceInstance(): IAiService;
|
|
4390
4604
|
}
|
|
4391
4605
|
|
|
4606
|
+
/**
|
|
4607
|
+
* A request on the plan the session refused: a direct (non-planner) edit that
|
|
4608
|
+
* is not valid, or an isolation action on a plan with no isolated run to act
|
|
4609
|
+
* on. Distinct from a plain Error so a surface can tell "you asked for
|
|
4610
|
+
* something invalid" from "something broke" and say which — the HTTP routes
|
|
4611
|
+
* used to collapse both into 404/500, which read to the TUI and VS Code as the
|
|
4612
|
+
* edit silently doing nothing. Carries no status code: core is
|
|
4613
|
+
* transport-agnostic, the route maps it.
|
|
4614
|
+
*/
|
|
4615
|
+
declare class PlanEditError extends Error {
|
|
4616
|
+
constructor(message: string);
|
|
4617
|
+
}
|
|
4618
|
+
|
|
4619
|
+
/** What the user last picked for one planner backend. */
|
|
4620
|
+
interface PlannerModelChoice {
|
|
4621
|
+
model: string;
|
|
4622
|
+
effort?: string;
|
|
4623
|
+
}
|
|
4624
|
+
/**
|
|
4625
|
+
* A candidate model as this planner's catalog lists it. Deliberately plain
|
|
4626
|
+
* data: a harness planner's catalog is its runner's own model list and a
|
|
4627
|
+
* vendor's is a picker list (ADR-0009), and the rule below is the same for
|
|
4628
|
+
* both — so the caller normalizes, and this module never reaches for a
|
|
4629
|
+
* ModelResolver, a config or the network.
|
|
4630
|
+
*/
|
|
4631
|
+
interface PlannerModelCandidate {
|
|
4632
|
+
id: string;
|
|
4633
|
+
variants?: {
|
|
4634
|
+
id: string;
|
|
4635
|
+
}[];
|
|
4636
|
+
}
|
|
4637
|
+
interface PlannerModelRecall {
|
|
4638
|
+
model: string;
|
|
4639
|
+
effort: string;
|
|
4640
|
+
source: 'remembered' | 'catalog-default' | 'none';
|
|
4641
|
+
}
|
|
4642
|
+
/** The slice of `SettingsService` this needs, so tests can pass a plain object. */
|
|
4643
|
+
interface PlannerModelStore {
|
|
4644
|
+
getPlannerModel(provider: string): PlannerModelChoice | undefined;
|
|
4645
|
+
setPlannerModel(provider: string, entry: PlannerModelChoice | undefined): void;
|
|
4646
|
+
}
|
|
4647
|
+
/**
|
|
4648
|
+
* Remembers, per planner backend, the model the user last chose for it.
|
|
4649
|
+
*
|
|
4650
|
+
* Switching the planner has to clear the model — an id is scoped to the agent
|
|
4651
|
+
* that listed it, so an OpenRouter slug handed to Claude Code points it at
|
|
4652
|
+
* something it cannot spawn. That clear is correct and stays; what was missing
|
|
4653
|
+
* is that switching *back* then forced a re-pick of a model the user had
|
|
4654
|
+
* already chosen. Both surfaces' clears and the restore now read one rule from
|
|
4655
|
+
* here rather than three copies drifting apart.
|
|
4656
|
+
*/
|
|
4657
|
+
declare class PlannerModelMemory {
|
|
4658
|
+
private store;
|
|
4659
|
+
constructor(store: PlannerModelStore);
|
|
4660
|
+
/** Record what the user picked for `provider`; a blank model forgets it instead. */
|
|
4661
|
+
remember(provider: string, model: string, effort?: string): void;
|
|
4662
|
+
/**
|
|
4663
|
+
* What the model and effort should become when `provider` takes over the
|
|
4664
|
+
* planner, given the models it actually serves. The `source` is what the
|
|
4665
|
+
* three surfaces word their notice from — restored, defaulted, or nothing.
|
|
4666
|
+
*/
|
|
4667
|
+
recall(provider: string, catalog: PlannerModelCandidate[]): PlannerModelRecall;
|
|
4668
|
+
}
|
|
4669
|
+
|
|
4670
|
+
/**
|
|
4671
|
+
* The daemon contract: every HTTP body the local daemon sends, in one place.
|
|
4672
|
+
*
|
|
4673
|
+
* The daemon's routes build their bodies against these types and the CLI's
|
|
4674
|
+
* `ApiClient` reads them back, so a field added on one side is a compile error
|
|
4675
|
+
* on the other. Before this there were three hand-written copies — the routes'
|
|
4676
|
+
* inline `c.json`, the client's per-method generics, and the TUI's slice of the
|
|
4677
|
+
* client — and they had drifted (the client declared a `headless` field the
|
|
4678
|
+
* daemon never sent, and typed `GET /sessions/:id`'s plan as the wrong shape).
|
|
4679
|
+
*
|
|
4680
|
+
* Types only. Core is the one package both the daemon and its clients already
|
|
4681
|
+
* depend on; importing from the daemon would pull its runtime into the CLI.
|
|
4682
|
+
*/
|
|
4683
|
+
/**
|
|
4684
|
+
* Why a request was refused, as a stable code a client switches on instead of
|
|
4685
|
+
* reading the message. Absent on a refusal nobody needs to tell apart — a
|
|
4686
|
+
* missing field, say — where the message is all there is.
|
|
4687
|
+
*/
|
|
4688
|
+
type DaemonErrorCode = 'session_not_found' | 'task_not_found' | 'no_plan' | 'already_executing' | 'workspace_not_found' | 'workspace_not_a_project' | 'conversation_busy'
|
|
4689
|
+
/** The user stopped the planner turn: the turn ended as asked, so a client stays quiet. */
|
|
4690
|
+
| 'planner_turn_stopped'
|
|
4691
|
+
/** The planner turn settled after its plan was dropped; nothing it produced was kept. */
|
|
4692
|
+
| 'planner_turn_discarded'
|
|
4693
|
+
/** The request asked for something the plan, task or conversation does not allow. */
|
|
4694
|
+
| 'refused' | 'checkpoint_not_waiting' | 'approval_not_outstanding';
|
|
4695
|
+
/** The body of every non-2xx answer a route gives. */
|
|
4696
|
+
interface ErrorBody {
|
|
4697
|
+
error: string;
|
|
4698
|
+
code?: DaemonErrorCode;
|
|
4699
|
+
/** Set with `workspace_not_a_project`: the directory the daemon refused, so a client can offer to initialize it. */
|
|
4700
|
+
workspace?: string;
|
|
4701
|
+
}
|
|
4702
|
+
interface OkResponse {
|
|
4703
|
+
ok: boolean;
|
|
4704
|
+
}
|
|
4705
|
+
/**
|
|
4706
|
+
* A plan as the planner routes return it: the session's plan state itself, not
|
|
4707
|
+
* the `SerializedPlan` a websocket `plan_generated` carries. The two differ —
|
|
4708
|
+
* this one holds raw tasks and the dialogue's bookkeeping — and a client that
|
|
4709
|
+
* reads either reads only the fields it needs.
|
|
4710
|
+
*/
|
|
4711
|
+
interface PlanResponse {
|
|
4712
|
+
plan: LegacyPlanState;
|
|
4713
|
+
}
|
|
4714
|
+
/** `POST /plans/:id/resolve-conflict`: `null` when the session had no conflict to hand a resolver task. */
|
|
4715
|
+
interface ResolveConflictResponse {
|
|
4716
|
+
plan: LegacyPlanState | null;
|
|
4717
|
+
}
|
|
4718
|
+
/** What `GET /api/models` returns, and what the pool's provider discovery produces. */
|
|
4719
|
+
interface ModelsResponse {
|
|
4720
|
+
models: DiscoveredModel[];
|
|
4721
|
+
modelsByRunner: Record<string, DiscoveredModel[]>;
|
|
4722
|
+
/** Each runner's manifest modes, so a surface can offer a per-task mode picker. */
|
|
4723
|
+
modesByRunner: Record<string, RunnerModeInfo[]>;
|
|
4724
|
+
orchestratorModel: string;
|
|
4725
|
+
providers: AiProvider[];
|
|
4726
|
+
/** Full cross-provider catalog for the orchestrator (planner) model picker. */
|
|
4727
|
+
orchestratorModels: OrchestratorOption[];
|
|
4728
|
+
/** Per-provider catalog-fetch failures, keyed by provider id. */
|
|
4729
|
+
providerErrors: Record<string, string>;
|
|
4730
|
+
}
|
|
4731
|
+
/** One-shot planning answers in the phase-tagged shape a saved session is read back in. */
|
|
4732
|
+
interface GeneratePlanResponse extends Pick<ModelsResponse, 'models' | 'modelsByRunner'> {
|
|
4733
|
+
plan: PlanState;
|
|
4734
|
+
}
|
|
4735
|
+
interface ExecuteResponse {
|
|
4736
|
+
status: 'running';
|
|
4737
|
+
}
|
|
4738
|
+
interface StopResponse {
|
|
4739
|
+
status: 'stopped';
|
|
4740
|
+
}
|
|
4741
|
+
interface CancelPlanningResponse {
|
|
4742
|
+
cancelled: boolean;
|
|
4743
|
+
}
|
|
4744
|
+
interface TaskMessageResponse {
|
|
4745
|
+
id: string;
|
|
4746
|
+
}
|
|
4747
|
+
interface ForceSendResponse {
|
|
4748
|
+
sent: boolean;
|
|
4749
|
+
}
|
|
4750
|
+
interface RemoveMessageResponse {
|
|
4751
|
+
removed: boolean;
|
|
4752
|
+
}
|
|
4753
|
+
interface MergeGateEntry {
|
|
4754
|
+
id: string;
|
|
4755
|
+
order: number;
|
|
4756
|
+
title: string;
|
|
4757
|
+
}
|
|
4758
|
+
interface MergeGateResponse {
|
|
4759
|
+
mergeGate: MergeGateEntry[];
|
|
4760
|
+
}
|
|
4761
|
+
interface IsolationDiffResponse {
|
|
4762
|
+
diff: string;
|
|
4763
|
+
}
|
|
4764
|
+
/** A merge that conflicts or is blocked is an outcome, not a refusal, so it answers 200 with the result. */
|
|
4765
|
+
type IsolationMergeResponse = IsolationMergeResult;
|
|
4766
|
+
/** A fork the daemon has already adopted. */
|
|
4767
|
+
interface ConversationForkResponse {
|
|
4768
|
+
sessionId: string;
|
|
4769
|
+
goal: string;
|
|
4770
|
+
plan: LegacyPlanState;
|
|
4771
|
+
}
|
|
4772
|
+
/** A fork made by a rewind, with the full text of the message it was made just before. */
|
|
4773
|
+
interface ConversationRewindResponse extends ConversationForkResponse {
|
|
4774
|
+
rewoundMessage: string;
|
|
4775
|
+
}
|
|
4776
|
+
interface RewindTargetsResponse {
|
|
4777
|
+
targets: RewindTarget[];
|
|
4778
|
+
}
|
|
4779
|
+
interface ConversationCompactResponse extends ConversationCompaction, PlanResponse {
|
|
4780
|
+
}
|
|
4781
|
+
interface PrdResponse {
|
|
4782
|
+
prdMarkdown: string;
|
|
4783
|
+
}
|
|
4784
|
+
interface RunnerEntry {
|
|
4785
|
+
id: string;
|
|
4786
|
+
name: string;
|
|
4787
|
+
enabled: boolean;
|
|
4788
|
+
}
|
|
4789
|
+
interface RunnersResponse {
|
|
4790
|
+
runners: RunnerEntry[];
|
|
4791
|
+
orchestratorModel: string;
|
|
4792
|
+
}
|
|
4793
|
+
/** Sessions: a saved one comes off its file, a live one from the pool's store. */
|
|
4794
|
+
interface SessionResponse {
|
|
4795
|
+
meta: SessionMeta;
|
|
4796
|
+
plan: PlanState;
|
|
4797
|
+
}
|
|
4798
|
+
interface AdoptSessionResponse extends OkResponse {
|
|
4799
|
+
plan: LegacyPlanState;
|
|
4800
|
+
goal: string;
|
|
4801
|
+
}
|
|
4802
|
+
interface TaskLogAttemptsResponse {
|
|
4803
|
+
attempts: number[];
|
|
4804
|
+
}
|
|
4805
|
+
interface TaskLogResponse {
|
|
4806
|
+
attempt: number;
|
|
4807
|
+
events: TaskLogEvent[];
|
|
4808
|
+
}
|
|
4809
|
+
type SessionListResponse = SessionMeta[];
|
|
4810
|
+
interface SettingsResponse {
|
|
4811
|
+
orchestratorModel: string;
|
|
4812
|
+
/** Who plans (ADR-0009) — a vendor id, or one of the three harness planners. */
|
|
4813
|
+
aiProvider: AiProvider;
|
|
4814
|
+
plannerThinkingEffort: string;
|
|
4815
|
+
maxParallel: number;
|
|
4816
|
+
tdd: UserSettings['tdd'];
|
|
4817
|
+
verification: UserSettings['verification'];
|
|
4818
|
+
modelAllowlist: UserSettings['modelAllowlist'];
|
|
4819
|
+
plannerModels: UserSettings['plannerModels'];
|
|
4820
|
+
runnerTransport: RunnerTransport;
|
|
4821
|
+
}
|
|
4822
|
+
/** What `PATCH /api/settings` answers: the settings as they now stand, plus what the write itself decided. */
|
|
4823
|
+
interface SettingsUpdateResponse extends SettingsResponse {
|
|
4824
|
+
/**
|
|
4825
|
+
* Which model a planner switch landed on and why — remembered for that
|
|
4826
|
+
* backend, its catalog default, or none. Present only when the write changed
|
|
4827
|
+
* the planner; absent for every other write, where nothing was recalled.
|
|
4828
|
+
*/
|
|
4829
|
+
switchRecall?: PlannerModelRecall;
|
|
4830
|
+
/** Env keys the daemon refused to apply, so a client does not persist what the daemon would not. */
|
|
4831
|
+
rejectedEnvKeys?: string[];
|
|
4832
|
+
}
|
|
4833
|
+
interface CommandDescriptor {
|
|
4834
|
+
name: string;
|
|
4835
|
+
description: string;
|
|
4836
|
+
}
|
|
4837
|
+
interface CommandsResponse {
|
|
4838
|
+
commands: CommandDescriptor[];
|
|
4839
|
+
}
|
|
4840
|
+
interface CommandResponse extends OkResponse {
|
|
4841
|
+
settings: SettingsResponse;
|
|
4842
|
+
}
|
|
4843
|
+
interface WorkspacesResponse {
|
|
4844
|
+
workspaces: string[];
|
|
4845
|
+
}
|
|
4846
|
+
interface ApprovalsResponse {
|
|
4847
|
+
pending: PendingApproval[];
|
|
4848
|
+
approvedScopes: string[];
|
|
4849
|
+
}
|
|
4850
|
+
interface ApprovalAnswerResponse extends OkResponse {
|
|
4851
|
+
granted: boolean;
|
|
4852
|
+
decision: ApprovalDecision['decision'];
|
|
4853
|
+
}
|
|
4854
|
+
|
|
4855
|
+
/**
|
|
4856
|
+
* Why a call on a session could not be made. Each is a class rather than a
|
|
4857
|
+
* message so the daemon can map it to a status and a stable code in one place,
|
|
4858
|
+
* and a client can switch on that code instead of reading the wording. Like
|
|
4859
|
+
* `PlanEditError`, none carries a status: core is transport-agnostic.
|
|
4860
|
+
*/
|
|
4861
|
+
/** No session with that id is held — never planned in this process, or dropped by a restart. */
|
|
4862
|
+
declare class SessionNotFoundError extends Error {
|
|
4863
|
+
constructor();
|
|
4864
|
+
}
|
|
4865
|
+
/** The session holds no plan (or an empty one) for the operation to act on. */
|
|
4866
|
+
declare class NoPlanError extends Error {
|
|
4867
|
+
constructor(operation: 'execute' | 'review');
|
|
4868
|
+
}
|
|
4869
|
+
/** A run is already live, and starting another would reset the one in flight. */
|
|
4870
|
+
declare class AlreadyExecutingError extends Error {
|
|
4871
|
+
constructor();
|
|
4872
|
+
}
|
|
4873
|
+
|
|
4392
4874
|
/**
|
|
4393
4875
|
* Where Ordewell keeps machine-global data (settings, daemon tokens, caches,
|
|
4394
4876
|
* user plugins). A single home for everything not tied to a project directory,
|
|
@@ -4419,6 +4901,8 @@ type CheckpointWithdrawnListener = (taskId: string) => void;
|
|
|
4419
4901
|
type IdleListener = (taskId: string, idleSince: string | null) => void;
|
|
4420
4902
|
declare class VerdictEngine {
|
|
4421
4903
|
private markerSeen;
|
|
4904
|
+
private pendingVerdicts;
|
|
4905
|
+
private structuredSessions;
|
|
4422
4906
|
private markerTails;
|
|
4423
4907
|
private checkpointCarry;
|
|
4424
4908
|
private pausedSessions;
|
|
@@ -4431,6 +4915,8 @@ declare class VerdictEngine {
|
|
|
4431
4915
|
* answer is typed into the session instead.
|
|
4432
4916
|
*/
|
|
4433
4917
|
private toolCheckpoints;
|
|
4918
|
+
/** The question a task's checkpoint asks, whole, for as long as it waits — by either route. */
|
|
4919
|
+
private checkpointQuestions;
|
|
4434
4920
|
private idleListeners;
|
|
4435
4921
|
/**
|
|
4436
4922
|
* Per-task generation. Replaced on every watch(), clear() and verdict.
|
|
@@ -4479,6 +4965,8 @@ declare class VerdictEngine {
|
|
|
4479
4965
|
* `\n`-terminated line, and the leading newline flushes a partial line.
|
|
4480
4966
|
*/
|
|
4481
4967
|
private resumeToken;
|
|
4968
|
+
/** What a task's waiting checkpoint asks, untruncated; undefined when none waits. */
|
|
4969
|
+
getCheckpointQuestion(taskId: string): string | undefined;
|
|
4482
4970
|
approveCheckpoint(taskId: string): void;
|
|
4483
4971
|
rejectCheckpoint(taskId: string, reason: string): void;
|
|
4484
4972
|
/**
|
|
@@ -4497,6 +4985,10 @@ declare class VerdictEngine {
|
|
|
4497
4985
|
* task's current one or another signal already settled it.
|
|
4498
4986
|
*/
|
|
4499
4987
|
signalComplete(taskId: string, generation: number, report: TaskCompleteArgs): void;
|
|
4988
|
+
/** The runner was told something after its evidence so far, so only what it reports from here counts. */
|
|
4989
|
+
private supersede;
|
|
4990
|
+
private acceptVerdict;
|
|
4991
|
+
private publishVerdict;
|
|
4500
4992
|
/**
|
|
4501
4993
|
* The runner's `checkpoint` call (ADR-0022, V5): raised through the same
|
|
4502
4994
|
* listeners as the marker, so the task waits on the user the same way, and
|
|
@@ -4504,6 +4996,8 @@ declare class VerdictEngine {
|
|
|
4504
4996
|
* withdrawn, never left hanging, once the attempt is over or the call goes.
|
|
4505
4997
|
*/
|
|
4506
4998
|
raiseCheckpoint(taskId: string, generation: number, question: string, signal: AbortSignal): Promise<CheckpointAnswer>;
|
|
4999
|
+
/** The open `checkpoint` call can no longer be answered: refuse it, and let the task out of the wait. */
|
|
5000
|
+
private callWentAway;
|
|
4507
5001
|
private withdrawToolCheckpoint;
|
|
4508
5002
|
private approvalOpened;
|
|
4509
5003
|
private approvalClosed;
|
|
@@ -4515,6 +5009,8 @@ declare class VerdictEngine {
|
|
|
4515
5009
|
markComplete(task: Task): Verdict;
|
|
4516
5010
|
/** Clear verification state for a task (used on retry). */
|
|
4517
5011
|
clear(task: Task): void;
|
|
5012
|
+
/** Drop a task's verification state and invalidate any callbacks still holding its generation. */
|
|
5013
|
+
private ceaseTracking;
|
|
4518
5014
|
/** Drop all tracking state (used on stop / loadPlan). */
|
|
4519
5015
|
reset(): void;
|
|
4520
5016
|
private decide;
|
|
@@ -4601,45 +5097,6 @@ declare function clampThinkingEffort(effort: string | undefined, variants: {
|
|
|
4601
5097
|
}[]): string | undefined;
|
|
4602
5098
|
declare function coerceAssignments(tasks: readonly Task[], perRunnerAllowlist: Partial<Record<RunnerId, string[]>>, allowedRunners?: RunnerId[], modelsByRunner?: Partial<Record<RunnerId, DiscoveredModel[]>>): Task[];
|
|
4603
5099
|
|
|
4604
|
-
/** What a runner offers a task: the models discovered for it and the modes its manifest declares. */
|
|
4605
|
-
interface RunnerCatalog {
|
|
4606
|
-
models: DiscoveredModel[];
|
|
4607
|
-
modes: RunnerModeInfo[];
|
|
4608
|
-
/**
|
|
4609
|
-
* The mode a task lands on when it carries none this runner offers: the
|
|
4610
|
-
* manifest's `autonomous`/`safe`-tagged mode under the user's toggle
|
|
4611
|
-
* (ADR-0001). Absent, `modes[0]` stands in — which for Codex is its
|
|
4612
|
-
* workspace-write sandbox, not the full access an unattended run needs.
|
|
4613
|
-
*/
|
|
4614
|
-
defaultMode?: string;
|
|
4615
|
-
}
|
|
4616
|
-
/**
|
|
4617
|
-
* The model, thinking effort and mode a runner offers for a task.
|
|
4618
|
-
*
|
|
4619
|
-
* A task's model, effort and mode are all scoped to its runner:
|
|
4620
|
-
* `claude-sonnet-4-5` on Codex, or `acceptEdits` on OpenCode, are not degraded
|
|
4621
|
-
* choices but unspawnable ones. So this is where any task acquires a runnable
|
|
4622
|
-
* assignment — a runner change (below) and a hand-added task derive it the same
|
|
4623
|
-
* way. Each field in `current` is preserved when the runner also offers it, and
|
|
4624
|
-
* otherwise snapped to that runner's preferred entry (discovery already sorts
|
|
4625
|
-
* models by the manifest's `preferredPatterns`; the mode is the catalog's
|
|
4626
|
-
* `defaultMode`).
|
|
4627
|
-
*
|
|
4628
|
-
* An empty catalog means discovery failed or the runner is a plugin we have no
|
|
4629
|
-
* list for — not that the runner offers nothing. That field is left out of the
|
|
4630
|
-
* patch and the runner validates last, matching `coerceAssignments`.
|
|
4631
|
-
*/
|
|
4632
|
-
declare function runnerAssignment(catalog: RunnerCatalog, current?: Pick<Task, 'assignedModel' | 'taskMode'>): Partial<Task>;
|
|
4633
|
-
/**
|
|
4634
|
-
* Move a task onto a different runner, carrying its model, thinking effort and
|
|
4635
|
-
* mode over to values that runner actually offers. A runner change is never a
|
|
4636
|
-
* single-field edit — it either brings the other three with it or leaves the
|
|
4637
|
-
* task unrunnable.
|
|
4638
|
-
*
|
|
4639
|
-
* Returns the patch to apply, or `{}` when there is nothing to change.
|
|
4640
|
-
*/
|
|
4641
|
-
declare function retargetTaskRunner(task: Task, runner: RunnerId, catalog: RunnerCatalog): Partial<Task>;
|
|
4642
|
-
|
|
4643
5100
|
declare function buildResearchToolsPrompt(): string;
|
|
4644
5101
|
/**
|
|
4645
5102
|
* System prompt for one read-only research subagent (issue #34). The digest
|
|
@@ -5067,8 +5524,9 @@ interface SessionLaunch {
|
|
|
5067
5524
|
* an `ITerminalSession`, so everything downstream of `onOutput` is unchanged;
|
|
5068
5525
|
* what a terminal cannot do sits on {@link StructuredSessionCapability}.
|
|
5069
5526
|
*
|
|
5070
|
-
* Ordewell owns the message queue (M1)
|
|
5071
|
-
*
|
|
5527
|
+
* Ordewell owns the message queue (M1). A message sent mid-turn is handed to a
|
|
5528
|
+
* runner that can take one at its next step (ADR-0023); otherwise it waits for
|
|
5529
|
+
* the turn to end rather than being typed into a runner that is busy.
|
|
5072
5530
|
*/
|
|
5073
5531
|
declare class StructuredSession extends AbstractTerminalSession implements StructuredSessionCapability {
|
|
5074
5532
|
private readonly launch;
|
|
@@ -5112,13 +5570,36 @@ declare class StructuredSession extends AbstractTerminalSession implements Struc
|
|
|
5112
5570
|
private issueTools;
|
|
5113
5571
|
private revokeTools;
|
|
5114
5572
|
protected baseHandleExit(code: number): void;
|
|
5115
|
-
/**
|
|
5573
|
+
/**
|
|
5574
|
+
* A reply typed at the task — a checkpoint answer, most often — is a user
|
|
5575
|
+
* message like any other: into the running turn where the runner takes one,
|
|
5576
|
+
* else the next turn. A runner that stopped to ask reads it at once either way.
|
|
5577
|
+
*/
|
|
5116
5578
|
write(text: string): void;
|
|
5117
5579
|
kill(): void;
|
|
5118
5580
|
turnState(): 'working' | 'idle';
|
|
5119
5581
|
onTurnEnd(listener: (reason: StructuredTurnEnd) => void): void;
|
|
5120
5582
|
onEvent(listener: (event: StructuredEvent) => void): void;
|
|
5121
5583
|
sendMessage(text: string): string;
|
|
5584
|
+
/**
|
|
5585
|
+
* Force send (ADR-0023, F1–F3): interrupt the running turn — and the tool
|
|
5586
|
+
* call in flight — then deliver this message as the turn that replaces it,
|
|
5587
|
+
* ahead of everything still queued. With no turn to interrupt it is a plain
|
|
5588
|
+
* {@link sendMessage}.
|
|
5589
|
+
*/
|
|
5590
|
+
forceSend(text: string): string;
|
|
5591
|
+
/** Force send a message still waiting in the queue. False once the runner has it, or it is gone. */
|
|
5592
|
+
forceSendQueued(id: string): boolean;
|
|
5593
|
+
/**
|
|
5594
|
+
* Behind earlier forced messages and ahead of the rest, handed-over ones
|
|
5595
|
+
* included: what the runner already has is the runner's to order (F2). Held
|
|
5596
|
+
* back from steering while the interrupt runs, it opens the next turn — and
|
|
5597
|
+
* a queue that is not empty when the turn ends is what keeps the task out of
|
|
5598
|
+
* "waiting for input" between the two (F3).
|
|
5599
|
+
*/
|
|
5600
|
+
private force;
|
|
5601
|
+
private runningTurn;
|
|
5602
|
+
/** No runner can recall a message once offered to it, so only a queued one comes back. */
|
|
5122
5603
|
removeQueued(id: string): boolean;
|
|
5123
5604
|
queued(): QueuedTaskMessage[];
|
|
5124
5605
|
nativeSessionId(): string | null;
|
|
@@ -5136,6 +5617,16 @@ declare class StructuredSession extends AbstractTerminalSession implements Struc
|
|
|
5136
5617
|
private startAdapter;
|
|
5137
5618
|
private openTurn;
|
|
5138
5619
|
private deliver;
|
|
5620
|
+
/**
|
|
5621
|
+
* Offer the oldest queued message to the running turn (ADR-0023, D2), one at
|
|
5622
|
+
* a time so the runner takes them in the order they were sent. A refusal
|
|
5623
|
+
* leaves it, and everything behind it, for the turn's end.
|
|
5624
|
+
*/
|
|
5625
|
+
private offerNext;
|
|
5626
|
+
private steered;
|
|
5627
|
+
private delivered;
|
|
5628
|
+
/** Back to waiting in Ordewell's queue, removable again; the log hears of it only if it had shown as handed over. */
|
|
5629
|
+
private requeue;
|
|
5139
5630
|
private route;
|
|
5140
5631
|
/**
|
|
5141
5632
|
* The runner spoke with no message of ours in flight. When it is working — a
|
|
@@ -5150,9 +5641,17 @@ declare class StructuredSession extends AbstractTerminalSession implements Struc
|
|
|
5150
5641
|
/**
|
|
5151
5642
|
* A queued message goes out as the turn closes, and the state never passes
|
|
5152
5643
|
* through `idle` on the way, so a listener told the turn ended can already
|
|
5153
|
-
* see the task is not waiting.
|
|
5644
|
+
* see the task is not waiting. Nor does a message the runner owes, or one
|
|
5645
|
+
* still being offered: the runner is about to read it, or Ordewell to send
|
|
5646
|
+
* it (ADR-0023, D5).
|
|
5154
5647
|
*/
|
|
5155
5648
|
private endTurn;
|
|
5649
|
+
/**
|
|
5650
|
+
* Between turns the oldest message opens the next one — but only once it is
|
|
5651
|
+
* back in Ordewell's hands: while it is on offer or owed, nothing overtakes it.
|
|
5652
|
+
*/
|
|
5653
|
+
private deliverNext;
|
|
5654
|
+
private undeliverQueued;
|
|
5156
5655
|
private emitEvent;
|
|
5157
5656
|
}
|
|
5158
5657
|
/**
|
|
@@ -5371,6 +5870,8 @@ interface KillTreeDeps {
|
|
|
5371
5870
|
unref?: () => void;
|
|
5372
5871
|
};
|
|
5373
5872
|
clearTimeoutImpl?: (handle: unknown) => void;
|
|
5873
|
+
/** Signals a pid, or a process group as its negated id. Injected so the group path needs no real processes. */
|
|
5874
|
+
killImpl?: (pid: number, signal: NodeJS.Signals | 0) => void;
|
|
5374
5875
|
}
|
|
5375
5876
|
/**
|
|
5376
5877
|
* Terminate `proc` and everything it started.
|
|
@@ -5600,57 +6101,6 @@ declare function sanitizeSlug(raw: string): string;
|
|
|
5600
6101
|
/** Save the PRD to `<workspace>/.scratch/<slug>/PRD.md` (to-prd native convention). */
|
|
5601
6102
|
declare function savePrdMarkdown(workspace: string, slug: string, markdown: string): string;
|
|
5602
6103
|
|
|
5603
|
-
/** What the user last picked for one planner backend. */
|
|
5604
|
-
interface PlannerModelChoice {
|
|
5605
|
-
model: string;
|
|
5606
|
-
effort?: string;
|
|
5607
|
-
}
|
|
5608
|
-
/**
|
|
5609
|
-
* A candidate model as this planner's catalog lists it. Deliberately plain
|
|
5610
|
-
* data: a harness planner's catalog is its runner's own model list and a
|
|
5611
|
-
* vendor's is a picker list (ADR-0009), and the rule below is the same for
|
|
5612
|
-
* both — so the caller normalizes, and this module never reaches for a
|
|
5613
|
-
* ModelResolver, a config or the network.
|
|
5614
|
-
*/
|
|
5615
|
-
interface PlannerModelCandidate {
|
|
5616
|
-
id: string;
|
|
5617
|
-
variants?: {
|
|
5618
|
-
id: string;
|
|
5619
|
-
}[];
|
|
5620
|
-
}
|
|
5621
|
-
interface PlannerModelRecall {
|
|
5622
|
-
model: string;
|
|
5623
|
-
effort: string;
|
|
5624
|
-
source: 'remembered' | 'catalog-default' | 'none';
|
|
5625
|
-
}
|
|
5626
|
-
/** The slice of `SettingsService` this needs, so tests can pass a plain object. */
|
|
5627
|
-
interface PlannerModelStore {
|
|
5628
|
-
getPlannerModel(provider: string): PlannerModelChoice | undefined;
|
|
5629
|
-
setPlannerModel(provider: string, entry: PlannerModelChoice | undefined): void;
|
|
5630
|
-
}
|
|
5631
|
-
/**
|
|
5632
|
-
* Remembers, per planner backend, the model the user last chose for it.
|
|
5633
|
-
*
|
|
5634
|
-
* Switching the planner has to clear the model — an id is scoped to the agent
|
|
5635
|
-
* that listed it, so an OpenRouter slug handed to Claude Code points it at
|
|
5636
|
-
* something it cannot spawn. That clear is correct and stays; what was missing
|
|
5637
|
-
* is that switching *back* then forced a re-pick of a model the user had
|
|
5638
|
-
* already chosen. Both surfaces' clears and the restore now read one rule from
|
|
5639
|
-
* here rather than three copies drifting apart.
|
|
5640
|
-
*/
|
|
5641
|
-
declare class PlannerModelMemory {
|
|
5642
|
-
private store;
|
|
5643
|
-
constructor(store: PlannerModelStore);
|
|
5644
|
-
/** Record what the user picked for `provider`; a blank model forgets it instead. */
|
|
5645
|
-
remember(provider: string, model: string, effort?: string): void;
|
|
5646
|
-
/**
|
|
5647
|
-
* What the model and effort should become when `provider` takes over the
|
|
5648
|
-
* planner, given the models it actually serves. The `source` is what the
|
|
5649
|
-
* three surfaces word their notice from — restored, defaulted, or nothing.
|
|
5650
|
-
*/
|
|
5651
|
-
recall(provider: string, catalog: PlannerModelCandidate[]): PlannerModelRecall;
|
|
5652
|
-
}
|
|
5653
|
-
|
|
5654
6104
|
/** How many AI tasks may run at once: `ORDEWELL_MAX_PARALLEL`, `/parallel`, `ordewell.maxParallelSessions`. */
|
|
5655
6105
|
declare const DEFAULT_MAX_PARALLEL = 3;
|
|
5656
6106
|
/**
|
|
@@ -5661,4 +6111,4 @@ declare const DEFAULT_MAX_PARALLEL = 3;
|
|
|
5661
6111
|
*/
|
|
5662
6112
|
declare function parseMaxParallel(value: unknown): number | null;
|
|
5663
6113
|
|
|
5664
|
-
export { ALLOWED_PLUGIN_HOSTS, ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractTerminalSession, ActiveTaskSession, type Adr0013IsolationRun, type Adr0013PlanIsolation, type Adr0013TaskRecord, AgentAdapter, AgentEvent, AgentProcessDeps, AgentStartOptions, AiProvider, ApplyTaskOpsResult, ApprovalAnswer, ApprovalDecision, ApprovalMode, ApprovalPolicy, ApprovalRequest, type AskOptions, AwaitingReason, BUILTIN_SKILL_NAMES, BaseAiService, BaseConfig, BaseFileSystem, BufferedTaskOutputSource, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CORE_PLANNER_PROMPT, type CappedRows, CheckpointAnswer, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, type CommandTier, type ComposeOptions, ConsoleLogger, ContextCollector, type Continuability, ConversationBusyError, type ConversationCompaction, ConversationEditError, type ConversationFork, ConversationMessage, type ConversationRequest, type ConversationRewind, type ConversationTurn, type ConversationVariant, DAEMON_SUBPROTOCOL, DAEMON_TOKEN_SUBPROTOCOL_PREFIX, DEFAULT_MAX_PARALLEL, DiscoveredModel, type EnvAdmission, EnvConfig, type ExecFileFn, type ExecImpl, FindSymbolOptions, FsPluginStore, GIT_READONLY_SUBCOMMANDS, GREP_PCRE_PROBE_ARGS, GeminiService, type GitExecFn, GlobOptions, type GrepInvocation, GrepOptions, type GrepRegex, type HasBinFn, HomeTranscriptReader, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IPluginStore, ITerminalRunner, ITerminalSession, IWorktreeIsolation, IsolationHandoff, IsolationLandedTask, IsolationMergeResult, IsolationOutcome, IsolationRun, IsolationTaskRecord, IsolationTaskStatus, IsolationView, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, LegacyPlanState, type LiveOutputLookup, type LiveTail, type LiveTailOptions, type MappedTool, MergeGateView, ModelResolver, type ModelResolverDeps, type ModifyPlanRequest, type NotificationAction, OPENCODE_MANIFEST, ORDEWELL_SETTABLE_ENV, OUTPUT_LINES_DEFAULT, OUTPUT_LINES_MAX, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, OrdewellMcpServer, PLUGIN_NAME_PATTERN, PROVIDER_CREDENTIAL_ENV, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanEditError, PlanIsolation, PlanParseError, type PlanRequest, PlanState, PlanStatus, PlanStore, Planner, type PlannerModelCandidate, type PlannerModelChoice, PlannerModelMemory, type PlannerModelRecall, type PlannerModelStore, type PlannerReplyClassification, type PlannerRuntimeToggles, type PlannerSubmission, PlannerToolHandler, PlannerUsage, type PluginSource, type PrdBlock, type PriorOutput, type ProbeFn, ProviderModelLists, type ProviderRegistration, QueuedMessage, QueuedTaskMessage, REFUSED_COMMANDS, ReadFileOpts, RepairEvidence, type RepairLoopOpts, type RepairVerdict, RepoGroupLayout, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchToolType, type ResearchTurn, ResolveContext, type RewindTarget, RunnerApprovals, type RunnerCatalog, RunnerId, RunnerInstallation, RunnerInvocation, type RunnerMode, RunnerModeInfo, RunnerPluginManifest, RunnerRegistry, RunnerSpawnOptions, RunnerTransport, SETTINGS_ENV_ALLOWLIST, SETTINGS_ENV_REFUSED, STATE_DIR, STOPPED_TOOL_RESULT, SYMBOL_LANGUAGES, type SaveSession, Session, SessionBroadcaster, type SessionData, type SessionDeps, SessionMessage, type SessionMeta, SessionNotice, type SessionPlanner, type SessionRuntimeSettings, SettingsService, type ShellDialect, type SkillInfo, type SkillMetadata, SkillsService, type SpawnSpec, StdioAgentAdapter, StructuredEvent, StructuredRunner, type StructuredRunnerDeps, StructuredSession, StructuredSessionCapability, StructuredTurnEnd, TASK_QUERY_ANSWER_MAX_CHARS, TASK_QUERY_ANSWER_OR_OPS, TASK_QUERY_FIELDS, TASK_QUERY_PROTOCOL, TASK_QUERY_REMINDER, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, type TaskAttemptSnapshot, TaskCompleteArgs, TaskControlError, TaskIsolation, TaskLogEvent, type TaskLogFile, type TaskLogLocation, TaskLogRecorder, type TaskLogRecorderDeps, TaskModeAgentAdapter, TaskOp, TaskOrchestrator, type TaskOrchestratorDeps, type TaskOrchestratorOptions, type TaskOutputAttempt, type TaskOutputSource, type TaskQuery, type TaskQueryCatalog, type TaskQueryField, TaskRunnerFlags, TaskSnapshot, TaskStartOptions, TaskTokenScope, TmuxRunner, type TmuxRunnerDeps, type TokenCarriers, type ToolCall, ToolOutcome, type ToolResult, type TranscriptQuery, type TranscriptReader, type TransportRoute, TransportRouter, TreeSnapshot, UsageRecord, type UserSettings, Verdict, VerdictEngine, type VerdictListener, type WorkspaceCheckDeps, WorkspaceNotAProjectError, WorkspaceNotFoundError, type WorkspaceProjectCheckDeps, type WorktreeIsolationDeps, admitSettingsEnv, applyHeadLimit, assertInstallablePluginUrl, assertPlainPluginName, assertWorkspaceExists, assertWorkspaceIsProject, augmentPromptWithPriorOutputs, augmentedPath, bearerHeaderValue, buildConflictRepairPrompt, buildConflictResolutionPrompt, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildRunnerInvocation, buildSplitPrompt, buildSubagentSystemPrompt, canContinue, clampThinkingEffort, classifyCommand, classifyPlannerReply, classifyPluginSource, clearAugmentedPathCache, clearDaemonToken, clearResearchShellCache, clearState, clipboardCopyCommand, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, composeContinuationPrompt, configuredProviders, continuability, createAiService, createSession, createSkillsService, createTaskAdapter,
|
|
6114
|
+
export { ALLOWED_PLUGIN_HOSTS, ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractTerminalSession, ActiveTaskSession, type AdoptSessionResponse, type Adr0013IsolationRun, type Adr0013PlanIsolation, type Adr0013TaskRecord, AgentAdapter, AgentEvent, AgentProcessDeps, AgentStartOptions, AiProvider, AlreadyExecutingError, ApplyTaskOpsResult, ApprovalAnswer, type ApprovalAnswerResponse, ApprovalDecision, ApprovalMode, ApprovalPolicy, ApprovalRequest, type ApprovalsResponse, type AskOptions, AwaitingReason, BUILTIN_SKILL_NAMES, BaseAiService, BaseConfig, BaseFileSystem, BufferedTaskOutputSource, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CORE_PLANNER_PROMPT, type CancelPlanningResponse, type CappedRows, CheckpointAnswer, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, type CommandDescriptor, type CommandResponse, type CommandTier, type CommandsResponse, type ComposeOptions, ConsoleLogger, ContextCollector, type Continuability, ConversationBusyError, type ConversationCompactResponse, type ConversationCompaction, ConversationEditError, type ConversationFork, type ConversationForkResponse, ConversationMessage, type ConversationRequest, type ConversationRewind, type ConversationRewindResponse, type ConversationTurn, type ConversationVariant, DAEMON_SUBPROTOCOL, DAEMON_TOKEN_SUBPROTOCOL_PREFIX, DEFAULT_MAX_PARALLEL, type DaemonErrorCode, DiscoveredModel, type EnvAdmission, EnvConfig, type ErrorBody, type ExecFileFn, type ExecImpl, type ExecuteResponse, FindSymbolOptions, type ForceSendResponse, FsPluginStore, GIT_READONLY_SUBCOMMANDS, GREP_PCRE_PROBE_ARGS, GeminiService, type GeneratePlanResponse, type GitExecFn, GlobOptions, type GrepInvocation, GrepOptions, type GrepRegex, HARNESS_PLANNER_REASON, type HasBinFn, HomeTranscriptReader, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IPluginStore, ITerminalRunner, ITerminalSession, IWorktreeIsolation, type IsolationDiffResponse, IsolationHandoff, IsolationLandedTask, type IsolationMergeResponse, IsolationMergeResult, IsolationOutcome, IsolationRun, IsolationTaskRecord, IsolationTaskStatus, IsolationView, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, LegacyPlanState, type LiveOutputLookup, type LiveTail, type LiveTailOptions, type MappedTool, type MergeGateEntry, type MergeGateResponse, MergeGateView, ModelResolver, type ModelResolverDeps, type ModelsResponse, type ModifyPlanRequest, NoPlanError, type NotificationAction, OPENCODE_MANIFEST, ORDEWELL_SETTABLE_ENV, OUTPUT_LINES_DEFAULT, OUTPUT_LINES_MAX, type OkResponse, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, OrdewellMcpServer, PLUGIN_NAME_PATTERN, PROVIDER_CREDENTIAL_ENV, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanEditError, PlanIsolation, PlanParseError, type PlanRequest, type PlanResponse, PlanState, PlanStatus, PlanStore, Planner, type PlannerBackendEntry, type PlannerModelCandidate, type PlannerModelChoice, PlannerModelMemory, type PlannerModelRecall, type PlannerModelStore, type PlannerReplyClassification, type PlannerRuntimeToggles, type PlannerSubmission, PlannerToolHandler, PlannerTurnDiscardedError, PlannerTurnStoppedError, type PlannerUsability, PlannerUsage, type PluginSource, type PrdBlock, type PrdResponse, type PriorOutput, type ProbeFn, ProviderModelLists, type ProviderRegistration, QueuedMessage, QueuedTaskMessage, REFUSED_COMMANDS, ReadFileOpts, type RemoveMessageResponse, RepairEvidence, type RepairLoopOpts, type RepairVerdict, RepoGroupLayout, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchToolType, type ResearchTurn, type ResolveConflictResponse, ResolveContext, type RewindTarget, type RewindTargetsResponse, RunnerApprovals, type RunnerCatalog, type RunnerEntry, RunnerId, RunnerInstallation, RunnerInvocation, type RunnerMode, RunnerModeInfo, RunnerPluginManifest, RunnerRegistry, RunnerSpawnOptions, RunnerTransport, type RunnersResponse, SETTINGS_ENV_ALLOWLIST, SETTINGS_ENV_REFUSED, STATE_DIR, STOPPED_TOOL_RESULT, SYMBOL_LANGUAGES, type SaveSession, Session, SessionBroadcaster, type SessionData, type SessionDeps, type SessionListResponse, SessionMessage, type SessionMeta, SessionNotFoundError, SessionNotice, type SessionPlanner, type SessionResponse, type SessionRuntimeSettings, type SettingsResponse, SettingsService, type SettingsUpdateResponse, type ShellDialect, type SkillInfo, type SkillMetadata, SkillsService, type SpawnSpec, StdioAgentAdapter, type StopResponse, StructuredEvent, StructuredRunner, type StructuredRunnerDeps, StructuredSession, StructuredSessionCapability, StructuredTurnEnd, TASK_QUERY_ANSWER_MAX_CHARS, TASK_QUERY_ANSWER_OR_OPS, TASK_QUERY_FIELDS, TASK_QUERY_PROTOCOL, TASK_QUERY_REMINDER, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, type TaskAttemptSnapshot, TaskCompleteArgs, TaskControlError, TaskIsolation, type TaskLogAttemptsResponse, TaskLogEvent, type TaskLogFile, type TaskLogLocation, TaskLogRecorder, type TaskLogRecorderDeps, type TaskLogResponse, type TaskMessageResponse, TaskModeAgentAdapter, TaskOp, TaskOrchestrator, type TaskOrchestratorDeps, type TaskOrchestratorOptions, type TaskOutputAttempt, type TaskOutputSource, type TaskQuery, type TaskQueryCatalog, type TaskQueryField, TaskRunnerFlags, TaskSnapshot, TaskStartOptions, TaskTokenScope, TmuxRunner, type TmuxRunnerDeps, type TokenCarriers, type ToolCall, ToolOutcome, type ToolResult, type TranscriptQuery, type TranscriptReader, type TransportRoute, TransportRouter, TreeSnapshot, UsageRecord, type UserSettings, Verdict, VerdictEngine, type VerdictListener, type WorkspaceCheckDeps, WorkspaceNotAProjectError, WorkspaceNotFoundError, type WorkspaceProjectCheckDeps, type WorkspacesResponse, type WorktreeIsolationDeps, admitSettingsEnv, applyHeadLimit, assertInstallablePluginUrl, assertPlainPluginName, assertWorkspaceExists, assertWorkspaceIsProject, augmentPromptWithPriorOutputs, augmentedPath, bearerHeaderValue, buildConflictRepairPrompt, buildConflictResolutionPrompt, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildRunnerInvocation, buildSplitPrompt, buildSubagentSystemPrompt, canContinue, clampThinkingEffort, classifyCommand, classifyPlannerReply, classifyPluginSource, clearAugmentedPathCache, clearDaemonToken, clearResearchShellCache, clearState, clipboardCopyCommand, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, composeContinuationPrompt, configuredProviders, continuability, createAiService, createSession, createSkillsService, createTaskAdapter, createWorktreeIsolation, daemonTokenPath, defaultLogger, definitionPattern, defuseMarkers, deleteSession, describeMergeResult, discoverGeminiModels, effectiveAllowlist, ensureDir, ensurePrivateDir, ensureStateDirIgnored, executionLogBlock, extractPrdBlock, extractPresentedToken, filterFallbackByAnchoredInclude, filterModelsForPrompt, formatSearchOutput, generatePlanWithRepair, getLatestSession, getProviderMeta, getSettingsPath, getStateDir, globalDataDir, grantScopeFor, grepRegexFromProbe, hasTmux, idSegment, includeGlobFor, isCliProvider, isOpenAiProvider, isPlainPluginName, isValidManifest, killTree, languageForId, listSessions, listTaskLogAttempts, loadSession, loadSessionPlanState, loadState, mapAgentTool, migrateOldConfigDir, migratePlanIsolation, mintDaemonToken, mintSessionId, modelContextBlock, modifyValidationFeedback, normalizeAgentArgs, normalizeGeminiModel, openTaskLog, parseMaxParallel, parseTaskQueryJson, pendingEditRulesBlock, plannerBackendEntries, prefixModelId, providerForRunner, reEmitPlanPrompt, reEmitTaskOpsPrompt, reEmitTaskQueryPrompt, readDaemonToken, readTaskLog, referencePattern, renderPlanMap, renderPriorOutputs, renderTaskQueryAnswer, repairLoop, researchShellWarning, researchToolsPath, resolveArgs, resolvePluginInstallDir, resolveProviderFromPrefix, resolveResearchShell, resolveSkillInvocation, resolveTaskRunnerFlags, resolveWithin, retargetTaskRunner, routeTransport, runnerAssignment, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, sessionDataDir, sessionRuntimeSettings, stateExists, stripModelPrefix, summarizeOutput, supportsTaskMode, taskOpsRejectedPrompt, taskQuerySignature, textHasTaskQuery, tmuxSessionName, tmuxSocketName, tmuxWindowName, tokenSubprotocols, tokensMatch, truncatedPlanReEmitPrompt, wellKnownBinDirs, withPath, writePrivateFile };
|