@ordewell/core 0.10.5 → 0.10.7
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/{IRunner-Crkt3tHD.d.ts → IFileSystem-C4_mpfze.d.ts} +97 -14
- package/dist/{IRunner-lMQIa5Wc.d.mts → IFileSystem-DUgeWWQN.d.mts} +97 -14
- package/dist/{ModeResolver-B4hhABNf.d.mts → ModeResolver-4qNjxcDs.d.mts} +1 -1
- package/dist/{ModeResolver-CUR5jCSU.d.ts → ModeResolver-DGK2rWHE.d.ts} +1 -1
- package/dist/{Task-D4QHjdGv.d.mts → Task-C0o4i3Nn.d.mts} +23 -4
- package/dist/{Task-D4QHjdGv.d.ts → Task-C0o4i3Nn.d.ts} +23 -4
- package/dist/{chunk-6LEA6WAM.mjs → chunk-DMG4ISUG.mjs} +923 -45
- package/dist/chunk-DMG4ISUG.mjs.map +1 -0
- package/dist/{chunk-RT4NQ2BZ.mjs → chunk-EEE2GBLG.mjs} +114 -27
- package/dist/chunk-EEE2GBLG.mjs.map +1 -0
- package/dist/chunk-H7QX32BH.mjs +647 -0
- package/dist/chunk-H7QX32BH.mjs.map +1 -0
- package/dist/{chunk-F3KIX7WR.mjs → chunk-LTHKFBKM.mjs} +4 -4
- package/dist/chunk-LTHKFBKM.mjs.map +1 -0
- package/dist/index.d.mts +278 -1701
- package/dist/index.d.ts +278 -1701
- package/dist/index.js +2744 -1915
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2186 -1535
- package/dist/index.mjs.map +1 -1
- package/dist/parsing.d.mts +2 -2
- package/dist/parsing.d.ts +2 -2
- package/dist/parsing.js +231 -75
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +3 -3
- package/dist/plan-utils.d.mts +20 -4
- package/dist/plan-utils.d.ts +20 -4
- package/dist/plan-utils.js +255 -97
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +33 -19
- package/dist/{plan-utils-wI8MuDBC.d.mts → runSettingsText-BgOmLxdw.d.mts} +1941 -108
- package/dist/{plan-utils-BVJCzNvm.d.ts → runSettingsText-BgXvajj2.d.ts} +1941 -108
- package/dist/testing.d.mts +2 -3
- package/dist/testing.d.ts +2 -3
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +1 -1
- package/dist/IFileSystem-ClBdp59f.d.ts +0 -78
- package/dist/IFileSystem-Db34maxC.d.mts +0 -78
- package/dist/chunk-4QLFM73A.mjs +0 -1407
- package/dist/chunk-4QLFM73A.mjs.map +0 -1
- package/dist/chunk-6LEA6WAM.mjs.map +0 -1
- package/dist/chunk-F3KIX7WR.mjs.map +0 -1
- package/dist/chunk-RT4NQ2BZ.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { A as ApprovalRecord, a as AttemptUsage, b as AwaitingReason, B as BUILTIN_SKILL_NAMES, D as DEFAULT_RUNNERS, c as DEFAULT_SUPERVISOR_RETRY_LIMIT, h as IntegrationDisposal, i as InvalidSkill, j as IsolationAvailability, k as IsolationHandoff, l as IsolationHandoffRepo, m as IsolationInactiveReason, o as IsolationLanding, p as IsolationMergeBlock, q as IsolationMergeBlockReason, s as IsolationOutcome, t as IsolationPruneResult, u as IsolationRemoval, v as IsolationRepo, w as IsolationRun, x as IsolationTaskRecord, y as IsolationTaskRef, z as IsolationTaskRepo, M as ModelUsage, O as PlanUsage, Q as PlannerResendState, S as PrepareIntent, T as PreparedTask, U as PreservedWork, V as PreviousWork, W as RefusedRemoval, X as RepairEvidence, Y as RepoGroupLayout,
|
|
3
|
-
import {
|
|
4
|
-
export { A as ACT_RISK, a as AUTORUN_RISK, c as
|
|
5
|
-
import {
|
|
6
|
-
export { A as AUTO_COMMANDS, b as AgentAdapterFactory, g as AllProviderModels, h as AnswerApprovalArgs, k as ApprovalKind, l as ApprovalMode, o as ApprovalPolicyOptions, q as ApprovalSource, C as CatalogModel, s as CheckpointArgs, t as CommandClassification, u as CommandTier, v as CommandWords, D as DEFAULT_PLANNER_ALLOWLIST, w as DENY_ALL, x as DiscoveryCommand, E as EditPlanArgs, F as FetchAllProviderModelsOptions, G as GIT_READONLY_SUBCOMMANDS,
|
|
7
|
-
import {
|
|
8
|
-
export {
|
|
9
|
-
import { R as RunnerModeInfo } from './ModeResolver-B4hhABNf.mjs';
|
|
10
|
-
export { a as autonomyLevelLabel, p as parseAutonomyLevel, r as runnerModesFrom } from './ModeResolver-B4hhABNf.mjs';
|
|
1
|
+
import { r as IsolationMergeResult, ai as Task, E as ExecutionActor, f as ExecutionRecord, g as GuardTrip, ah as SupervisorLevel, e as ExecutionCommandName, G as GuardTarget, n as IsolationLandedTask, I as IWorktreeIsolation, F as IsolationTaskStatus, J as PlanIsolation, a4 as RunnerId, $ as ResearchProgress, av as UsageRecord, _ as ResearchLogEntry, d as DiscoveredModel, L as LegacyPlanState, a5 as RunnerSessionCost, a2 as ResearchToolType, R as PlannerUsage, ap as TaskSkillSnapshot, af as SkillsService, aq as TaskSnapshot, K as PlanState, H as IsolationView, ax as Verdict } from './Task-C0o4i3Nn.mjs';
|
|
2
|
+
export { A as ApprovalRecord, a as AttemptUsage, b as AwaitingReason, B as BUILTIN_SKILL_NAMES, C as ConversationMessage, D as DEFAULT_RUNNERS, c as DEFAULT_SUPERVISOR_RETRY_LIMIT, h as IntegrationDisposal, i as InvalidSkill, j as IsolationAvailability, k as IsolationHandoff, l as IsolationHandoffRepo, m as IsolationInactiveReason, o as IsolationLanding, p as IsolationMergeBlock, q as IsolationMergeBlockReason, s as IsolationOutcome, t as IsolationPruneResult, u as IsolationRemoval, v as IsolationRepo, w as IsolationRun, x as IsolationTaskRecord, y as IsolationTaskRef, z as IsolationTaskRepo, M as ModelUsage, N as PlanStatus, O as PlanUsage, Q as PlannerResendState, S as PrepareIntent, T as PreparedTask, U as PreservedWork, V as PreviousWork, W as RefusedRemoval, X as RepairEvidence, Y as ReplyRun, Z as RepoGroupLayout, a0 as ResearchStep, a1 as ResearchStepOutcome, a3 as RunSettings, a6 as SetupFailure, a7 as ShadowedSkill, a8 as SkillAppliesTo, a9 as SkillCatalog, aa as SkillInfo, ab as SkillLoad, ac as SkillLoadNotice, ad as SkillMetadata, ae as SkillSource, al as TaskIsolation, am as TaskIsolationState, an as TaskModelAssignment, ar as TaskStatus, as as TaskUsageSummary, at as TreeSnapshot, au as UsageLine, aw as UsageTotals, ay as VerificationCheck, az as addAttemptUsage, aA as addModelUsage, aB as addPlannerUsage, aC as addUsage, aD as addUsageTotals, aE as countedSessionCost, aF as createEmptyPlan, aG as createSkillsService, aH as createTask, aI as endAttemptUsage, aJ as flattenTasks, aK as flattenTasksWithParents, aL as isAwaitingReason, aM as isMeasured, aN as isSupervisorLevel, aO as isUserMessage, aP as migratePlanState, aQ as partedPromptUsage, aR as pausedOnLimit, aS as planUsage, aT as plannerContextFill, aU as rejoinPlanTree, aV as resumedSessionWindow, aW as startAttemptUsage, aX as taskUsageSummary, aY as usageLine, aZ as waitsForApproval } from './Task-C0o4i3Nn.mjs';
|
|
3
|
+
import { bv as StartAdmission, bw as StartWait, aY as ResolveAll, a8 as IWebFetcher, cp as WebReadPolicy, cn as WebRead, co as WebReadDecision, aw as PendingApprovals, K as ConversationTurn, aL as PlannerModes, a6 as IAiService, I as ConversationRequest, n as AssignmentWriter, m as AssignmentScope, c1 as TaskQueryCatalog, k as AssignmentCatalog, b7 as RunnerCatalog, bl as SessionMessage, bh as SessionBroadcaster, bn as SessionNotice, aC as PlanStore, bX as TaskOrchestrator, ab as IsolationRunController, at as OrchestratorObserver, bQ as TaskLogEvent, a7 as INotification, a2 as GlobalRunSettings, aF as PlannerConversationHost, aE as PlannerConversation, av as PendingApproval, E as ConversationCompaction, a_ as RewindTarget, b6 as RunView, b1 as RunMergeView, b_ as TaskOutputSource, cl as UserSettings, ae as LiveTailOptions, ad as LiveTail, bm as SessionMeta, aK as PlannerModelStore, aJ as PlannerModelRecall, aG as PlannerModelCandidate } from './runSettingsText-BgOmLxdw.mjs';
|
|
4
|
+
export { A as ACT_RISK, a as AUTORUN_RISK, b as AdoptSessionResponse, c as ApplyTaskOpsResult, d as ApprovalAnswerResponse, e as ApprovalBlock, f as ApprovalRequestMessage, g as ApprovalStatus, h as ApprovalsResponse, i as ApproveReviewResponse, j as AskOptions, l as AssignmentIssue, o as AutoMergeTrigger, B as BlockingSubject, C as CHAT_COMMANDS, p as CHECKPOINT_TRUNCATE_LENGTH, q as CancelPlanningResponse, r as CancelResumeResponse, s as CliAgentAiService, t as CliAgentAiServiceDeps, u as CommandBlock, v as CommandDescriptor, w as CommandStatus, x as CommandsResponse, y as CompactionBlock, z as ConversationBusyError, D as ConversationCompactResponse, F as ConversationEditError, G as ConversationForkResponse, H as ConversationInput, J as ConversationRewindResponse, L as ConversationView, M as DEFAULT_WEB_READ_BUDGET, N as DaemonErrorCode, O as DecideOptions, P as DiffRow, Q as DiffRowKind, R as DiffStat, S as DisplayBlock, T as EMPTY_CONVERSATION, U as EMPTY_HOLD, V as EMPTY_RUN, W as EMPTY_TASK_LOG, X as EMPTY_TASK_LOG_FOLLOW, Y as ErrorBody, Z as ExecuteResponse, _ as ExecutionSummary, $ as ForceSendResponse, a0 as GatedConversation, a1 as GeneratePlanResponse, a3 as HEADLESS_CLI_COMMANDS, a4 as HeldEdit, a5 as HeldEditMark, a9 as IsolationDiffResponse, aa as IsolationMergeResponse, ac as LiveOutputLookup, af as LocalEntry, ag as MarkdownToken, ah as MergeGateEntry, ai as MergeGateResponse, aj as MessageBlock, ak as MessageRole, al as ModelsResponse, am as NOT_STARTED, an as NO_TURN, ao as NewTaskFields, ap as NotificationAction, aq as OUTPUT_LINES_DEFAULT, ar as OUTPUT_LINES_MAX, as as OkResponse, au as OutputPreview, ax as PendingApprovalsOptions, ay as PlanBlock, az as PlanMarkerStatus, aA as PlanResponse, aB as PlanSnapshot, aD as PlannerCommandSyntax, aH as PlannerModelChoice, aI as PlannerModelMemory, aM as PlannerNotReady, aN as PlannerNotReadyError, aO as PlannerReadinessConfig, aP as PlannerSubmission, aQ as PlannerTurnDiscardedError, aR as PlannerTurnStoppedError, aS as PlannerUsageLimitError, aT as PrdResponse, aU as PromptHold, aV as RUN_SETTINGS_DEFAULTS, aX as RemoveMessageResponse, aZ as ResolveConflictResponse, a$ as RewindTargetsResponse, b0 as RunInput, b2 as RunSettingsError, b3 as RunSnapshotFrame, b4 as RunTask, b5 as RunTaskStatus, b8 as RunnerLoadedBlock, b9 as RunnersResponse, ba as STOPPED_BEFORE_START, bb as SUPERVISOR_LEVEL_LABEL, bc as SerializedConversationMessage, bd as SerializedPendingTurn, be as SerializedPlan, bf as SerializedTask, bg as SerializedTaskStatus, bi as SessionData, bj as SessionFrame, bk as SessionListResponse, bo as SessionResponse, bp as SettingsResponse, bq as SettingsService, br as SettingsUpdateResponse, bs as SkillInvocation, bt as SkillLoadBlock, bu as SkillToken, bx as StopResponse, by as StreamStamp, bz as SubagentBlock, bA as SubagentChild, bB as SubagentStatus, bC as SurfacePlan, bD as SurfacePlanState, bE as SurfaceTask, bF as TASK_QUERY_ANSWER_MAX_CHARS, bG as TASK_QUERY_ANSWER_OR_OPS, bH as TASK_QUERY_FIELDS, bI as TASK_QUERY_PROTOCOL, bJ as TASK_QUERY_REMINDER, bK as TERMINAL_UI_COMMANDS, bL as TakenPrompt, bM as TaskAttemptSnapshot, bN as TaskControlError, bO as TaskLogAttemptsResponse, bP as TaskLogBatch, bR as TaskLogFollow, bS as TaskLogFollowInput, bT as TaskLogResponse, bU as TaskLogView, bV as TaskMessageResponse, bW as TaskOp, bY as TaskOrchestratorDeps, bZ as TaskOrchestratorOptions, b$ as TaskPlacement, c0 as TaskQuery, c2 as TaskQueryField, c3 as TaskRef, c4 as TaskRowAction, c5 as TaskRowContext, c6 as TaskRowIsolation, c7 as TaskRowKind, c8 as TaskRowPlacement, c9 as TaskRowSubject, ca as TaskRowUsage, cb as TaskRowView, cc as TaskStartResponse, cd as TaskStatusKind, ce as ThinkingDisplayBlock, cf as ToolBlock, cg as ToolHeadline, ch as ToolStatus, ci as TreeTask, cj as TurnGate, ck as UsageBlock, cm as WAITS_FOR_APPROVAL_LABEL, cq as Worded, cr as WorkspacesResponse, cs as abbreviateHome, ct as aheadOfDraft, cu as applyTaskOps, cv as approvalLabel, cw as assignmentIssue, cx as assignmentIssueText, cy as automergeSummary, cz as autorunSummary, cA as awaitingLabel, cB as blockedByLabel, cC as blockingFailures, cD as canMergeTasks, cE as canSetDependencies, cF as canSplitTask, cG as capConflictFiles, cH as classifyOutcome, cI as coalesceTaskLog, cJ as createAiService, cK as dependencyCandidates, cL as dependentsNotice, cM as dependentsOf, cN as describePlannerNotReady, cO as diffRows, cP as diffStat, cQ as diffSummary, cR as digestTaskLog, cS as drainNext, cT as executionSummary, cU as followTaskLog, cV as followTurn, cW as fromTranscript, cX as getSettingsPath, cY as hasHiddenDetail, cZ as holdPrompt, c_ as isTaskRunning, c$ as loadedSkillTokens, d0 as markAction, d1 as markRequestFor, d2 as markdownHtml, d3 as markdownTokens, d4 as namedRepos, d5 as newTaskFields, d6 as opsEditable, d7 as outputLines, d8 as outputPreview, d9 as parseCount, da as parseSwitch, db as parseTaskOpsJson, dc as parseTaskQueryJson, dd as pastGateConfirmation, de as plannerMessage, df as plannerNotReady, dg as plannerNotReadyFor, dh as plannerTranscript, di as reconcileApprovals, dj as reduceConversation, dk as reduceRun, dl as reduceTaskLog, dm as renderTaskQueryAnswer, dn as replayTaskLog, dp as resolveSkillInvocation, dq as resolveTaskRef, dr as resolveUserTaskRef, ds as resumeLabel, dt as resumeTime, du as runSettingsOf, dv as runnerToolSubject, dw as serializePlan, dx as serializeTask, dy as serializeTaskStatus, dz as skillTokens, dA as skippedLabel, dB as stopTurn, dC as subtreeIds, dD as summarizeToolCall, dE as supervisorSummary, dF as surfacePlan, dG as surfacePlanState, dH as takeAt, dI as taskLogForSurface, dJ as taskOrderLabel, dK as taskPlacement, dL as taskQuerySignature, dM as taskRef, dN as taskRefOf, dO as taskRowActions, dP as taskRowView, dQ as taskStartedNotice, dR as taskStatusKind, dS as textHasTaskOps, dT as textHasTaskQuery, dU as titledRefs, dV as titledTaskRef, dW as titledTaskRefOf, dX as toTaskLogEvent, dY as toolHeadline, dZ as trimToolOutput, d_ as truncateCheckpointSummary, d$ as unsendAll, e0 as unsendLatest, e1 as walkPlan } from './runSettingsText-BgOmLxdw.mjs';
|
|
5
|
+
import { j as ApprovalDecision, J as IApproval, L as IFileSystem, ak as ResearchShell, aj as ReadFileOpts, aU as ToolOutcome, H as GrepOptions, B as GlobOptions, y as FindSymbolOptions, M as IRunner, K as IConfig, a9 as PlannerBackendId, af as ProviderModelLists, f as AiProvider, m as ApprovalModeSetting, ac as PlannerToolHandler, ay as RunnerRegistry, a3 as OrchestratorOption, d as AgentProcessDeps, aM as TaskModeAgentAdapter, a as AgentAdapter, e as AgentStartOptions, c as AgentEvent, ap as RunnerCommand, ad as ProjectMcpServer, N as IRunnerSession, n as ApprovalPolicy, i as ApprovalAnswer, a4 as OrdewellMcpServer, aJ as TaskCompleteArgs, r as CheckpointAnswer, aE as StructuredTurnEnd, aD as StructuredEvent, aL as TaskMessageFrom, ah as QueuedTaskMessage, aR as TaskStartOptions, aS as TaskTokenScope, at as RunnerManifest, aQ as TaskRunnerFlags } from './IFileSystem-DUgeWWQN.mjs';
|
|
6
|
+
export { A as AUTO_COMMANDS, b as AgentAdapterFactory, g as AllProviderModels, h as AnswerApprovalArgs, k as ApprovalKind, l as ApprovalMode, o as ApprovalPolicyOptions, p as ApprovalRequest, q as ApprovalSource, C as CatalogModel, s as CheckpointArgs, t as CommandClassification, u as CommandTier, v as CommandWords, D as DEFAULT_PLANNER_ALLOWLIST, w as DENY_ALL, x as DiscoveryCommand, E as EditPlanArgs, F as FetchAllProviderModelsOptions, G as GIT_READONLY_SUBCOMMANDS, z as GREP_DEFAULT_HEAD_LIMIT, I as GrepOutputMode, O as InvokedCommand, P as LineBuffer, Q as ListModelsArgs, R as ListRunnersArgs, S as LoadSkillArgs, T as McpClientConfig, U as McpCredential, V as McpTool, W as McpToolContext, X as McpToolReply, Y as MessageTaskArgs, Z as ModelCatalog, _ as ModelShortcut, $ as ORCHESTRATOR_SHORTCUTS, a0 as ORDEWELL_MCP_PATH, a1 as ORDEWELL_MCP_SERVER_NAME, a2 as OneTaskArgs, a5 as OwnerOnlyFile, a6 as PLANNER_EXECUTION_TOOLS, a7 as PLANNER_TOOLS, a8 as PlannerAllowlist, aa as PlannerStartOptions, ab as PlannerTokenScope, ae as ProviderCredentialSource, ag as ProviderModelsResult, ai as REFUSED_COMMANDS, al as ResearchShellDeps, am as RetryTaskArgs, an as RunCommandArgs, ao as RunPlanArgs, aq as RunnerCommandKind, ar as RunnerEntry, as as RunnerFeatures, au as RunnerMcpServer, av as RunnerMode, aw as RunnerModelDiscovery, ax as RunnerModelRef, az as SEARCH_EXCLUSIONS, aA as ShellDialect, aB as SpawnFn, aC as StandingDecision, aF as SubmitPlanArgs, aG as TASK_COMPLETE_TOOL, aH as TASK_COMPLETION_CONTRACT, aI as TASK_TOOLS, aK as TaskDiffArgs, aN as TaskModeUnsupportedError, aO as TaskOutputArgs, aP as TaskQueryArgs, aT as TaskToolHandler, aW as approvalScopes, aX as classifyCommand, aY as clearResearchShellCache, aZ as collectProviderCredentials, a_ as commandAllowedBy, a$ as effectiveApprovalMode, b0 as enabledRunners, b1 as fetchAllProviderModels, b2 as findRunnerCommand, b3 as isGranted, b4 as isRunnerApproval, b5 as knownModelId, b6 as mcpClientConfig, b7 as ownerOnlyConfigFile, b8 as parseAllowlist, b9 as parseApprovalModeSetting, ba as researchShellWarning, bb as researchToolsPath, bc as resolveModelShortcut, bd as resolveProvider, be as resolveResearchShell, bf as scopeAllowed, bg as sharedMcpServer, bh as toApprovalDecision, bi as toOrchestratorOptions, bj as toolAllowed } from './IFileSystem-DUgeWWQN.mjs';
|
|
7
|
+
import { R as RunnerModeInfo } from './ModeResolver-4qNjxcDs.mjs';
|
|
8
|
+
export { a as autonomyLevelLabel, p as parseAutonomyLevel, r as runnerModesFrom } from './ModeResolver-4qNjxcDs.mjs';
|
|
11
9
|
import { ChildProcess } from 'child_process';
|
|
12
10
|
import { EventEmitter } from 'events';
|
|
13
11
|
import 'zod/v4';
|
|
@@ -42,10 +40,13 @@ type ExecutionCommand = {
|
|
|
42
40
|
task: string;
|
|
43
41
|
from: 'fresh' | 'session';
|
|
44
42
|
message?: string;
|
|
45
|
-
}
|
|
43
|
+
}
|
|
44
|
+
/** `force`: the user's force send (ADR-0023, F1), which interrupts the running turn and is read next. */
|
|
45
|
+
| {
|
|
46
46
|
command: 'message_task';
|
|
47
47
|
task: string;
|
|
48
48
|
text: string;
|
|
49
|
+
force?: boolean;
|
|
49
50
|
}
|
|
50
51
|
/** `answer` is checked here rather than typed: an `allow` must reach the seam to be refused with its reason. */
|
|
51
52
|
| {
|
|
@@ -64,20 +65,89 @@ type ExecutionCommand = {
|
|
|
64
65
|
command: 'skip_task';
|
|
65
66
|
task: string;
|
|
66
67
|
reason?: string;
|
|
68
|
+
}
|
|
69
|
+
/** The user's force start: past a failed dependency or a merge gate, queued behind dependencies still under way (ADR-0035). */
|
|
70
|
+
| {
|
|
71
|
+
command: 'force_start';
|
|
72
|
+
task: string;
|
|
73
|
+
}
|
|
74
|
+
/** The user vouches for the task's work, which lands as a passed verdict's would; never anyone else (ADR-0029). */
|
|
75
|
+
| {
|
|
76
|
+
command: 'mark_complete';
|
|
77
|
+
task: string;
|
|
78
|
+
}
|
|
79
|
+
/** The user takes a completion back: the task is not started again, and held until it is retried or started. */
|
|
80
|
+
| {
|
|
81
|
+
command: 'mark_not_done';
|
|
82
|
+
task: string;
|
|
83
|
+
}
|
|
84
|
+
/** Stop a structured task's running turn, keeping its session: it then waits for the user's message. */
|
|
85
|
+
| {
|
|
86
|
+
command: 'interrupt_task';
|
|
87
|
+
task: string;
|
|
88
|
+
}
|
|
89
|
+
/** Force send a message queued behind the running turn (ADR-0023, F1); `id` is the one `message_task` answered with. */
|
|
90
|
+
| {
|
|
91
|
+
command: 'force_send_queued';
|
|
92
|
+
task: string;
|
|
93
|
+
id: string;
|
|
94
|
+
}
|
|
95
|
+
/** Take back a message still queued behind the running turn. */
|
|
96
|
+
| {
|
|
97
|
+
command: 'remove_queued';
|
|
98
|
+
task: string;
|
|
99
|
+
id: string;
|
|
100
|
+
}
|
|
101
|
+
/** Keep a task paused on a usage limit from resuming on its own at the reset: it waits for the user's Resume now or Retry. */
|
|
102
|
+
| {
|
|
103
|
+
command: 'cancel_resume';
|
|
104
|
+
task: string;
|
|
105
|
+
}
|
|
106
|
+
/** The user's answer to the checkpoint a task waits at: it goes on, or is told `reason` to act on. */
|
|
107
|
+
| {
|
|
108
|
+
command: 'answer_checkpoint';
|
|
109
|
+
task: string;
|
|
110
|
+
answer: 'approve' | 'reject';
|
|
111
|
+
reason?: string;
|
|
112
|
+
}
|
|
113
|
+
/** The user signs off the plan's review: every task in it is approved, as executing it approves them, and it runs. */
|
|
114
|
+
| {
|
|
115
|
+
command: 'approve_review';
|
|
116
|
+
};
|
|
117
|
+
/** What a control answers besides its line, for the surface whose button asked. */
|
|
118
|
+
type CommandPayload =
|
|
119
|
+
/** `message_task`: the queued message's id, which the surface's button answers with. */
|
|
120
|
+
{
|
|
121
|
+
kind: 'message';
|
|
122
|
+
id: string;
|
|
123
|
+
}
|
|
124
|
+
/** `force_start` queued behind dependencies still under way, rather than started: the line saying so. */
|
|
125
|
+
| {
|
|
126
|
+
kind: 'queued';
|
|
127
|
+
line: string;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The user's `merge_all`, merged or stopped: what the Merge all card
|
|
131
|
+
* renders. Whether it closed the run is the Session's `run_closed` (ADR-0013).
|
|
132
|
+
*/
|
|
133
|
+
| {
|
|
134
|
+
kind: 'merge';
|
|
135
|
+
result: IsolationMergeResult;
|
|
67
136
|
};
|
|
68
137
|
/**
|
|
69
138
|
* What a call came to: `message` is written for the caller, a model included,
|
|
70
|
-
* to act on.
|
|
71
|
-
*
|
|
139
|
+
* to act on. A refusal carries a payload only where the act ran and stopped:
|
|
140
|
+
* a Merge all that git would not take.
|
|
72
141
|
*/
|
|
73
142
|
type CommandOutcome = {
|
|
74
143
|
ok: true;
|
|
75
144
|
message: string;
|
|
76
|
-
|
|
145
|
+
payload?: CommandPayload;
|
|
77
146
|
} | {
|
|
78
147
|
ok: false;
|
|
79
148
|
outcome: 'refused' | 'declined';
|
|
80
149
|
message: string;
|
|
150
|
+
payload?: CommandPayload;
|
|
81
151
|
};
|
|
82
152
|
/** What the seam does with a valid command: run it, ask the user first, or refuse with a note the caller can act on. */
|
|
83
153
|
type Consent = {
|
|
@@ -114,9 +184,9 @@ interface WaitingRequest {
|
|
|
114
184
|
subject: string;
|
|
115
185
|
}
|
|
116
186
|
/**
|
|
117
|
-
* What the seam reads and calls. The Session supplies it from
|
|
118
|
-
*
|
|
119
|
-
*
|
|
187
|
+
* What the seam reads and calls. The Session supplies it from the operations
|
|
188
|
+
* behind the surfaces' buttons, so a command lands exactly as the matching
|
|
189
|
+
* button press does, whoever asked.
|
|
120
190
|
*/
|
|
121
191
|
interface ExecutionHost {
|
|
122
192
|
/** The plan's task tree; null when there is no plan. */
|
|
@@ -148,12 +218,12 @@ interface ExecutionHost {
|
|
|
148
218
|
maxParallel(): number;
|
|
149
219
|
/** The run waits on the user to stash or skip isolation before anything starts. */
|
|
150
220
|
runBlocked(): boolean;
|
|
151
|
-
/**
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
221
|
+
/**
|
|
222
|
+
* Every reason the task cannot start now, from the scheduler's one start
|
|
223
|
+
* rule (ADR-0034). Takes the task, not its id: one a held edit changes or
|
|
224
|
+
* adds is judged as the edit leaves it.
|
|
225
|
+
*/
|
|
226
|
+
startWaits(task: Readonly<Task>): readonly StartWait[];
|
|
157
227
|
/** The runner requests waiting on a task for an answer. */
|
|
158
228
|
waitingRequests(taskId: string): readonly WaitingRequest[];
|
|
159
229
|
/** A start is told who asked: whether a run it opens continues the last one depends on it (ADR-0029). */
|
|
@@ -165,6 +235,11 @@ interface ExecutionHost {
|
|
|
165
235
|
*/
|
|
166
236
|
joinRun(approved: number): Promise<string>;
|
|
167
237
|
startTask(taskId: string, actor: ExecutionActor): Promise<void>;
|
|
238
|
+
/** Force start the task; answers the line saying it waits for its dependencies, when it was queued behind them rather than started. */
|
|
239
|
+
forceStart(taskId: string): Promise<string | undefined>;
|
|
240
|
+
markComplete(taskId: string): Promise<void>;
|
|
241
|
+
markNotDone(taskId: string): Promise<void>;
|
|
242
|
+
interrupt(taskId: string): Promise<void>;
|
|
168
243
|
stopTask(taskId: string): Promise<void>;
|
|
169
244
|
stopRun(): void;
|
|
170
245
|
retryTask(taskId: string, actor: ExecutionActor): Promise<void>;
|
|
@@ -174,8 +249,22 @@ interface ExecutionHost {
|
|
|
174
249
|
/** Resume a task paused on a usage limit now; see {@link TaskOrchestrator.resumeNow}. */
|
|
175
250
|
resumeNow(taskId: string, message: string | undefined, actor: ExecutionActor): Promise<void>;
|
|
176
251
|
messageTask(taskId: string, text: string): string;
|
|
177
|
-
|
|
178
|
-
|
|
252
|
+
/** Force send (ADR-0023, F1): interrupt the running turn and deliver this next. */
|
|
253
|
+
forceMessage(taskId: string, text: string): string;
|
|
254
|
+
/** False once the message was delivered. */
|
|
255
|
+
forceSendQueued(taskId: string, id: string): boolean;
|
|
256
|
+
/** False once the message was delivered or taken back. */
|
|
257
|
+
removeQueued(taskId: string, id: string): boolean;
|
|
258
|
+
/** False when no resume was scheduled. */
|
|
259
|
+
cancelResume(taskId: string): Promise<boolean>;
|
|
260
|
+
/** The task waits at a checkpoint, and a runner is left to hear the answer. */
|
|
261
|
+
awaitsCheckpoint(taskId: string): boolean;
|
|
262
|
+
answerCheckpoint(taskId: string, approve: boolean, reason?: string): void;
|
|
263
|
+
/** Sign off the review: the plan is the user's, and runs. */
|
|
264
|
+
approveReview(): Promise<void>;
|
|
265
|
+
/** Answer a runner's request, as its card does; false once it was answered or withdrawn. */
|
|
266
|
+
answerRequest(requestId: string, decision: ApprovalDecision): boolean;
|
|
267
|
+
/** Merge all, through the queue it shares with landings. */
|
|
179
268
|
mergeAll(): Promise<IsolationMergeResult>;
|
|
180
269
|
/** Keep the call in the timeline, worded as `text`. */
|
|
181
270
|
record(record: ExecutionRecord, text: string): void;
|
|
@@ -208,12 +297,13 @@ interface ExecutionCommandsDeps {
|
|
|
208
297
|
now?: () => string;
|
|
209
298
|
}
|
|
210
299
|
/**
|
|
211
|
-
* The command seam (ADR-0029, #91): the one place an execution action
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* user where consent needs a person,
|
|
215
|
-
*
|
|
216
|
-
*
|
|
300
|
+
* The command seam (ADR-0029, #91): the one place an execution action
|
|
301
|
+
* reaches the scheduler, whether the user, a planner turn or the supervisor
|
|
302
|
+
* asked. It resolves the task, checks the call against the plan's state, who
|
|
303
|
+
* asked and the user's approval, asks the user where consent needs a person,
|
|
304
|
+
* runs the Session operation behind the matching button, and records the call
|
|
305
|
+
* in the timeline with who asked. A refusal names the task and the reason,
|
|
306
|
+
* worded for whoever asked to act on ({@link voiceOf}).
|
|
217
307
|
*/
|
|
218
308
|
declare class ExecutionCommands {
|
|
219
309
|
private readonly deps;
|
|
@@ -269,8 +359,9 @@ declare class ExecutionCommands {
|
|
|
269
359
|
private asksToApprove;
|
|
270
360
|
/**
|
|
271
361
|
* Who may do what without the mandate (#23): the user's own call needs no
|
|
272
|
-
* consent
|
|
273
|
-
* as the autonomy level says;
|
|
362
|
+
* consent, and their own controls are theirs alone; a planner turn may
|
|
363
|
+
* always end or steer work, and starts it only as the autonomy level says;
|
|
364
|
+
* the supervisor's level decides for it.
|
|
274
365
|
*/
|
|
275
366
|
private consent;
|
|
276
367
|
/**
|
|
@@ -282,6 +373,19 @@ declare class ExecutionCommands {
|
|
|
282
373
|
private prepareRunPlan;
|
|
283
374
|
/** A start of one task: `run_task`, or a fresh `retry_task`, which also takes a task that failed or waits on the user. */
|
|
284
375
|
private prepareStart;
|
|
376
|
+
/**
|
|
377
|
+
* The user's force start goes past what the scheduler waits for, so only
|
|
378
|
+
* what no start could get past is refused here; the start rule decides the
|
|
379
|
+
* rest at the claim, and a dependency still under way queues it.
|
|
380
|
+
*/
|
|
381
|
+
private prepareForceStart;
|
|
382
|
+
/** Signing off the review approves every task in the plan, as executing it does: the seam records that before it acts. */
|
|
383
|
+
private prepareApproveReview;
|
|
384
|
+
private prepareMarkComplete;
|
|
385
|
+
private prepareMarkNotDone;
|
|
386
|
+
private prepareInterrupt;
|
|
387
|
+
private prepareCancelResume;
|
|
388
|
+
private prepareCheckpoint;
|
|
285
389
|
private prepareContinue;
|
|
286
390
|
/**
|
|
287
391
|
* A pause is not a failure: the attempt stopped on its account's limit, so
|
|
@@ -292,6 +396,13 @@ declare class ExecutionCommands {
|
|
|
292
396
|
private prepareStop;
|
|
293
397
|
private prepareStopRun;
|
|
294
398
|
private prepareMessage;
|
|
399
|
+
/** A message queued behind the running turn, sent now or taken back; one delivered meanwhile is past either. */
|
|
400
|
+
private prepareQueued;
|
|
401
|
+
/**
|
|
402
|
+
* The user answers a runner's request as its card does. Anyone else only
|
|
403
|
+
* narrows or hands it on: allowing would widen the mode the plan gave the
|
|
404
|
+
* task (ADR-0029).
|
|
405
|
+
*/
|
|
295
406
|
private prepareAnswer;
|
|
296
407
|
private prepareMergeAll;
|
|
297
408
|
/**
|
|
@@ -326,1150 +437,10 @@ declare class ExecutionCommands {
|
|
|
326
437
|
private located;
|
|
327
438
|
/** A reference read against the plan as the held edit leaves it, where the handles its batch gives come first. */
|
|
328
439
|
private locateAsEdited;
|
|
329
|
-
/** A reference as a caller writes one — see {@link resolveTaskRef}. */
|
|
440
|
+
/** A reference as a caller writes one — see {@link resolveTaskRef}; the user's as they type one ({@link resolveUserTaskRef}). */
|
|
330
441
|
private locate;
|
|
331
442
|
}
|
|
332
443
|
|
|
333
|
-
/**
|
|
334
|
-
* The planner's read channel: a `{"taskQuery":{...}}` reply asking Ordewell to
|
|
335
|
-
* show it what the per-turn plan block deliberately leaves out.
|
|
336
|
-
*
|
|
337
|
-
* The plan block carries only short fields, so a planner asked to "add a line
|
|
338
|
-
* to task 3's prompt" would be rewriting text it has never read. Inlining every
|
|
339
|
-
* body on every turn was rejected — a twenty-task plan re-sends thousands of
|
|
340
|
-
* tokens per message — so the planner asks instead, and pays for the detail
|
|
341
|
-
* only on the turns it uses it.
|
|
342
|
-
*
|
|
343
|
-
* This module owns the wire shape and the rendering of the answer; the loop,
|
|
344
|
-
* the budgets and the injection live in the Session, and the classification
|
|
345
|
-
* lives in PlanRepair alongside the plan and task-ops envelopes.
|
|
346
|
-
*/
|
|
347
|
-
/** The long fields a query may ask for. Everything else is already in the plan block. */
|
|
348
|
-
declare const TASK_QUERY_FIELDS: readonly ["description", "prompt", "userSteps", "verdict", "outputSummary", "userStoriesCovered", "skills", "output"];
|
|
349
|
-
type TaskQueryField = typeof TASK_QUERY_FIELDS[number];
|
|
350
|
-
/** Lines a `output` read returns when the query sets no count. */
|
|
351
|
-
declare const OUTPUT_LINES_DEFAULT = 80;
|
|
352
|
-
/** Hard cap on `outputLines` — the tail read is bounded however the planner asks. */
|
|
353
|
-
declare const OUTPUT_LINES_MAX = 400;
|
|
354
|
-
/**
|
|
355
|
-
* Character budget the rendered answer converges to. A running output tail is
|
|
356
|
-
* the only part with no natural bound — a runner may print for minutes — so
|
|
357
|
-
* the tail absorbs the clamp; everything else (task bodies, the catalog cap)
|
|
358
|
-
* is bounded upstream.
|
|
359
|
-
*/
|
|
360
|
-
declare const TASK_QUERY_ANSWER_MAX_CHARS = 20000;
|
|
361
|
-
interface TaskQuery {
|
|
362
|
-
/** Task references to read in full, as {@link resolveTaskRef} reads them. */
|
|
363
|
-
tasks: string[];
|
|
364
|
-
/** Narrows what comes back. Omitted means every field in {@link TASK_QUERY_FIELDS}. */
|
|
365
|
-
fields?: TaskQueryField[];
|
|
366
|
-
/** Also return the full runner/model catalog with labels, variants and mode descriptions. */
|
|
367
|
-
catalog: boolean;
|
|
368
|
-
/** Line count for `output` reads. Clamped at render to [1, {@link OUTPUT_LINES_MAX}]. */
|
|
369
|
-
outputLines?: number;
|
|
370
|
-
/** A previous answer's next offset: the output tail then covers only what came after it. */
|
|
371
|
-
outputSince?: number;
|
|
372
|
-
}
|
|
373
|
-
declare function textHasTaskQuery(text: string): boolean;
|
|
374
|
-
/** Parse a `{"taskQuery":...}` reply. Throws PlanParseError when the JSON is unusable. */
|
|
375
|
-
declare function parseTaskQueryJson(text: string): TaskQuery;
|
|
376
|
-
/** Stable identity of a query, so a turn can recognise the planner asking the same thing twice. */
|
|
377
|
-
declare function taskQuerySignature(query: TaskQuery): string;
|
|
378
|
-
/** What a full-catalog read is answered from. Models arrive already allowlist-filtered. */
|
|
379
|
-
interface TaskQueryCatalog {
|
|
380
|
-
runners: RunnerId[];
|
|
381
|
-
models: Partial<Record<RunnerId, DiscoveredModel[]>>;
|
|
382
|
-
modes: Record<RunnerId, RunnerModeInfo[]>;
|
|
383
|
-
autonomousDefault: boolean;
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Appended when the planner has spent its read budget, or asked the identical
|
|
387
|
-
* question twice. The detail still comes back — refusing it would leave the
|
|
388
|
-
* planner editing text it has not read, which is the whole failure this
|
|
389
|
-
* channel exists to prevent — but the turn is told to land.
|
|
390
|
-
*/
|
|
391
|
-
declare const TASK_QUERY_ANSWER_OR_OPS: string;
|
|
392
|
-
/**
|
|
393
|
-
* The protocol as the planner is taught it, owned here beside the parser so the
|
|
394
|
-
* two cannot drift. Both planner backends get these lines verbatim (ADR-0009):
|
|
395
|
-
* a harness planner has no tool loop to reach, so the envelope is the channel.
|
|
396
|
-
*/
|
|
397
|
-
declare const TASK_QUERY_PROTOCOL: string[];
|
|
398
|
-
/** The one-line reminder the per-turn plan block carries, so the protocol has a single owner. */
|
|
399
|
-
declare const TASK_QUERY_REMINDER = "- To READ a task in full (prompt, user steps, verdict, output, user stories) or the whole model/mode catalog before editing, reply with ONLY {\"taskQuery\":{\"tasks\":[\"<id or #order>\"],\"catalog\":true}} \u2014 it changes nothing, and you then reply again with your ops.";
|
|
400
|
-
/**
|
|
401
|
-
* Where an `output` read is answered from: the orchestrator's live capture of
|
|
402
|
-
* the task's latest attempt. Injected so this module stays planner-side and
|
|
403
|
-
* never imports the orchestrator.
|
|
404
|
-
*/
|
|
405
|
-
type LiveOutputLookup = (taskId: string, opts: LiveTailOptions) => LiveTail | null;
|
|
406
|
-
/**
|
|
407
|
-
* Render the injected answer to one read. Never persisted — it is context for
|
|
408
|
-
* the planner's next reply and nothing else — so it is built fresh from live
|
|
409
|
-
* state on every query rather than cached. `liveOutput` backs the `output`
|
|
410
|
-
* field; omitting it reads as "nothing captured".
|
|
411
|
-
*/
|
|
412
|
-
declare function renderTaskQueryAnswer(query: TaskQuery, tasks: readonly Task[], catalog: TaskQueryCatalog, liveOutput?: LiveOutputLookup): string;
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* The SSRF guard for anything that leaves the machine on the planner's behalf.
|
|
416
|
-
* An unguarded `http://169.254.169.254/` would hand a prompt-injected planner
|
|
417
|
-
* the cloud metadata credentials, so every outbound host is vetted here: IP
|
|
418
|
-
* literals by range, names by every address DNS answers with.
|
|
419
|
-
*/
|
|
420
|
-
type ResolveAll = (host: string) => Promise<string[]>;
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* The one decision every planner web read goes through, whichever runner
|
|
424
|
-
* plans and whichever path carries the bytes (ADR-0027). A fetch names the
|
|
425
|
-
* URL it reads; a search names its query and the provider that receives it.
|
|
426
|
-
*/
|
|
427
|
-
type WebRead = {
|
|
428
|
-
kind: 'fetch';
|
|
429
|
-
url: string;
|
|
430
|
-
}
|
|
431
|
-
/** `provider` keys the grant; `providerLabel`, when given, names it to the person asked. */
|
|
432
|
-
| {
|
|
433
|
-
kind: 'search';
|
|
434
|
-
query: string;
|
|
435
|
-
provider: string;
|
|
436
|
-
providerLabel?: string;
|
|
437
|
-
note?: string;
|
|
438
|
-
};
|
|
439
|
-
/** A refusal's `reason` is written for the planner: it says what to do next. */
|
|
440
|
-
type WebReadDecision = {
|
|
441
|
-
allowed: true;
|
|
442
|
-
} | {
|
|
443
|
-
allowed: false;
|
|
444
|
-
reason: string;
|
|
445
|
-
};
|
|
446
|
-
interface DecideOptions {
|
|
447
|
-
/**
|
|
448
|
-
* Research subagents run in the background where nothing can prompt
|
|
449
|
-
* (ADR-0008, T6). When false, a read that would ask is refused with the gap
|
|
450
|
-
* to report, rather than raising a prompt nobody can answer.
|
|
451
|
-
*/
|
|
452
|
-
prompting?: boolean;
|
|
453
|
-
}
|
|
454
|
-
interface WebReadPolicyOptions {
|
|
455
|
-
approval: IApproval;
|
|
456
|
-
/** The secrets Ordewell holds — provider keys, MCP tokens — read per request. */
|
|
457
|
-
secrets?: () => Iterable<string>;
|
|
458
|
-
/** Defaults to `process.env`; its credential-named values are secrets too. */
|
|
459
|
-
env?: () => Record<string, string | undefined>;
|
|
460
|
-
/** How many web reads one planner turn may make; read per request, so a settings change applies at once. */
|
|
461
|
-
budget?: () => number;
|
|
462
|
-
/** The planner turn in progress; a new one starts a new budget. */
|
|
463
|
-
turn?: () => string | undefined;
|
|
464
|
-
/** Override DNS resolution (every answer for a name) in tests. */
|
|
465
|
-
resolveHost?: ResolveAll;
|
|
466
|
-
}
|
|
467
|
-
declare const DEFAULT_WEB_READ_BUDGET = 40;
|
|
468
|
-
declare class WebReadPolicy {
|
|
469
|
-
private readonly approval;
|
|
470
|
-
private readonly resolveHost;
|
|
471
|
-
private readonly secrets;
|
|
472
|
-
private readonly env;
|
|
473
|
-
private readonly budget;
|
|
474
|
-
private readonly turn;
|
|
475
|
-
private spent;
|
|
476
|
-
constructor(opts: WebReadPolicyOptions);
|
|
477
|
-
/**
|
|
478
|
-
* Every check that needs no network runs first, then the budget and the
|
|
479
|
-
* approval, and only then is a fetch's host resolved: a lookup is itself a
|
|
480
|
-
* request, so `<data>.attacker.example` would leave through DNS even for a
|
|
481
|
-
* read that is then excluded, over budget or declined.
|
|
482
|
-
*/
|
|
483
|
-
decide(read: WebRead, opts?: DecideOptions): Promise<WebReadDecision>;
|
|
484
|
-
private subagentRefusal;
|
|
485
|
-
/**
|
|
486
|
-
* Whether a search through `provider` would run without asking anyone, for
|
|
487
|
-
* a runner whose own search raises no request and is set on or off when
|
|
488
|
-
* its session starts (ADR-0027). A zero budget disables it; no query is
|
|
489
|
-
* known yet, so secrets and individual reads cannot be checked or counted.
|
|
490
|
-
*/
|
|
491
|
-
searchesUnasked(provider: string): boolean;
|
|
492
|
-
/** The last check, the one that leaves the machine: every DNS answer for the host must be public. */
|
|
493
|
-
private resolved;
|
|
494
|
-
private refuse;
|
|
495
|
-
private vetFetch;
|
|
496
|
-
private vetSearch;
|
|
497
|
-
private spend;
|
|
498
|
-
private refund;
|
|
499
|
-
private carriesSecret;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
interface IWebFetcher {
|
|
503
|
-
/**
|
|
504
|
-
* The web-read policy's decision (ADR-0027), for a read this fetcher will
|
|
505
|
-
* carry or one a runner carries natively, such as Claude's `WebFetch`.
|
|
506
|
-
* `fetch` and `search` decide for themselves; never call both.
|
|
507
|
-
*/
|
|
508
|
-
decide(read: WebRead): Promise<WebReadDecision>;
|
|
509
|
-
/** Whether a runner's own search through `provider` would run unasked; see `WebReadPolicy.searchesUnasked`. */
|
|
510
|
-
searchesUnasked?(provider: string): boolean;
|
|
511
|
-
fetch(url: string): Promise<ToolOutcome>;
|
|
512
|
-
/**
|
|
513
|
-
* Optional web search. A fetcher without it makes the `web_search` tool
|
|
514
|
-
* report itself unavailable rather than failing the turn — the same
|
|
515
|
-
* degradation `fetch` already uses when no fetcher is wired at all.
|
|
516
|
-
*/
|
|
517
|
-
search?(query: string): Promise<ToolOutcome>;
|
|
518
|
-
/**
|
|
519
|
-
* A variant of this fetcher for a research subagent: same policy, cache,
|
|
520
|
-
* transport and budget, but a read that would ask a person is refused
|
|
521
|
-
* instead (ADR-0027, ADR-0008 T6). Absent means subagents get no web tools
|
|
522
|
-
* and the `fetch`/`web_search` tools report themselves unavailable.
|
|
523
|
-
*/
|
|
524
|
-
forSubagent?(): IWebFetcher;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
/**
|
|
528
|
-
* A person's approvals of project MCP servers, kept across sessions
|
|
529
|
-
* (ADR-0028). Keyed by repository root and scope, which names the server
|
|
530
|
-
* and hashes its definition: a changed definition is a new question.
|
|
531
|
-
*/
|
|
532
|
-
interface ProjectServerApprovals {
|
|
533
|
-
approved(repoRoot: string, scope: string): boolean;
|
|
534
|
-
remember(repoRoot: string, scope: string): void;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
interface CliAgentAiServiceDeps extends Partial<AgentProcessDeps> {
|
|
538
|
-
/** Overrides adapter construction. Tests supply a fake agent; production picks by runner id. */
|
|
539
|
-
createAdapter?: (runner: string, deps: AgentProcessDeps) => AgentAdapter | null;
|
|
540
|
-
/** Workspace root the agent explores. Defaults to the host process's cwd. */
|
|
541
|
-
workspaceRoot?: () => string;
|
|
542
|
-
/** Where a conversation's planner tools are served (ADR-0022). Absent: no conversation can start. */
|
|
543
|
-
mcpServer?: OrdewellMcpServer;
|
|
544
|
-
/** A person's approvals of project MCP servers, kept across sessions (ADR-0028). Defaults to Ordewell's data directory. */
|
|
545
|
-
projectServerApprovals?: ProjectServerApprovals;
|
|
546
|
-
}
|
|
547
|
-
/**
|
|
548
|
-
* A coding agent driven as Ordewell's planner (ADR-0009).
|
|
549
|
-
*
|
|
550
|
-
* The second transport behind `IAiService`, sitting beside `OpenAiService` and
|
|
551
|
-
* `GeminiService`. It deliberately does **not** extend {@link BaseAiService}:
|
|
552
|
-
* that class's body is Ordewell executing research tools on a model's behalf,
|
|
553
|
-
* which is precisely the part a coding agent replaces. What it reuses instead
|
|
554
|
-
* is everything above the transport — `settleReply` (the empty-reply nudge
|
|
555
|
-
* and the turn's settling), the plan validator, the `ResearchProgress` events the
|
|
556
|
-
* four surfaces already render. That is why this backend reaches VS Code, the
|
|
557
|
-
* web UI, the CLI and the TUI without any of them learning a coding agent is
|
|
558
|
-
* on the other end.
|
|
559
|
-
*/
|
|
560
|
-
declare class CliAgentAiService implements IAiService {
|
|
561
|
-
private config;
|
|
562
|
-
private readonly runner;
|
|
563
|
-
private readonly processDeps;
|
|
564
|
-
private readonly makeAdapter;
|
|
565
|
-
private readonly workspaceRoot;
|
|
566
|
-
private environmentSecrets;
|
|
567
|
-
/** The conversation's session, from its start until the next session boundary. */
|
|
568
|
-
private session;
|
|
569
|
-
private readonly mcpServer;
|
|
570
|
-
private readonly projectServerApprovals;
|
|
571
|
-
private activeAbort;
|
|
572
|
-
constructor(config: IConfig, deps?: CliAgentAiServiceDeps);
|
|
573
|
-
hasActiveConversation(): boolean;
|
|
574
|
-
/**
|
|
575
|
-
* False when the running agent process was spawned under a model/effort the
|
|
576
|
-
* user has since changed in the picker. Unlike a vendor backend, the model
|
|
577
|
-
* is a spawn-time argument to the agent CLI (`--model`), not a per-request
|
|
578
|
-
* field — `continueConversation` sends the next turn to whatever process is
|
|
579
|
-
* already running, so a plain config read here would silently keep planning
|
|
580
|
-
* on the old model. No conversation yet is vacuously "current".
|
|
581
|
-
*/
|
|
582
|
-
conversationMatchesConfig(): boolean;
|
|
583
|
-
/** Always: a conversation whose planner cannot reach the Ordewell MCP server fails to start rather than falling back to the envelopes. */
|
|
584
|
-
plannerToolsAttached(): boolean;
|
|
585
|
-
/** The agent's own session id, a resumption hint only — Ordewell's transcript is authoritative (T4). */
|
|
586
|
-
nativeSessionId(): string | null;
|
|
587
|
-
heldSecrets(): readonly string[];
|
|
588
|
-
restart(): void;
|
|
589
|
-
reset(): void;
|
|
590
|
-
startConversation(req: ConversationRequest): Promise<ConversationTurn>;
|
|
591
|
-
continueConversation(userMessage: string, onProgress: (progress: ResearchProgress) => void, signal?: AbortSignal): Promise<ConversationTurn>;
|
|
592
|
-
private openingMessage;
|
|
593
|
-
/**
|
|
594
|
-
* Drive one user message to a settled planner turn through
|
|
595
|
-
* {@link settleReply}, the loop the API backend settles through too. The
|
|
596
|
-
* tool rounds belong to the agent now, so one call is one agent turn —
|
|
597
|
-
* continued while it left subagents running in the background.
|
|
598
|
-
*/
|
|
599
|
-
private runConversation;
|
|
600
|
-
/**
|
|
601
|
-
* Run one agent turn: stream its events into `ResearchProgress`, collect the
|
|
602
|
-
* reply text, and return the research steps produced. Tool calls are matched
|
|
603
|
-
* to their results by the agent's own call id — matching by tool name puts
|
|
604
|
-
* one file's body on another file's row the moment an agent runs two reads
|
|
605
|
-
* at once, which all three of these do routinely.
|
|
606
|
-
*/
|
|
607
|
-
/**
|
|
608
|
-
* A turn, and then — while the agent ended it with subagents still in the
|
|
609
|
-
* background — a turn asking it to wait for them: whatever they find would
|
|
610
|
-
* otherwise be said into a closed turn, or, in a one-shot, into a session
|
|
611
|
-
* already thrown away. Bounded by `waits`, shared across a reply's sends.
|
|
612
|
-
*/
|
|
613
|
-
private runTurnAwaitingAgents;
|
|
614
|
-
private runTurn;
|
|
615
|
-
/**
|
|
616
|
-
* The only way this service starts an agent, and it takes a planner start by
|
|
617
|
-
* type: the read-only boundary (ADR-0008/0009) cannot be crossed into task
|
|
618
|
-
* mode from here without changing this signature. A planner that cannot
|
|
619
|
-
* reach its tools cannot submit a plan, so it is respawned once and never
|
|
620
|
-
* left to plan without them (ADR-0025).
|
|
621
|
-
*/
|
|
622
|
-
private startAdapter;
|
|
623
|
-
private newAdapter;
|
|
624
|
-
/** Whether the web-read policy lets the runner's own session-wide search run unasked now (ADR-0027). */
|
|
625
|
-
private nativeSearch;
|
|
626
|
-
/**
|
|
627
|
-
* The live agent process, restarted from its own session id if it died
|
|
628
|
-
* between turns. Resume is a hint: when it fails, the caller's next
|
|
629
|
-
* `startConversation` reseeds from Ordewell's transcript, which is the same
|
|
630
|
-
* degradation `restoreChat` already performs on every surface.
|
|
631
|
-
*
|
|
632
|
-
* Also restarted when the policy's decision on the runner's own search has
|
|
633
|
-
* changed since the process was spawned: the running thread would otherwise
|
|
634
|
-
* keep searching unasked after Full turned Guarded. Codex 0.162 applies
|
|
635
|
-
* `thread/resume`'s `config.web_search` either way (checked live).
|
|
636
|
-
*/
|
|
637
|
-
private ensureAdapter;
|
|
638
|
-
/**
|
|
639
|
-
* What the planner gets of the repository's config, its runner being
|
|
640
|
-
* launched without it (ADR-0028): the instruction files, which are text, in
|
|
641
|
-
* its system prompt, and the project MCP servers it may start. Decided once
|
|
642
|
-
* per conversation, so a respawn starts the same servers without asking.
|
|
643
|
-
*/
|
|
644
|
-
private repoConfig;
|
|
645
|
-
private plannerModel;
|
|
646
|
-
/**
|
|
647
|
-
* A plan from one-shot agent sessions: only what a submit_plan call
|
|
648
|
-
* accepted, never the reply text, so a plan the tool refused cannot come
|
|
649
|
-
* back in as the JSON the agent echoed. A session that ends without an
|
|
650
|
-
* accepted call is followed by one corrective session, then fails.
|
|
651
|
-
*/
|
|
652
|
-
private submittedPlan;
|
|
653
|
-
/**
|
|
654
|
-
* A single agent session that answers one prompt and exits. Used by every
|
|
655
|
-
* non-conversational entry point. A plan-shaped envelope in its text
|
|
656
|
-
* streams to the plan display, as a vendor planner's one-shot does, and the
|
|
657
|
-
* prose around it is not streamed at all, since no turn is open to show it in.
|
|
658
|
-
*/
|
|
659
|
-
private oneShot;
|
|
660
|
-
researchAndPlan(userDescription: string, runners: RunnerId[], modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, fs: IFileSystem, onProgress: (progress: ResearchProgress) => void, _fetcher?: IWebFetcher, runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: PlannerModes, signal?: AbortSignal): Promise<{
|
|
661
|
-
tasks: Task[];
|
|
662
|
-
researchLog: ResearchLogEntry[];
|
|
663
|
-
researchResults: string;
|
|
664
|
-
}>;
|
|
665
|
-
generatePlanDirect(userDescription: string, runners?: RunnerId[], modelsByRunner?: Partial<Record<RunnerId, DiscoveredModel[]>>, onToken?: (token: string) => void, _fs?: IFileSystem, _fetcher?: IWebFetcher, runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: PlannerModes, signal?: AbortSignal): Promise<Task[]>;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
/**
|
|
669
|
-
* The planner tools a session offers its conversation (ADR-0022). A backend
|
|
670
|
-
* that can inject the Ordewell MCP server into its planner issues a planner
|
|
671
|
-
* token bound to `sessionId` and these handlers; API planners use the same task read handlers directly in their tool loop.
|
|
672
|
-
*/
|
|
673
|
-
interface PlannerToolsOffer {
|
|
674
|
-
sessionId: string;
|
|
675
|
-
handler: PlannerToolHandler;
|
|
676
|
-
}
|
|
677
|
-
/**
|
|
678
|
-
* Everything the conversation loop needs to start planning (ADR-0002).
|
|
679
|
-
* The AI service keeps the tool-use message history internally across turns;
|
|
680
|
-
* the surfaces only exchange user/assistant messages with it.
|
|
681
|
-
*/
|
|
682
|
-
interface ConversationRequest {
|
|
683
|
-
goal: string;
|
|
684
|
-
runners: RunnerId[];
|
|
685
|
-
modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>;
|
|
686
|
-
fs: IFileSystem;
|
|
687
|
-
onProgress: (progress: ResearchProgress) => void;
|
|
688
|
-
fetcher?: IWebFetcher;
|
|
689
|
-
runnerModes?: Record<RunnerId, RunnerModeInfo[]>;
|
|
690
|
-
autonomousDefault?: boolean;
|
|
691
|
-
/** Where tasks will run (ADR-0013, ADR-0014): in worktrees, the prompt drops file-overlap ordering and describes a repo group. */
|
|
692
|
-
isolatedExecution?: IsolatedExecution;
|
|
693
|
-
/** A plan the planner submits starts at once (ADR-0030), so the opening prompt has no outline gate. */
|
|
694
|
-
autorun?: boolean;
|
|
695
|
-
signal?: AbortSignal;
|
|
696
|
-
/**
|
|
697
|
-
* Persisted dialogue to seed a resumed conversation (session reload). The
|
|
698
|
-
* turns are injected into the message history verbatim — no LLM call happens
|
|
699
|
-
* for them; the first call is the turn opened by `initialMessage`.
|
|
700
|
-
*/
|
|
701
|
-
priorHistory?: ConversationMessage[];
|
|
702
|
-
/**
|
|
703
|
-
* The user message that opens this turn. Defaults to `goal` — set it when
|
|
704
|
-
* resuming so the system prompt keeps the original goal while the turn
|
|
705
|
-
* carries the user's new message.
|
|
706
|
-
*/
|
|
707
|
-
initialMessage?: string;
|
|
708
|
-
plannerTools?: PlannerToolsOffer;
|
|
709
|
-
/**
|
|
710
|
-
* The session's approval policy, which a harness planner's own tool
|
|
711
|
-
* requests are decided against as the API planner's are (ADR-0026). Absent:
|
|
712
|
-
* nobody can be asked, so they are denied.
|
|
713
|
-
*/
|
|
714
|
-
approval?: IApproval;
|
|
715
|
-
/**
|
|
716
|
-
* The workspace's skill catalog. Every planner is shown the task skills it
|
|
717
|
-
* may attach; only one with tools is shown the planner skills, which load
|
|
718
|
-
* through `load_skill` alone (ADR-0024).
|
|
719
|
-
*/
|
|
720
|
-
skills?: readonly SkillInfo[];
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
* One planner turn's outcome. The planner talks to the user (`message`),
|
|
724
|
-
* commits a full plan (`plan`, a `{tasks:[...]}` JSON object), emits targeted
|
|
725
|
-
* task edits (`task_ops`, a `{taskOps:[...]}` JSON object), or asks to read
|
|
726
|
-
* task bodies and the full catalog before editing (`task_query`, a
|
|
727
|
-
* `{taskQuery:{...}}` JSON object). The Session validates and applies task ops
|
|
728
|
-
* atomically and answers queries out of its own state; the AI service only
|
|
729
|
-
* parses them.
|
|
730
|
-
*/
|
|
731
|
-
type ConversationTurn =
|
|
732
|
-
/**
|
|
733
|
-
* `aborted`: the call was stopped, and `text` is only what it had by then.
|
|
734
|
-
* `failed`: the call ended without a reply (a dead agent, a usage limit),
|
|
735
|
-
* and `text` says why; `usageLimit`, where the runner also said in a field
|
|
736
|
-
* whether that was its usage limit (see {@link TurnFailure}).
|
|
737
|
-
*/
|
|
738
|
-
{
|
|
739
|
-
kind: 'message';
|
|
740
|
-
text: string;
|
|
741
|
-
researchLog: ResearchLogEntry[];
|
|
742
|
-
aborted?: boolean;
|
|
743
|
-
failed?: boolean;
|
|
744
|
-
usageLimit?: UsageLimitSignal | false;
|
|
745
|
-
} | {
|
|
746
|
-
kind: 'plan';
|
|
747
|
-
tasks: Task[];
|
|
748
|
-
text: string;
|
|
749
|
-
researchLog: ResearchLogEntry[];
|
|
750
|
-
} | {
|
|
751
|
-
kind: 'task_ops';
|
|
752
|
-
ops: TaskOp[];
|
|
753
|
-
text: string;
|
|
754
|
-
researchLog: ResearchLogEntry[];
|
|
755
|
-
} | {
|
|
756
|
-
kind: 'task_query';
|
|
757
|
-
query: TaskQuery;
|
|
758
|
-
text: string;
|
|
759
|
-
researchLog: ResearchLogEntry[];
|
|
760
|
-
};
|
|
761
|
-
interface IAiService {
|
|
762
|
-
/** Credential values from the harness planner's effective environment, for the outbound secret check. */
|
|
763
|
-
heldSecrets?(): readonly string[];
|
|
764
|
-
/**
|
|
765
|
-
* Begin the planner conversation: collect workspace context, run the
|
|
766
|
-
* research/tool loop, and return the first planner turn. The service
|
|
767
|
-
* retains the full API message history for subsequent
|
|
768
|
-
* {@link continueConversation} calls.
|
|
769
|
-
*/
|
|
770
|
-
startConversation(req: ConversationRequest): Promise<ConversationTurn>;
|
|
771
|
-
/**
|
|
772
|
-
* Feed the user's reply into the active conversation and return the next
|
|
773
|
-
* planner turn. Throws if no conversation is active.
|
|
774
|
-
*/
|
|
775
|
-
continueConversation(userMessage: string, onProgress: (progress: ResearchProgress) => void, signal?: AbortSignal): Promise<ConversationTurn>;
|
|
776
|
-
/**
|
|
777
|
-
* Whether a planner conversation is currently held in memory. A branching
|
|
778
|
-
* predicate only — never a test for whether there is anything to release.
|
|
779
|
-
* The harness backend holds an OS process that outlives its conversation, so
|
|
780
|
-
* guarding {@link reset} with this leaks an agent process; call `reset`
|
|
781
|
-
* unconditionally instead.
|
|
782
|
-
*/
|
|
783
|
-
hasActiveConversation(): boolean;
|
|
784
|
-
/**
|
|
785
|
-
* Optional: end the planner's live process but keep its own session id, so
|
|
786
|
-
* the next turn starts a fresh one resumed from it (ADR-0009). What a
|
|
787
|
-
* supervisor does to a planner that crashed or hung (ADR-0029). Absent where
|
|
788
|
-
* there is no process to end: the next call is a fresh request anyway.
|
|
789
|
-
*/
|
|
790
|
-
restart?(): void;
|
|
791
|
-
/**
|
|
792
|
-
* Whether the active conversation (if any) still matches the planner
|
|
793
|
-
* model/effort currently configured. Optional, and true when absent: a
|
|
794
|
-
* vendor backend re-reads its model from config on every turn, so there is
|
|
795
|
-
* nothing to drift. A harness planner (ADR-0009) is the exception — its
|
|
796
|
-
* model is baked into the agent process at spawn — so only
|
|
797
|
-
* {@link CliAgentAiService} answers this for real. False tells the caller
|
|
798
|
-
* the same thing an absent conversation would: don't call
|
|
799
|
-
* `continueConversation`, restart instead so the new model takes effect.
|
|
800
|
-
*/
|
|
801
|
-
conversationMatchesConfig?(): boolean;
|
|
802
|
-
/**
|
|
803
|
-
* Whether the planner reads the catalog and submits plans through Ordewell's
|
|
804
|
-
* MCP tools (ADR-0022). Optional, and false when absent: only a harness
|
|
805
|
-
* planner the server attached to has them, and every other planner keeps
|
|
806
|
-
* the per-turn catalog and the envelopes.
|
|
807
|
-
*/
|
|
808
|
-
plannerToolsAttached?(): boolean;
|
|
809
|
-
/**
|
|
810
|
-
* Optional: prune bulky raw tool output out of the live conversation, in
|
|
811
|
-
* place, keeping subagent digests. Returns the characters removed. Absent
|
|
812
|
-
* where the backend holds no tool transcript to prune (a harness planner's
|
|
813
|
-
* agent owns its own context).
|
|
814
|
-
*/
|
|
815
|
-
pruneContext?(): number;
|
|
816
|
-
/**
|
|
817
|
-
* One-shot research + plan for non-conversational surfaces (CLI `plan --goal`,
|
|
818
|
-
* web REST). Never asks questions — it plans with what it can find.
|
|
819
|
-
*/
|
|
820
|
-
researchAndPlan(userDescription: string, runners: RunnerId[], modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, fs: IFileSystem, onProgress: (progress: ResearchProgress) => void, fetcher?: IWebFetcher, runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: PlannerModes, signal?: AbortSignal): Promise<{
|
|
821
|
-
tasks: Task[];
|
|
822
|
-
researchLog: ResearchLogEntry[];
|
|
823
|
-
researchResults: string;
|
|
824
|
-
}>;
|
|
825
|
-
generatePlanDirect(userDescription: string, runners: RunnerId[], modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, onToken?: (token: string) => void, fs?: IFileSystem, fetcher?: IWebFetcher, runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: PlannerModes, signal?: AbortSignal): Promise<Task[]>;
|
|
826
|
-
/**
|
|
827
|
-
* Release everything this service holds: the conversation, any in-flight
|
|
828
|
-
* turn, and — on the harness backend — the agent process itself. Idempotent
|
|
829
|
-
* and cheap in every implementation, so callers never gate it.
|
|
830
|
-
*/
|
|
831
|
-
reset(): void;
|
|
832
|
-
}
|
|
833
|
-
/**
|
|
834
|
-
* The single branch point between planner transports. Two of them talk HTTP to
|
|
835
|
-
* an LLM vendor; the third (ADR-0009) drives a coding agent already installed
|
|
836
|
-
* on the machine. Everything downstream — the plan contract, the research-step
|
|
837
|
-
* stream, the four surfaces — is shared.
|
|
838
|
-
*/
|
|
839
|
-
declare function createAiService(config: IConfig, deps?: CliAgentAiServiceDeps): IAiService;
|
|
840
|
-
|
|
841
|
-
/** The dialogue record a fork carries — what {@link PlannerConversation.clone} returns. */
|
|
842
|
-
interface ForkedDialogue {
|
|
843
|
-
conversationHistory: ConversationMessage[];
|
|
844
|
-
researchLog: ResearchLogEntry[];
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
/** A user's message as sent, and the skills its `/name` tokens load. */
|
|
848
|
-
interface SkillInvocation {
|
|
849
|
-
text: string;
|
|
850
|
-
skills: SkillLoad[];
|
|
851
|
-
}
|
|
852
|
-
/**
|
|
853
|
-
* A path with the home directory written `~`, for a notice or listing. On
|
|
854
|
-
* Windows the drive letter's case is not significant and the separators are
|
|
855
|
-
* rendered `/`, so the same skill reads alike wherever the session reloads.
|
|
856
|
-
*/
|
|
857
|
-
declare function abbreviateHome(file: string, home?: string, platform?: NodeJS.Platform): string;
|
|
858
|
-
/**
|
|
859
|
-
* Resolve the `/skill-name` tokens in a message to snapshots of the skills they
|
|
860
|
-
* name. Pure and exported so surfaces can resolve without a full Session. The text itself is never rewritten.
|
|
861
|
-
*
|
|
862
|
-
* Every distinct skill named loads, once, in the order first named. A token
|
|
863
|
-
* naming no skill is plain text, wherever it stands — a whole message of
|
|
864
|
-
* `/unknown` included: embedded in a sentence it is as likely to be incidental
|
|
865
|
-
* text (a path, an example command) as a typo'd invocation. So is one naming
|
|
866
|
-
* a skill with `user-invocable: false`, which only the model may invoke.
|
|
867
|
-
*/
|
|
868
|
-
declare function resolveSkillInvocation(text: string, skillsService: Pick<SkillsService, 'findSkill'>, home?: string): SkillInvocation;
|
|
869
|
-
/**
|
|
870
|
-
* What the planner receives for a user message: the bodies of the skills it
|
|
871
|
-
* loaded, then the message as the user wrote it. The one composition for a
|
|
872
|
-
* live send and for a replay of the transcript, so a resumed conversation
|
|
873
|
-
* hands the planner what the live one did.
|
|
874
|
-
*/
|
|
875
|
-
declare function plannerMessage(text: string, loads: readonly SkillLoad[]): string;
|
|
876
|
-
/**
|
|
877
|
-
* The transcript as the planner is to see it on a replay: each user message
|
|
878
|
-
* carries the skills loaded after it, composed by {@link plannerMessage}, and
|
|
879
|
-
* the load entries themselves are folded away. Sessions saved before skill
|
|
880
|
-
* loads existed hold the expanded text in the message and replay unchanged.
|
|
881
|
-
* A failed turn's entry is left out: the planner never said it.
|
|
882
|
-
*/
|
|
883
|
-
declare function plannerTranscript(history: readonly ConversationMessage[]): ConversationMessage[];
|
|
884
|
-
|
|
885
|
-
/**
|
|
886
|
-
* What a stopped runner says about why it stopped, and what ending an attempt
|
|
887
|
-
* does to the runner it leaves behind. TaskOrchestrator acts on the answers.
|
|
888
|
-
*/
|
|
889
|
-
|
|
890
|
-
/**
|
|
891
|
-
* A turn's failure as its runner reported it: its words, and `usageLimit`
|
|
892
|
-
* where its protocol also says in a field whether it was the limit (Codex's
|
|
893
|
-
* `codexErrorInfo`).
|
|
894
|
-
*/
|
|
895
|
-
interface TurnFailure {
|
|
896
|
-
message: string;
|
|
897
|
-
usageLimit?: UsageLimitSignal | false;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
/** What a usage limit that ended a planner turn led to. */
|
|
901
|
-
interface PlannerLimit {
|
|
902
|
-
/** The line the transcript keeps, drawn as a failure. */
|
|
903
|
-
text: string;
|
|
904
|
-
/** When what the turn took goes again on its own; null when it waits for the user's next message. */
|
|
905
|
-
resendAt: Date | null;
|
|
906
|
-
/** Why nothing goes again on its own, when nothing does: what the planner did, as in "the planner hit its usage limit and …". */
|
|
907
|
-
held?: string;
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
/**
|
|
911
|
-
* The planner turn (see CONTEXT.md): the one piece of planner work that holds
|
|
912
|
-
* the conversation, from its claim to its settled outcome. Its signal is what a
|
|
913
|
-
* stop aborts.
|
|
914
|
-
*/
|
|
915
|
-
declare class PlannerTurn {
|
|
916
|
-
private readonly controller;
|
|
917
|
-
private dropped;
|
|
918
|
-
private forced;
|
|
919
|
-
get signal(): AbortSignal;
|
|
920
|
-
/** The plan it was answering was dropped under it, so nothing it settles may land. */
|
|
921
|
-
get abandoned(): boolean;
|
|
922
|
-
/** A force send stopped it, not the user: the forced turn follows. A turn already stopped stays the user's stop. */
|
|
923
|
-
get forceSent(): boolean;
|
|
924
|
-
stop(by?: 'force_send'): void;
|
|
925
|
-
abandon(): void;
|
|
926
|
-
}
|
|
927
|
-
/** What a planner turn may change: the whole plan, or tasks through edits. */
|
|
928
|
-
type PlanChange = 'plan' | 'edit';
|
|
929
|
-
/**
|
|
930
|
-
* A wake-up turn (ADR-0029): a supervisor's turn on wake-up digests alone, no
|
|
931
|
-
* user message in it. What it may do is its level's, decided by the host.
|
|
932
|
-
*/
|
|
933
|
-
interface WakeUpTurn {
|
|
934
|
-
/** Reads the turn may make, in place of a user message's caps. */
|
|
935
|
-
readBudget: number;
|
|
936
|
-
/**
|
|
937
|
-
* Why a whole plan, or a task edit, is refused in this turn, worded for the
|
|
938
|
-
* model; undefined when its level allows it. Asked when the change is made
|
|
939
|
-
* and again as it lands, so a level lowered during the turn applies at once.
|
|
940
|
-
*/
|
|
941
|
-
refused(change: PlanChange): string | undefined;
|
|
942
|
-
/** Told to the model after the digests and never saved, like the plan block: who it is in this turn, and what it may do. */
|
|
943
|
-
brief?: string;
|
|
944
|
-
}
|
|
945
|
-
/** 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. */
|
|
946
|
-
type ToolRead<T> = {
|
|
947
|
-
status: 'refused';
|
|
948
|
-
} | {
|
|
949
|
-
status: 'answered';
|
|
950
|
-
value: T;
|
|
951
|
-
landNow: boolean;
|
|
952
|
-
};
|
|
953
|
-
/** A plan or task edit handed to the open turn over a channel other than its reply (ADR-0022). */
|
|
954
|
-
type PlannerSubmission = {
|
|
955
|
-
kind: 'plan';
|
|
956
|
-
tasks: Task[];
|
|
957
|
-
} | {
|
|
958
|
-
kind: 'task_ops';
|
|
959
|
-
ops: TaskOp[];
|
|
960
|
-
};
|
|
961
|
-
/** Everything (re)opening a conversation needs besides the dialogue itself. */
|
|
962
|
-
type ConversationOpening = Omit<ConversationRequest, 'goal' | 'onProgress' | 'signal' | 'priorHistory' | 'initialMessage'>;
|
|
963
|
-
/**
|
|
964
|
-
* What the conversation needs from the session that hosts it. The session keeps
|
|
965
|
-
* plan state, persistence and scheduling; the conversation reaches them only
|
|
966
|
-
* through here, so a fake host is enough to drive it.
|
|
967
|
-
*/
|
|
968
|
-
interface PlannerConversationHost {
|
|
969
|
-
/** The plan the transcript lives on (`conversationHistory`, `researchLog`). */
|
|
970
|
-
plan(): LegacyPlanState | null;
|
|
971
|
-
goal(): string;
|
|
972
|
-
aiService(): IAiService;
|
|
973
|
-
onProgress(progress: ResearchProgress): void;
|
|
974
|
-
/** Fresh discovery, allowlist-filtered the way the system prompt shows it. */
|
|
975
|
-
opening(runners: RunnerId[]): Promise<ConversationOpening>;
|
|
976
|
-
/** What the per-turn catalog block and every read draw from, as of now. */
|
|
977
|
-
catalog(): TaskQueryCatalog;
|
|
978
|
-
/** Whether autorun is on now (ADR-0030); the planner is told in the turn after it changes. */
|
|
979
|
-
autorun(): boolean;
|
|
980
|
-
/** The enabled runners and allowlist as of now; the planner is told in the turn after either changes. */
|
|
981
|
-
assignmentScope(): AssignmentScope;
|
|
982
|
-
/** Run updates no turn has carried yet, taken by the turn that asks: the next turn is told, whoever opens it. */
|
|
983
|
-
takeRunUpdates(): string[];
|
|
984
|
-
tasks(): readonly Task[];
|
|
985
|
-
/**
|
|
986
|
-
* The orchestrator's live capture for a task's latest attempt, backing the
|
|
987
|
-
* `output` field of a read. Injected the same way as the catalog so the
|
|
988
|
-
* conversation never reaches into execution state directly.
|
|
989
|
-
*/
|
|
990
|
-
liveOutput: LiveOutputLookup;
|
|
991
|
-
isExecuting(): boolean;
|
|
992
|
-
/** The session's single mutation ritual: op → persist → notify (default: the plan). */
|
|
993
|
-
mutate(op: () => boolean, notify?: () => void): LegacyPlanState | null;
|
|
994
|
-
broadcast: SessionBroadcaster;
|
|
995
|
-
/** `turnId`: the planner turn whose commit this is, when one is. */
|
|
996
|
-
broadcastPlan(turnId?: string): void;
|
|
997
|
-
/** Validate a batch against live state. Pure — nothing is applied. */
|
|
998
|
-
validateOps(ops: TaskOp[]): ApplyTaskOpsResult;
|
|
999
|
-
/** The workspace's skill catalog under its repo group's layout, which the skills a plan or edit attaches are checked against. */
|
|
1000
|
-
taskSkills(): SkillLookup;
|
|
1001
|
-
/** Tell the user something the transcript does not carry. */
|
|
1002
|
-
notice(level: SessionNotice['level'], message: string): void;
|
|
1003
|
-
/** Load planner-produced tasks: an edit keeps run state, a commit starts over. Returns how many landed. */
|
|
1004
|
-
adoptTasks(tasks: readonly Task[], how: 'edit' | 'commit'): number;
|
|
1005
|
-
capturePrd(text: string): void;
|
|
1006
|
-
/** The planner turn was stopped or abandoned: whatever it is waiting on (a parked approval) will never be answered. */
|
|
1007
|
-
turnAborted(): void;
|
|
1008
|
-
/** A planner turn let the conversation go, so the next one may take it. */
|
|
1009
|
-
turnReleased?(): void;
|
|
1010
|
-
/** A turn ended on the planner's usage limit, which it reported as `said`: what is sent again, and when. */
|
|
1011
|
-
usageLimit(said: TurnFailure): PlannerLimit;
|
|
1012
|
-
}
|
|
1013
|
-
/**
|
|
1014
|
-
* A conversation edit (rewind, fork) the conversation refused because the
|
|
1015
|
-
* request itself is wrong — no such message, nothing to fork. Transport-agnostic
|
|
1016
|
-
* like `PlanEditError`: a route maps it to a status, core carries none.
|
|
1017
|
-
*/
|
|
1018
|
-
declare class ConversationEditError extends Error {
|
|
1019
|
-
constructor(message: string);
|
|
1020
|
-
}
|
|
1021
|
-
/**
|
|
1022
|
-
* Refused because a planner turn is in flight. Distinct from a bad request:
|
|
1023
|
-
* the same call succeeds once the turn settles, and the turn would otherwise
|
|
1024
|
-
* append its reply to a transcript that no longer holds the message it
|
|
1025
|
-
* answers.
|
|
1026
|
-
*/
|
|
1027
|
-
declare class ConversationBusyError extends ConversationEditError {
|
|
1028
|
-
constructor(operation: string);
|
|
1029
|
-
}
|
|
1030
|
-
/**
|
|
1031
|
-
* A planner turn that settled after the plan it was answering was dropped (a
|
|
1032
|
-
* new plan, another session adopted, the session closed), or after its call
|
|
1033
|
-
* was cut off by something other than its own stop. Nothing it produced was
|
|
1034
|
-
* committed: landing it would write one session's reply into another's
|
|
1035
|
-
* transcript.
|
|
1036
|
-
*/
|
|
1037
|
-
declare class PlannerTurnDiscardedError extends Error {
|
|
1038
|
-
constructor(options?: ErrorOptions);
|
|
1039
|
-
}
|
|
1040
|
-
/**
|
|
1041
|
-
* A wake-up turn's backend ended without a reply — a dead agent, a usage
|
|
1042
|
-
* limit — and said why. A user's turn shows that in the chat instead; a
|
|
1043
|
-
* wake-up has nobody waiting on it, so its supervisor is told (ADR-0029).
|
|
1044
|
-
*/
|
|
1045
|
-
declare class PlannerTurnFailedError extends Error {
|
|
1046
|
-
constructor(message: string);
|
|
1047
|
-
}
|
|
1048
|
-
/**
|
|
1049
|
-
* A planner turn ended on the planner's usage limit (#84). Nothing of it
|
|
1050
|
-
* lands: the transcript keeps the failure instead, out of the planner's own
|
|
1051
|
-
* dialogue, and the turn's inputs wait to be sent again — at `resendAt`, or
|
|
1052
|
-
* with the next input when it is null.
|
|
1053
|
-
*/
|
|
1054
|
-
declare class PlannerUsageLimitError extends PlannerTurnFailedError {
|
|
1055
|
-
readonly resendAt: Date | null;
|
|
1056
|
-
/** Why nothing is sent again on its own, when nothing is. */
|
|
1057
|
-
readonly held?: string;
|
|
1058
|
-
constructor(limit: PlannerLimit);
|
|
1059
|
-
}
|
|
1060
|
-
/**
|
|
1061
|
-
* The user stopped the turn and the backend reported that as a thrown error
|
|
1062
|
-
* rather than a settled reply. Typed so a surface can stay quiet for it without
|
|
1063
|
-
* reading the message: some SDKs' abort errors are plain `Error`s by name, and
|
|
1064
|
-
* a real failure can mention "aborted" too.
|
|
1065
|
-
*/
|
|
1066
|
-
declare class PlannerTurnStoppedError extends Error {
|
|
1067
|
-
constructor(options?: ErrorOptions);
|
|
1068
|
-
}
|
|
1069
|
-
/** A user message a rewind can fork the conversation from just before. */
|
|
1070
|
-
interface RewindTarget {
|
|
1071
|
-
/** Position in the transcript — what {@link PlannerConversation.cloneBefore} takes. */
|
|
1072
|
-
index: number;
|
|
1073
|
-
preview: string;
|
|
1074
|
-
/** The whole message — the preview cuts it to one line, and a surface confirming the rewind quotes it. */
|
|
1075
|
-
content: string;
|
|
1076
|
-
timestamp: string;
|
|
1077
|
-
}
|
|
1078
|
-
/** What a rewind forks from, and the message it lands just before. */
|
|
1079
|
-
interface RewoundDialogue {
|
|
1080
|
-
dialogue: ForkedDialogue;
|
|
1081
|
-
rewoundMessage: string;
|
|
1082
|
-
}
|
|
1083
|
-
/** What a compaction left behind. */
|
|
1084
|
-
interface ConversationCompaction {
|
|
1085
|
-
summary: string;
|
|
1086
|
-
/** Transcript entries kept verbatim after the summary entry. */
|
|
1087
|
-
keptMessages: number;
|
|
1088
|
-
}
|
|
1089
|
-
/** A point a failed turn returns the dialogue to. Opaque outside this module. */
|
|
1090
|
-
interface TranscriptSnapshot {
|
|
1091
|
-
readonly plan: LegacyPlanState;
|
|
1092
|
-
readonly history: ConversationMessage[] | undefined;
|
|
1093
|
-
readonly researchLog: ResearchLogEntry[] | undefined;
|
|
1094
|
-
readonly persisted: number;
|
|
1095
|
-
readonly savedInBackground: number;
|
|
1096
|
-
/** What the planner had been told of the user's runners when the turn began. */
|
|
1097
|
-
readonly toldScope: AssignmentScope | null;
|
|
1098
|
-
}
|
|
1099
|
-
interface ReplyOptions {
|
|
1100
|
-
signal?: AbortSignal;
|
|
1101
|
-
/**
|
|
1102
|
-
* Run inside the mutation that lands the turn's outcome — the edit, the
|
|
1103
|
-
* plan or the reply — so what the caller drops with it (the inputs the turn
|
|
1104
|
-
* answered) leaves disk in the same save.
|
|
1105
|
-
*/
|
|
1106
|
-
onCommit?: () => void;
|
|
1107
|
-
/** Wake-up digests delivered with this turn (ADR-0029), oldest first, ahead of the user's message if there is one. */
|
|
1108
|
-
wakeUps?: readonly string[];
|
|
1109
|
-
/** Set when the turn is a wake-up's alone. */
|
|
1110
|
-
wakeUp?: WakeUpTurn;
|
|
1111
|
-
/** The user's message was force sent: the turn replaces the one it stopped (ADR-0023). */
|
|
1112
|
-
forced?: boolean;
|
|
1113
|
-
}
|
|
1114
|
-
/**
|
|
1115
|
-
* The planner conversation (ADR-0002), end to end: the persisted dialogue
|
|
1116
|
-
* record, the live model context behind it, and every turn from the user's
|
|
1117
|
-
* message to a settled, persisted outcome.
|
|
1118
|
-
*
|
|
1119
|
-
* It is the only writer of `conversationHistory` and of the planner's
|
|
1120
|
-
* `researchLog`. The writes land on the host's plan object — which is what the
|
|
1121
|
-
* session persists and broadcasts — but only ever inside the host's mutation
|
|
1122
|
-
* ritual or ahead of a turn that will either reach it or be rolled back.
|
|
1123
|
-
*
|
|
1124
|
-
* The live model context (a vendor service's message list, a harness planner's
|
|
1125
|
-
* process and native session id) is disposable: {@link reset} drops it and the
|
|
1126
|
-
* next turn is replayed from the transcript. That is what lets the transcript
|
|
1127
|
-
* be replaced by a summary, or copied into a fork, without the model's memory
|
|
1128
|
-
* drifting from it.
|
|
1129
|
-
*/
|
|
1130
|
-
declare class PlannerConversation {
|
|
1131
|
-
private readonly host;
|
|
1132
|
-
/** Bumped on every persist, so a rollback can tell whether its writes already reached disk. */
|
|
1133
|
-
private persisted;
|
|
1134
|
-
/** Saves an execution event made while a turn may be in flight; see {@link restore}. */
|
|
1135
|
-
private savedInBackground;
|
|
1136
|
-
/** What the planner was last told of autorun: by its opening prompt, or a turn's block since. */
|
|
1137
|
-
private toldAutorun;
|
|
1138
|
-
/** The runners and allowlist the planner was last told of: its opening prompt, or a turn's block since. Null until a conversation opens. */
|
|
1139
|
-
private toldScope;
|
|
1140
|
-
private live;
|
|
1141
|
-
private openTurn;
|
|
1142
|
-
constructor(host: PlannerConversationHost);
|
|
1143
|
-
get transcript(): readonly ConversationMessage[];
|
|
1144
|
-
/** Whether a planner turn holds the conversation. */
|
|
1145
|
-
get isTurnInFlight(): boolean;
|
|
1146
|
-
/** Stop the planner turn in flight; it settles as stopped. False when none is. */
|
|
1147
|
-
stopTurn(by?: 'force_send'): boolean;
|
|
1148
|
-
/**
|
|
1149
|
-
* Drop the planner turn in flight together with the plan it was answering:
|
|
1150
|
-
* it is stopped, whatever it settles is discarded, and the conversation is
|
|
1151
|
-
* free at once rather than when the abandoned turn finishes unwinding.
|
|
1152
|
-
*/
|
|
1153
|
-
abandonTurn(): void;
|
|
1154
|
-
/**
|
|
1155
|
-
* Free the conversation from a turn that did not end when stopped — a hung
|
|
1156
|
-
* wake-up (ADR-0029). Unlike {@link abandonTurn} the plan stays, so what the
|
|
1157
|
-
* turn wrote is taken back as its failure would have, and its end is
|
|
1158
|
-
* announced: the turn itself may never get there.
|
|
1159
|
-
*/
|
|
1160
|
-
abandonHungTurn(): void;
|
|
1161
|
-
/**
|
|
1162
|
-
* Run planner work that is not a conversation turn — one-shot plan
|
|
1163
|
-
* generation — as the planner turn, so it is stopped, refused and superseded
|
|
1164
|
-
* like one. It starts a fresh plan, so it supersedes the turn in flight.
|
|
1165
|
-
*/
|
|
1166
|
-
hold<T>(signal: AbortSignal | undefined, body: (turn: PlannerTurn) => Promise<T>): Promise<T>;
|
|
1167
|
-
/**
|
|
1168
|
-
* Take the conversation for a new planner turn. A caller's own signal stops
|
|
1169
|
-
* the turn too; the relay is detached on release because a caller may reuse
|
|
1170
|
-
* that signal, and a stale listener would stop the next turn with it.
|
|
1171
|
-
*/
|
|
1172
|
-
private claim;
|
|
1173
|
-
/** The user turn being answered, for what the host raises during it — an approval the turn's research asks for. */
|
|
1174
|
-
get currentTurnId(): string | undefined;
|
|
1175
|
-
/** The open turn's wake-up rules, when the supervisor is answering it rather than the user's message. */
|
|
1176
|
-
get currentWakeUp(): WakeUpTurn | undefined;
|
|
1177
|
-
recordPlannerSkill(skill: SkillLoad): boolean;
|
|
1178
|
-
/**
|
|
1179
|
-
* Hand the open turn a plan (already validated) or a task edit. The turn
|
|
1180
|
-
* settles with it exactly as with the same plan or ops parsed out of its
|
|
1181
|
-
* reply, and it wins over any envelope that reply carries. A later
|
|
1182
|
-
* submission replaces an earlier one. False when no user turn is open.
|
|
1183
|
-
*/
|
|
1184
|
-
submit(submission: PlannerSubmission): boolean;
|
|
1185
|
-
/**
|
|
1186
|
-
* Tell surfaces what the turn's edit would leave, from the same applier that
|
|
1187
|
-
* lands it, so an edit that would not apply shows nothing. It stays shown
|
|
1188
|
-
* from the moment it is handed in until it lands, is refused, or the turn
|
|
1189
|
-
* ends: the backend's reply claims it, but it has not landed by then.
|
|
1190
|
-
*/
|
|
1191
|
-
private showHeld;
|
|
1192
|
-
private clearHeld;
|
|
1193
|
-
/**
|
|
1194
|
-
* The edit the open turn already holds, for a further edit in the same reply
|
|
1195
|
-
* to join rather than replace. Empty when it holds nothing; null when it holds
|
|
1196
|
-
* a whole plan, which an edit cannot be layered on.
|
|
1197
|
-
*/
|
|
1198
|
-
pendingOps(): TaskOp[] | null;
|
|
1199
|
-
/**
|
|
1200
|
-
* A read the planner makes through a tool. It spends the same per-turn budget
|
|
1201
|
-
* as an envelope read, so a planner cannot read more by switching channels:
|
|
1202
|
-
* past the soft limit, or on a repeated question, the answer still comes but
|
|
1203
|
-
* is told to land the turn; at the hard limit it is refused. `signature`
|
|
1204
|
-
* names the question, for the repeat check.
|
|
1205
|
-
*/
|
|
1206
|
-
read<T>(signature: string, answer: () => Promise<T>): Promise<ToolRead<T>>;
|
|
1207
|
-
/** Whether the model still holds this conversation in memory. */
|
|
1208
|
-
get isActive(): boolean;
|
|
1209
|
-
append(role: ConversationMessage['role'], content: string, opts?: {
|
|
1210
|
-
timestamp?: string;
|
|
1211
|
-
kind?: ConversationMessage['kind'];
|
|
1212
|
-
}): void;
|
|
1213
|
-
private appendEntries;
|
|
1214
|
-
/** Swap the whole transcript. The live context no longer matches it, so pair with {@link reset}. */
|
|
1215
|
-
replace(messages: readonly ConversationMessage[]): void;
|
|
1216
|
-
snapshot(): TranscriptSnapshot | null;
|
|
1217
|
-
/**
|
|
1218
|
-
* Put the dialogue back where {@link snapshot} found it — unless anything
|
|
1219
|
-
* was persisted since, because then memory already matches disk and every
|
|
1220
|
-
* surface, and undoing it would erase work the user has seen land. Also a
|
|
1221
|
-
* no-op once a different plan has been adopted.
|
|
1222
|
-
*
|
|
1223
|
-
* A background save (a task settling mid-turn) wrote the turn's writes to
|
|
1224
|
-
* disk without landing anything the user saw, so it does not stop the undo;
|
|
1225
|
-
* the undo is saved in turn, or a reload would bring the writes back.
|
|
1226
|
-
*/
|
|
1227
|
-
restore(snapshot: TranscriptSnapshot): boolean;
|
|
1228
|
-
/**
|
|
1229
|
-
* The host calls this after every persist. `background` is a save no call
|
|
1230
|
-
* of the user's made — an execution event landing mid-turn.
|
|
1231
|
-
*/
|
|
1232
|
-
markPersisted(opts?: {
|
|
1233
|
-
background?: boolean;
|
|
1234
|
-
}): void;
|
|
1235
|
-
/**
|
|
1236
|
-
* Drop the live model context. Idempotent; the harness backend holds an OS
|
|
1237
|
-
* process here, so callers never gate it on {@link isActive}.
|
|
1238
|
-
*/
|
|
1239
|
-
reset(): void;
|
|
1240
|
-
/**
|
|
1241
|
-
* The user messages a rewind may land before. The opening message is the
|
|
1242
|
-
* goal: cutting it leaves a conversation about nothing, which is a new
|
|
1243
|
-
* session, not a rewind. After a compaction the summary entry, always
|
|
1244
|
-
* first, plays the goal's part: what it replaced is gone, so a rewind stops
|
|
1245
|
-
* at it.
|
|
1246
|
-
*/
|
|
1247
|
-
rewindTargets(): RewindTarget[];
|
|
1248
|
-
/**
|
|
1249
|
-
* Replace the transcript with a summary of it, keeping the last two
|
|
1250
|
-
* exchanges as they were, and drop the live context so the next message
|
|
1251
|
-
* replays from the shorter record.
|
|
1252
|
-
*
|
|
1253
|
-
* The summary is one hidden turn through whichever planner is configured —
|
|
1254
|
-
* on the live context when it still matches, replayed from the transcript
|
|
1255
|
-
* when not — so the compaction is the same for a vendor API and a harness
|
|
1256
|
-
* agent. Whatever the turn emits besides the summary is discarded, ops
|
|
1257
|
-
* included: it condenses the conversation, never the plan. Nothing is
|
|
1258
|
-
* written until the summary is in hand, so a failed or stopped turn leaves
|
|
1259
|
-
* the transcript exactly as it was.
|
|
1260
|
-
*/
|
|
1261
|
-
compact(signal?: AbortSignal): Promise<ConversationCompaction>;
|
|
1262
|
-
private summarize;
|
|
1263
|
-
/**
|
|
1264
|
-
* A copy of the dialogue record for a forked session to carry. Refused
|
|
1265
|
-
* mid-turn: the copy would hold the user's message without the reply to it.
|
|
1266
|
-
* The live context is not part of it — the fork replays from this record on
|
|
1267
|
-
* its first turn, like any adopted session.
|
|
1268
|
-
*/
|
|
1269
|
-
clone(): ForkedDialogue;
|
|
1270
|
-
/**
|
|
1271
|
-
* A copy of the dialogue as it stood just before the user message at
|
|
1272
|
-
* `index` (a position from {@link rewindTargets}) — what a rewind forks
|
|
1273
|
-
* from — plus that message's full text, for a surface to offer back. This
|
|
1274
|
-
* conversation is not touched. The research trace is cut at the same point
|
|
1275
|
-
* by time: its entries carry no link to the message that caused them.
|
|
1276
|
-
*/
|
|
1277
|
-
cloneBefore(index: number): RewoundDialogue;
|
|
1278
|
-
/**
|
|
1279
|
-
* What the skill check of a landed plan or edit warned about, kept in the
|
|
1280
|
-
* transcript so every surface shows it, on reload too, and not only the
|
|
1281
|
-
* planner that may have read it in a tool result. Call inside the host's
|
|
1282
|
-
* mutation ritual, so the broadcast plan carries it.
|
|
1283
|
-
*/
|
|
1284
|
-
recordSkillWarnings(warnings: readonly string[], timestamp?: string): void;
|
|
1285
|
-
/**
|
|
1286
|
-
* A call at the command seam (ADR-0029), kept where it happened in the
|
|
1287
|
-
* dialogue: a reload shows it, and a planner replayed from the transcript
|
|
1288
|
-
* knows what was started or stopped, and by whom. Call inside the host's
|
|
1289
|
-
* mutation ritual.
|
|
1290
|
-
*/
|
|
1291
|
-
recordExecution(record: ExecutionRecord, text: string): void;
|
|
1292
|
-
/**
|
|
1293
|
-
* Open the conversation on the host's fresh plan: the goal is its first
|
|
1294
|
-
* message. `prepare` (discovery) runs inside the turn, so a stop reaches it.
|
|
1295
|
-
*/
|
|
1296
|
-
start(goal: SkillInvocation, prepare: () => Promise<ConversationOpening>, signal?: AbortSignal): Promise<LegacyPlanState>;
|
|
1297
|
-
/**
|
|
1298
|
-
* Every later user message, from the transcript append to a persisted
|
|
1299
|
-
* outcome. A turn that throws before anything was persisted takes its own
|
|
1300
|
-
* writes back out, so session memory never drifts from disk and the UI.
|
|
1301
|
-
*/
|
|
1302
|
-
reply(message: string | SkillInvocation, options?: ReplyOptions): Promise<LegacyPlanState>;
|
|
1303
|
-
private replyTurn;
|
|
1304
|
-
/**
|
|
1305
|
-
* A wake-up turn lands only a real answer. Stopped — by the user, or by its
|
|
1306
|
-
* timeout — it lands nothing, not the fragment a backend hands back; a
|
|
1307
|
-
* failure is thrown rather than shown, for the supervisor to retry
|
|
1308
|
-
* (ADR-0029).
|
|
1309
|
-
*/
|
|
1310
|
-
private assertWakeUpAnswered;
|
|
1311
|
-
/**
|
|
1312
|
-
* A turn that ended on the planner's usage limit lands nothing. What it
|
|
1313
|
-
* wrote is taken back, its failure is kept in its place, and the limit's
|
|
1314
|
-
* wait is armed in the same save. Only a turn Ordewell started gets here,
|
|
1315
|
-
* so a limit is never acted on for a planner nobody asked anything of.
|
|
1316
|
-
*/
|
|
1317
|
-
private assertNotLimited;
|
|
1318
|
-
/**
|
|
1319
|
-
* A failure kept in the transcript, drawn as one on reload too, and never
|
|
1320
|
-
* replayed to the planner. Stamped after the newest entry: surfaces take
|
|
1321
|
-
* only entries newer than the last they synced.
|
|
1322
|
-
*/
|
|
1323
|
-
private recordFailure;
|
|
1324
|
-
private assertIdle;
|
|
1325
|
-
/**
|
|
1326
|
-
* Refuse to land a turn that no longer belongs here: it was abandoned, its
|
|
1327
|
-
* plan is no longer the host's, or its call was cut off by something other
|
|
1328
|
-
* than its own stop (`IAiService.reset` under a plan change) — what such a
|
|
1329
|
-
* call hands back is a fragment of an answer to a dialogue that is gone.
|
|
1330
|
-
*/
|
|
1331
|
-
private assertCurrent;
|
|
1332
|
-
/**
|
|
1333
|
-
* {@link assertCurrent} on the far side of an await that precedes a plan
|
|
1334
|
-
* mutation: the skill check waits on git, and a stop, rewind or session
|
|
1335
|
-
* switch in that window drops the edit instead of landing it on whatever
|
|
1336
|
-
* plan is current by then. A stop counts here because nothing has landed
|
|
1337
|
-
* yet — the user asked for the turn to end before it changed the plan.
|
|
1338
|
-
*/
|
|
1339
|
-
private assertStillCurrent;
|
|
1340
|
-
/**
|
|
1341
|
-
* A live conversation is only safe to continue in-place when it also
|
|
1342
|
-
* matches the model/effort configured right now — a harness planner's
|
|
1343
|
-
* running process was spawned with the old one baked in and cannot pick up
|
|
1344
|
-
* a switch (ADR-0009). Otherwise the turn resumes from the transcript.
|
|
1345
|
-
*/
|
|
1346
|
-
private canContinueLive;
|
|
1347
|
-
/**
|
|
1348
|
-
* Bracket one user turn with its start and end, under an id minted here:
|
|
1349
|
-
* the turn is where the stream a surface draws begins and ends, and only the
|
|
1350
|
-
* conversation sees all of it — every backend call, read and retry.
|
|
1351
|
-
*/
|
|
1352
|
-
private userTurn;
|
|
1353
|
-
private requirePlan;
|
|
1354
|
-
/** The message as typed, then one entry per skill it loaded, sharing its timestamp so a reload keeps them together. */
|
|
1355
|
-
private userEntries;
|
|
1356
|
-
private recordUser;
|
|
1357
|
-
/**
|
|
1358
|
-
* Write the turn's held inputs inside the mutation that lands the outcome —
|
|
1359
|
-
* call at its top, before the assistant entries, so the transcript reads in
|
|
1360
|
-
* the order it happened and the inputs leave the plan in the save that
|
|
1361
|
-
* carried their answer (ADR-0029). They go back where the turn opened, ahead
|
|
1362
|
-
* of whatever it wrote as it ran (a planner skill load, a command at the
|
|
1363
|
-
* seam), not at the end.
|
|
1364
|
-
*/
|
|
1365
|
-
private commitInput;
|
|
1366
|
-
private recordResearch;
|
|
1367
|
-
/**
|
|
1368
|
-
* Reopen the model context from the transcript — because the in-memory one
|
|
1369
|
-
* is gone (session reload, extension restart), or because it is stale
|
|
1370
|
-
* against the planner config now in effect. No LLM call happens for the
|
|
1371
|
-
* replayed turns; the first call is the one the user's message opens.
|
|
1372
|
-
*/
|
|
1373
|
-
private resume;
|
|
1374
|
-
/**
|
|
1375
|
-
* Answer every read the planner emits until it says something else.
|
|
1376
|
-
*
|
|
1377
|
-
* The channel is a text envelope rather than a registered tool because the
|
|
1378
|
-
* protocol has to be identical on both planner backends (ADR-0009): Ordewell
|
|
1379
|
-
* owns a tool loop only in the API case, and a harness planner running as a
|
|
1380
|
-
* coding-agent subprocess can only be reached this way.
|
|
1381
|
-
*
|
|
1382
|
-
* Draining here — outside {@link repairLoop} — is what keeps reads free of
|
|
1383
|
-
* the repair budget. A planner that looks a task up and *then* fumbles its
|
|
1384
|
-
* ops JSON still gets its two corrective retries; charging it for the read
|
|
1385
|
-
* would cost it the chance to fix the edit.
|
|
1386
|
-
*/
|
|
1387
|
-
private drainTaskQueries;
|
|
1388
|
-
/**
|
|
1389
|
-
* The backend's answer, with what was handed in while it ran standing in
|
|
1390
|
-
* for whatever its reply carried. Taken once: a corrective re-send after a
|
|
1391
|
-
* rejected edit must not settle on the same submission again. A stopped
|
|
1392
|
-
* turn commits nothing, the same as a stopped reply with a plan in it.
|
|
1393
|
-
*/
|
|
1394
|
-
private claimSubmission;
|
|
1395
|
-
/**
|
|
1396
|
-
* Render one read out of live state. Never persisted to the transcript: the
|
|
1397
|
-
* detail is context for the planner's next reply, and re-sending it on every
|
|
1398
|
-
* later turn is exactly the cost this channel exists to avoid.
|
|
1399
|
-
*/
|
|
1400
|
-
private taskQueryAnswer;
|
|
1401
|
-
/**
|
|
1402
|
-
* Drive a planner turn, its reads already drained, to a persisted, broadcast
|
|
1403
|
-
* outcome. Task edits apply atomically; validation failures are fed back to
|
|
1404
|
-
* the model for up to 2 silent retries, then surfaced as a message with the
|
|
1405
|
-
* plan untouched. The first turn and every later turn route through here —
|
|
1406
|
-
* one path, not two.
|
|
1407
|
-
*/
|
|
1408
|
-
private settle;
|
|
1409
|
-
/** A name not found at submit only warns: a task the attaching one depends on may create it. */
|
|
1410
|
-
private warnSkills;
|
|
1411
|
-
/** Validate + commit a task_ops turn atomically. Returns the errors on rejection (plan untouched). */
|
|
1412
|
-
private applyTaskOps;
|
|
1413
|
-
/** The edit was refused as it landed: what it showed is not coming. */
|
|
1414
|
-
private refusedHeld;
|
|
1415
|
-
/** Commit a settled (non-task_ops) turn through the host's mutation ritual. */
|
|
1416
|
-
private commit;
|
|
1417
|
-
/**
|
|
1418
|
-
* The autorun rule (ADR-0030) when it changed since the planner was last
|
|
1419
|
-
* told — in the opening prompt or an earlier turn — so a switch mid-
|
|
1420
|
-
* conversation reaches its next turn without repeating in every one.
|
|
1421
|
-
*/
|
|
1422
|
-
private autorunBlock;
|
|
1423
|
-
/**
|
|
1424
|
-
* The user's runner or allowlist change, when the planner was not told yet —
|
|
1425
|
-
* the same once-per-change rule as autorun, for API and harness planners
|
|
1426
|
-
* alike. Tasks the change leaves outside the scope are named, not touched.
|
|
1427
|
-
*
|
|
1428
|
-
* A reloaded session is not told: {@link resume} takes the scope as it is
|
|
1429
|
-
* then, as it does the autorun rule, since the catalog the first turn carries
|
|
1430
|
-
* and `list_runners` already show the runners as they are now.
|
|
1431
|
-
*/
|
|
1432
|
-
private runnersChangedBlock;
|
|
1433
|
-
private runUpdatesBlock;
|
|
1434
|
-
/**
|
|
1435
|
-
* The catalog the planner may actually draw from — model ids and task-mode
|
|
1436
|
-
* ids, per runner in the plan — emitted on EVERY turn, before any plan exists
|
|
1437
|
-
* or after. The system prompt shows this once at conversation start; a long
|
|
1438
|
-
* clarifying conversation outlives that single showing and the planner
|
|
1439
|
-
* starts misquoting it, so this re-states it per turn instead.
|
|
1440
|
-
*
|
|
1441
|
-
* The host's catalog is allowlist-filtered, so a restricted allowlist stays a
|
|
1442
|
-
* hard bound on every turn, and reads the plan's runners live, so a runner
|
|
1443
|
-
* admitted mid-session by a retarget is shown like every other. A planner
|
|
1444
|
-
* with Ordewell's tools gets a reminder to read the catalog instead.
|
|
1445
|
-
*/
|
|
1446
|
-
private catalogBlock;
|
|
1447
|
-
/**
|
|
1448
|
-
* The "you are here" block for post-plan chat: current tasks with stable
|
|
1449
|
-
* references, plus the read and edit protocols. Injected per turn (never
|
|
1450
|
-
* persisted) so the model always sees live statuses — including which tasks
|
|
1451
|
-
* are locked by a running execution.
|
|
1452
|
-
*/
|
|
1453
|
-
private planContextBlock;
|
|
1454
|
-
/** One line per task, subtasks indented under their parent, with stable references — null until the plan has tasks. */
|
|
1455
|
-
private currentPlanLines;
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
|
-
interface SessionMeta {
|
|
1459
|
-
id: string;
|
|
1460
|
-
goal: string;
|
|
1461
|
-
runners: RunnerId[];
|
|
1462
|
-
taskCount: number;
|
|
1463
|
-
status: PlanStatus;
|
|
1464
|
-
createdAt: string;
|
|
1465
|
-
updatedAt: string;
|
|
1466
|
-
}
|
|
1467
|
-
interface SessionData {
|
|
1468
|
-
meta: SessionMeta;
|
|
1469
|
-
/** The full plan state — including conversationHistory, prdMarkdown, and queuedMessages. */
|
|
1470
|
-
plan: LegacyPlanState;
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
444
|
/**
|
|
1474
445
|
* The policy half of the planner's filesystem: path confinement, the tiered
|
|
1475
446
|
* `bash` gate, and the definition-first symbol lookup. Adapters supply only the
|
|
@@ -1782,78 +753,6 @@ declare class HttpWebFetcher implements IWebFetcher {
|
|
|
1782
753
|
private hop;
|
|
1783
754
|
}
|
|
1784
755
|
|
|
1785
|
-
/**
|
|
1786
|
-
* The bridge between "core needs an answer" and "a human somewhere is looking
|
|
1787
|
-
* at a UI". Core cannot prompt: the human may be at a browser, a TUI, a CLI
|
|
1788
|
-
* stream, or a VS Code webview, and on the web server they are on the far end
|
|
1789
|
-
* of a socket. So the Session parks a promise here, announces the request
|
|
1790
|
-
* through the normal broadcast seam, and every surface answers through the
|
|
1791
|
-
* same `resolve(id, granted)` call.
|
|
1792
|
-
*
|
|
1793
|
-
* Timeouts are load-bearing rather than defensive: a planner turn that blocks
|
|
1794
|
-
* forever on an unanswered prompt would hang the whole research loop with no
|
|
1795
|
-
* visible cause. On expiry the request resolves to denied and the model gets a
|
|
1796
|
-
* normal, actionable tool result. A task runner's request is the exception
|
|
1797
|
-
* (ADR-0018, A1): the runner is parked on it rather than a research loop, and
|
|
1798
|
-
* it waits for a person — or the supervisor — however long that takes.
|
|
1799
|
-
*/
|
|
1800
|
-
interface PendingApproval {
|
|
1801
|
-
id: string;
|
|
1802
|
-
request: ApprovalRequest;
|
|
1803
|
-
createdAt: string;
|
|
1804
|
-
}
|
|
1805
|
-
interface PendingApprovalsOptions {
|
|
1806
|
-
/** Denies and resolves after this long with no answer. Default 5 minutes. */
|
|
1807
|
-
timeoutMs?: number;
|
|
1808
|
-
/** Announce a new request to the surfaces. */
|
|
1809
|
-
onRequest?: (pending: PendingApproval) => void;
|
|
1810
|
-
/** Announce that a request is no longer actionable (answered or expired). */
|
|
1811
|
-
onSettled?: (id: string, granted: boolean, settled: {
|
|
1812
|
-
request: ApprovalRequest;
|
|
1813
|
-
decision: ApprovalDecision;
|
|
1814
|
-
}) => void;
|
|
1815
|
-
}
|
|
1816
|
-
interface AskOptions {
|
|
1817
|
-
/**
|
|
1818
|
-
* An id the caller already announced the request under. One still in use is
|
|
1819
|
-
* refused — denied at once — rather than overwriting the request that has it.
|
|
1820
|
-
*/
|
|
1821
|
-
id?: string;
|
|
1822
|
-
/** Wait for an answer however long it takes. */
|
|
1823
|
-
noTimeout?: boolean;
|
|
1824
|
-
/**
|
|
1825
|
-
* Given the answer as the request settles, before anything awaiting the
|
|
1826
|
-
* promise runs: a caller about to tear down what asked (a runner being
|
|
1827
|
-
* stopped) must deliver the answer before it goes.
|
|
1828
|
-
*/
|
|
1829
|
-
onDecision?: (decision: ApprovalDecision) => void;
|
|
1830
|
-
}
|
|
1831
|
-
declare class PendingApprovals {
|
|
1832
|
-
private readonly opts;
|
|
1833
|
-
private readonly entries;
|
|
1834
|
-
private readonly listeners;
|
|
1835
|
-
constructor(opts?: PendingApprovalsOptions);
|
|
1836
|
-
/** Hear each new request once it is announced — the supervisor wakes on a runner's (ADR-0029). */
|
|
1837
|
-
listen(listener: (pending: PendingApproval) => void): () => void;
|
|
1838
|
-
/** Park a request and return the promise the approval policy awaits. */
|
|
1839
|
-
ask(request: ApprovalRequest, options?: AskOptions): Promise<boolean>;
|
|
1840
|
-
/** Park a request whose answer is more than yes or no. */
|
|
1841
|
-
decide(request: ApprovalRequest, options?: AskOptions): Promise<ApprovalDecision>;
|
|
1842
|
-
/**
|
|
1843
|
-
* Answer one request. Returns false when the id is unknown or already
|
|
1844
|
-
* settled. "Allow for this task" on a request that did not offer it is a
|
|
1845
|
-
* plain allow: no grant is made that the requester never proposed.
|
|
1846
|
-
*/
|
|
1847
|
-
resolve(id: string, answer: ApprovalAnswer): boolean;
|
|
1848
|
-
/** Everything still awaiting an answer — replayed to a surface that connects late. */
|
|
1849
|
-
outstanding(): PendingApproval[];
|
|
1850
|
-
/**
|
|
1851
|
-
* Deny everything in flight, or only the requests `which` picks. Called on
|
|
1852
|
-
* abort and on session reset.
|
|
1853
|
-
*/
|
|
1854
|
-
clear(which?: (request: ApprovalRequest) => boolean, note?: string): void;
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
756
|
/**
|
|
1858
757
|
* Carries a structured task's tool requests to the session's one approval
|
|
1859
758
|
* seam (ADR-0018, A1), so a runner's request is answered through
|
|
@@ -2297,6 +1196,8 @@ interface ResearchTurn {
|
|
|
2297
1196
|
finishReason?: string;
|
|
2298
1197
|
/** Exact prompt tokens this turn consumed, when the provider reports usage — drives proactive compaction. */
|
|
2299
1198
|
promptTokens?: number;
|
|
1199
|
+
/** The segment `text` streamed under, where the provider streams it. */
|
|
1200
|
+
segmentId?: string;
|
|
2300
1201
|
}
|
|
2301
1202
|
interface ResearchChat {
|
|
2302
1203
|
sendMessage(text: string, signal?: AbortSignal): Promise<ResearchTurn>;
|
|
@@ -2931,12 +1832,13 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
2931
1832
|
/** An interrupt was sent during the current turn, so an aborted result is that interrupt, not a failure. */
|
|
2932
1833
|
private interruptRequested;
|
|
2933
1834
|
private readonly permissions;
|
|
2934
|
-
/**
|
|
2935
|
-
private
|
|
2936
|
-
/** The
|
|
2937
|
-
private pendingBreak;
|
|
2938
|
-
/** The model answering the planner's current message, as its `message_start` named it. */
|
|
1835
|
+
/** This turn's runs of reply text, each a text block named `<message id>:<block index>`. */
|
|
1836
|
+
private replyRuns;
|
|
1837
|
+
/** The model answering the planner's current message, and the message's id, as its `message_start` named them. */
|
|
2939
1838
|
private plannerModel;
|
|
1839
|
+
private streamingMessage;
|
|
1840
|
+
/** The message the last `assistant` line was part of, and how many of its blocks the lines have carried. */
|
|
1841
|
+
private lineMessage;
|
|
2940
1842
|
/**
|
|
2941
1843
|
* The session's `total_cost_usd` as last counted. A resume starts from what
|
|
2942
1844
|
* was counted of that session before, and is undefined without it: the CLI
|
|
@@ -3135,6 +2037,13 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
3135
2037
|
* complete usage instead.
|
|
3136
2038
|
*/
|
|
3137
2039
|
private finishForegroundSubagent;
|
|
2040
|
+
/**
|
|
2041
|
+
* The id of the next block an `assistant` line carries, `<message>:<index>`.
|
|
2042
|
+
* The CLI sends a message as one line per content block, in order, so a
|
|
2043
|
+
* block's place among its message's lines is the `index` its stream events
|
|
2044
|
+
* carry (checked against every recorded transcript).
|
|
2045
|
+
*/
|
|
2046
|
+
private blockId;
|
|
3138
2047
|
/**
|
|
3139
2048
|
* Partial output of the planner's own message. The complete `assistant` line
|
|
3140
2049
|
* for each block follows its deltas and is authoritative for that block (see
|
|
@@ -3179,8 +2088,8 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
3179
2088
|
private threadModel;
|
|
3180
2089
|
private readonly rpc;
|
|
3181
2090
|
private startOpts;
|
|
3182
|
-
/**
|
|
3183
|
-
private
|
|
2091
|
+
/** The planner thread's runs of reply text this turn, each under its `agentMessage` item's id. */
|
|
2092
|
+
private replyRuns;
|
|
3184
2093
|
/** The turn in flight. `turn/interrupt` and `turn/steer` cannot be sent before it has an id. */
|
|
3185
2094
|
private turn;
|
|
3186
2095
|
/** The last turn this adapter ended — so its second end signal, landing late, ends nothing. */
|
|
@@ -3507,9 +2416,10 @@ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
|
|
|
3507
2416
|
private dropUnreadSteers;
|
|
3508
2417
|
/**
|
|
3509
2418
|
* Whatever of the turn's own messages the stream missed. Each part is
|
|
3510
|
-
* emitted once, so a turn the stream saw whole adds nothing here;
|
|
3511
|
-
*
|
|
3512
|
-
*
|
|
2419
|
+
* emitted once, so a turn the stream saw whole adds nothing here; a text
|
|
2420
|
+
* part whose completion was lost completes as the run its deltas streamed
|
|
2421
|
+
* under, its part's id; one that lost every frame still reaches the
|
|
2422
|
+
* plain-text channel, which a summary falls back to.
|
|
3513
2423
|
*/
|
|
3514
2424
|
private readBack;
|
|
3515
2425
|
/**
|
|
@@ -3531,7 +2441,7 @@ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
|
|
|
3531
2441
|
*/
|
|
3532
2442
|
interrupt(timeoutMs: number): Promise<boolean>;
|
|
3533
2443
|
onProcessExit(listener: (code: number, lastWords?: string) => void): void;
|
|
3534
|
-
answerPermission(id: string, decision: ApprovalDecision): boolean
|
|
2444
|
+
answerPermission(id: string, decision: ApprovalDecision): boolean | Promise<boolean>;
|
|
3535
2445
|
/**
|
|
3536
2446
|
* OpenCode 2.x replaced the 1.x HTTP surface rather than extending it, and
|
|
3537
2447
|
* only 2.x answers `/api/info` with its version. A 1.x server — or one that
|
|
@@ -3634,17 +2544,48 @@ declare function mapAgentTool(name: string): MappedTool;
|
|
|
3634
2544
|
*/
|
|
3635
2545
|
declare function normalizeAgentArgs(tool: ResearchToolType, args: Record<string, unknown>): Record<string, unknown>;
|
|
3636
2546
|
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
2547
|
+
interface PlannerBackendOptions {
|
|
2548
|
+
/** The planner provider configured now. */
|
|
2549
|
+
provider(): PlannerBackendId;
|
|
2550
|
+
/** A backend for the provider configured now. */
|
|
2551
|
+
create(): IAiService;
|
|
2552
|
+
/** Whether a planner turn is running on the backend. */
|
|
2553
|
+
busy(): boolean;
|
|
2554
|
+
}
|
|
2555
|
+
/**
|
|
2556
|
+
* The planner transport for the provider configured *right now* (ADR-0009),
|
|
2557
|
+
* and the one place it is let go.
|
|
2558
|
+
*
|
|
2559
|
+
* Resolved on every read rather than once at construction, because a Session
|
|
2560
|
+
* outlives the choice: VS Code hosts exactly one for the whole window, and the
|
|
2561
|
+
* webview pills and `/planner` switch backends underneath it. A service
|
|
2562
|
+
* captured at construction kept the old backend and was handed the new one's
|
|
2563
|
+
* model — an OpenCode model id spawned as `claude --model opencode/…`.
|
|
2564
|
+
*
|
|
2565
|
+
* Letting a backend go — a switch to another provider, or settings that its
|
|
2566
|
+
* client was built from — waits until no planner turn is running on it:
|
|
2567
|
+
* `reset()` cuts the call in flight off, and the turn would end with neither an
|
|
2568
|
+
* answer nor its inputs. A model or effort change needs no reset: a turn on a
|
|
2569
|
+
* live context that no longer matches the configuration replays instead
|
|
2570
|
+
* (`conversationMatchesConfig`). A harness planner holds an OS process, so a
|
|
2571
|
+
* backend replaced is always reset, never just dropped.
|
|
2572
|
+
*/
|
|
2573
|
+
declare class PlannerBackend {
|
|
2574
|
+
private readonly options;
|
|
2575
|
+
private live;
|
|
2576
|
+
private liveProvider;
|
|
2577
|
+
/** Settings it was built from changed while a turn ran on it. */
|
|
2578
|
+
private stale;
|
|
2579
|
+
/** `pinned`: a backend injected whole, which is reset but never replaced. */
|
|
2580
|
+
constructor(options: PlannerBackendOptions | {
|
|
2581
|
+
pinned: IAiService;
|
|
2582
|
+
busy(): boolean;
|
|
2583
|
+
});
|
|
2584
|
+
current(): IAiService;
|
|
2585
|
+
/** What the backend was built from changed: it is reset now, or as soon as the turn running on it ends. */
|
|
2586
|
+
settingsChanged(): void;
|
|
2587
|
+
/** Make the switch or the reset that waited, if one did. Call while no turn runs: as one is about to take the conversation, and as one lets it go. */
|
|
2588
|
+
settle(): void;
|
|
3648
2589
|
}
|
|
3649
2590
|
|
|
3650
2591
|
type ModelsByRunner = Partial<Record<RunnerId, DiscoveredModel[]>>;
|
|
@@ -3678,6 +2619,8 @@ declare class SessionCatalog {
|
|
|
3678
2619
|
constructor(deps: SessionCatalogDeps);
|
|
3679
2620
|
/** The runners enabled right now. */
|
|
3680
2621
|
enabledRunners(): RunnerId[];
|
|
2622
|
+
/** The runners `writer` may put a task on now ({@link assignableRunners}); undefined means any. */
|
|
2623
|
+
runnersFor(writer: AssignmentWriter): RunnerId[] | undefined;
|
|
3681
2624
|
/**
|
|
3682
2625
|
* The allowlist in force right now. Unset means no restriction — falling
|
|
3683
2626
|
* back to the one planning started under would keep a restriction the user
|
|
@@ -3686,8 +2629,6 @@ declare class SessionCatalog {
|
|
|
3686
2629
|
allowlist(): Record<string, string[]>;
|
|
3687
2630
|
/** The enabled runners and allowlist together, for whoever compares an assignment with them. */
|
|
3688
2631
|
scope(): AssignmentScope;
|
|
3689
|
-
/** The models the user allows on one runner; unset means no restriction. */
|
|
3690
|
-
allowlistFor(runner: RunnerId): string[] | undefined;
|
|
3691
2632
|
/**
|
|
3692
2633
|
* The discovered catalog as the resolver holds it now, per runner, with this
|
|
3693
2634
|
* session's own discovery as the fallback where the resolver has nothing
|
|
@@ -3724,16 +2665,21 @@ declare class SessionCatalog {
|
|
|
3724
2665
|
current(): TaskQueryCatalog;
|
|
3725
2666
|
queryCatalog(runners: RunnerId[]): TaskQueryCatalog;
|
|
3726
2667
|
/**
|
|
3727
|
-
* The catalog
|
|
3728
|
-
*
|
|
3729
|
-
*
|
|
3730
|
-
*
|
|
3731
|
-
*
|
|
3732
|
-
|
|
2668
|
+
* The catalog an assignment is resolved against — the same discovered
|
|
2669
|
+
* models and manifest modes the per-turn catalog block shows the planner,
|
|
2670
|
+
* so a refusal can never name something invalid that the planner was never
|
|
2671
|
+
* told about. The models are not filtered by the allowlist here: the
|
|
2672
|
+
* resolver reads the allowlist itself (`resolveAssignment`).
|
|
2673
|
+
*/
|
|
2674
|
+
edit(runners?: RunnerId[]): AssignmentCatalog & {
|
|
2675
|
+
runnerModes: Record<RunnerId, RunnerModeInfo[]>;
|
|
2676
|
+
};
|
|
2677
|
+
/**
|
|
2678
|
+
* What a runner offers a task moved to it or added on it. Spawns the
|
|
2679
|
+
* runner's CLI to list models; null for a runner no manifest declares,
|
|
2680
|
+
* which has no CLI to ask.
|
|
3733
2681
|
*/
|
|
3734
|
-
|
|
3735
|
-
/** What a runner offers, as `runnerAssignment` needs it. Spawns the runner's CLI to list models. */
|
|
3736
|
-
runner(runner: RunnerId): Promise<RunnerCatalog>;
|
|
2682
|
+
runner(runner: RunnerId): Promise<RunnerCatalog | null>;
|
|
3737
2683
|
/**
|
|
3738
2684
|
* The one place planning discovers what it may draw from: the runners'
|
|
3739
2685
|
* models and their modes. `filteredModels` is the allowlisted view a prompt
|
|
@@ -3813,12 +2759,14 @@ interface SessionEventRelayDeps {
|
|
|
3813
2759
|
* and remembered for a surface joining late, so Session announces it too. A
|
|
3814
2760
|
* model switch is a plan edit, which Session's editor announces as one.
|
|
3815
2761
|
*/
|
|
3816
|
-
type RelayObserver = Required<Omit<OrchestratorObserver, 'onTaskSettled' | 'onRunStarted' | 'onAutoMerge' | 'onUsageLimitWait' | 'onModelSwitched' | 'onTaskIdle' | 'onIsolationHandoff'>>;
|
|
2762
|
+
type RelayObserver = Required<Omit<OrchestratorObserver, 'onTaskSettled' | 'onRunStarted' | 'onAutoMerge' | 'onUsageLimitWait' | 'onModelSwitched' | 'onTaskIdle' | 'onIsolationHandoff' | 'onRunClosed'>>;
|
|
3817
2763
|
/**
|
|
3818
2764
|
* Turns orchestrator and planner events into {@link SessionMessage}
|
|
3819
2765
|
* broadcasts — the one place a surface's view of a Session is produced. It
|
|
3820
|
-
* never persists
|
|
3821
|
-
*
|
|
2766
|
+
* never persists, and holds nothing of a planner turn: a turn keeps what it
|
|
2767
|
+
* writes until it lands (`PlannerConversation`). Where an event also owes a
|
|
2768
|
+
* save, the Session does that before handing the event on, so no surface sees
|
|
2769
|
+
* state the disk lacks.
|
|
3822
2770
|
*/
|
|
3823
2771
|
declare class SessionEventRelay {
|
|
3824
2772
|
private readonly broadcast;
|
|
@@ -3830,12 +2778,6 @@ declare class SessionEventRelay {
|
|
|
3830
2778
|
private readonly awaitingApproval;
|
|
3831
2779
|
private readonly checkpointQuestion;
|
|
3832
2780
|
private readonly waitsForApproval;
|
|
3833
|
-
/**
|
|
3834
|
-
* The in-flight turn's subagent activity, grouped one run per subagent so a
|
|
3835
|
-
* replay nests each step under its own brief/result. Folded into the plan's
|
|
3836
|
-
* researchLog at persist — see {@link flushSubagentRuns}.
|
|
3837
|
-
*/
|
|
3838
|
-
private pendingSubagents;
|
|
3839
2781
|
private statusHeld;
|
|
3840
2782
|
private statusOwed;
|
|
3841
2783
|
/** The planner's requests announced and not yet settled, as they were announced: a surface joining now is owed them. */
|
|
@@ -3868,20 +2810,6 @@ declare class SessionEventRelay {
|
|
|
3868
2810
|
/** `turnId`: the planner turn whose commit this is, when one is. */
|
|
3869
2811
|
planGenerated(plan: LegacyPlanState | null, goal: string, turnId?: string): void;
|
|
3870
2812
|
progress(progress: ResearchProgress): void;
|
|
3871
|
-
/** The run for `subagentId`, created on first sighting so a step arriving
|
|
3872
|
-
* before (or without) its started event still gets a home. */
|
|
3873
|
-
private subagentRun;
|
|
3874
|
-
/**
|
|
3875
|
-
* Fold the turn's subagent runs into the plan's researchLog as one contiguous
|
|
3876
|
-
* group per subagent — its entry then its steps, in the order they started —
|
|
3877
|
-
* so a replay nests each step under its own subagent however the live stream
|
|
3878
|
-
* interleaved. A harness planner already logs its child steps through the
|
|
3879
|
-
* turn's researchLog; they are pulled out of that position and re-grouped
|
|
3880
|
-
* rather than duplicated.
|
|
3881
|
-
*/
|
|
3882
|
-
flushSubagentRuns(plan: LegacyPlanState): void;
|
|
3883
|
-
/** Forget a turn's subagent runs that will never be persisted. */
|
|
3884
|
-
dropSubagentRuns(): void;
|
|
3885
2813
|
}
|
|
3886
2814
|
|
|
3887
2815
|
/** Which session's logs, in which workspace. */
|
|
@@ -4052,7 +2980,7 @@ interface SessionParts {
|
|
|
4052
2980
|
modelResolver: ModelResolver;
|
|
4053
2981
|
settings: () => SessionRuntimeSettings;
|
|
4054
2982
|
hostSessionId?: string;
|
|
4055
|
-
|
|
2983
|
+
backend: PlannerBackend;
|
|
4056
2984
|
planner: SessionPlanner;
|
|
4057
2985
|
store: PlanStore;
|
|
4058
2986
|
orchestrator: TaskOrchestrator;
|
|
@@ -4083,7 +3011,7 @@ interface SessionParts {
|
|
|
4083
3011
|
* (setModels, setRunnerList, …) stay on the host; Session never emits them.
|
|
4084
3012
|
*/
|
|
4085
3013
|
declare class Session {
|
|
4086
|
-
private readonly
|
|
3014
|
+
private readonly backend;
|
|
4087
3015
|
private readonly usage;
|
|
4088
3016
|
private readonly events;
|
|
4089
3017
|
private readonly planner;
|
|
@@ -4103,6 +3031,8 @@ declare class Session {
|
|
|
4103
3031
|
* supervisor has first.
|
|
4104
3032
|
*/
|
|
4105
3033
|
private sentHandoff;
|
|
3034
|
+
/** The run was forgotten and no surface has been told yet; see {@link announceClosed}. */
|
|
3035
|
+
private closedUnannounced;
|
|
4106
3036
|
/** The edit the open planner turn holds, as last announced: a surface that joins mid-turn is shown it. */
|
|
4107
3037
|
private sentHeld;
|
|
4108
3038
|
private readonly notifications;
|
|
@@ -4139,8 +3069,6 @@ declare class Session {
|
|
|
4139
3069
|
private turnEffects;
|
|
4140
3070
|
/** Every turn's effects with starts still owed: a turn's may still be running its starts when the next opens. */
|
|
4141
3071
|
private readonly owingEffects;
|
|
4142
|
-
/** What the planner's next turn is told before anything else; see {@link PlannerConversationHost.takeRunUpdates}. */
|
|
4143
|
-
private readonly untoldRunUpdates;
|
|
4144
3072
|
private unlistenApprovals;
|
|
4145
3073
|
private readonly plannerTools;
|
|
4146
3074
|
constructor(parts: SessionParts);
|
|
@@ -4185,9 +3113,9 @@ declare class Session {
|
|
|
4185
3113
|
/** The open planner turn is the supervisor's, acting at Act: its edits and added tasks are its own (ADR-0029). */
|
|
4186
3114
|
private supervisorEditing;
|
|
4187
3115
|
/**
|
|
4188
|
-
* The runners a planner edit may put a task on
|
|
4189
|
-
*
|
|
4190
|
-
*
|
|
3116
|
+
* The runners a planner edit may put a task on (`assignableRunners`). An
|
|
3117
|
+
* edit is checked as it is made and again as it lands against this one set,
|
|
3118
|
+
* so what was accepted cannot be refused at commit.
|
|
4191
3119
|
*/
|
|
4192
3120
|
private editRunners;
|
|
4193
3121
|
/**
|
|
@@ -4227,7 +3155,6 @@ declare class Session {
|
|
|
4227
3155
|
* task under the same id (ADR-0029).
|
|
4228
3156
|
*/
|
|
4229
3157
|
private keepApprovals;
|
|
4230
|
-
private approveTask;
|
|
4231
3158
|
/**
|
|
4232
3159
|
* Answer an outstanding approval. Every surface funnels here — the web
|
|
4233
3160
|
* server's HTTP route, the VS Code webview, the TUI prompt — so the decision
|
|
@@ -4268,9 +3195,9 @@ declare class Session {
|
|
|
4268
3195
|
*/
|
|
4269
3196
|
private syncPlanTasks;
|
|
4270
3197
|
/**
|
|
4271
|
-
* Persists PlanStore state to disk. PlanStore is the single authority.
|
|
4272
|
-
*
|
|
4273
|
-
*
|
|
3198
|
+
* Persists PlanStore state to disk. PlanStore is the single authority. Any
|
|
3199
|
+
* save may come in the middle of a planner turn, and finds nothing of it to
|
|
3200
|
+
* write: a turn holds what it writes until the mutation that lands it.
|
|
4274
3201
|
*/
|
|
4275
3202
|
private persist;
|
|
4276
3203
|
/** A new plan on a long-lived Session gets its own persisted identity (unless the host fixed one). */
|
|
@@ -4279,8 +3206,8 @@ declare class Session {
|
|
|
4279
3206
|
* The plan scope ends: everything that belongs to the plan this Session
|
|
4280
3207
|
* holds goes, so nothing of it reaches the next one — a new plan, another
|
|
4281
3208
|
* session adopted, or the Session closed. Its run is stopped, the planner
|
|
4282
|
-
* turn in flight is abandoned with
|
|
4283
|
-
*
|
|
3209
|
+
* turn in flight is abandoned with everything it held, what that turn
|
|
3210
|
+
* deferred is settled, and the conversation, supervision, usage ledger,
|
|
4284
3211
|
* execution log and planner prompts are cleared. A new plan on the same
|
|
4285
3212
|
* Session keeps the scopes the user granted (`keepGrants`); a session
|
|
4286
3213
|
* boundary does not (ADR-0008).
|
|
@@ -4424,12 +3351,6 @@ declare class Session {
|
|
|
4424
3351
|
*/
|
|
4425
3352
|
compactConversation(signal?: AbortSignal): Promise<ConversationCompaction>;
|
|
4426
3353
|
rewindTargets(): RewindTarget[];
|
|
4427
|
-
/**
|
|
4428
|
-
* Hand the planner turn in flight a validated plan or a task edit; the turn
|
|
4429
|
-
* commits it as it would the same JSON in the planner's reply. False when
|
|
4430
|
-
* no turn is open.
|
|
4431
|
-
*/
|
|
4432
|
-
submitToTurn(submission: PlannerSubmission): boolean;
|
|
4433
3354
|
/** A plan the planner submitted through its tool, already checked against the live catalog. */
|
|
4434
3355
|
private submitPlanFromTool;
|
|
4435
3356
|
/**
|
|
@@ -4486,7 +3407,6 @@ declare class Session {
|
|
|
4486
3407
|
* level at each call. Other sessions' runs keep theirs until they end.
|
|
4487
3408
|
*/
|
|
4488
3409
|
applyRunSettings(changes: Partial<GlobalRunSettings>): void;
|
|
4489
|
-
executePlan(): Promise<void>;
|
|
4490
3410
|
private idlePlan;
|
|
4491
3411
|
private runWholePlan;
|
|
4492
3412
|
/**
|
|
@@ -4496,11 +3416,7 @@ declare class Session {
|
|
|
4496
3416
|
* would make it.
|
|
4497
3417
|
*/
|
|
4498
3418
|
private joinRun;
|
|
4499
|
-
approveReview(): Promise<LegacyPlanState>;
|
|
4500
|
-
/** Answers the line saying the task waits for its dependencies, when it was queued behind them rather than started. */
|
|
4501
|
-
forceStartTask(taskId: string): Promise<string | undefined>;
|
|
4502
3419
|
private startOneTask;
|
|
4503
|
-
runTask(taskId: string): Promise<void>;
|
|
4504
3420
|
/**
|
|
4505
3421
|
* A stale id — a task removed since the surface last drew it — is refused.
|
|
4506
3422
|
* Reloading the plan to find it never could, and reset the verifier under
|
|
@@ -4509,20 +3425,8 @@ declare class Session {
|
|
|
4509
3425
|
private requireTask;
|
|
4510
3426
|
/** Start whatever the scheduler can now fit — after the parallel limit was raised mid-run, say. */
|
|
4511
3427
|
reschedule(): Promise<void>;
|
|
4512
|
-
retryTask(taskId: string): Promise<void>;
|
|
4513
3428
|
private restartTask;
|
|
4514
|
-
/**
|
|
4515
|
-
* Continue a finished structured task in its saved runner session with the
|
|
4516
|
-
* user's message (ADR-0018, K1); throws `TaskControlError` for a task that
|
|
4517
|
-
* cannot be continued.
|
|
4518
|
-
*/
|
|
4519
|
-
continueTask(taskId: string, message: string): Promise<void>;
|
|
4520
3429
|
private resumeTask;
|
|
4521
|
-
cancelTask(taskId: string): Promise<void>;
|
|
4522
|
-
markTaskComplete(taskId: string): Promise<void>;
|
|
4523
|
-
markTaskIncomplete(taskId: string): Promise<void>;
|
|
4524
|
-
/** Resume a task paused on a usage limit now, once the user says it has reset; see {@link TaskOrchestrator.resumeNow}. */
|
|
4525
|
-
resumeNow(taskId: string): Promise<void>;
|
|
4526
3430
|
/**
|
|
4527
3431
|
* Keep what waits on the planner's usage limit from being sent at the reset:
|
|
4528
3432
|
* it goes with the user's next message instead. False when nothing waits on
|
|
@@ -4530,7 +3434,7 @@ declare class Session {
|
|
|
4530
3434
|
*/
|
|
4531
3435
|
cancelPlannerResend(): boolean;
|
|
4532
3436
|
/** Keep a task paused on a usage limit from resuming on its own; see {@link TaskOrchestrator.cancelScheduledResume}. */
|
|
4533
|
-
cancelScheduledResume
|
|
3437
|
+
private cancelScheduledResume;
|
|
4534
3438
|
/**
|
|
4535
3439
|
* The plan follows a model switch the user made in the runner (#106), and
|
|
4536
3440
|
* the task's log says what the plan holds once that settled: a write-back
|
|
@@ -4541,8 +3445,8 @@ declare class Session {
|
|
|
4541
3445
|
private followRunnerModel;
|
|
4542
3446
|
/** Said through both channels: a host shows one or the other, never both (the daemon's toasts are no-ops). */
|
|
4543
3447
|
private notice;
|
|
4544
|
-
approveCheckpoint
|
|
4545
|
-
rejectCheckpoint
|
|
3448
|
+
private approveCheckpoint;
|
|
3449
|
+
private rejectCheckpoint;
|
|
4546
3450
|
/** Whether an answer would reach the task: it waits at a checkpoint and a runner is left to hear it. */
|
|
4547
3451
|
awaitsCheckpoint(taskId: string): boolean;
|
|
4548
3452
|
/**
|
|
@@ -4550,20 +3454,21 @@ declare class Session {
|
|
|
4550
3454
|
* `TaskControlError` for one that cannot take it. A task waiting for input
|
|
4551
3455
|
* is back in progress, and saved so before any surface is told.
|
|
4552
3456
|
*/
|
|
4553
|
-
sendTaskMessage
|
|
3457
|
+
private sendTaskMessage;
|
|
4554
3458
|
/**
|
|
4555
3459
|
* Force send (ADR-0023, F1): interrupt the task's running turn and deliver
|
|
4556
3460
|
* this message next. Throws `TaskControlError` where a plain message would.
|
|
4557
3461
|
*/
|
|
4558
|
-
forceSendTaskMessage
|
|
3462
|
+
private forceSendTaskMessage;
|
|
4559
3463
|
/**
|
|
4560
|
-
* The task runner's own command `/name args` (#66), as a turn of its own
|
|
4561
|
-
*
|
|
3464
|
+
* The task runner's own command `/name args` (#66), as a turn of its own;
|
|
3465
|
+
* not an execution control, so it carries no command at the seam and the
|
|
3466
|
+
* daemon hands it straight to the runner. Throws `TaskControlError` where a
|
|
3467
|
+
* plain message would.
|
|
4562
3468
|
*/
|
|
4563
3469
|
invokeTaskCommand(taskId: string, name: string, args?: string): string;
|
|
4564
|
-
forceSendQueuedTaskMessage
|
|
4565
|
-
removeQueuedTaskMessage
|
|
4566
|
-
interruptTask(taskId: string): Promise<void>;
|
|
3470
|
+
private forceSendQueuedTaskMessage;
|
|
3471
|
+
private removeQueuedTaskMessage;
|
|
4567
3472
|
/** Replay a run a dirty tree blocked, after stashing the tracked changes. */
|
|
4568
3473
|
continueWithStash(): Promise<void>;
|
|
4569
3474
|
/** Replay a run a dirty tree blocked, in the workspace root, for this run only. */
|
|
@@ -4589,13 +3494,20 @@ declare class Session {
|
|
|
4589
3494
|
/**
|
|
4590
3495
|
* "Merge all": each repo's integration branch into whatever the user has
|
|
4591
3496
|
* checked out there — every repo, or none if any cannot take it. The one
|
|
4592
|
-
* irreversible step of isolated execution.
|
|
4593
|
-
* supervisor's merge_all
|
|
4594
|
-
*
|
|
4595
|
-
* which is what opens a merge gate (ADR-0020); it waits for no ops
|
|
4596
|
-
* and refuses while one runs.
|
|
3497
|
+
* irreversible step of isolated execution. The user's Merge all and the
|
|
3498
|
+
* supervisor's merge_all reach it through the seam; automatic gate merging
|
|
3499
|
+
* shares the scheduler's half of it. During a run it merges what has landed
|
|
3500
|
+
* so far, which is what opens a merge gate (ADR-0020); it waits for no ops
|
|
3501
|
+
* task, and refuses while one runs.
|
|
4597
3502
|
*/
|
|
4598
|
-
|
|
3503
|
+
private mergeAll;
|
|
3504
|
+
/**
|
|
3505
|
+
* Say so when the isolated run is gone: a merge that left nothing to hand
|
|
3506
|
+
* over clears it up (ADR-0013), and so does a discard. Surfaces fold this
|
|
3507
|
+
* instead of reading the merge result, which cannot tell a merge that ended
|
|
3508
|
+
* the run from one that only opened a gate (ADR-0020).
|
|
3509
|
+
*/
|
|
3510
|
+
private announceClosed;
|
|
4599
3511
|
/** Remove the run's worktrees and task branches; keep its integration branch to review or merge. */
|
|
4600
3512
|
cleanupRun(): Promise<void>;
|
|
4601
3513
|
/**
|
|
@@ -4622,10 +3534,7 @@ declare class Session {
|
|
|
4622
3534
|
* a hold would stall every task's status for as long, and an
|
|
4623
3535
|
* `execution_complete` the control triggers would overtake the status held
|
|
4624
3536
|
* back — which a surface treats as the end of the stream. Instead each status
|
|
4625
|
-
* announced while one runs is saved first (see {@link observer})
|
|
4626
|
-
* background save of an execution event: it may land mid planner turn. So
|
|
4627
|
-
* is the last one where the control is itself execution, not the user's
|
|
4628
|
-
* word on the plan (`background`).
|
|
3537
|
+
* announced while one runs is saved first (see {@link observer}).
|
|
4629
3538
|
*/
|
|
4630
3539
|
private withSave;
|
|
4631
3540
|
private saveForControl;
|
|
@@ -4671,7 +3580,12 @@ declare class Session {
|
|
|
4671
3580
|
persist?: boolean;
|
|
4672
3581
|
}): void;
|
|
4673
3582
|
destroy(): void;
|
|
4674
|
-
|
|
3583
|
+
/**
|
|
3584
|
+
* The planner's settings or credentials changed: its backend is let go and
|
|
3585
|
+
* built afresh from them, once no planner turn is running on it (see
|
|
3586
|
+
* {@link PlannerBackend}).
|
|
3587
|
+
*/
|
|
3588
|
+
plannerSettingsChanged(): void;
|
|
4675
3589
|
}
|
|
4676
3590
|
|
|
4677
3591
|
/**
|
|
@@ -4687,345 +3601,6 @@ declare class PlanEditError extends Error {
|
|
|
4687
3601
|
constructor(message: string);
|
|
4688
3602
|
}
|
|
4689
3603
|
|
|
4690
|
-
/** What the preflight reads: the planner choice and whatever it needs to be reachable. */
|
|
4691
|
-
type PlannerReadinessConfig = Pick<IConfig, 'aiProvider' | 'planningModel' | 'openaiCompatibleBaseUrl' | 'getProviderApiKey'>;
|
|
4692
|
-
/**
|
|
4693
|
-
* Why the selected planner cannot plan yet, as data. Each surface words it with
|
|
4694
|
-
* its own command spelling (`describePlannerNotReady`), so a daemon, a chat and
|
|
4695
|
-
* a shell script can all say the same thing without sharing a syntax.
|
|
4696
|
-
*/
|
|
4697
|
-
type PlannerNotReady = {
|
|
4698
|
-
code: 'no_key';
|
|
4699
|
-
provider: AiProvider;
|
|
4700
|
-
label: string;
|
|
4701
|
-
keyEnvVar: string;
|
|
4702
|
-
} | {
|
|
4703
|
-
code: 'no_base_url';
|
|
4704
|
-
provider: AiProvider;
|
|
4705
|
-
label: string;
|
|
4706
|
-
baseUrlEnvVar: string;
|
|
4707
|
-
} | {
|
|
4708
|
-
code: 'no_model';
|
|
4709
|
-
provider: AiProvider;
|
|
4710
|
-
label: string;
|
|
4711
|
-
};
|
|
4712
|
-
/**
|
|
4713
|
-
* What the selected planner still needs before it can plan, or null when it is
|
|
4714
|
-
* ready. There are two ways in (ADR-0009), and only one of them involves a
|
|
4715
|
-
* credential: a harness planner drives a coding agent already installed on the
|
|
4716
|
-
* machine, authenticated by the user's own subscription, so demanding an API
|
|
4717
|
-
* key of it turns a working setup into a wall. Its model is optional too: an
|
|
4718
|
-
* unset id means "the agent's own default".
|
|
4719
|
-
*/
|
|
4720
|
-
declare function plannerNotReady(config: PlannerReadinessConfig): PlannerNotReady | null;
|
|
4721
|
-
/**
|
|
4722
|
-
* `plannerNotReady` judged on a host's own config — the one way every host
|
|
4723
|
-
* builds the preflight's input, so none can hand it a key the selected
|
|
4724
|
-
* planner's transport will not read (a stored OpenRouter key passing for an
|
|
4725
|
-
* OpenAI planner, which then failed inside the transport). Every planner turn
|
|
4726
|
-
* judges through this too, so none can let through what another refuses.
|
|
4727
|
-
*/
|
|
4728
|
-
declare function plannerNotReadyFor(config: Pick<IConfig, 'aiProvider' | 'orchestratorModel' | 'planningModel' | 'openaiCompatibleBaseUrl' | 'getProviderApiKey'>): PlannerNotReady | null;
|
|
4729
|
-
/** How one surface spells the commands a not-ready message points at. */
|
|
4730
|
-
interface PlannerCommandSyntax {
|
|
4731
|
-
pickPlanner: string;
|
|
4732
|
-
setKey(provider: AiProvider): string;
|
|
4733
|
-
setModel: string;
|
|
4734
|
-
}
|
|
4735
|
-
declare const TERMINAL_UI_COMMANDS: PlannerCommandSyntax;
|
|
4736
|
-
/** The VS Code chat shares the terminal's slash commands, except that its `/model` needs `set`. */
|
|
4737
|
-
declare const CHAT_COMMANDS: PlannerCommandSyntax;
|
|
4738
|
-
declare const HEADLESS_CLI_COMMANDS: PlannerCommandSyntax;
|
|
4739
|
-
declare function describePlannerNotReady(reason: PlannerNotReady, commands: PlannerCommandSyntax): string;
|
|
4740
|
-
/**
|
|
4741
|
-
* A planner turn refused before it began. Carries the reason as data so a
|
|
4742
|
-
* client that spells commands differently (the headless CLI) can re-word it;
|
|
4743
|
-
* the message is the terminal UI's spelling, which is what most clients show.
|
|
4744
|
-
*/
|
|
4745
|
-
declare class PlannerNotReadyError extends Error {
|
|
4746
|
-
readonly reason: PlannerNotReady;
|
|
4747
|
-
constructor(reason: PlannerNotReady);
|
|
4748
|
-
}
|
|
4749
|
-
|
|
4750
|
-
/** What the user last picked for one planner backend. */
|
|
4751
|
-
interface PlannerModelChoice {
|
|
4752
|
-
model: string;
|
|
4753
|
-
effort?: string;
|
|
4754
|
-
}
|
|
4755
|
-
/**
|
|
4756
|
-
* A candidate model as this planner's catalog lists it. Deliberately plain
|
|
4757
|
-
* data: a harness planner's catalog is its runner's own model list and a
|
|
4758
|
-
* vendor's is a picker list (ADR-0009), and the rule below is the same for
|
|
4759
|
-
* both — so the caller normalizes, and this module never reaches for a
|
|
4760
|
-
* ModelResolver, a config or the network.
|
|
4761
|
-
*/
|
|
4762
|
-
interface PlannerModelCandidate {
|
|
4763
|
-
id: string;
|
|
4764
|
-
variants?: {
|
|
4765
|
-
id: string;
|
|
4766
|
-
}[];
|
|
4767
|
-
}
|
|
4768
|
-
interface PlannerModelRecall {
|
|
4769
|
-
model: string;
|
|
4770
|
-
effort: string;
|
|
4771
|
-
source: 'remembered' | 'catalog-default' | 'none';
|
|
4772
|
-
}
|
|
4773
|
-
/** The slice of `SettingsService` this needs, so tests can pass a plain object. */
|
|
4774
|
-
interface PlannerModelStore {
|
|
4775
|
-
getPlannerModel(provider: string): PlannerModelChoice | undefined;
|
|
4776
|
-
setPlannerModel(provider: string, entry: PlannerModelChoice | undefined): void;
|
|
4777
|
-
}
|
|
4778
|
-
/**
|
|
4779
|
-
* Remembers, per planner backend, the model the user last chose for it.
|
|
4780
|
-
*
|
|
4781
|
-
* Switching the planner has to clear the model — an id is scoped to the agent
|
|
4782
|
-
* that listed it, so an OpenRouter slug handed to Claude Code points it at
|
|
4783
|
-
* something it cannot spawn. That clear is correct and stays; what was missing
|
|
4784
|
-
* is that switching *back* then forced a re-pick of a model the user had
|
|
4785
|
-
* already chosen. The rule itself is `selectPlanner`'s; this is the storage
|
|
4786
|
-
* the surfaces that keep their memory in the settings file hand it.
|
|
4787
|
-
*/
|
|
4788
|
-
declare class PlannerModelMemory {
|
|
4789
|
-
private store;
|
|
4790
|
-
constructor(store: PlannerModelStore);
|
|
4791
|
-
/** Record what the user picked for `provider`; a blank model forgets it instead. */
|
|
4792
|
-
remember(provider: string, model: string, effort?: string): void;
|
|
4793
|
-
getPlannerModel(provider: string): PlannerModelChoice | undefined;
|
|
4794
|
-
/**
|
|
4795
|
-
* What the model and effort should become when `provider` takes over the
|
|
4796
|
-
* planner, given the models it actually serves. The `source` is what the
|
|
4797
|
-
* three surfaces word their notice from — restored, defaulted, or nothing.
|
|
4798
|
-
*/
|
|
4799
|
-
recall(provider: string, catalog: PlannerModelCandidate[]): PlannerModelRecall;
|
|
4800
|
-
}
|
|
4801
|
-
|
|
4802
|
-
/**
|
|
4803
|
-
* The daemon contract: every HTTP body the local daemon sends, in one place.
|
|
4804
|
-
*
|
|
4805
|
-
* The daemon's routes build their bodies against these types and the CLI's
|
|
4806
|
-
* `ApiClient` reads them back, so a field added on one side is a compile error
|
|
4807
|
-
* on the other. Before this there were three hand-written copies — the routes'
|
|
4808
|
-
* inline `c.json`, the client's per-method generics, and the TUI's slice of the
|
|
4809
|
-
* client — and they had drifted (the client declared a `headless` field the
|
|
4810
|
-
* daemon never sent, and typed `GET /sessions/:id`'s plan as the wrong shape).
|
|
4811
|
-
*
|
|
4812
|
-
* Types only. Core is the one package both the daemon and its clients already
|
|
4813
|
-
* depend on; importing from the daemon would pull its runtime into the CLI.
|
|
4814
|
-
*/
|
|
4815
|
-
/**
|
|
4816
|
-
* Why a request was refused, as a stable code a client switches on instead of
|
|
4817
|
-
* reading the message. Absent on a refusal nobody needs to tell apart — a
|
|
4818
|
-
* missing field, say — where the message is all there is.
|
|
4819
|
-
*/
|
|
4820
|
-
type DaemonErrorCode = 'session_not_found' | 'task_not_found' | 'no_plan' | 'already_executing' | 'workspace_not_found' | 'workspace_not_a_project' | 'conversation_busy'
|
|
4821
|
-
/** The user stopped the planner turn: the turn ended as asked, so a client stays quiet. */
|
|
4822
|
-
| 'planner_turn_stopped'
|
|
4823
|
-
/** The planner turn settled after its plan was dropped; nothing it produced was kept. */
|
|
4824
|
-
| 'planner_turn_discarded'
|
|
4825
|
-
/** The selected planner cannot plan yet (no key, no base URL, no model); `plannerNotReady` says which. */
|
|
4826
|
-
| 'planner_not_ready'
|
|
4827
|
-
/** The request asked for something the plan, task or conversation does not allow. */
|
|
4828
|
-
| 'refused' | 'checkpoint_not_waiting' | 'approval_not_outstanding';
|
|
4829
|
-
/** The body of every non-2xx answer a route gives. */
|
|
4830
|
-
interface ErrorBody {
|
|
4831
|
-
error: string;
|
|
4832
|
-
code?: DaemonErrorCode;
|
|
4833
|
-
/** Set with `workspace_not_a_project`: the directory the daemon refused, so a client can offer to initialize it. */
|
|
4834
|
-
workspace?: string;
|
|
4835
|
-
/** Set with `planner_not_ready`: the reason as data, so a client can word it in its own commands. */
|
|
4836
|
-
plannerNotReady?: PlannerNotReady;
|
|
4837
|
-
}
|
|
4838
|
-
interface OkResponse {
|
|
4839
|
-
ok: boolean;
|
|
4840
|
-
}
|
|
4841
|
-
/** A task start's answer: `queued` says why it did not start now, when the task waits for its dependencies instead. */
|
|
4842
|
-
interface TaskStartResponse extends OkResponse {
|
|
4843
|
-
queued?: string;
|
|
4844
|
-
}
|
|
4845
|
-
/**
|
|
4846
|
-
* A plan as the planner routes return it: the session's plan state, not the
|
|
4847
|
-
* `SerializedPlan` a websocket `plan_generated` carries. The two differ —
|
|
4848
|
-
* this one holds raw tasks and the dialogue's bookkeeping — and a client that
|
|
4849
|
-
* reads either reads only the fields it needs. Skill bodies stay in the
|
|
4850
|
-
* session: loads and attempt snapshots arrive as notices.
|
|
4851
|
-
*/
|
|
4852
|
-
interface PlanResponse {
|
|
4853
|
-
plan: SurfacePlan;
|
|
4854
|
-
}
|
|
4855
|
-
/** `POST /plans/:id/resolve-conflict`: `null` when the session had no conflict to hand a resolver task. */
|
|
4856
|
-
interface ResolveConflictResponse {
|
|
4857
|
-
plan: SurfacePlan | null;
|
|
4858
|
-
}
|
|
4859
|
-
/** What `GET /api/models` returns, and what the pool's provider discovery produces. */
|
|
4860
|
-
interface ModelsResponse {
|
|
4861
|
-
models: DiscoveredModel[];
|
|
4862
|
-
modelsByRunner: Record<string, DiscoveredModel[]>;
|
|
4863
|
-
/** Each runner's manifest modes, so a surface can offer a per-task mode picker. */
|
|
4864
|
-
modesByRunner: Record<string, RunnerModeInfo[]>;
|
|
4865
|
-
orchestratorModel: string;
|
|
4866
|
-
providers: AiProvider[];
|
|
4867
|
-
/** Full cross-provider catalog for the orchestrator (planner) model picker. */
|
|
4868
|
-
orchestratorModels: OrchestratorOption[];
|
|
4869
|
-
/** Per-provider catalog-fetch failures, keyed by provider id. */
|
|
4870
|
-
providerErrors: Record<string, string>;
|
|
4871
|
-
}
|
|
4872
|
-
/** One-shot planning answers in the phase-tagged shape a saved session is read back in. */
|
|
4873
|
-
interface GeneratePlanResponse extends Pick<ModelsResponse, 'models' | 'modelsByRunner'> {
|
|
4874
|
-
plan: SurfacePlanState;
|
|
4875
|
-
/** The host notes the plan's transcript records, a skill check's warnings among them, which the phase-tagged plan does not carry. */
|
|
4876
|
-
notes?: string[];
|
|
4877
|
-
}
|
|
4878
|
-
interface ExecuteResponse {
|
|
4879
|
-
status: 'running';
|
|
4880
|
-
}
|
|
4881
|
-
interface StopResponse {
|
|
4882
|
-
status: 'stopped';
|
|
4883
|
-
}
|
|
4884
|
-
interface CancelPlanningResponse {
|
|
4885
|
-
cancelled: boolean;
|
|
4886
|
-
}
|
|
4887
|
-
/** `POST /api/plans/:id/tasks/:taskId/resume/cancel` — false when no resume was scheduled for the task. */
|
|
4888
|
-
interface CancelResumeResponse {
|
|
4889
|
-
cancelled: boolean;
|
|
4890
|
-
}
|
|
4891
|
-
interface TaskMessageResponse {
|
|
4892
|
-
id: string;
|
|
4893
|
-
}
|
|
4894
|
-
interface ForceSendResponse {
|
|
4895
|
-
sent: boolean;
|
|
4896
|
-
}
|
|
4897
|
-
interface RemoveMessageResponse {
|
|
4898
|
-
removed: boolean;
|
|
4899
|
-
}
|
|
4900
|
-
interface MergeGateEntry {
|
|
4901
|
-
id: string;
|
|
4902
|
-
order: number;
|
|
4903
|
-
title: string;
|
|
4904
|
-
}
|
|
4905
|
-
interface MergeGateResponse {
|
|
4906
|
-
mergeGate: MergeGateEntry[];
|
|
4907
|
-
}
|
|
4908
|
-
interface IsolationDiffResponse {
|
|
4909
|
-
diff: string;
|
|
4910
|
-
}
|
|
4911
|
-
/** A merge that conflicts or is blocked is an outcome, not a refusal, so it answers 200 with the result. */
|
|
4912
|
-
type IsolationMergeResponse = IsolationMergeResult;
|
|
4913
|
-
/** A fork the daemon has already adopted. */
|
|
4914
|
-
interface ConversationForkResponse {
|
|
4915
|
-
sessionId: string;
|
|
4916
|
-
goal: string;
|
|
4917
|
-
plan: SurfacePlan;
|
|
4918
|
-
}
|
|
4919
|
-
/** A fork made by a rewind, with the full text of the message it was made just before. */
|
|
4920
|
-
interface ConversationRewindResponse extends ConversationForkResponse {
|
|
4921
|
-
rewoundMessage: string;
|
|
4922
|
-
}
|
|
4923
|
-
interface RewindTargetsResponse {
|
|
4924
|
-
targets: RewindTarget[];
|
|
4925
|
-
}
|
|
4926
|
-
interface ConversationCompactResponse extends ConversationCompaction, PlanResponse {
|
|
4927
|
-
}
|
|
4928
|
-
interface PrdResponse {
|
|
4929
|
-
prdMarkdown: string;
|
|
4930
|
-
}
|
|
4931
|
-
interface RunnerEntry {
|
|
4932
|
-
id: string;
|
|
4933
|
-
name: string;
|
|
4934
|
-
enabled: boolean;
|
|
4935
|
-
}
|
|
4936
|
-
interface RunnersResponse {
|
|
4937
|
-
runners: RunnerEntry[];
|
|
4938
|
-
orchestratorModel: string;
|
|
4939
|
-
}
|
|
4940
|
-
/** Sessions: a saved one comes off its file, a live one from the pool's store. */
|
|
4941
|
-
interface SessionResponse {
|
|
4942
|
-
meta: SessionMeta;
|
|
4943
|
-
plan: SurfacePlanState;
|
|
4944
|
-
}
|
|
4945
|
-
interface AdoptSessionResponse extends OkResponse {
|
|
4946
|
-
plan: SurfacePlan;
|
|
4947
|
-
goal: string;
|
|
4948
|
-
}
|
|
4949
|
-
interface TaskLogAttemptsResponse {
|
|
4950
|
-
attempts: number[];
|
|
4951
|
-
}
|
|
4952
|
-
interface TaskLogResponse {
|
|
4953
|
-
attempt: number;
|
|
4954
|
-
events: TaskLogEvent[];
|
|
4955
|
-
}
|
|
4956
|
-
type SessionListResponse = SessionMeta[];
|
|
4957
|
-
interface SettingsResponse {
|
|
4958
|
-
orchestratorModel: string;
|
|
4959
|
-
/** Who plans (ADR-0009) — a vendor id, or a runner serving as a harness planner. */
|
|
4960
|
-
aiProvider: PlannerBackendId;
|
|
4961
|
-
plannerThinkingEffort: string;
|
|
4962
|
-
maxParallel: number;
|
|
4963
|
-
modelAllowlist: UserSettings['modelAllowlist'];
|
|
4964
|
-
plannerModels: UserSettings['plannerModels'];
|
|
4965
|
-
/** The user's run settings (ADR-0030), each at its default until set. */
|
|
4966
|
-
run: GlobalRunSettings;
|
|
4967
|
-
}
|
|
4968
|
-
/** What `PATCH /api/settings` answers: the settings as they now stand, plus what the write itself decided. */
|
|
4969
|
-
interface SettingsUpdateResponse extends SettingsResponse {
|
|
4970
|
-
/**
|
|
4971
|
-
* Which model a planner switch landed on and why — remembered for that
|
|
4972
|
-
* backend, its catalog default, or none. Present only when the write changed
|
|
4973
|
-
* the planner; absent for every other write, where nothing was recalled.
|
|
4974
|
-
*/
|
|
4975
|
-
switchRecall?: PlannerModelRecall;
|
|
4976
|
-
/** Env keys the daemon refused to apply, so a client does not persist what the daemon would not. */
|
|
4977
|
-
rejectedEnvKeys?: string[];
|
|
4978
|
-
}
|
|
4979
|
-
interface CommandDescriptor {
|
|
4980
|
-
name: string;
|
|
4981
|
-
description: string;
|
|
4982
|
-
}
|
|
4983
|
-
interface CommandsResponse {
|
|
4984
|
-
commands: CommandDescriptor[];
|
|
4985
|
-
}
|
|
4986
|
-
interface WorkspacesResponse {
|
|
4987
|
-
workspaces: string[];
|
|
4988
|
-
}
|
|
4989
|
-
interface ApprovalsResponse {
|
|
4990
|
-
pending: PendingApproval[];
|
|
4991
|
-
approvedScopes: string[];
|
|
4992
|
-
}
|
|
4993
|
-
interface ApprovalAnswerResponse extends OkResponse {
|
|
4994
|
-
granted: boolean;
|
|
4995
|
-
decision: ApprovalDecision['decision'];
|
|
4996
|
-
}
|
|
4997
|
-
/**
|
|
4998
|
-
* Where a frame stands in its session's broadcast stream. A client holding
|
|
4999
|
-
* several sockets on one session gets every broadcast on each, and a frame's
|
|
5000
|
-
* content is no identity: two clears of a held edit are the same JSON. `seq`
|
|
5001
|
-
* rises by one per broadcast of the session for as long as the daemon runs,
|
|
5002
|
-
* whichever Session object holds the id; `stream` names the daemon process,
|
|
5003
|
-
* so a restarted daemon's numbering is never compared with the last one's.
|
|
5004
|
-
*/
|
|
5005
|
-
interface StreamStamp {
|
|
5006
|
-
stream: string;
|
|
5007
|
-
seq: number;
|
|
5008
|
-
}
|
|
5009
|
-
/** A broadcast as the session's socket carries it. Unstamped from a daemon older than the stamp. */
|
|
5010
|
-
type SessionFrame = (SessionMessage | SessionNotice) & Partial<StreamStamp>;
|
|
5011
|
-
type ApprovalRequestMessage = Extract<SessionMessage, {
|
|
5012
|
-
type: 'approval_request';
|
|
5013
|
-
}>;
|
|
5014
|
-
/**
|
|
5015
|
-
* What a session's socket sends right after `connected`: its run as it stands,
|
|
5016
|
-
* so a client that joins mid-run has the run view before the next update —
|
|
5017
|
-
* the held edit's preview included — and the planner's approval requests
|
|
5018
|
-
* still waiting, which no later frame would announce again. `seq` is the last
|
|
5019
|
-
* broadcast it accounts for. Every frame after it is a {@link SessionFrame}.
|
|
5020
|
-
*/
|
|
5021
|
-
interface RunSnapshotFrame extends Partial<StreamStamp> {
|
|
5022
|
-
type: 'run_snapshot';
|
|
5023
|
-
sessionId: string;
|
|
5024
|
-
view: RunView;
|
|
5025
|
-
/** Absent from a daemon older than the field: nothing is known, not "none waiting". */
|
|
5026
|
-
approvals?: ApprovalRequestMessage[];
|
|
5027
|
-
}
|
|
5028
|
-
|
|
5029
3604
|
/**
|
|
5030
3605
|
* Why a call on a session could not be made. Each is a class rather than a
|
|
5031
3606
|
* message so the daemon can map it to a status and a stable code in one place,
|
|
@@ -5211,7 +3786,7 @@ declare abstract class AbstractRunnerSession implements IRunnerSession {
|
|
|
5211
3786
|
abstract nativeSessionId(): string | null;
|
|
5212
3787
|
abstract commands(): RunnerCommand[];
|
|
5213
3788
|
abstract invokeCommand(name: string, args?: string): string;
|
|
5214
|
-
abstract answerPermission(id: string, decision: ApprovalDecision): boolean
|
|
3789
|
+
abstract answerPermission(id: string, decision: ApprovalDecision): boolean | Promise<boolean>;
|
|
5215
3790
|
abstract onTaskComplete(listener: (report: TaskCompleteArgs) => void): void;
|
|
5216
3791
|
abstract onToolCheckpoint(handler: (question: string, signal: AbortSignal) => Promise<CheckpointAnswer>): void;
|
|
5217
3792
|
}
|
|
@@ -5268,6 +3843,8 @@ declare class StructuredSession extends AbstractRunnerSession {
|
|
|
5268
3843
|
private readonly text;
|
|
5269
3844
|
private state;
|
|
5270
3845
|
private turn;
|
|
3846
|
+
/** A terminal event ends the turn before the adapter releases its send. */
|
|
3847
|
+
private sending;
|
|
5271
3848
|
private turnCount;
|
|
5272
3849
|
private queue;
|
|
5273
3850
|
private messageCount;
|
|
@@ -5349,7 +3926,7 @@ declare class StructuredSession extends AbstractRunnerSession {
|
|
|
5349
3926
|
queued(): QueuedTaskMessage[];
|
|
5350
3927
|
nativeSessionId(): string | null;
|
|
5351
3928
|
sessionCost(): RunnerSessionCost | null;
|
|
5352
|
-
answerPermission(id: string, decision: ApprovalDecision): boolean
|
|
3929
|
+
answerPermission(id: string, decision: ApprovalDecision): boolean | Promise<boolean>;
|
|
5353
3930
|
/** Every open request goes unanswered once the process that asked is gone. */
|
|
5354
3931
|
private withdrawPermissions;
|
|
5355
3932
|
interrupt(): Promise<void>;
|
|
@@ -5848,4 +4425,4 @@ declare const DEFAULT_MAX_PARALLEL = 5;
|
|
|
5848
4425
|
*/
|
|
5849
4426
|
declare function parseMaxParallel(value: unknown): number | null;
|
|
5850
4427
|
|
|
5851
|
-
export { ALL_PROVIDERS, AbstractRunner, AbstractRunnerSession, type
|
|
4428
|
+
export { ALL_PROVIDERS, AbstractRunner, AbstractRunnerSession, type Adr0013IsolationRun, type Adr0013PlanIsolation, type Adr0013TaskRecord, AgentAdapter, AgentEvent, AgentProcessDeps, AgentStartOptions, AiProvider, AlreadyExecutingError, ApprovalAnswer, ApprovalDecision, ApprovalModeSetting, ApprovalPolicy, AssignmentScope, BaseAiService, BaseConfig, BaseFileSystem, BufferedTaskOutputSource, type ByPlannerBackend, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CMD_EXE_MAX_COMMAND_LINE, CODEX_SANDBOX_DOCS, CODEX_SANDBOX_OFF_LINE, type CachedPage, type CappedRows, CheckpointAnswer, type CheckpointListener, ClaudeCodeAdapter, CodexAdapter, CodexSandboxAvailability, CommandLineTooLongError, type CommandOutcome, type CommandPayload, type ConfiguredPlanner, type Consent, ConsoleLogger, ContextCollector, type Continuability, ConversationCompaction, type ConversationFork, ConversationRequest, type ConversationRewind, ConversationTurn, DAEMON_SUBPROTOCOL, DAEMON_TOKEN_SUBPROTOCOL_PREFIX, DEFAULT_MAX_PARALLEL, type DirEntry, DiscoveredModel, DuckDuckGoSearchProvider, EmbeddedNewlineError, type EnvAdmission, EnvConfig, type ExecImpl, ExecutableNotFoundError, ExecutionActor, type ExecutionCommand, ExecutionCommandName, ExecutionCommands, type ExecutionHost, ExecutionRecord, FindSymbolOptions, GREP_PCRE_PROBE_ARGS, GeminiService, type GitExecFn, GlobOptions, GlobalRunSettings, type GrepInvocation, GrepOptions, type GrepRegex, GuardTarget, GuardTrip, HARNESS_PLANNER_REASON, type HasBinFn, HttpWebFetcher, type HttpWebFetcherOptions, IAiService, IApproval, IConfig, IFileSystem, type ILogger, INotification, IRunner, IRunnerSession, type ISearchProvider, IWorktreeIsolation, IsolationLandedTask, IsolationMergeResult, IsolationTaskStatus, IsolationView, type KillTreeDeps, type LaunchDeps, type LaunchPlan, LegacyPlanState, LiveTail, LiveTailOptions, type LoopGuard, type MappedTool, type MergeWordingHandoff, ModelResolver, type ModelResolverDeps, NoPlanError, OPENCODE_MANIFEST, ORDEWELL_SETTABLE_ENV, OpenAiService, OpenCodeAdapter, OrchestratorObserver, OrchestratorOption, OrdewellMcpServer, PROVIDER_CREDENTIAL_ENV, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, PendingApproval, PendingApprovals, PlanEditError, PlanIsolation, type PlanRequest, PlanState, PlanStore, Planner, type PlannerBackendEntry, PlannerBackendId, type PlannerChoice, PlannerModelCandidate, type PlannerModelLookup, PlannerModelRecall, type PlannerModelSource, PlannerModelStore, type PlannerSelectionChange, type PlannerSelectionCurrent, type PlannerSelectionResult, type PlannerSelectionState, PlannerToolHandler, type PlannerUsability, PlannerUsage, type PrdBlock, ProviderModelLists, type ProviderRegistration, QueuedTaskMessage, ReadFileOpts, type ResearchChat, ResearchLogEntry, ResearchShell, type ResearchTurn, type ResolvedChoice, type ResolvedPlanner, RewindTarget, RunMergeView, RunView, RunnerApprovals, RunnerCommand, RunnerId, RunnerInstallation, RunnerManifest, RunnerModeInfo, RunnerRegistry, RunnerSessionCost, type RunnerSpawnOptions, SETTINGS_ENV_ALLOWLIST, SETTINGS_ENV_REFUSED, STATE_DIR, STATE_DIR_IGNORE, STOPPED_TOOL_RESULT, SUPERVISOR_LEVELS, SYMBOL_LANGUAGES, type SaveSession, type SearchHit, type SearchOutcome, type SearchPage, type SearchTransport, Session, SessionBroadcaster, type SessionDeps, SessionMessage, SessionMeta, SessionNotFoundError, SessionNotice, type SessionPlanner, type SessionRuntimeSettings, SkillsService, type SpawnSpec, StartAdmission, StdioAgentAdapter, StructuredEvent, StructuredRunner, type StructuredRunnerDeps, StructuredSession, StructuredTurnEnd, SupervisorLevel, type SupervisorPolicy, Task, TaskCompleteArgs, TaskLogEvent, type TaskLogFile, type TaskLogLocation, TaskLogRecorder, type TaskLogRecorderDeps, TaskMessageFrom, TaskModeAgentAdapter, TaskOrchestrator, TaskOutputSource, TaskQueryCatalog, TaskRunnerFlags, TaskStartOptions, TaskTokenScope, type TokenCarriers, type ToolCall, ToolOutcome, type ToolResult, UsageRecord, UserSettings, VerdictEngine, type VerdictListener, WINDOWS_MAX_COMMAND_LINE, WebRead, WebReadDecision, type WebResponse, WebResponseCache, type WebResponseCacheOptions, type WebTransport, type WorkspaceCheckDeps, WorkspaceNotAProjectError, WorkspaceNotFoundError, type WorkspaceProjectCheckDeps, type WorktreeIsolationDeps, admitSettingsEnv, applyHeadLimit, assertWorkspaceExists, assertWorkspaceIsProject, augmentedPath, bearerHeaderValue, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, canContinue, checkoutRule, clearAugmentedPathCache, clearDaemonToken, clearState, clipboardCopyCommand, codexSandboxNotice, configuredProviders, continuability, createSession, createTaskAdapter, createWorktreeIsolation, daemonTokenPath, defaultEnabledRunners, defaultLogger, definitionPattern, deleteSession, describeMergeResult, detectInstalledPlanner, discoverGeminiModels, ensureDir, ensurePrivateDir, ensureStateDirIgnored, extractPrdBlock, extractPresentedToken, filterFallbackByAnchoredInclude, findInstalledPlanner, formatSearchOutput, getLatestSession, getProviderMeta, getStateDir, globalDataDir, grantScopeFor, grepRegexFromProbe, idSegment, includeGlobFor, installedPlannerAnswered, installedPlannerDetected, isApiProvider, isCliProvider, isExecutableResolved, isOpenAiProvider, isPlannerBackend, isRepoGroup, isVendorModelFor, killTree, languageForId, listSessions, listTaskLogAttempts, listTree, loadSession, loadSessionPlanState, loadState, looksLikeChallenge, mapAgentTool, mergeTarget, migrateOldConfigDir, migratePlanIsolation, mintDaemonToken, mintSessionId, normalizeAgentArgs, normalizeGeminiModel, openTaskLog, parseMaxParallel, parseSearchHits, planDirectLaunch, plannerBackendEntries, prefixModelId, providerForRunner, readDaemonToken, readTaskLog, recordInstalledPlanner, recordedInstalledPlanner, referencePattern, removedPluginNotice, reposWithWork, resetInstalledPlanner, resolveProviderFromPrefix, resolveTaskRunnerFlags, resolveWithin, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, selectPlanner, sessionDataDir, sessionRuntimeSettings, sharedSearchProvider, sharedWebResponseCache, stateExists, stripAnsi, stripModelPrefix, supportsTaskMode, tokenSubprotocols, tokensMatch, wellKnownBinDirs, windowsCommandLine, withPath, writePrivateFile };
|