@ordewell/core 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/{IFileSystem-BnLh-_SK.d.mts → IFileSystem-D96mT-bm.d.ts} +1 -1
- package/dist/{IFileSystem-DofiRcCo.d.ts → IFileSystem-DXJCRw5x.d.mts} +1 -1
- package/dist/IRunner-CGCihlGQ.d.ts +1165 -0
- package/dist/IRunner-XVUddYVX.d.mts +1165 -0
- package/dist/{ModeResolver-DkMYf4uS.d.ts → ModeResolver-DE-o2lRF.d.mts} +2 -2
- package/dist/{ModeResolver-DZzJSdIU.d.mts → ModeResolver-EWlpmVAy.d.ts} +2 -2
- package/dist/Task-1Q19y7sZ.d.mts +1122 -0
- package/dist/Task-1Q19y7sZ.d.ts +1122 -0
- package/dist/{chunk-ZV5LDNCO.mjs → chunk-2M4X3VB7.mjs} +18 -6
- package/dist/chunk-2M4X3VB7.mjs.map +1 -0
- package/dist/{chunk-Y36NIASW.mjs → chunk-BLLIBCCS.mjs} +153 -264
- package/dist/chunk-BLLIBCCS.mjs.map +1 -0
- package/dist/chunk-H5O74L77.mjs +185 -0
- package/dist/chunk-H5O74L77.mjs.map +1 -0
- package/dist/{chunk-LGQNXPBX.mjs → chunk-UUU46PVQ.mjs} +72 -192
- package/dist/chunk-UUU46PVQ.mjs.map +1 -0
- package/dist/index.d.mts +1119 -930
- package/dist/index.d.ts +1119 -930
- package/dist/index.js +8361 -8849
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8197 -8614
- package/dist/index.mjs.map +1 -1
- package/dist/order-labels.d.mts +1 -4
- package/dist/order-labels.d.ts +1 -4
- package/dist/{parsing-ddZXZFP4.d.ts → parsing-CZdp2p_n.d.ts} +5 -3
- package/dist/{parsing-B6ctfF80.d.mts → parsing-GgUJoYKs.d.mts} +5 -3
- package/dist/parsing.d.mts +3 -6
- package/dist/parsing.d.ts +3 -6
- package/dist/parsing.js +25 -4
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +3 -2
- package/dist/{plan-utils-CKgNtDwQ.d.mts → plan-utils-BMayhGBj.d.mts} +89 -14
- package/dist/{plan-utils--kQRzSE-.d.ts → plan-utils-Cv48fe7r.d.ts} +89 -14
- package/dist/plan-utils.d.mts +4 -4
- package/dist/plan-utils.d.ts +4 -4
- package/dist/plan-utils.js +128 -65
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +10 -2
- package/dist/testing.d.mts +12 -24
- package/dist/testing.d.ts +12 -24
- package/dist/testing.js +29 -29
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +21 -27
- package/dist/testing.mjs.map +1 -1
- package/package.json +1 -1
- package/skills/tdd/SKILL.md +19 -0
- package/dist/Task-BnLxkVQF.d.mts +0 -2594
- package/dist/Task-BnLxkVQF.d.ts +0 -2594
- package/dist/chunk-LGQNXPBX.mjs.map +0 -1
- package/dist/chunk-Y36NIASW.mjs.map +0 -1
- package/dist/chunk-ZV5LDNCO.mjs.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import {
|
|
4
|
-
export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DiffRow, e as DiffRowKind, f as DiffStat, g as DisplayBlock, E as EMPTY_CONVERSATION, h as EMPTY_HOLD, i as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry,
|
|
5
|
-
import { I as IFileSystem, R as ReadFileOpts, T as ToolOutcome, b as GrepOptions, a as GlobOptions, F as FindSymbolOptions } from './IFileSystem-
|
|
6
|
-
export { G as GREP_DEFAULT_HEAD_LIMIT, c as GrepOutputMode, S as SEARCH_EXCLUSIONS } from './IFileSystem-
|
|
7
|
-
import {
|
|
8
|
-
export {
|
|
1
|
+
import { W as RunnerId, E as PlanStatus, L as LegacyPlanState, n as IsolationMergeResult, j as IsolationLandedTask, I as IWorktreeIsolation, w as IsolationTaskStatus, P as PlanIsolation, a3 as SkillsService, _ as SkillInfo, N as RepoGroupLayout, c as DiscoveredModel, a9 as Task, S as ResearchProgress, O as ResearchLogEntry, C as ConversationMessage, ao as UsageRecord, ah as TaskSnapshot, a as AwaitingReason, g as IsolationHandoff, s as IsolationRun, t as IsolationTaskRecord, aa as TaskIsolation, x as IsolationView, o as IsolationOutcome, K as RepairEvidence, am as TreeSnapshot, av as Verdict, ag as TaskSkillSnapshot, $ as SkillLoad, Q as QueuedMessage, A as ActiveTaskSession, V as ResearchToolType, G as PlannerUsage, z as PlanState } from './Task-1Q19y7sZ.js';
|
|
2
|
+
export { B as BUILTIN_SKILL_NAMES, D as DEFAULT_RUNNERS, b as DiscoveredMode, d as IntegrationDisposal, e as InvalidSkill, f as IsolationAvailability, h as IsolationHandoffRepo, i as IsolationInactiveReason, k as IsolationLanding, l as IsolationMergeBlock, m as IsolationMergeBlockReason, p as IsolationPruneResult, q as IsolationRemoval, r as IsolationRepo, u as IsolationTaskRef, v as IsolationTaskRepo, M as Message, y as PlanModificationWarnings, F as PlannerTaskView, H as PreparedTask, J as PreservedWork, R as RefusedRemoval, T as ResearchStep, U as ResearchStepOutcome, X as ShadowedSkill, Y as SkillAppliesTo, Z as SkillCatalog, a0 as SkillLoadNotice, a1 as SkillMetadata, a2 as SkillSource, a4 as StreamEvent, a5 as StreamStepEvent, a6 as StreamThinkingEvent, a7 as SubagentLogEntry, a8 as SubagentOutcome, ab as TaskIsolationState, ac as TaskMode, ad as TaskModelAssignment, ae as TaskOutputSummary, af as TaskSkillNotice, ai as TaskStatus, aj as TaskType, ak as TaskWithParent, al as ThinkingBlock, an as UsageLine, ap as UsageTotals, aq as UserPromptEntry, ar as UserStep, as as ValidationCheck, at as ValidationContext, au as ValidationResult, aw as VerificationCheck, ax as addPlannerUsage, ay as addTaskToPlan, az as addUsage, aA as createEmptyPlan, aB as createSkillsService, aC as createTask, aD as emptyWarnings, aE as flattenTasks, aF as flattenTasksWithParents, aG as inheritedOps, aH as inheritedSkills, aI as isAwaitingReason, aJ as isMeasured, aK as isSkillName, aL as isUserMessage, aM as keepExecutionState, aN as migrateLegacyPlan, aO as migrateLoadedTasks, aP as migratePlanState, aQ as migrateTask, aR as opsFlag, aS as partedPromptUsage, aT as plannerContextFill, aU as plannerTaskView, aV as removeTaskFromPlan, aW as renumberTasks, aX as skillNames, aY as updateTaskInPlan, aZ as usageLine, a_ as validateModifiedPlan, a$ as warningsText } from './Task-1Q19y7sZ.js';
|
|
3
|
+
import { R as TaskOp, M as MergeGateView, j as EditCatalog, u as SessionBroadcaster, A as ApplyTaskOpsResult, w as SessionNotice, v as SessionMessage, K as TaskLogEvent, H as SurfacePlan, I as SurfacePlanState } from './plan-utils-Cv48fe7r.js';
|
|
4
|
+
export { a as ApprovalBlock, b as ApprovalStatus, C as CHECKPOINT_TRUNCATE_LENGTH, c as ConversationInput, d as ConversationView, D as DiffRow, e as DiffRowKind, f as DiffStat, g as DisplayBlock, E as EMPTY_CONVERSATION, h as EMPTY_HOLD, i as EMPTY_TASK_LOG, G as GatedConversation, L as LocalEntry, k as MessageBlock, l as MessageRole, N as NOT_STARTED, m as NO_TURN, n as NewTaskFields, O as OutputPreview, P as PlanBlock, o as PlanMarkerStatus, p as PromptHold, S as SerializedConversationMessage, q as SerializedPlan, r as SerializedQueuedMessage, s as SerializedTask, t as SerializedTaskStatus, x as SkillLoadBlock, y as SkillToken, z as SubagentBlock, B as SubagentChild, F as SubagentStatus, J as SurfaceTask, T as TakenPrompt, Q as TaskLogView, U as TaskRef, V as TaskRowAction, W as TaskRowContext, X as TaskRowIsolation, Y as TaskRowKind, Z as TaskRowPlacement, _ as TaskRowSubject, $ as TaskRowView, a0 as TaskStatusKind, a1 as ThinkingDisplayBlock, a2 as ToolBlock, a3 as ToolHeadline, a4 as ToolStatus, a5 as TurnGate, a6 as UsageBlock, a7 as aheadOfDraft, a8 as applyTaskOps, a9 as approvalLabel, aa as awaitingLabel, ab as canMergeTasks, ac as canSetDependencies, ad as canSplitTask, ae as capConflictFiles, af as classifyOutcome, ag as coalesceTaskLog, ah as dependencyCandidates, ai as dependentsNotice, aj as dependentsOf, ak as diffRows, al as diffStat, am as diffSummary, an as digestTaskLog, ao as drainNext, ap as executionSummary, aq as followTurn, ar as fromTranscript, as as hasHiddenDetail, at as holdPrompt, au as isTaskRunning, av as loadedSkillTokens, aw as markAction, ax as markRequestFor, ay as namedRepos, az as newTaskFields, aA as opsEditable, aB as outputLines, aC as outputPreview, aD as parseTaskOpsJson, aE as pastGateConfirmation, aF as reduceConversation, aG as reduceTaskLog, aH as replayTaskLog, aI as runnerToolSubject, aJ as serializePlan, aK as serializeTask, aL as serializeTaskStatus, aM as skillTokens, aN as stopTurn, aO as summarizeToolCall, aP as surfacePlan, aQ as surfacePlanState, aR as taskLogForSurface, aS as taskRowActions, aT as taskRowView, aU as taskStartedNotice, aV as taskStatusKind, aW as textHasTaskOps, aX as titledRefs, aY as toTaskLogEvent, aZ as toolHeadline, a_ as trimToolOutput, a$ as truncateCheckpointSummary, b0 as unsendAll, b1 as unsendLatest } from './plan-utils-Cv48fe7r.js';
|
|
5
|
+
import { I as IFileSystem, R as ReadFileOpts, T as ToolOutcome, b as GrepOptions, a as GlobOptions, F as FindSymbolOptions } from './IFileSystem-D96mT-bm.js';
|
|
6
|
+
export { G as GREP_DEFAULT_HEAD_LIMIT, c as GrepOutputMode, S as SEARCH_EXCLUSIONS } from './IFileSystem-D96mT-bm.js';
|
|
7
|
+
import { I as IApproval, m as ApprovalRequest, h as ApprovalDecision, g as ApprovalAnswer, s as IRunner, r as IConfig, e as AiProvider, W as ProviderModelLists, j as ApprovalMode, t as IRunnerSession, c as AgentProcessDeps, A as AgentAdapter, P as OrdewellMcpServer, U as PlannerToolHandler, a2 as RunnerRegistry, Y as QueuedTaskMessage, N as OrchestratorOption, aa as TaskModeAgentAdapter, d as AgentStartOptions, b as AgentEvent, k as ApprovalPolicy, a9 as TaskCompleteArgs, o as CheckpointAnswer, a5 as StructuredTurnEnd, a4 as StructuredEvent, af as TaskStartOptions, ag as TaskTokenScope, $ as RunnerManifest, ae as TaskRunnerFlags } from './IRunner-CGCihlGQ.js';
|
|
8
|
+
export { a as AgentAdapterFactory, f as AllProviderModels, i as ApprovalKind, l as ApprovalPolicyOptions, n as ApprovalSource, C as CatalogModel, p as CheckpointArgs, D as DENY_ALL, q as DiscoveryCommand, E as EditPlanArgs, F as FetchAllProviderModelsOptions, L as LineBuffer, u as ListModelsArgs, v as ListRunnersArgs, w as LoadSkillArgs, M as McpClientConfig, x as McpCredential, y as McpTool, z as McpToolContext, B as McpToolReply, G as ModelCatalog, H as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, J as ORDEWELL_MCP_PATH, K as ORDEWELL_MCP_SERVER_NAME, Q as OwnerOnlyFile, R as PLANNER_TOOLS, S as PlannerStartOptions, T as PlannerTokenScope, V as ProviderCredentialSource, X as ProviderModelsResult, Z as RunnerEntry, _ as RunnerFeatures, a0 as RunnerMode, a1 as RunnerModelDiscovery, a3 as SpawnFn, a6 as SubmitPlanArgs, a7 as TASK_COMPLETE_TOOL, a8 as TASK_TOOLS, ab as TaskModeUnsupportedError, ac as TaskOutputArgs, ad as TaskQueryArgs, ah as TaskToolHandler, ai as approvalScopes, aj as collectProviderCredentials, ak as enabledRunners, al as fetchAllProviderModels, am as isGranted, an as isRunnerApproval, ao as knownModelId, ap as mcpClientConfig, aq as ownerOnlyConfigFile, ar as resolveModelShortcut, as as resolveProvider, at as sharedMcpServer, au as toApprovalDecision, av as toOrchestratorOptions } from './IRunner-CGCihlGQ.js';
|
|
9
|
+
import { R as RunnerModeInfo } from './ModeResolver-EWlpmVAy.js';
|
|
10
|
+
export { M as ManifestLookup, a as autonomyLevelLabel, b as buildModeGuide, f as filteredBuildModes, p as parseAutonomyLevel, r as resolveDefaultMode, c as resolveTaskMode, d as runnerModesFrom } from './ModeResolver-EWlpmVAy.js';
|
|
9
11
|
import { ChildProcess } from 'child_process';
|
|
10
|
-
import { b as PlanParseError } from './parsing-
|
|
11
|
-
export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, c as PlanTaskError, d as PlanTasksResult, T as TASK_OPS_ENVELOPE_KEY, e as TASK_QUERY_ENVELOPE_KEY, f as checkDepsResolve, g as checkImmutableLog, h as checkInProgress, i as checkNoCycles, j as checkUniqueIds, k as escapeControlCharsInStrings, l as extractJsonObject, m as extractObjectWithBalance, n as extractObjectsWithKey, o as looksLikePlanAttempt, p as opensWithJsonObject, q as parsePartialPlan, r as parsePlanJson, s as
|
|
12
|
+
import { b as PlanParseError } from './parsing-CZdp2p_n.js';
|
|
13
|
+
export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, c as PlanTaskError, d as PlanTasksResult, T as TASK_OPS_ENVELOPE_KEY, e as TASK_QUERY_ENVELOPE_KEY, f as checkDepsResolve, g as checkImmutableLog, h as checkInProgress, i as checkNoCycles, j as checkUniqueIds, k as escapeControlCharsInStrings, l as extractJsonObject, m as extractObjectWithBalance, n as extractObjectsWithKey, o as looksLikePlanAttempt, p as opensWithJsonObject, q as parsePartialPlan, r as parsePlanJson, s as requestedSkills, t as stripModelNoise, u as stripTrailingCommas, v as validatePlanModification, w as validatePlanTasks } from './parsing-CZdp2p_n.js';
|
|
14
|
+
import { EventEmitter } from 'events';
|
|
12
15
|
export { resolveOrderLabel, taskOrderLabel, taskRef, titledTaskRef } from './order-labels.js';
|
|
13
|
-
import 'events';
|
|
14
16
|
import 'zod/v4';
|
|
15
17
|
|
|
16
18
|
interface SessionMeta {
|
|
@@ -410,7 +412,7 @@ declare class RunnerApprovals {
|
|
|
410
412
|
/** The open request ids of each live structured session. */
|
|
411
413
|
private readonly open;
|
|
412
414
|
constructor(approvals: PendingApprovals);
|
|
413
|
-
wrap(runner:
|
|
415
|
+
wrap(runner: IRunner): IRunner;
|
|
414
416
|
/** How many of a task's runner requests wait for an answer — what "waiting for approval" is derived from. */
|
|
415
417
|
waiting(taskId: string): number;
|
|
416
418
|
private watch;
|
|
@@ -650,6 +652,7 @@ type GitExecFn = (file: string, args: string[], opts: {
|
|
|
650
652
|
stdout: string;
|
|
651
653
|
stderr: string;
|
|
652
654
|
}>;
|
|
655
|
+
|
|
653
656
|
interface WorktreeIsolationDeps {
|
|
654
657
|
config: Pick<IConfig, 'worktreeIsolation' | 'worktreeSetupCommand' | 'workspaceRepos' | 'worktreeLinks'>;
|
|
655
658
|
/** Test seam: every git invocation goes through this. */
|
|
@@ -699,86 +702,31 @@ declare class ConsoleLogger implements ILogger {
|
|
|
699
702
|
}
|
|
700
703
|
declare const defaultLogger: ILogger;
|
|
701
704
|
|
|
702
|
-
interface UserSettings {
|
|
703
|
-
tdd: {
|
|
704
|
-
enabled: boolean;
|
|
705
|
-
};
|
|
706
|
-
verification: {
|
|
707
|
-
enabled: boolean;
|
|
708
|
-
};
|
|
709
|
-
modelAllowlist?: Record<string, string[]>;
|
|
710
|
-
/** Last model (and its thinking effort) the user chose for each planner backend, keyed by AiProvider id. */
|
|
711
|
-
plannerModels?: Record<string, {
|
|
712
|
-
model: string;
|
|
713
|
-
effort?: string;
|
|
714
|
-
}>;
|
|
715
|
-
/**
|
|
716
|
-
* Runners the user picked for planning. Absent — not empty — is what falls
|
|
717
|
-
* back to the environment's defaults; `[]` is a deliberate "none of them".
|
|
718
|
-
*/
|
|
719
|
-
enabledRunners?: string[];
|
|
720
|
-
/**
|
|
721
|
-
* How tasks' runners are driven (ADR-0018). A run copies it onto its plan
|
|
722
|
-
* when it starts, so a change applies from the next run.
|
|
723
|
-
*/
|
|
724
|
-
runnerTransport: RunnerTransport;
|
|
725
|
-
}
|
|
726
705
|
/**
|
|
727
|
-
*
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
* harness
|
|
731
|
-
* `getAll()` re-reads whenever the mtime moves, a lane needing a toggle
|
|
732
|
-
* `true` would silently plan with `false` the moment another lane pinned its
|
|
733
|
-
* own — turning an A/B of that toggle into a comparison of one condition
|
|
734
|
-
* against itself.
|
|
706
|
+
* Task skills end to end (ADR-0024): a skill reaches a runner only by being
|
|
707
|
+
* attached to its task in the plan, and Ordewell puts its body in the task's
|
|
708
|
+
* prompt — so it works the same on every runner, and nothing is written to a
|
|
709
|
+
* harness's own skills directory.
|
|
735
710
|
*/
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
private filePath;
|
|
739
|
-
private cache;
|
|
740
|
-
private cachedMtimeMs;
|
|
711
|
+
/** Where a task's skill names are looked up: global first, then the workspace folders it reads. */
|
|
712
|
+
interface SkillLookup extends Pick<SkillsService, 'findSkill' | 'searchedDirs'> {
|
|
741
713
|
/**
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
714
|
+
* Set when tasks get worktrees: of `skills`, the workspace ones git will not
|
|
715
|
+
* carry into them, each SKILL.md path mapped to the folder to commit,
|
|
716
|
+
* relative to the workspace root.
|
|
745
717
|
*/
|
|
746
|
-
|
|
747
|
-
constructor(filePath?: string);
|
|
748
|
-
getAll(): UserSettings;
|
|
749
|
-
private fileMtimeMs;
|
|
750
|
-
getTdd(): boolean;
|
|
751
|
-
setTdd(enabled: boolean): void;
|
|
752
|
-
getVerification(): boolean;
|
|
753
|
-
setVerification(enabled: boolean): void;
|
|
754
|
-
getRunnerTransport(): RunnerTransport;
|
|
755
|
-
setRunnerTransport(transport: RunnerTransport): void;
|
|
756
|
-
getModelAllowlist(runner: string): string[] | undefined;
|
|
757
|
-
setModelAllowlist(runner: string, ids: string[] | undefined): void;
|
|
758
|
-
getPlannerModel(provider: string): {
|
|
759
|
-
model: string;
|
|
760
|
-
effort?: string;
|
|
761
|
-
} | undefined;
|
|
762
|
-
setPlannerModel(provider: string, entry: {
|
|
763
|
-
model: string;
|
|
764
|
-
effort?: string;
|
|
765
|
-
} | undefined): void;
|
|
766
|
-
getEnabledRunners(): string[] | undefined;
|
|
767
|
-
setEnabledRunners(ids: string[]): void;
|
|
768
|
-
private load;
|
|
769
|
-
private persist;
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
/** How the same toggle is named once a host has read it off disk. */
|
|
773
|
-
interface PlannerRuntimeToggles {
|
|
774
|
-
tddEnabled: boolean;
|
|
775
|
-
verificationEnabled: boolean;
|
|
718
|
+
uncommitted?(skills: readonly SkillInfo[]): Promise<Map<string, string>>;
|
|
776
719
|
}
|
|
777
720
|
/**
|
|
778
|
-
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
721
|
+
* Where a workspace's skills are read, known without asking git: the repos
|
|
722
|
+
* of its group in layout order (`['.']` for one repository), and whether
|
|
723
|
+
* tasks will get worktrees, which only a committed skill reaches.
|
|
781
724
|
*/
|
|
725
|
+
interface SkillLayout {
|
|
726
|
+
repos: readonly string[];
|
|
727
|
+
worktrees: boolean;
|
|
728
|
+
}
|
|
729
|
+
|
|
782
730
|
/**
|
|
783
731
|
* Where the run's tasks will work: `false` in the shared workspace root;
|
|
784
732
|
* otherwise each in its own worktree of every repo of the group (ADR-0013,
|
|
@@ -787,47 +735,24 @@ interface PlannerRuntimeToggles {
|
|
|
787
735
|
type IsolatedExecution = false | RepoGroupLayout;
|
|
788
736
|
interface PlannerModes {
|
|
789
737
|
autonomousDefault: boolean;
|
|
790
|
-
verification: boolean;
|
|
791
738
|
/** Not a toggle: a fact about the run. */
|
|
792
739
|
isolatedExecution: IsolatedExecution;
|
|
740
|
+
/**
|
|
741
|
+
* Where the run's tasks will look their skills up (ADR-0024), also a fact
|
|
742
|
+
* about the run. A plan attaching a planner skill is refused against it,
|
|
743
|
+
* and a coding agent's submit_plan call is refused in its turn rather than
|
|
744
|
+
* accepted and then failed. Absent: the plan is not checked.
|
|
745
|
+
*/
|
|
746
|
+
taskSkills?: SkillLookup;
|
|
793
747
|
}
|
|
794
748
|
|
|
795
|
-
/** Context of one task attempt, enough to locate its transcript. */
|
|
796
|
-
interface TranscriptQuery {
|
|
797
|
-
runner: string;
|
|
798
|
-
/** The task's working directory (the agent's cwd at spawn). */
|
|
799
|
-
cwd: string;
|
|
800
|
-
/** When the agent process started, ISO — used to reject older sessions. */
|
|
801
|
-
startedAt?: string;
|
|
802
|
-
/**
|
|
803
|
-
* The task's completion marker UUID. The prompt carries it, so a transcript
|
|
804
|
-
* that does not contain it belongs to some other task — parallel attempts in
|
|
805
|
-
* one cwd are otherwise indistinguishable by directory and recency.
|
|
806
|
-
*/
|
|
807
|
-
marker: string;
|
|
808
|
-
}
|
|
809
|
-
/** Reads the agent's own session transcript for a task's final answer. */
|
|
810
|
-
interface TranscriptReader {
|
|
811
|
-
/** Last assistant-authored prose, clamped to `maxChars` from the end, or null. */
|
|
812
|
-
finalAssistantText(query: TranscriptQuery, maxChars?: number): Promise<string | null>;
|
|
813
|
-
}
|
|
814
|
-
/** The part of a task attempt its output is looked up by. */
|
|
815
|
-
interface TaskOutputAttempt {
|
|
816
|
-
readonly taskId: string;
|
|
817
|
-
readonly runner: string;
|
|
818
|
-
/** Null when the attempt ended before its working directory was settled. */
|
|
819
|
-
readonly cwd: string | null;
|
|
820
|
-
readonly startedAt: string;
|
|
821
|
-
/** The completion marker UUID the attempt's prompt carried. */
|
|
822
|
-
readonly completionMarker: string;
|
|
823
|
-
}
|
|
824
749
|
interface LiveTailOptions {
|
|
825
750
|
maxLines: number;
|
|
826
751
|
/** A previous {@link LiveTail.nextOffset}: only output after it is rendered. */
|
|
827
752
|
sinceOffset?: number;
|
|
828
753
|
}
|
|
829
754
|
interface LiveTail {
|
|
830
|
-
/**
|
|
755
|
+
/** Plain text, escapes and control characters removed. */
|
|
831
756
|
text: string;
|
|
832
757
|
/** Total output received so far; pass it back as `sinceOffset` to read only what follows. */
|
|
833
758
|
nextOffset: number;
|
|
@@ -839,13 +764,13 @@ interface LiveTail {
|
|
|
839
764
|
*/
|
|
840
765
|
interface TaskOutputSource {
|
|
841
766
|
/** Start capturing a session; replaces any earlier capture of the task. */
|
|
842
|
-
attach(taskId: string, session:
|
|
767
|
+
attach(taskId: string, session: IRunnerSession): void;
|
|
843
768
|
/** Stop capturing the task's session; what was captured stays readable. */
|
|
844
769
|
detach(taskId: string): void;
|
|
845
770
|
/** Drop every capture (a new plan reuses task ids). */
|
|
846
771
|
reset(): void;
|
|
847
|
-
/** The
|
|
848
|
-
finalText(
|
|
772
|
+
/** The task's final answer: the summary its runner reported through `task_complete`, else what its last turn said. */
|
|
773
|
+
finalText(taskId: string): string;
|
|
849
774
|
/** Recent output of the task's latest capture, or null if it never had one. */
|
|
850
775
|
liveTail(taskId: string, opts: LiveTailOptions): LiveTail | null;
|
|
851
776
|
}
|
|
@@ -865,7 +790,7 @@ interface TaskOutputSource {
|
|
|
865
790
|
* lives in PlanRepair alongside the plan and task-ops envelopes.
|
|
866
791
|
*/
|
|
867
792
|
/** The long fields a query may ask for. Everything else is already in the plan block. */
|
|
868
|
-
declare const TASK_QUERY_FIELDS: readonly ["description", "prompt", "userSteps", "verdict", "outputSummary", "userStoriesCovered", "output"];
|
|
793
|
+
declare const TASK_QUERY_FIELDS: readonly ["description", "prompt", "userSteps", "verdict", "outputSummary", "userStoriesCovered", "skills", "output"];
|
|
869
794
|
type TaskQueryField = typeof TASK_QUERY_FIELDS[number];
|
|
870
795
|
/** Lines a `output` read returns when the query sets no count. */
|
|
871
796
|
declare const OUTPUT_LINES_DEFAULT = 80;
|
|
@@ -936,7 +861,7 @@ interface CliAgentAiServiceDeps extends Partial<AgentProcessDeps> {
|
|
|
936
861
|
createAdapter?: (runner: string, deps: AgentProcessDeps) => AgentAdapter | null;
|
|
937
862
|
/** Workspace root the agent explores. Defaults to the host process's cwd. */
|
|
938
863
|
workspaceRoot?: () => string;
|
|
939
|
-
/** Where a conversation's planner tools are served (ADR-0022). Absent:
|
|
864
|
+
/** Where a conversation's planner tools are served (ADR-0022). Absent: no conversation can start. */
|
|
940
865
|
mcpServer?: OrdewellMcpServer;
|
|
941
866
|
}
|
|
942
867
|
/**
|
|
@@ -946,8 +871,8 @@ interface CliAgentAiServiceDeps extends Partial<AgentProcessDeps> {
|
|
|
946
871
|
* `GeminiService`. It deliberately does **not** extend {@link BaseAiService}:
|
|
947
872
|
* that class's body is Ordewell executing research tools on a model's behalf,
|
|
948
873
|
* which is precisely the part a coding agent replaces. What it reuses instead
|
|
949
|
-
* is everything above the transport — `settleReply` (reply
|
|
950
|
-
* and the
|
|
874
|
+
* is everything above the transport — `settleReply` (the empty-reply nudge
|
|
875
|
+
* and the turn's settling), the plan validator, the `ResearchProgress` events the
|
|
951
876
|
* four surfaces already render. That is why this backend reaches VS Code, the
|
|
952
877
|
* web UI, the CLI and the TUI without any of them learning a coding agent is
|
|
953
878
|
* on the other end.
|
|
@@ -969,8 +894,6 @@ declare class CliAgentAiService implements IAiService {
|
|
|
969
894
|
private readonly mcpServer;
|
|
970
895
|
/** The planner token the running process was spawned with; revoked with the process (ADR-0022, A3). */
|
|
971
896
|
private plannerToken;
|
|
972
|
-
/** Whether the running planner was spawned with its tools and the CLI reported them connected. */
|
|
973
|
-
private toolsAttached;
|
|
974
897
|
private activeAbort;
|
|
975
898
|
/**
|
|
976
899
|
* Every subagent this conversation has reported starting, and finishing.
|
|
@@ -989,7 +912,7 @@ declare class CliAgentAiService implements IAiService {
|
|
|
989
912
|
* on the old model. No conversation yet is vacuously "current".
|
|
990
913
|
*/
|
|
991
914
|
conversationMatchesConfig(): boolean;
|
|
992
|
-
/**
|
|
915
|
+
/** Always: a conversation whose planner cannot reach the Ordewell MCP server fails to start rather than falling back to the envelopes. */
|
|
993
916
|
plannerToolsAttached(): boolean;
|
|
994
917
|
/** The agent's own session id, a resumption hint only — Ordewell's transcript is authoritative (T4). */
|
|
995
918
|
nativeSessionId(): string | null;
|
|
@@ -1018,7 +941,8 @@ declare class CliAgentAiService implements IAiService {
|
|
|
1018
941
|
* mode from here without changing this signature.
|
|
1019
942
|
*/
|
|
1020
943
|
private startAdapter;
|
|
1021
|
-
|
|
944
|
+
private newAdapter;
|
|
945
|
+
/** One spawn with the Ordewell server injected: the adapter once the runner reports it connected, otherwise why not, with nothing left running. */
|
|
1022
946
|
private startWithTools;
|
|
1023
947
|
/** Kill the planner process, and with it the token it was spawned with. */
|
|
1024
948
|
private disposeAdapter;
|
|
@@ -1030,12 +954,18 @@ declare class CliAgentAiService implements IAiService {
|
|
|
1030
954
|
*/
|
|
1031
955
|
private ensureAdapter;
|
|
1032
956
|
private plannerModel;
|
|
957
|
+
/**
|
|
958
|
+
* A plan from one-shot agent sessions: only what a submit_plan call
|
|
959
|
+
* accepted, never the reply text, so a plan the tool refused cannot come
|
|
960
|
+
* back in as the JSON the agent echoed. A session that ends without an
|
|
961
|
+
* accepted call is followed by one corrective session, then fails.
|
|
962
|
+
*/
|
|
963
|
+
private submittedPlan;
|
|
1033
964
|
/**
|
|
1034
965
|
* A single agent session that answers one prompt and exits. Used by every
|
|
1035
|
-
* non-conversational entry point
|
|
1036
|
-
* the
|
|
1037
|
-
*
|
|
1038
|
-
* around it is not streamed at all, since no turn is open to show it in.
|
|
966
|
+
* non-conversational entry point. A plan-shaped envelope in its text
|
|
967
|
+
* streams to the plan display, as a vendor planner's one-shot does, and the
|
|
968
|
+
* prose around it is not streamed at all, since no turn is open to show it in.
|
|
1039
969
|
*/
|
|
1040
970
|
private oneShot;
|
|
1041
971
|
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<{
|
|
@@ -1073,7 +1003,6 @@ interface ConversationRequest {
|
|
|
1073
1003
|
fetcher?: IWebFetcher;
|
|
1074
1004
|
runnerModes?: Record<RunnerId, RunnerModeInfo[]>;
|
|
1075
1005
|
autonomousDefault?: boolean;
|
|
1076
|
-
verificationEnabled?: boolean;
|
|
1077
1006
|
/**
|
|
1078
1007
|
* The planner model's context window when the catalog knows it. Threaded here
|
|
1079
1008
|
* so a usage record can carry it (and the UI can show context fill); absent
|
|
@@ -1096,6 +1025,12 @@ interface ConversationRequest {
|
|
|
1096
1025
|
*/
|
|
1097
1026
|
initialMessage?: string;
|
|
1098
1027
|
plannerTools?: PlannerToolsOffer;
|
|
1028
|
+
/**
|
|
1029
|
+
* The workspace's skill catalog. Every planner is shown the task skills it
|
|
1030
|
+
* may attach; only one with tools is shown the planner skills, which load
|
|
1031
|
+
* through `load_skill` alone (ADR-0024).
|
|
1032
|
+
*/
|
|
1033
|
+
skills?: readonly SkillInfo[];
|
|
1099
1034
|
}
|
|
1100
1035
|
/**
|
|
1101
1036
|
* One planner turn's outcome. The planner talks to the user (`message`),
|
|
@@ -1106,10 +1041,13 @@ interface ConversationRequest {
|
|
|
1106
1041
|
* atomically and answers queries out of its own state; the AI service only
|
|
1107
1042
|
* parses them.
|
|
1108
1043
|
*/
|
|
1109
|
-
type ConversationTurn =
|
|
1044
|
+
type ConversationTurn =
|
|
1045
|
+
/** `aborted`: the call was stopped, and `text` is only what it had by then. */
|
|
1046
|
+
{
|
|
1110
1047
|
kind: 'message';
|
|
1111
1048
|
text: string;
|
|
1112
1049
|
researchLog: ResearchLogEntry[];
|
|
1050
|
+
aborted?: boolean;
|
|
1113
1051
|
} | {
|
|
1114
1052
|
kind: 'plan';
|
|
1115
1053
|
tasks: Task[];
|
|
@@ -1191,6 +1129,11 @@ interface IAiService {
|
|
|
1191
1129
|
* and cheap in every implementation, so callers never gate it.
|
|
1192
1130
|
*/
|
|
1193
1131
|
reset(): void;
|
|
1132
|
+
/**
|
|
1133
|
+
* A one-shot plan from a prompt the caller built, so built for this
|
|
1134
|
+
* planner's transport: one with {@link plannerToolsAttached} is asked for a
|
|
1135
|
+
* submit_plan call, never JSON in its reply.
|
|
1136
|
+
*/
|
|
1194
1137
|
sendPlanningPrompt(prompt: string, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean): Promise<Task[]>;
|
|
1195
1138
|
}
|
|
1196
1139
|
/**
|
|
@@ -1463,16 +1406,8 @@ declare class PlanStore {
|
|
|
1463
1406
|
unblockDependents(id: string): void;
|
|
1464
1407
|
setTaskVerdict(id: string, verdict: Task['verdict']): void;
|
|
1465
1408
|
setTaskOutputSummary(id: string, summary: Task['outputSummary']): void;
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
tasks: {
|
|
1469
|
-
id: string;
|
|
1470
|
-
title: string;
|
|
1471
|
-
dependencies: string[];
|
|
1472
|
-
parallelGroups: number[][];
|
|
1473
|
-
}[];
|
|
1474
|
-
parallelGroups: number[][];
|
|
1475
|
-
};
|
|
1409
|
+
setTaskRunnerSessionId(id: string, runnerSessionId: string | undefined): void;
|
|
1410
|
+
setTaskAttemptSkills(id: string, skills: Task['attemptSkills']): void;
|
|
1476
1411
|
/**
|
|
1477
1412
|
* Widen the plan's runner set. Retargeting a task onto a runner the plan has
|
|
1478
1413
|
* not used before has to land here as well as on the plan state, or
|
|
@@ -1493,23 +1428,12 @@ type IsolationNoticeLevel = 'info' | 'warn' | 'error';
|
|
|
1493
1428
|
interface IsolationRunListener {
|
|
1494
1429
|
/** The run record changed and should be persisted with the plan. */
|
|
1495
1430
|
changed(): void;
|
|
1496
|
-
/**
|
|
1497
|
-
* A run opened — the one moment shared by Execute, a manual task run and
|
|
1498
|
-
* a force start, so whatever a run pins for its whole length is read here.
|
|
1499
|
-
* Whether it isolates is decided later, at its first change task.
|
|
1500
|
-
*/
|
|
1501
|
-
opened(): void;
|
|
1502
1431
|
/** A run did not start: `repos` of the group have tracked changes. */
|
|
1503
1432
|
blocked(repos: string[]): void;
|
|
1504
1433
|
/** An isolated run closed and handed its integration branches over. */
|
|
1505
1434
|
handoff(handoff: IsolationHandoff): void;
|
|
1506
1435
|
/** Already said through the notifications; also for a surface that shows no toasts. */
|
|
1507
1436
|
notice(level: IsolationNoticeLevel, message: string): void;
|
|
1508
|
-
/**
|
|
1509
|
-
* These tasks' worktrees are about to be removed. An agent left running in
|
|
1510
|
-
* one would sit in a deleted directory, so it has to go first.
|
|
1511
|
-
*/
|
|
1512
|
-
releasing(taskIds: string[]): void;
|
|
1513
1437
|
}
|
|
1514
1438
|
interface IsolationRunControllerDeps {
|
|
1515
1439
|
isolation: IWorktreeIsolation;
|
|
@@ -1552,6 +1476,8 @@ declare class IsolationRunController {
|
|
|
1552
1476
|
/** Resolver task id → the conflicted task it resolves; see {@link linkResolver}. */
|
|
1553
1477
|
private resolvers;
|
|
1554
1478
|
private opening;
|
|
1479
|
+
/** Bumped by an interrupt, so an activation in flight across it does not open the run it ended. */
|
|
1480
|
+
private activations;
|
|
1555
1481
|
/** The start a dirty tree turned away, handed back once the user chooses how to go on. */
|
|
1556
1482
|
private blockedStart;
|
|
1557
1483
|
/** The dirty repos behind {@link blockedStart}, for the stash notice. */
|
|
@@ -1604,6 +1530,15 @@ declare class IsolationRunController {
|
|
|
1604
1530
|
* the safe rule then.
|
|
1605
1531
|
*/
|
|
1606
1532
|
plannerLayout(): Promise<IsolatedExecution>;
|
|
1533
|
+
/**
|
|
1534
|
+
* Where the workspace's skills are read, and whether tasks get worktrees.
|
|
1535
|
+
* Read synchronously inside a planner turn or a chip edit, so it comes from
|
|
1536
|
+
* the files, not git or the planner's last layout: a restored session is
|
|
1537
|
+
* right from its first edit. The run's repos while it isolates; otherwise
|
|
1538
|
+
* the group the workspace holds, in worktrees unless isolation is off or
|
|
1539
|
+
* this run chose to share the root.
|
|
1540
|
+
*/
|
|
1541
|
+
skillLayout(): SkillLayout;
|
|
1607
1542
|
/**
|
|
1608
1543
|
* Go on with the start a dirty tree turned away. `stash` puts the user's
|
|
1609
1544
|
* tracked changes on the git stash first, so the run isolates; `shared` runs
|
|
@@ -1746,6 +1681,10 @@ declare class IsolationRunController {
|
|
|
1746
1681
|
* whole. One that cannot be continued for another reason — it ran from a
|
|
1747
1682
|
* different workspace path — keeps its integration branch in each repo that
|
|
1748
1683
|
* has not merged it: only the user gives landed work up.
|
|
1684
|
+
*
|
|
1685
|
+
* False when `interrupted` came while git was minting: a newer activation
|
|
1686
|
+
* may be minting its own run, so this one is never installed over it, and
|
|
1687
|
+
* is discarded rather than left as branches no record names.
|
|
1749
1688
|
*/
|
|
1750
1689
|
private mint;
|
|
1751
1690
|
private reportCopies;
|
|
@@ -1897,7 +1836,7 @@ interface OrchestratorObserver {
|
|
|
1897
1836
|
}): void;
|
|
1898
1837
|
onTick?(): void;
|
|
1899
1838
|
onExecutionComplete?(): void;
|
|
1900
|
-
/**
|
|
1839
|
+
/** The run is parked behind queued user messages, with nothing live, until they are drained. */
|
|
1901
1840
|
onQueueReady?(): void;
|
|
1902
1841
|
onReviewNeeded?(data: {
|
|
1903
1842
|
tasks: Task[];
|
|
@@ -1931,8 +1870,8 @@ interface OrchestratorObserver {
|
|
|
1931
1870
|
}): void;
|
|
1932
1871
|
}
|
|
1933
1872
|
/**
|
|
1934
|
-
* A message or interrupt a task cannot take: it is not running, it
|
|
1935
|
-
*
|
|
1873
|
+
* A message or interrupt a task cannot take: it is not running, or it is
|
|
1874
|
+
* waiting on something a message does not answer.
|
|
1936
1875
|
* The request is wrong, not the orchestrator, so a surface says why.
|
|
1937
1876
|
*/
|
|
1938
1877
|
declare class TaskControlError extends Error {
|
|
@@ -1948,17 +1887,18 @@ interface TaskAttemptSnapshot {
|
|
|
1948
1887
|
runner: string;
|
|
1949
1888
|
cwd: string | null;
|
|
1950
1889
|
startedAt: string;
|
|
1890
|
+
skills: readonly TaskSkillSnapshot[];
|
|
1951
1891
|
}
|
|
1952
1892
|
/**
|
|
1953
1893
|
* The wiring a {@link TaskOrchestrator} runs on, every collaborator resolved.
|
|
1954
|
-
* {@link
|
|
1955
|
-
* through
|
|
1956
|
-
*
|
|
1894
|
+
* {@link TaskOrchestrator.compose} is the only production caller; tests build
|
|
1895
|
+
* one through it too. The constructor makes nothing itself, so there is exactly
|
|
1896
|
+
* one place defaults live.
|
|
1957
1897
|
*/
|
|
1958
1898
|
interface TaskOrchestratorDeps {
|
|
1959
1899
|
config: IConfig;
|
|
1960
1900
|
notifications: INotification;
|
|
1961
|
-
|
|
1901
|
+
runner: IRunner;
|
|
1962
1902
|
store: PlanStore;
|
|
1963
1903
|
output: TaskOutputSource;
|
|
1964
1904
|
/** The plan's isolation run and the open run's lifecycle (ADR-0013). */
|
|
@@ -1970,30 +1910,27 @@ interface TaskOrchestratorDeps {
|
|
|
1970
1910
|
workspaceRoot: () => string;
|
|
1971
1911
|
/** The workspace's own variables for a task's cwd (ADR-0016). */
|
|
1972
1912
|
workspaceEnv: (cwd: string) => Promise<WorkspaceEnv>;
|
|
1973
|
-
/**
|
|
1974
|
-
|
|
1975
|
-
/** Read once as a run opens, never per spawn (ADR-0018, S1). */
|
|
1976
|
-
runnerTransport: () => RunnerTransport;
|
|
1913
|
+
/** The skill catalog over workspace roots, as {@link workspaceSkillRoots} orders them — read at each spawn. */
|
|
1914
|
+
skillsAt: (roots: readonly string[]) => SkillLookup;
|
|
1977
1915
|
/** What the task's last saved attempt did, or null when it left no log (ADR-0020). */
|
|
1978
1916
|
previousAttemptFromLog: (taskId: string) => string | null;
|
|
1979
1917
|
}
|
|
1980
1918
|
/**
|
|
1981
|
-
* What a caller supplies to {@link
|
|
1982
|
-
* gets its default there. This is what a host or test chooses, not the
|
|
1983
|
-
* wiring the orchestrator itself runs on.
|
|
1919
|
+
* What a caller supplies to {@link TaskOrchestrator.compose}; every optional
|
|
1920
|
+
* one gets its default there. This is what a host or test chooses, not the
|
|
1921
|
+
* resolved wiring the orchestrator itself runs on.
|
|
1984
1922
|
*/
|
|
1985
1923
|
interface TaskOrchestratorOptions {
|
|
1986
1924
|
config: IConfig;
|
|
1987
1925
|
notifications: INotification;
|
|
1988
|
-
|
|
1926
|
+
runner: IRunner;
|
|
1989
1927
|
store?: PlanStore;
|
|
1990
1928
|
output?: TaskOutputSource;
|
|
1991
1929
|
isolation?: IWorktreeIsolation;
|
|
1992
1930
|
registry?: RunnerRegistry | null;
|
|
1993
1931
|
workspaceRoot?: () => string;
|
|
1994
1932
|
workspaceEnv?: (cwd: string) => Promise<WorkspaceEnv>;
|
|
1995
|
-
|
|
1996
|
-
runnerTransport?: () => RunnerTransport;
|
|
1933
|
+
skillsAt?: (roots: readonly string[]) => SkillLookup;
|
|
1997
1934
|
previousAttemptFromLog?: (taskId: string) => string | null;
|
|
1998
1935
|
}
|
|
1999
1936
|
/**
|
|
@@ -2002,14 +1939,14 @@ interface TaskOrchestratorOptions {
|
|
|
2002
1939
|
* All task-shaped state — the plan tree, the flat index, the completed set
|
|
2003
1940
|
* — lives in {@link PlanStore}, injected at construction. The orchestrator
|
|
2004
1941
|
* calls `store.markCompleted(id)` / `store.markFailed(id)` instead of mutating
|
|
2005
|
-
* task state directly. A task completes only after the runner
|
|
2006
|
-
*
|
|
2007
|
-
* failure and does not unblock dependent work.
|
|
1942
|
+
* task state directly. A task completes only after the runner reports it done
|
|
1943
|
+
* through `task_complete` on its attempt's token; process exit without that
|
|
1944
|
+
* evidence is a visible failure and does not unblock dependent work.
|
|
2008
1945
|
*/
|
|
2009
1946
|
declare class TaskOrchestrator {
|
|
2010
1947
|
private config;
|
|
2011
1948
|
private notifications;
|
|
2012
|
-
private
|
|
1949
|
+
private runner;
|
|
2013
1950
|
private store;
|
|
2014
1951
|
private output;
|
|
2015
1952
|
private attempts;
|
|
@@ -2020,8 +1957,6 @@ declare class TaskOrchestrator {
|
|
|
2020
1957
|
private reviewApproved;
|
|
2021
1958
|
private retryCounts;
|
|
2022
1959
|
private spawnCounts;
|
|
2023
|
-
/** The terminal a verdict left open, by task; see {@link LingeringRunners}. */
|
|
2024
|
-
private lingering;
|
|
2025
1960
|
/**
|
|
2026
1961
|
* A full-plan run a failure paused. Retrying the failed task is the explicit
|
|
2027
1962
|
* resume the pause waits for — without this a retry only reset the task to
|
|
@@ -2060,20 +1995,13 @@ declare class TaskOrchestrator {
|
|
|
2060
1995
|
private registry;
|
|
2061
1996
|
private workspaceRootFn;
|
|
2062
1997
|
private observers;
|
|
2063
|
-
private
|
|
2064
|
-
private readRunnerTransport;
|
|
1998
|
+
private skillsAt;
|
|
2065
1999
|
private previousAttemptFromLog;
|
|
2066
|
-
/**
|
|
2067
|
-
* The setting as the latest run copied it when it opened. Every spawn of
|
|
2068
|
-
* that run uses this, so flipping the setting mid-run changes the next run
|
|
2069
|
-
* only — the plan, not a live setting, says what runs (ADR-0001).
|
|
2070
|
-
*/
|
|
2071
|
-
private planTransport;
|
|
2072
2000
|
constructor(deps: TaskOrchestratorDeps);
|
|
2073
2001
|
/**
|
|
2074
2002
|
* The composition root: resolves every optional collaborator and wires the
|
|
2075
2003
|
* isolation listener that the constructor cannot, because it needs the
|
|
2076
|
-
* instance's own (private) emit
|
|
2004
|
+
* instance's own (private) emit seam. Nothing else in the
|
|
2077
2005
|
* codebase constructs an orchestrator, so this is the one place defaults
|
|
2078
2006
|
* live — a host or test supplies what it cares about and gets the rest.
|
|
2079
2007
|
*/
|
|
@@ -2082,7 +2010,7 @@ declare class TaskOrchestrator {
|
|
|
2082
2010
|
getIdleSince(taskId: string): string | null;
|
|
2083
2011
|
/**
|
|
2084
2012
|
* What an ops retry is told about the attempt before. The saved log is read
|
|
2085
|
-
* whether or not the session was reloaded, so both behave alike; the
|
|
2013
|
+
* whether or not the session was reloaded, so both behave alike; the output
|
|
2086
2014
|
* buffer is the fallback for a runner that has no log. A reload clears the
|
|
2087
2015
|
* attempt count along with the buffer, so a retry made since is what says
|
|
2088
2016
|
* there was an attempt to report on.
|
|
@@ -2119,13 +2047,13 @@ declare class TaskOrchestrator {
|
|
|
2119
2047
|
forceSendQueuedTaskMessage(taskId: string, id: string): boolean;
|
|
2120
2048
|
/** Take back a message still queued behind a turn; false once it was delivered. */
|
|
2121
2049
|
removeQueuedTaskMessage(taskId: string, id: string): boolean;
|
|
2122
|
-
/** Stop a structured task's running turn; it then waits for input like any turn that ends without
|
|
2050
|
+
/** Stop a structured task's running turn; it then waits for input like any turn that ends without a `task_complete` call. */
|
|
2123
2051
|
interruptTask(taskId: string): Promise<void>;
|
|
2124
2052
|
/** What is waiting for a structured task's turn to end; empty for any other task. */
|
|
2125
2053
|
getQueuedTaskMessages(taskId: string): QueuedTaskMessage[];
|
|
2126
|
-
private
|
|
2054
|
+
private runnerSession;
|
|
2127
2055
|
/**
|
|
2128
|
-
* A structured turn that ended without
|
|
2056
|
+
* A structured turn that ended without a `task_complete` call (ADR-0018, W1). No
|
|
2129
2057
|
* verdict is guessed: the task waits for input, unless a checkpoint in the
|
|
2130
2058
|
* same turn already has it waiting, or a queued message went straight out —
|
|
2131
2059
|
* the session never passes through idle then, so nothing flickers.
|
|
@@ -2151,7 +2079,6 @@ declare class TaskOrchestrator {
|
|
|
2151
2079
|
/** Task id → session id of every attempt whose runner is up; a spawn in flight has no session yet. */
|
|
2152
2080
|
get activeSessionMap(): Map<string, string>;
|
|
2153
2081
|
getAttempt(taskId: string): TaskAttemptSnapshot | undefined;
|
|
2154
|
-
getAttemptSession(taskId: string): ITerminalSession | undefined;
|
|
2155
2082
|
get queuedCount(): number;
|
|
2156
2083
|
/**
|
|
2157
2084
|
* "Merge all"; a settled run that merged everything is cleared up and
|
|
@@ -2172,18 +2099,12 @@ declare class TaskOrchestrator {
|
|
|
2172
2099
|
* the task has started, and for every other task.
|
|
2173
2100
|
*/
|
|
2174
2101
|
getMergeGate(taskId: string): string[];
|
|
2175
|
-
|
|
2176
|
-
/** The transport the plan's latest run copied from the setting; null before its first run. */
|
|
2177
|
-
get runnerTransport(): RunnerTransport | null;
|
|
2178
|
-
/** Take over a saved plan's copied transport. The next run copies the setting afresh. */
|
|
2179
|
-
adoptRunnerTransport(transport: RunnerTransport | null): void;
|
|
2180
|
-
queueMessage(text: string): void;
|
|
2102
|
+
queueMessage(text: string, skills?: readonly SkillLoad[]): void;
|
|
2181
2103
|
getQueuedMessages(): QueuedMessage[];
|
|
2182
2104
|
/** Take one unsent message back out of the queue; false when it was never there (or already drained). */
|
|
2183
2105
|
removeQueuedMessage(id: string): boolean;
|
|
2184
2106
|
setQueuedMessages(messages: QueuedMessage[]): void;
|
|
2185
2107
|
clearQueuedMessages(): void;
|
|
2186
|
-
processNextQueuedMessage(): QueuedMessage | null;
|
|
2187
2108
|
loadPlan(tasks: readonly Task[], planRunners?: RunnerId[]): void;
|
|
2188
2109
|
/**
|
|
2189
2110
|
* Adopt an edited plan without letting go of the run in progress. Everything
|
|
@@ -2224,7 +2145,16 @@ declare class TaskOrchestrator {
|
|
|
2224
2145
|
* run up, so neither may happen under a task the plan still shows at work.
|
|
2225
2146
|
*/
|
|
2226
2147
|
private get settled();
|
|
2227
|
-
|
|
2148
|
+
/**
|
|
2149
|
+
* The boundary a verdict crosses: nothing awaits the verifier's listener, so
|
|
2150
|
+
* a throw from reading the output, landing, releasing a worktree or the tick
|
|
2151
|
+
* after would be an unhandled rejection — and an attempt left integrating is
|
|
2152
|
+
* live work forever. One that never settled fails (a repair waits on the
|
|
2153
|
+
* user, as its conflict did); either way the run halts and says why.
|
|
2154
|
+
*/
|
|
2155
|
+
private deliverVerdict;
|
|
2156
|
+
/** Work nothing awaits: a rejection is said, not left unhandled. */
|
|
2157
|
+
private unawaited;
|
|
2228
2158
|
private onVerdict;
|
|
2229
2159
|
private afterVerdict;
|
|
2230
2160
|
/**
|
|
@@ -2281,7 +2211,6 @@ declare class TaskOrchestrator {
|
|
|
2281
2211
|
*/
|
|
2282
2212
|
releaseTask(taskId: string): Promise<void>;
|
|
2283
2213
|
markTaskComplete(taskId: string): Promise<void>;
|
|
2284
|
-
markAiTaskComplete(taskId: string): Promise<void>;
|
|
2285
2214
|
/**
|
|
2286
2215
|
* Undo a completion: return the task to "not executed" — pending, verdict and
|
|
2287
2216
|
* summary dropped, archive entry removed. It is put on hold like a cancel, so
|
|
@@ -2328,16 +2257,9 @@ declare class TaskOrchestrator {
|
|
|
2328
2257
|
isAllComplete(): boolean;
|
|
2329
2258
|
isAnyFailed(): boolean;
|
|
2330
2259
|
approveReview(): Promise<void>;
|
|
2331
|
-
getPlanVisualization(): {
|
|
2332
|
-
tasks: {
|
|
2333
|
-
id: string;
|
|
2334
|
-
title: string;
|
|
2335
|
-
dependencies: string[];
|
|
2336
|
-
parallelGroups: number[][];
|
|
2337
|
-
}[];
|
|
2338
|
-
parallelGroups: number[][];
|
|
2339
|
-
};
|
|
2340
2260
|
tick(): Promise<void>;
|
|
2261
|
+
/** Whether the scheduler may start `id` now: it passes every readiness gate and a slot is free. */
|
|
2262
|
+
private stillReady;
|
|
2341
2263
|
/**
|
|
2342
2264
|
* A run paused at merge gates says so, as plainly as a task that waits on
|
|
2343
2265
|
* the user: which tasks wait, and that Merge all lets them go on (ADR-0020).
|
|
@@ -2351,13 +2273,14 @@ declare class TaskOrchestrator {
|
|
|
2351
2273
|
* unwound (both leave `startTask` with nothing further to announce).
|
|
2352
2274
|
*/
|
|
2353
2275
|
private spawnAttempt;
|
|
2276
|
+
/** For a skill the main checkout has, the folder a worktree only gets once it is committed. */
|
|
2277
|
+
private uncommittedSkillFolder;
|
|
2354
2278
|
/**
|
|
2355
|
-
*
|
|
2356
|
-
*
|
|
2357
|
-
*
|
|
2358
|
-
* a host without a router included — never a silent downgrade.
|
|
2279
|
+
* The roots whose `.ordewell/skills/` an attempt at `cwd` reads: in a repo
|
|
2280
|
+
* group, `cwd` holds each repo — a worktree of it when isolated, the
|
|
2281
|
+
* workspace's own checkout when not — and no folder of its own (ADR-0014).
|
|
2359
2282
|
*/
|
|
2360
|
-
private
|
|
2283
|
+
private skillRoots;
|
|
2361
2284
|
/**
|
|
2362
2285
|
* A continue whose runner never announced the session it was told to
|
|
2363
2286
|
* resume. Nothing was continued, and nothing fresh was started in its place.
|
|
@@ -2383,24 +2306,17 @@ declare class TaskOrchestrator {
|
|
|
2383
2306
|
* it receives for an attempt that is no longer current).
|
|
2384
2307
|
*
|
|
2385
2308
|
* A user interruption also bumps the verifier's generation *before* stopping
|
|
2386
|
-
* the runner:
|
|
2309
|
+
* the runner: a runner may fire onExit synchronously from
|
|
2387
2310
|
* stop(), and if that exit reaches VerdictEngine under the still-valid
|
|
2388
2311
|
* generation it delivers a verdict that marks the task 'completed' for one
|
|
2389
|
-
* tick — long enough for the scheduler to start a dependent task.
|
|
2390
|
-
*
|
|
2391
|
-
* ends), and stop/load reset the whole verifier themselves.
|
|
2312
|
+
* tick — long enough for the scheduler to start a dependent task. Stop and
|
|
2313
|
+
* load reset the whole verifier themselves.
|
|
2392
2314
|
*/
|
|
2393
2315
|
private endAttempt;
|
|
2394
2316
|
/** Kept on the task once the attempt ends, so a continue can resume it after a reload (ADR-0018, K1). */
|
|
2395
2317
|
private saveNativeSession;
|
|
2396
2318
|
private endAllAttempts;
|
|
2397
2319
|
}
|
|
2398
|
-
/**
|
|
2399
|
-
* Build a {@link TaskOrchestrator}, filling in every collaborator a caller did
|
|
2400
|
-
* not inject. The one entry point for hosts, bench harnesses and tests alike;
|
|
2401
|
-
* {@link TaskOrchestrator} itself constructs nothing.
|
|
2402
|
-
*/
|
|
2403
|
-
declare function createTaskOrchestrator(options: TaskOrchestratorOptions): TaskOrchestrator;
|
|
2404
2320
|
|
|
2405
2321
|
/**
|
|
2406
2322
|
* Everything needed to produce a plan from a goal. Carries the planning context
|
|
@@ -2417,9 +2333,13 @@ interface PlanRequest {
|
|
|
2417
2333
|
autonomousDefault?: boolean;
|
|
2418
2334
|
signal?: AbortSignal;
|
|
2419
2335
|
perRunnerAllowlist?: Partial<Record<RunnerId, string[]>>;
|
|
2420
|
-
/** The mode toggles this run honours. `modesFor('one-shot', …)` decides which apply. */
|
|
2421
2336
|
modes?: PlannerModes;
|
|
2422
2337
|
}
|
|
2338
|
+
/** A generated plan, and what its skill check warned about. */
|
|
2339
|
+
interface GeneratedPlan extends LegacyPlanState {
|
|
2340
|
+
/** Names not found yet, or no skill could have; the plan still lands. Absent means none, or not checked. */
|
|
2341
|
+
skillWarnings?: string[];
|
|
2342
|
+
}
|
|
2423
2343
|
interface ModifyPlanRequest {
|
|
2424
2344
|
existingPlan: LegacyPlanState;
|
|
2425
2345
|
userRequest: string;
|
|
@@ -2444,10 +2364,14 @@ interface ModifyDuringExecutionRequest {
|
|
|
2444
2364
|
perRunnerAllowlist?: Partial<Record<RunnerId, string[]>>;
|
|
2445
2365
|
/** Where the run in force puts each task (ADR-0013, ADR-0014). */
|
|
2446
2366
|
isolatedExecution?: IsolatedExecution;
|
|
2367
|
+
/** The workspace's skill catalog under its repo group's layout, which the rewritten tasks' skills are checked against. */
|
|
2368
|
+
skills: SkillLookup;
|
|
2447
2369
|
}
|
|
2448
2370
|
interface ModifyDuringExecutionResult {
|
|
2449
2371
|
pendingTasks: Task[];
|
|
2450
2372
|
message: string;
|
|
2373
|
+
/** Skill names not found yet; the edit still lands, as a submitted plan's does. Absent means none. */
|
|
2374
|
+
skillWarnings?: string[];
|
|
2451
2375
|
}
|
|
2452
2376
|
/**
|
|
2453
2377
|
* Owns one-shot plan generation and plan modification — the "planning is a
|
|
@@ -2466,8 +2390,12 @@ declare class Planner {
|
|
|
2466
2390
|
private readonly resolveAiService;
|
|
2467
2391
|
constructor(config: IConfig, aiService: IAiService | (() => IAiService));
|
|
2468
2392
|
private get aiService();
|
|
2469
|
-
/**
|
|
2470
|
-
|
|
2393
|
+
/**
|
|
2394
|
+
* One-shot plan generation for non-conversational surfaces. Never asks
|
|
2395
|
+
* questions. A plan attaching a planner skill to a task is refused, not
|
|
2396
|
+
* returned: there is no conversation to send it back through.
|
|
2397
|
+
*/
|
|
2398
|
+
generate(req: PlanRequest): Promise<GeneratedPlan>;
|
|
2471
2399
|
modify(req: ModifyPlanRequest): Promise<{
|
|
2472
2400
|
tasks: Task[];
|
|
2473
2401
|
}>;
|
|
@@ -2563,9 +2491,7 @@ declare class RunnerInstallation {
|
|
|
2563
2491
|
* typing a real goal is the failure this exists to prevent.
|
|
2564
2492
|
*
|
|
2565
2493
|
* "Usable" is deliberately shallow: the binary answers `--version`, and the
|
|
2566
|
-
* runner has a connector to plan over.
|
|
2567
|
-
* manifest-level planner capability, so a plugin can declare itself
|
|
2568
|
-
* plannable, is a follow-up. Whether the user's subscription is
|
|
2494
|
+
* runner has a connector to plan over. Whether the user's subscription is
|
|
2569
2495
|
* live cannot be known without spending a turn on it, so an expired login
|
|
2570
2496
|
* surfaces where it actually bites — as the agent's own error text on the
|
|
2571
2497
|
* first turn.
|
|
@@ -2641,6 +2567,37 @@ declare function isCliProvider(id: AiProvider): boolean;
|
|
|
2641
2567
|
declare function runnerForProvider(id: AiProvider): string | null;
|
|
2642
2568
|
/** The harness planner that wraps a given runner, or null when none does. */
|
|
2643
2569
|
declare function providerForRunner(runner: string): AiProvider | null;
|
|
2570
|
+
/** One runner's planner usability, as `RunnerInstallation.plannerUsability` reports it. */
|
|
2571
|
+
interface PlannerUsability {
|
|
2572
|
+
usable: boolean;
|
|
2573
|
+
reason?: string;
|
|
2574
|
+
}
|
|
2575
|
+
/**
|
|
2576
|
+
* One entry of the planner backend list (ADR-0009). `id` is the `AiProvider`
|
|
2577
|
+
* either way; `runner` is set only for a harness planner, whose model catalog
|
|
2578
|
+
* comes from that runner, and `reason` is the second line a surface renders —
|
|
2579
|
+
* the block detail for a harness planner, the API-key variable for a vendor.
|
|
2580
|
+
*/
|
|
2581
|
+
interface PlannerBackendEntry {
|
|
2582
|
+
id: AiProvider;
|
|
2583
|
+
label: string;
|
|
2584
|
+
kind: 'harness' | 'vendor';
|
|
2585
|
+
runner?: string;
|
|
2586
|
+
usable: boolean;
|
|
2587
|
+
reason?: string;
|
|
2588
|
+
}
|
|
2589
|
+
/** The detail a usable harness planner is always shown with. */
|
|
2590
|
+
declare const HARNESS_PLANNER_REASON = "coding agent \u00B7 no API key needed";
|
|
2591
|
+
/**
|
|
2592
|
+
* The planner backends every surface offers, in order: the harness planners
|
|
2593
|
+
* first, always listed so a missing CLI is greyed with its reason rather than
|
|
2594
|
+
* hidden, then the configured vendors in `PROVIDER_PRIORITY` order. Pure: the
|
|
2595
|
+
* caller supplies what it knows of each runner (VS Code its `plannerUsability`
|
|
2596
|
+
* results, the TUI its installed set) and maps the entries to its own item
|
|
2597
|
+
* type, keeping surface-specific affordances — e.g. the CLI's empty-vendor
|
|
2598
|
+
* placeholder — to itself.
|
|
2599
|
+
*/
|
|
2600
|
+
declare function plannerBackendEntries(usability: Readonly<Record<string, PlannerUsability>>, configured: readonly AiProvider[]): PlannerBackendEntry[];
|
|
2644
2601
|
/**
|
|
2645
2602
|
* The single definition of which providers count as "configured" — one API
|
|
2646
2603
|
* key each, or (for `openai_compatible`) an explicit base URL. Every surface
|
|
@@ -2719,7 +2676,7 @@ interface EnvAdmission {
|
|
|
2719
2676
|
*/
|
|
2720
2677
|
declare function admitSettingsEnv(env: Record<string, unknown>): EnvAdmission;
|
|
2721
2678
|
|
|
2722
|
-
/** Whether a runner's tasks
|
|
2679
|
+
/** Whether Ordewell can run a runner's tasks (ADR-0018, S3). */
|
|
2723
2680
|
declare function supportsTaskMode(runner: string): boolean;
|
|
2724
2681
|
/** The adapter that drives one task. Throws {@link TaskModeUnsupportedError} for a runner without a connector. */
|
|
2725
2682
|
declare function createTaskAdapter(runner: string, deps: AgentProcessDeps): TaskModeAgentAdapter;
|
|
@@ -2740,8 +2697,8 @@ interface SpawnSpec {
|
|
|
2740
2697
|
*
|
|
2741
2698
|
* Subclasses own their agent's protocol: what to spawn, how to phrase a user
|
|
2742
2699
|
* turn, and how to read one protocol line. Everything below — line framing,
|
|
2743
|
-
* turn lifecycle, abort
|
|
2744
|
-
*
|
|
2700
|
+
* turn lifecycle, abort — is the same for all of them, and the process itself
|
|
2701
|
+
* is a {@link RunnerProcess}.
|
|
2745
2702
|
*/
|
|
2746
2703
|
declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
2747
2704
|
protected deps: AgentProcessDeps;
|
|
@@ -2749,8 +2706,7 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2749
2706
|
protected process: ChildProcess | null;
|
|
2750
2707
|
protected sessionId: string | null;
|
|
2751
2708
|
private readonly stdout;
|
|
2752
|
-
private
|
|
2753
|
-
private exited;
|
|
2709
|
+
private readonly runner;
|
|
2754
2710
|
/** Set for the duration of a turn. Outside one, events are buffered rather than dropped. */
|
|
2755
2711
|
private turnEmit;
|
|
2756
2712
|
/** Set for the duration of a turn. Pinged on every raw line, whether or not `handleLine` turns it into an event. */
|
|
@@ -2772,11 +2728,6 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2772
2728
|
/** A task's session, which wants what the agent says on its own after a turn closed; a planner registers none and drops it. */
|
|
2773
2729
|
private outOfTurnListener;
|
|
2774
2730
|
private disposed;
|
|
2775
|
-
/** Resolves when the process ends, so a handshake can lose the race instead of waiting out its timeout. */
|
|
2776
|
-
protected processEnded: Promise<void>;
|
|
2777
|
-
/** The environment the agent was spawned under, for any side process a handshake needs. */
|
|
2778
|
-
protected spawnEnv: NodeJS.ProcessEnv;
|
|
2779
|
-
private markEnded;
|
|
2780
2731
|
/** What this process is to the user — a planner or a task's runner — for the words a failure is reported in. */
|
|
2781
2732
|
protected role: 'planner' | 'task';
|
|
2782
2733
|
constructor(deps: AgentProcessDeps);
|
|
@@ -2792,6 +2743,17 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2792
2743
|
/** Protocol handshake, if the agent needs one before it accepts a turn. */
|
|
2793
2744
|
protected handshake(_opts: AgentStartOptions): Promise<void>;
|
|
2794
2745
|
start(opts: AgentStartOptions): Promise<void>;
|
|
2746
|
+
/**
|
|
2747
|
+
* Every protocol line goes to `handleLine`, turn or no turn: an agent's
|
|
2748
|
+
* handshake and its session-id announcement both arrive before the first
|
|
2749
|
+
* message is sent, and dropping them left the handshake waiting on a reply
|
|
2750
|
+
* that had already come and gone.
|
|
2751
|
+
*/
|
|
2752
|
+
private readProtocol;
|
|
2753
|
+
/** Resolves when the process ends, so a handshake can lose the race instead of waiting out its timeout. */
|
|
2754
|
+
protected get processEnded(): Promise<void>;
|
|
2755
|
+
/** The environment the agent was spawned under, for any side process a handshake needs. */
|
|
2756
|
+
protected get spawnEnv(): NodeJS.ProcessEnv;
|
|
2795
2757
|
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
2796
2758
|
onOutOfTurn(listener: (event: AgentEvent) => void): void;
|
|
2797
2759
|
nativeSessionId(): string | null;
|
|
@@ -2839,7 +2801,7 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
2839
2801
|
* A task's turn whose `result` arrived while background work was still open.
|
|
2840
2802
|
* The CLI reports that result when the model stops talking, then opens a turn
|
|
2841
2803
|
* of its own when the work finishes; a turn ended at the first result would
|
|
2842
|
-
* lose everything
|
|
2804
|
+
* lose everything done after it, the `task_complete` call included.
|
|
2843
2805
|
*/
|
|
2844
2806
|
private resultHeld;
|
|
2845
2807
|
private followOnTimer;
|
|
@@ -2859,8 +2821,7 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
2859
2821
|
/**
|
|
2860
2822
|
* A task's run: the manifest decides what its mode and effort mean
|
|
2861
2823
|
* (ADR-0001), and this adds only the protocol around them. No tool list and
|
|
2862
|
-
* no system prompt — the task's prompt is its first turn
|
|
2863
|
-
* transport. `--permission-prompt-tool stdio` routes the questions the mode
|
|
2824
|
+
* no system prompt — the task's prompt is its first turn. `--permission-prompt-tool stdio` routes the questions the mode
|
|
2864
2825
|
* leaves open to the control channel, where the adapter must answer them;
|
|
2865
2826
|
* without it `-p` refuses them silently and nothing can ever surface one.
|
|
2866
2827
|
*/
|
|
@@ -2868,7 +2829,6 @@ declare class ClaudeCodeAdapter extends StdioAgentAdapter implements TaskModeAge
|
|
|
2868
2829
|
/** The file holding the token lives exactly as long as the process that reads it. */
|
|
2869
2830
|
private ordewellServerArgs;
|
|
2870
2831
|
private removeMcpConfig;
|
|
2871
|
-
start(opts: AgentStartOptions): Promise<void>;
|
|
2872
2832
|
/** Asks the CLI itself, which reports `pending` until its connection attempt settles. */
|
|
2873
2833
|
mcpAttached(): Promise<boolean>;
|
|
2874
2834
|
/**
|
|
@@ -2974,16 +2934,12 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
2974
2934
|
private threadId;
|
|
2975
2935
|
/** The model Codex opened the thread with — usage records name it. */
|
|
2976
2936
|
private threadModel;
|
|
2977
|
-
private
|
|
2978
|
-
private settleHandshake;
|
|
2979
|
-
private handshakeError;
|
|
2937
|
+
private readonly rpc;
|
|
2980
2938
|
private startOpts;
|
|
2981
2939
|
/** Whether this turn has already emitted prose — see the `agentMessage` case. */
|
|
2982
2940
|
private turnHasText;
|
|
2983
2941
|
/** The turn in flight. `turn/interrupt` and `turn/steer` cannot be sent before it has an id. */
|
|
2984
2942
|
private turn;
|
|
2985
|
-
/** The JSON-RPC id of the `turn/start` that opened {@link turn}. */
|
|
2986
|
-
private turnRequestId;
|
|
2987
2943
|
/** The last turn this adapter ended — so its second end signal, landing late, ends nothing. */
|
|
2988
2944
|
private endedTurnId;
|
|
2989
2945
|
/** An interrupt was asked for during this turn, so however it ends, it was cut short. */
|
|
@@ -2994,8 +2950,6 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
2994
2950
|
* that belongs to no turn of the agent's any more (ADR-0023, F4).
|
|
2995
2951
|
*/
|
|
2996
2952
|
private readonly interruptedTurnIds;
|
|
2997
|
-
/** An interrupt asked for before Codex named the turn, sent once it does. */
|
|
2998
|
-
private interruptOnStart;
|
|
2999
2953
|
/** A task's approval requests still waiting for an answer, by the request id as a string. */
|
|
3000
2954
|
private readonly openPermissions;
|
|
3001
2955
|
/**
|
|
@@ -3005,10 +2959,6 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
3005
2959
|
private readonly fileChangePaths;
|
|
3006
2960
|
/** The row each announced file of an in-flight `fileChange` item is shown under, by the file's shown path. */
|
|
3007
2961
|
private readonly fileChangeRows;
|
|
3008
|
-
/** Requests this adapter sent and awaits an answer to, by JSON-RPC id. */
|
|
3009
|
-
private readonly pendingRequests;
|
|
3010
|
-
private resumeAttempted;
|
|
3011
|
-
private resumeFallbackSent;
|
|
3012
2962
|
private sandbox;
|
|
3013
2963
|
/** The Ordewell server's startup state, as Codex last reported it for this thread. */
|
|
3014
2964
|
private mcpStartup;
|
|
@@ -3019,6 +2969,7 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
3019
2969
|
* one stream; the thread id is what tells them apart (see {@link subagentOf}).
|
|
3020
2970
|
*/
|
|
3021
2971
|
private readonly subagents;
|
|
2972
|
+
constructor(deps: AgentProcessDeps);
|
|
3022
2973
|
protected spawnSpec(opts: AgentStartOptions): SpawnSpec;
|
|
3023
2974
|
/**
|
|
3024
2975
|
* `initialize`, then `thread/start`, both before the first user message. A
|
|
@@ -3028,16 +2979,18 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
3028
2979
|
* construction. A task's runs as its mode says (see {@link threadParams}).
|
|
3029
2980
|
*/
|
|
3030
2981
|
protected handshake(opts: AgentStartOptions): Promise<void>;
|
|
2982
|
+
private handshakeIncomplete;
|
|
3031
2983
|
/**
|
|
3032
2984
|
* Open this session's thread. A resume id means the previous
|
|
3033
2985
|
* process died mid-session: `thread/resume` puts the agent back in front of
|
|
3034
2986
|
* the context it already paid to read. A planner's failed resume is not an
|
|
3035
|
-
* error —
|
|
3036
|
-
*
|
|
3037
|
-
*
|
|
3038
|
-
*
|
|
2987
|
+
* error — it falls back to a fresh thread, which is the same degradation
|
|
2988
|
+
* `restoreChat` performs on every surface (T4). A task's is: Continue (K1)
|
|
2989
|
+
* offers the session that did the work, and a fresh thread in its place
|
|
2990
|
+
* would pretend it was resumed.
|
|
3039
2991
|
*/
|
|
3040
|
-
private
|
|
2992
|
+
private openThread;
|
|
2993
|
+
private requestThread;
|
|
3041
2994
|
private threadParams;
|
|
3042
2995
|
/**
|
|
3043
2996
|
* Codex's own startup report for the server, which it sends once the thread
|
|
@@ -3048,10 +3001,12 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
3048
3001
|
private effort;
|
|
3049
3002
|
/**
|
|
3050
3003
|
* `turn/interrupt` names the turn as well as the thread, so an interrupt
|
|
3051
|
-
* asked for before Codex has named the turn waits for it
|
|
3052
|
-
* with an empty result, then ends the turn as `interrupted`.
|
|
3004
|
+
* asked for before Codex has named the turn waits for it, as a steer does.
|
|
3005
|
+
* Codex acknowledges with an empty result, then ends the turn as `interrupted`.
|
|
3053
3006
|
*/
|
|
3054
3007
|
interrupt(timeoutMs: number): Promise<boolean>;
|
|
3008
|
+
/** Run `send` now if Codex has named the turn, and once it does if not. */
|
|
3009
|
+
private whenNamed;
|
|
3055
3010
|
/**
|
|
3056
3011
|
* `turn/steer` into the running turn (ADR-0023). Codex answers with the
|
|
3057
3012
|
* turn's id at once — acceptance, not delivery — and shows the input to the
|
|
@@ -3070,6 +3025,8 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
3070
3025
|
*/
|
|
3071
3026
|
answerPermission(id: string, decision: ApprovalDecision): boolean;
|
|
3072
3027
|
protected turnPayload(message: string): string;
|
|
3028
|
+
/** `turn/start`'s answer. One for a turn that has since closed or been replaced names and closes nothing. */
|
|
3029
|
+
private turnAnswered;
|
|
3073
3030
|
protected handleLine(line: string, emit: (event: AgentEvent) => void): void;
|
|
3074
3031
|
private turnStarted;
|
|
3075
3032
|
/**
|
|
@@ -3148,8 +3105,8 @@ declare class CodexAdapter extends StdioAgentAdapter implements TaskModeAgentAda
|
|
|
3148
3105
|
* (ADR-0009, ADR-0018).
|
|
3149
3106
|
*
|
|
3150
3107
|
* The odd one out: `opencode serve` is a real server rather than a stdio
|
|
3151
|
-
* protocol, so this adapter owns both halves of the boundary — it
|
|
3152
|
-
* process
|
|
3108
|
+
* protocol, so this adapter owns both halves of the boundary — it starts the
|
|
3109
|
+
* process as the same {@link RunnerProcess} every other adapter uses, then
|
|
3153
3110
|
* talks to it through the injected `fetch`. Both are part of the one seam the
|
|
3154
3111
|
* tests drive.
|
|
3155
3112
|
*
|
|
@@ -3169,12 +3126,8 @@ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
|
|
|
3169
3126
|
/** Sent on every request to a task's server, which a per-task password secures. */
|
|
3170
3127
|
private authorization;
|
|
3171
3128
|
private sessionId;
|
|
3172
|
-
private
|
|
3173
|
-
private exited;
|
|
3174
|
-
private exitCode;
|
|
3129
|
+
private readonly runner;
|
|
3175
3130
|
private disposed;
|
|
3176
|
-
private markEnded;
|
|
3177
|
-
private readonly processEnded;
|
|
3178
3131
|
private planner;
|
|
3179
3132
|
private task;
|
|
3180
3133
|
/** The last assistant message already settled — the baseline {@link recoverReply} measures a new reply against. */
|
|
@@ -3190,7 +3143,19 @@ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
|
|
|
3190
3143
|
/** The Ordewell server this process was configured with; null when none was given or its config could not be merged. */
|
|
3191
3144
|
private ordewell;
|
|
3192
3145
|
constructor(deps: AgentProcessDeps);
|
|
3146
|
+
private get processEnded();
|
|
3147
|
+
private get exited();
|
|
3193
3148
|
start(opts: AgentStartOptions): Promise<void>;
|
|
3149
|
+
private launch;
|
|
3150
|
+
/**
|
|
3151
|
+
* Where `serve` listens, or null once it ends or gives up. Stdout only: that
|
|
3152
|
+
* is where `serve` prints its address, and stderr can carry another URL — a
|
|
3153
|
+
* warning about a provider it could not reach. Read a line at a time, and
|
|
3154
|
+
* only until the address is known.
|
|
3155
|
+
*/
|
|
3156
|
+
private serverAddress;
|
|
3157
|
+
/** From the server's address to an open session — the 2.x API's, or a 1.x one created or resumed. */
|
|
3158
|
+
private connect;
|
|
3194
3159
|
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
3195
3160
|
/**
|
|
3196
3161
|
* One task turn. `prompt_async` only queues the work, so the turn is over
|
|
@@ -3219,8 +3184,8 @@ declare class OpenCodeAdapter implements TaskModeAgentAdapter {
|
|
|
3219
3184
|
/**
|
|
3220
3185
|
* Whatever of the turn's own messages the stream missed. Each part is
|
|
3221
3186
|
* emitted once, so a turn the stream saw whole adds nothing here; one that
|
|
3222
|
-
* lost its last text part still reaches the plain-text channel,
|
|
3223
|
-
*
|
|
3187
|
+
* lost its last text part still reaches the plain-text channel, which a
|
|
3188
|
+
* summary falls back to.
|
|
3224
3189
|
*/
|
|
3225
3190
|
private readBack;
|
|
3226
3191
|
/**
|
|
@@ -3340,12 +3305,191 @@ declare function mapAgentTool(name: string): MappedTool;
|
|
|
3340
3305
|
*/
|
|
3341
3306
|
declare function normalizeAgentArgs(tool: ResearchToolType, args: Record<string, unknown>): Record<string, unknown>;
|
|
3342
3307
|
|
|
3308
|
+
/** What a runner offers a task: the models discovered for it and the modes its manifest declares. */
|
|
3309
|
+
interface RunnerCatalog {
|
|
3310
|
+
models: DiscoveredModel[];
|
|
3311
|
+
modes: RunnerModeInfo[];
|
|
3312
|
+
/**
|
|
3313
|
+
* The mode a task lands on when it carries none this runner offers: the
|
|
3314
|
+
* manifest's `autonomous`/`safe`-tagged mode under the user's toggle
|
|
3315
|
+
* (ADR-0001). Absent, `modes[0]` stands in — which for Codex is its
|
|
3316
|
+
* workspace-write sandbox, not the full access an unattended run needs.
|
|
3317
|
+
*/
|
|
3318
|
+
defaultMode?: string;
|
|
3319
|
+
}
|
|
3320
|
+
/**
|
|
3321
|
+
* The model, thinking effort and mode a runner offers for a task.
|
|
3322
|
+
*
|
|
3323
|
+
* A task's model, effort and mode are all scoped to its runner:
|
|
3324
|
+
* `claude-sonnet-4-5` on Codex, or `acceptEdits` on OpenCode, are not degraded
|
|
3325
|
+
* choices but unspawnable ones. So this is where any task acquires a runnable
|
|
3326
|
+
* assignment — a runner change (below) and a hand-added task derive it the same
|
|
3327
|
+
* way. Each field in `current` is preserved when the runner also offers it, and
|
|
3328
|
+
* otherwise snapped to that runner's preferred entry (discovery already sorts
|
|
3329
|
+
* models by the manifest's `preferredPatterns`; the mode is the catalog's
|
|
3330
|
+
* `defaultMode`).
|
|
3331
|
+
*
|
|
3332
|
+
* An empty catalog means discovery failed — not that the runner offers nothing. That field is left out of the
|
|
3333
|
+
* patch and the runner validates last, matching `coerceAssignments`.
|
|
3334
|
+
*/
|
|
3335
|
+
declare function runnerAssignment(catalog: RunnerCatalog, current?: Pick<Task, 'assignedModel' | 'taskMode'>): Partial<Task>;
|
|
3336
|
+
/**
|
|
3337
|
+
* Move a task onto a different runner, carrying its model, thinking effort and
|
|
3338
|
+
* mode over to values that runner actually offers. A runner change is never a
|
|
3339
|
+
* single-field edit — it either brings the other three with it or leaves the
|
|
3340
|
+
* task unrunnable.
|
|
3341
|
+
*
|
|
3342
|
+
* Returns the patch to apply, or `{}` when there is nothing to change.
|
|
3343
|
+
*/
|
|
3344
|
+
declare function retargetTaskRunner(task: Task, runner: RunnerId, catalog: RunnerCatalog): Partial<Task>;
|
|
3345
|
+
|
|
3346
|
+
type ModelsByRunner = Partial<Record<RunnerId, DiscoveredModel[]>>;
|
|
3347
|
+
interface SessionCatalogDeps {
|
|
3348
|
+
config: Pick<IConfig, 'enabledRunners' | 'autonomousMode'>;
|
|
3349
|
+
registry: Pick<RunnerRegistry, 'getManifest'>;
|
|
3350
|
+
modelResolver: Pick<ModelResolver, 'modelsForRunners' | 'getCachedRunnerModels'>;
|
|
3351
|
+
/** Read at each call: a toggle or allowlist edit made since the session was built counts (#69). */
|
|
3352
|
+
settings: () => {
|
|
3353
|
+
enabledRunners?: RunnerId[];
|
|
3354
|
+
modelAllowlist?: Record<string, string[]>;
|
|
3355
|
+
};
|
|
3356
|
+
/** The runners of the plan being edited; empty while the session has none. */
|
|
3357
|
+
planRunners: () => RunnerId[];
|
|
3358
|
+
}
|
|
3359
|
+
/**
|
|
3360
|
+
* What a session may assign: the enabled runners, their modes, the models
|
|
3361
|
+
* discovery found for them and the allowlist narrowing those. Every view of
|
|
3362
|
+
* it — the planner's per-turn block, its tools, a user's direct edit — reads
|
|
3363
|
+
* it here, so none can be shown or checked against something the others are not.
|
|
3364
|
+
*
|
|
3365
|
+
* The discovered models are remembered per runner and only ever merged into:
|
|
3366
|
+
* discovering one runner must not forget another's, since coercion later clamps
|
|
3367
|
+
* thinking efforts against whatever was last found.
|
|
3368
|
+
*/
|
|
3369
|
+
declare class SessionCatalog {
|
|
3370
|
+
private readonly deps;
|
|
3371
|
+
private discovered;
|
|
3372
|
+
constructor(deps: SessionCatalogDeps);
|
|
3373
|
+
/** The runners enabled right now. */
|
|
3374
|
+
enabledRunners(): RunnerId[];
|
|
3375
|
+
/**
|
|
3376
|
+
* The allowlist in force right now. Unset means no restriction — falling
|
|
3377
|
+
* back to the one planning started under would keep a restriction the user
|
|
3378
|
+
* has since cleared.
|
|
3379
|
+
*/
|
|
3380
|
+
allowlist(): Record<string, string[]>;
|
|
3381
|
+
/** The models the user allows on one runner; unset means no restriction. */
|
|
3382
|
+
allowlistFor(runner: RunnerId): string[] | undefined;
|
|
3383
|
+
/**
|
|
3384
|
+
* The discovered catalog as the resolver holds it now, per runner, with this
|
|
3385
|
+
* session's own discovery as the fallback where the resolver has nothing
|
|
3386
|
+
* cached. The resolver's cache outlives this session's snapshot in both
|
|
3387
|
+
* directions — an allowlist picker re-discovers into it mid-session — and a
|
|
3388
|
+
* model allowed after that must reach the planner with its real label and
|
|
3389
|
+
* variants, not as an id-only stub. Never triggers discovery itself.
|
|
3390
|
+
*/
|
|
3391
|
+
models(): ModelsByRunner;
|
|
3392
|
+
/** What this session's own discovery found for a runner; empty when it never ran there. */
|
|
3393
|
+
known(runner: RunnerId): DiscoveredModel[];
|
|
3394
|
+
/** Discover the runners' models, spawning their CLIs where the resolver has none cached, and remember them. */
|
|
3395
|
+
discover(runners: RunnerId[]): Promise<ModelsByRunner>;
|
|
3396
|
+
/**
|
|
3397
|
+
* Keep what an admitted runner was found to offer, for the next coercion's
|
|
3398
|
+
* effort clamping. An empty list is discovery having found nothing, not a
|
|
3399
|
+
* runner offering nothing, so it never displaces what is known.
|
|
3400
|
+
*/
|
|
3401
|
+
admit(runner: RunnerId, models: DiscoveredModel[]): void;
|
|
3402
|
+
/** Session boundaries are hard: nothing discovered for one goal informs the next. */
|
|
3403
|
+
reset(): void;
|
|
3404
|
+
modes(runners: RunnerId[]): Record<RunnerId, RunnerModeInfo[]>;
|
|
3405
|
+
/**
|
|
3406
|
+
* What a planner may assign right now: every enabled runner, its modes, and
|
|
3407
|
+
* its allowlisted models. Discovers a runner's models the first time it is
|
|
3408
|
+
* asked for.
|
|
3409
|
+
*/
|
|
3410
|
+
live(): Promise<TaskQueryCatalog>;
|
|
3411
|
+
queryCatalog(runners: RunnerId[]): TaskQueryCatalog;
|
|
3412
|
+
/**
|
|
3413
|
+
* The catalog a model/task-mode edit is checked against — the same
|
|
3414
|
+
* discovered models and manifest modes the per-turn catalog block shows the
|
|
3415
|
+
* planner, so a refusal here can never name something invalid that the
|
|
3416
|
+
* planner was never told about. The catalog is not filtered by the
|
|
3417
|
+
* allowlist here — `checkModelAndModeValidity` narrows by allowlist itself,
|
|
3418
|
+
* the same way `coerceAssignments` does.
|
|
3419
|
+
*/
|
|
3420
|
+
edit(runners?: RunnerId[]): EditCatalog;
|
|
3421
|
+
/** What a runner offers, as `runnerAssignment` needs it. Spawns the runner's CLI to list models. */
|
|
3422
|
+
runner(runner: RunnerId): Promise<RunnerCatalog>;
|
|
3423
|
+
/**
|
|
3424
|
+
* The one place planning discovers what it may draw from: the runners'
|
|
3425
|
+
* models and their modes. `filteredModels` is the allowlisted view a prompt
|
|
3426
|
+
* may show; `modelsByRunner` stays whole because coercion needs real labels
|
|
3427
|
+
* and variants.
|
|
3428
|
+
*/
|
|
3429
|
+
planning(runners: RunnerId[]): Promise<{
|
|
3430
|
+
modelsByRunner: Partial<Record<string, DiscoveredModel[]>>;
|
|
3431
|
+
filteredModels: Partial<Record<string, DiscoveredModel[]>>;
|
|
3432
|
+
runnerModes: Record<string, RunnerModeInfo[]>;
|
|
3433
|
+
}>;
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3343
3436
|
/** The dialogue record a fork carries — what {@link PlannerConversation.clone} returns. */
|
|
3344
3437
|
interface ForkedDialogue {
|
|
3345
3438
|
conversationHistory: ConversationMessage[];
|
|
3346
3439
|
researchLog: ResearchLogEntry[];
|
|
3347
3440
|
}
|
|
3348
3441
|
|
|
3442
|
+
/** A user's message as sent, and the skills its `/name` tokens load. */
|
|
3443
|
+
interface SkillInvocation {
|
|
3444
|
+
text: string;
|
|
3445
|
+
skills: SkillLoad[];
|
|
3446
|
+
}
|
|
3447
|
+
/**
|
|
3448
|
+
* A path with the home directory written `~`, for a notice or listing. On
|
|
3449
|
+
* Windows the drive letter's case is not significant and the separators are
|
|
3450
|
+
* rendered `/`, so the same skill reads alike wherever the session reloads.
|
|
3451
|
+
*/
|
|
3452
|
+
declare function abbreviateHome(file: string, home?: string, platform?: NodeJS.Platform): string;
|
|
3453
|
+
/**
|
|
3454
|
+
* Resolve the `/skill-name` tokens in a message to snapshots of the skills they
|
|
3455
|
+
* name. Pure and exported so surfaces can resolve without a full Session. The text itself is never rewritten.
|
|
3456
|
+
*
|
|
3457
|
+
* Every distinct skill named loads, once, in the order first named. A token
|
|
3458
|
+
* naming no skill is plain text, wherever it stands — a whole message of
|
|
3459
|
+
* `/unknown` included: embedded in a sentence it is as likely to be incidental
|
|
3460
|
+
* text (a path, an example command) as a typo'd invocation. So is one naming
|
|
3461
|
+
* a skill with `user-invocable: false`, which only the model may invoke.
|
|
3462
|
+
*/
|
|
3463
|
+
declare function resolveSkillInvocation(text: string, skillsService: Pick<SkillsService, 'findSkill'>, home?: string): SkillInvocation;
|
|
3464
|
+
/**
|
|
3465
|
+
* What the planner receives for a user message: the bodies of the skills it
|
|
3466
|
+
* loaded, then the message as the user wrote it. The one composition for a
|
|
3467
|
+
* live send and for a replay of the transcript, so a resumed conversation
|
|
3468
|
+
* hands the planner what the live one did.
|
|
3469
|
+
*/
|
|
3470
|
+
declare function plannerMessage(text: string, loads: readonly SkillLoad[]): string;
|
|
3471
|
+
/**
|
|
3472
|
+
* The transcript as the planner is to see it on a replay: each user message
|
|
3473
|
+
* carries the skills loaded after it, composed by {@link plannerMessage}, and
|
|
3474
|
+
* the load entries themselves are folded away. Sessions saved before skill
|
|
3475
|
+
* loads existed hold the expanded text in the message and replay unchanged.
|
|
3476
|
+
*/
|
|
3477
|
+
declare function plannerTranscript(history: readonly ConversationMessage[]): ConversationMessage[];
|
|
3478
|
+
|
|
3479
|
+
/**
|
|
3480
|
+
* The planner turn (see CONTEXT.md): the one piece of planner work that holds
|
|
3481
|
+
* the conversation, from its claim to its settled outcome. Its signal is what a
|
|
3482
|
+
* stop aborts.
|
|
3483
|
+
*/
|
|
3484
|
+
declare class PlannerTurn {
|
|
3485
|
+
private readonly controller;
|
|
3486
|
+
private dropped;
|
|
3487
|
+
get signal(): AbortSignal;
|
|
3488
|
+
/** The plan it was answering was dropped under it, so nothing it settles may land. */
|
|
3489
|
+
get abandoned(): boolean;
|
|
3490
|
+
stop(): void;
|
|
3491
|
+
abandon(): void;
|
|
3492
|
+
}
|
|
3349
3493
|
/** 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. */
|
|
3350
3494
|
type ToolRead<T> = {
|
|
3351
3495
|
status: 'refused';
|
|
@@ -3386,7 +3530,7 @@ interface PlannerConversationHost {
|
|
|
3386
3530
|
* conversation never reaches into execution state directly.
|
|
3387
3531
|
*/
|
|
3388
3532
|
liveOutput: LiveOutputLookup;
|
|
3389
|
-
|
|
3533
|
+
isExecuting(): boolean;
|
|
3390
3534
|
/** The session's single mutation ritual: op → persist → notify (default: the plan). */
|
|
3391
3535
|
mutate(op: () => boolean, notify?: () => void): LegacyPlanState | null;
|
|
3392
3536
|
broadcast: SessionBroadcaster;
|
|
@@ -3394,13 +3538,19 @@ interface PlannerConversationHost {
|
|
|
3394
3538
|
broadcastPlan(turnId?: string): void;
|
|
3395
3539
|
/** Validate a batch against live state. Pure — nothing is applied. */
|
|
3396
3540
|
validateOps(ops: TaskOp[]): ApplyTaskOpsResult;
|
|
3541
|
+
/** The workspace's skill catalog under its repo group's layout, which the skills a plan or edit attaches are checked against. */
|
|
3542
|
+
taskSkills(): SkillLookup;
|
|
3543
|
+
/** Tell the user something the transcript does not carry. */
|
|
3544
|
+
notice(level: SessionNotice['level'], message: string): void;
|
|
3397
3545
|
/** Load planner-produced tasks: an edit keeps run state, a commit starts over. Returns how many landed. */
|
|
3398
3546
|
adoptTasks(tasks: readonly Task[], how: 'edit' | 'commit'): number;
|
|
3399
3547
|
capturePrd(text: string): void;
|
|
3400
3548
|
/** Park a structural edit until the next batch boundary. Returns the queue length. */
|
|
3401
|
-
queueEdit(
|
|
3549
|
+
queueEdit(message: SkillInvocation): number;
|
|
3402
3550
|
/** Wake a scheduler an applied edit may have unblocked. */
|
|
3403
3551
|
afterEdit(): Promise<void>;
|
|
3552
|
+
/** The planner turn was stopped or abandoned: whatever it is waiting on (a parked approval) will never be answered. */
|
|
3553
|
+
turnAborted(): void;
|
|
3404
3554
|
}
|
|
3405
3555
|
/**
|
|
3406
3556
|
* A conversation edit (rewind, fork) the conversation refused because the
|
|
@@ -3419,6 +3569,25 @@ declare class ConversationEditError extends Error {
|
|
|
3419
3569
|
declare class ConversationBusyError extends ConversationEditError {
|
|
3420
3570
|
constructor(operation: string);
|
|
3421
3571
|
}
|
|
3572
|
+
/**
|
|
3573
|
+
* A planner turn that settled after the plan it was answering was dropped (a
|
|
3574
|
+
* new plan, another session adopted, the session closed), or after its call
|
|
3575
|
+
* was cut off by something other than its own stop. Nothing it produced was
|
|
3576
|
+
* committed: landing it would write one session's reply into another's
|
|
3577
|
+
* transcript.
|
|
3578
|
+
*/
|
|
3579
|
+
declare class PlannerTurnDiscardedError extends Error {
|
|
3580
|
+
constructor(options?: ErrorOptions);
|
|
3581
|
+
}
|
|
3582
|
+
/**
|
|
3583
|
+
* The user stopped the turn and the backend reported that as a thrown error
|
|
3584
|
+
* rather than a settled reply. Typed so a surface can stay quiet for it without
|
|
3585
|
+
* reading the message: some SDKs' abort errors are plain `Error`s by name, and
|
|
3586
|
+
* a real failure can mention "aborted" too.
|
|
3587
|
+
*/
|
|
3588
|
+
declare class PlannerTurnStoppedError extends Error {
|
|
3589
|
+
constructor(options?: ErrorOptions);
|
|
3590
|
+
}
|
|
3422
3591
|
/** A user message a rewind can fork the conversation from just before. */
|
|
3423
3592
|
interface RewindTarget {
|
|
3424
3593
|
/** Position in the transcript — what {@link PlannerConversation.cloneBefore} takes. */
|
|
@@ -3449,8 +3618,6 @@ interface TranscriptSnapshot {
|
|
|
3449
3618
|
}
|
|
3450
3619
|
interface ReplyOptions {
|
|
3451
3620
|
signal?: AbortSignal;
|
|
3452
|
-
/** The user's words before skill expansion — what a mid-run queue replays later. */
|
|
3453
|
-
verbatim?: string;
|
|
3454
3621
|
}
|
|
3455
3622
|
/**
|
|
3456
3623
|
* The planner conversation (ADR-0002), end to end: the persisted dialogue
|
|
@@ -3474,15 +3641,35 @@ declare class PlannerConversation {
|
|
|
3474
3641
|
private persisted;
|
|
3475
3642
|
/** Saves an execution event made while a turn may be in flight; see {@link restore}. */
|
|
3476
3643
|
private savedInBackground;
|
|
3477
|
-
private
|
|
3478
|
-
private compacting;
|
|
3644
|
+
private live;
|
|
3479
3645
|
private openTurn;
|
|
3480
3646
|
constructor(host: PlannerConversationHost);
|
|
3481
3647
|
get transcript(): readonly ConversationMessage[];
|
|
3482
|
-
/** Whether a
|
|
3648
|
+
/** Whether a planner turn holds the conversation. */
|
|
3483
3649
|
get isTurnInFlight(): boolean;
|
|
3650
|
+
/** Stop the planner turn in flight; it settles as stopped. False when none is. */
|
|
3651
|
+
stopTurn(): boolean;
|
|
3652
|
+
/**
|
|
3653
|
+
* Drop the planner turn in flight together with the plan it was answering:
|
|
3654
|
+
* it is stopped, whatever it settles is discarded, and the conversation is
|
|
3655
|
+
* free at once rather than when the abandoned turn finishes unwinding.
|
|
3656
|
+
*/
|
|
3657
|
+
abandonTurn(): void;
|
|
3658
|
+
/**
|
|
3659
|
+
* Run planner work that is not a conversation turn — one-shot plan
|
|
3660
|
+
* generation — as the planner turn, so it is stopped, refused and superseded
|
|
3661
|
+
* like one. It starts a fresh plan, so it supersedes the turn in flight.
|
|
3662
|
+
*/
|
|
3663
|
+
hold<T>(signal: AbortSignal | undefined, body: (turn: PlannerTurn) => Promise<T>): Promise<T>;
|
|
3664
|
+
/**
|
|
3665
|
+
* Take the conversation for a new planner turn. A caller's own signal stops
|
|
3666
|
+
* the turn too; the relay is detached on release because a caller may reuse
|
|
3667
|
+
* that signal, and a stale listener would stop the next turn with it.
|
|
3668
|
+
*/
|
|
3669
|
+
private claim;
|
|
3484
3670
|
/** The user turn being answered, for what the host raises during it — an approval the turn's research asks for. */
|
|
3485
3671
|
get currentTurnId(): string | undefined;
|
|
3672
|
+
recordPlannerSkill(skill: SkillLoad): boolean;
|
|
3486
3673
|
/**
|
|
3487
3674
|
* Hand the open turn a plan (already validated) or a task edit. The turn
|
|
3488
3675
|
* settles with it exactly as with the same plan or ops parsed out of its
|
|
@@ -3512,6 +3699,7 @@ declare class PlannerConversation {
|
|
|
3512
3699
|
timestamp?: string;
|
|
3513
3700
|
kind?: ConversationMessage['kind'];
|
|
3514
3701
|
}): void;
|
|
3702
|
+
private appendEntries;
|
|
3515
3703
|
/** Swap the whole transcript. The live context no longer matches it, so pair with {@link reset}. */
|
|
3516
3704
|
replace(messages: readonly ConversationMessage[]): void;
|
|
3517
3705
|
snapshot(): TranscriptSnapshot | null;
|
|
@@ -3583,20 +3771,30 @@ declare class PlannerConversation {
|
|
|
3583
3771
|
* Call inside the host's mutation ritual.
|
|
3584
3772
|
*/
|
|
3585
3773
|
recordQueuedEdits(messages: string[], taskCount: number): void;
|
|
3774
|
+
/**
|
|
3775
|
+
* What the skill check of a landed plan or edit warned about, kept in the
|
|
3776
|
+
* transcript so every surface shows it, on reload too, and not only the
|
|
3777
|
+
* planner that may have read it in a tool result. Call inside the host's
|
|
3778
|
+
* mutation ritual, so the broadcast plan carries it.
|
|
3779
|
+
*/
|
|
3780
|
+
recordSkillWarnings(warnings: readonly string[], timestamp?: string): void;
|
|
3586
3781
|
/**
|
|
3587
3782
|
* Queued edits the between-batches drain could not apply. Recorded so the
|
|
3588
3783
|
* transcript does not go on promising a change that never landed. Call
|
|
3589
3784
|
* inside the host's mutation ritual.
|
|
3590
3785
|
*/
|
|
3591
3786
|
recordQueuedEditsFailed(messages: string[], reason: string): void;
|
|
3592
|
-
/**
|
|
3593
|
-
|
|
3787
|
+
/**
|
|
3788
|
+
* Open the conversation on the host's fresh plan: the goal is its first
|
|
3789
|
+
* message. `prepare` (discovery) runs inside the turn, so a stop reaches it.
|
|
3790
|
+
*/
|
|
3791
|
+
start(goal: SkillInvocation, prepare: () => Promise<ConversationOpening>, signal?: AbortSignal): Promise<LegacyPlanState>;
|
|
3594
3792
|
/**
|
|
3595
3793
|
* Every later user message, from the transcript append to a persisted
|
|
3596
3794
|
* outcome. A turn that throws before anything was persisted takes its own
|
|
3597
3795
|
* writes back out, so session memory never drifts from disk and the UI.
|
|
3598
3796
|
*/
|
|
3599
|
-
reply(message: string, options?: ReplyOptions): Promise<LegacyPlanState>;
|
|
3797
|
+
reply(message: string | SkillInvocation, options?: ReplyOptions): Promise<LegacyPlanState>;
|
|
3600
3798
|
private replyTurn;
|
|
3601
3799
|
/**
|
|
3602
3800
|
* Whether a settled structural edit reaches work a runner is executing. Only
|
|
@@ -3607,7 +3805,28 @@ declare class PlannerConversation {
|
|
|
3607
3805
|
*/
|
|
3608
3806
|
private editTouchesLiveWork;
|
|
3609
3807
|
private assertIdle;
|
|
3610
|
-
|
|
3808
|
+
/**
|
|
3809
|
+
* Refuse to land a turn that no longer belongs here: it was abandoned, its
|
|
3810
|
+
* plan is no longer the host's, or its call was cut off by something other
|
|
3811
|
+
* than its own stop (`IAiService.reset` under a plan change) — what such a
|
|
3812
|
+
* call hands back is a fragment of an answer to a dialogue that is gone.
|
|
3813
|
+
*/
|
|
3814
|
+
private assertCurrent;
|
|
3815
|
+
/**
|
|
3816
|
+
* {@link assertCurrent} on the far side of an await that precedes a plan
|
|
3817
|
+
* mutation: the skill check waits on git, and a stop, rewind or session
|
|
3818
|
+
* switch in that window drops the edit instead of landing it on whatever
|
|
3819
|
+
* plan is current by then. A stop counts here because nothing has landed
|
|
3820
|
+
* yet — the user asked for the turn to end before it changed the plan.
|
|
3821
|
+
*/
|
|
3822
|
+
private assertStillCurrent;
|
|
3823
|
+
/**
|
|
3824
|
+
* A live conversation is only safe to continue in-place when it also
|
|
3825
|
+
* matches the model/effort configured right now — a harness planner's
|
|
3826
|
+
* running process was spawned with the old one baked in and cannot pick up
|
|
3827
|
+
* a switch (ADR-0009). Otherwise the turn resumes from the transcript.
|
|
3828
|
+
*/
|
|
3829
|
+
private canContinueLive;
|
|
3611
3830
|
/**
|
|
3612
3831
|
* Bracket one user turn with its start and end, under an id minted here:
|
|
3613
3832
|
* the turn is where the stream a surface draws begins and ends, and only the
|
|
@@ -3615,6 +3834,7 @@ declare class PlannerConversation {
|
|
|
3615
3834
|
*/
|
|
3616
3835
|
private userTurn;
|
|
3617
3836
|
private requirePlan;
|
|
3837
|
+
/** The message as typed, then one entry per skill it loaded, sharing its timestamp so a reload keeps them together. */
|
|
3618
3838
|
private recordUser;
|
|
3619
3839
|
private recordResearch;
|
|
3620
3840
|
/**
|
|
@@ -3652,12 +3872,15 @@ declare class PlannerConversation {
|
|
|
3652
3872
|
*/
|
|
3653
3873
|
private taskQueryAnswer;
|
|
3654
3874
|
/**
|
|
3655
|
-
* Drive a planner turn to a persisted, broadcast
|
|
3656
|
-
* atomically; validation failures are fed back to
|
|
3657
|
-
* silent retries, then surfaced as a message with the
|
|
3658
|
-
* first turn and every later turn route through here —
|
|
3875
|
+
* Drive a planner turn, its reads already drained, to a persisted, broadcast
|
|
3876
|
+
* outcome. Task edits apply atomically; validation failures are fed back to
|
|
3877
|
+
* the model for up to 2 silent retries, then surfaced as a message with the
|
|
3878
|
+
* plan untouched. The first turn and every later turn route through here —
|
|
3879
|
+
* one path, not two.
|
|
3659
3880
|
*/
|
|
3660
3881
|
private settle;
|
|
3882
|
+
/** A name not found at submit only warns: a task the attaching one depends on may create it. */
|
|
3883
|
+
private warnSkills;
|
|
3661
3884
|
/** Validate + commit a task_ops turn atomically. Returns the errors on rejection (plan untouched). */
|
|
3662
3885
|
private applyTaskOps;
|
|
3663
3886
|
/** Commit a settled (non-task_ops) turn through the host's mutation ritual. */
|
|
@@ -3686,42 +3909,48 @@ declare class PlannerConversation {
|
|
|
3686
3909
|
private currentPlanLines;
|
|
3687
3910
|
}
|
|
3688
3911
|
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3912
|
+
interface UserSettings {
|
|
3913
|
+
modelAllowlist?: Record<string, string[]>;
|
|
3914
|
+
/** Last model (and its thinking effort) the user chose for each planner backend, keyed by AiProvider id. */
|
|
3915
|
+
plannerModels?: Record<string, {
|
|
3916
|
+
model: string;
|
|
3917
|
+
effort?: string;
|
|
3918
|
+
}>;
|
|
3919
|
+
/**
|
|
3920
|
+
* Runners the user picked for planning. Absent — not empty — is what falls
|
|
3921
|
+
* back to the environment's defaults; `[]` is a deliberate "none of them".
|
|
3922
|
+
*/
|
|
3923
|
+
enabledRunners?: string[];
|
|
3924
|
+
}
|
|
3925
|
+
/**
|
|
3926
|
+
* The model allowlist, remembered planner models and enabled runners are shared
|
|
3927
|
+
* across processes by default. `ORDEWELL_SETTINGS_PATH` lets independent runs
|
|
3928
|
+
* use separate files: otherwise a write in one run would change another's
|
|
3929
|
+
* settings when `getAll()` detects the new mtime.
|
|
3930
|
+
*/
|
|
3931
|
+
declare function getSettingsPath(): string;
|
|
3932
|
+
declare class SettingsService {
|
|
3933
|
+
private filePath;
|
|
3934
|
+
private cache;
|
|
3935
|
+
private cachedMtimeMs;
|
|
3936
|
+
constructor(filePath?: string);
|
|
3937
|
+
getAll(): UserSettings;
|
|
3938
|
+
private fileMtimeMs;
|
|
3939
|
+
getModelAllowlist(runner: string): string[] | undefined;
|
|
3940
|
+
setModelAllowlist(runner: string, ids: string[] | undefined): void;
|
|
3941
|
+
getPlannerModel(provider: string): {
|
|
3942
|
+
model: string;
|
|
3943
|
+
effort?: string;
|
|
3944
|
+
} | undefined;
|
|
3945
|
+
setPlannerModel(provider: string, entry: {
|
|
3946
|
+
model: string;
|
|
3947
|
+
effort?: string;
|
|
3948
|
+
} | undefined): void;
|
|
3949
|
+
getEnabledRunners(): string[] | undefined;
|
|
3950
|
+
setEnabledRunners(ids: string[]): void;
|
|
3951
|
+
private load;
|
|
3952
|
+
private persist;
|
|
3694
3953
|
}
|
|
3695
|
-
interface SkillInfo {
|
|
3696
|
-
name: string;
|
|
3697
|
-
description: string;
|
|
3698
|
-
metadata: SkillMetadata;
|
|
3699
|
-
/** Full content of SKILL.md with frontmatter stripped */
|
|
3700
|
-
content: string;
|
|
3701
|
-
/** Absolute path to the SKILL.md file */
|
|
3702
|
-
path: string;
|
|
3703
|
-
/** Whether this came from global (~/.ordewell/skills/) or local (.ordewell/skills/) */
|
|
3704
|
-
source: 'global' | 'local';
|
|
3705
|
-
}
|
|
3706
|
-
declare class SkillsService {
|
|
3707
|
-
private workspaceRoot?;
|
|
3708
|
-
constructor(workspaceRoot?: string | undefined);
|
|
3709
|
-
private localDir;
|
|
3710
|
-
private globalDir;
|
|
3711
|
-
private readSeedManifest;
|
|
3712
|
-
private recordSeed;
|
|
3713
|
-
/** A seed the user never edited: safe to replace with a newer built-in. */
|
|
3714
|
-
private isUntouchedSeed;
|
|
3715
|
-
private seed;
|
|
3716
|
-
seedBuiltinSkill(name: string): boolean;
|
|
3717
|
-
/** Removes a retired built-in's seed from the global dir, but only if it's untouched by the user. */
|
|
3718
|
-
private isUnmodifiedRetiredSeed;
|
|
3719
|
-
private pruneRetired;
|
|
3720
|
-
findSkill(name: string): SkillInfo | undefined;
|
|
3721
|
-
listSkills(): SkillInfo[];
|
|
3722
|
-
getSkillContent(name: string): string | undefined;
|
|
3723
|
-
}
|
|
3724
|
-
declare function createSkillsService(workspaceRoot?: string): SkillsService;
|
|
3725
3954
|
|
|
3726
3955
|
/** The `planner_usage` member of the session broadcast union. */
|
|
3727
3956
|
type PlannerUsageMessage = Extract<SessionMessage, {
|
|
@@ -3766,8 +3995,12 @@ interface SessionEventRelayDeps {
|
|
|
3766
3995
|
/** What a task's waiting checkpoint asks, whole. */
|
|
3767
3996
|
checkpointQuestion?: (taskId: string) => string | undefined;
|
|
3768
3997
|
}
|
|
3769
|
-
/**
|
|
3770
|
-
|
|
3998
|
+
/**
|
|
3999
|
+
* Every orchestrator event the relay announces. `onTaskSettled` is persistence
|
|
4000
|
+
* only and `onQueueReady` is the Session's cue to drain its queue, so both are
|
|
4001
|
+
* the Session's alone.
|
|
4002
|
+
*/
|
|
4003
|
+
type RelayObserver = Required<Omit<OrchestratorObserver, 'onTaskSettled' | 'onQueueReady'>>;
|
|
3771
4004
|
/**
|
|
3772
4005
|
* Turns orchestrator and planner events into {@link SessionMessage}
|
|
3773
4006
|
* broadcasts — the one place a surface's view of a Session is produced. It
|
|
@@ -3860,31 +4093,11 @@ interface GeneratePlanOptions {
|
|
|
3860
4093
|
type SessionPlanner = Pick<Planner, 'generate' | 'modifyDuringExecution'>;
|
|
3861
4094
|
/** Runtime prefs read live — may toggle between operations. */
|
|
3862
4095
|
interface SessionRuntimeSettings {
|
|
3863
|
-
tddEnabled: boolean;
|
|
3864
|
-
verificationEnabled?: boolean;
|
|
3865
4096
|
modelAllowlist?: Record<string, string[]>;
|
|
3866
|
-
/** Read once as a run starts, never per spawn (ADR-0018, S1). Absent means terminal. */
|
|
3867
|
-
runnerTransport?: RunnerTransport;
|
|
3868
4097
|
/** Absent means the user never chose, and `config.enabledRunners` (the host's defaults) decides. */
|
|
3869
4098
|
enabledRunners?: RunnerId[];
|
|
3870
4099
|
}
|
|
3871
4100
|
declare function sessionRuntimeSettings(settings: UserSettings): SessionRuntimeSettings;
|
|
3872
|
-
/**
|
|
3873
|
-
* Resolve `/skill-name` invocations to their skill's markdown content. Pure
|
|
3874
|
-
* and exported so surfaces and verification can drive substitution without a
|
|
3875
|
-
* full Session.
|
|
3876
|
-
*
|
|
3877
|
-
* A message that is *only* `/skill-name` keeps the legacy whole-message
|
|
3878
|
-
* behaviour: an unknown skill becomes a notice naming what IS available,
|
|
3879
|
-
* instead of a bare slash token a runner would mis-resolve in its own skills
|
|
3880
|
-
* directory. Anywhere else in a message, a matching token is spliced in place
|
|
3881
|
-
* (surrounding text is untouched); a token that doesn't name a real skill is
|
|
3882
|
-
* left as plain text rather than raising a notice, since embedded in a
|
|
3883
|
-
* sentence it's as likely to be incidental text (a path, an example command)
|
|
3884
|
-
* as a typo'd invocation. The same skill name repeated only expands its first
|
|
3885
|
-
* occurrence — later repeats stay literal.
|
|
3886
|
-
*/
|
|
3887
|
-
declare function resolveSkillInvocation(text: string, skillsService: Pick<SkillsService, 'findSkill' | 'listSkills'>): string;
|
|
3888
4101
|
/** Where a fork landed: the new session's id, and what adopting it needs. */
|
|
3889
4102
|
interface ConversationFork {
|
|
3890
4103
|
sessionId: string;
|
|
@@ -3900,14 +4113,14 @@ type SaveSession = (plan: LegacyPlanState, goal: string, workspace: string, sess
|
|
|
3900
4113
|
/**
|
|
3901
4114
|
* Everything a delivery surface constructs to host a session. Structural config
|
|
3902
4115
|
* (orchestratorModel, providerModelLists) is snapshotted inside `config` at
|
|
3903
|
-
* construction and never re-read from the environment. Runtime settings
|
|
3904
|
-
*
|
|
4116
|
+
* construction and never re-read from the environment. Runtime settings
|
|
4117
|
+
* (enabled runners) are read live via the `settings` callback so a
|
|
3905
4118
|
* toggle between operations takes effect.
|
|
3906
4119
|
*/
|
|
3907
4120
|
interface SessionDeps {
|
|
3908
4121
|
config: IConfig;
|
|
3909
4122
|
notifications: INotification;
|
|
3910
|
-
runner:
|
|
4123
|
+
runner: IRunner;
|
|
3911
4124
|
registry: RunnerRegistry;
|
|
3912
4125
|
/** Resolves the workspace root for the orchestrator (lazy — VS Code can change it). */
|
|
3913
4126
|
workspaceRoot: () => string;
|
|
@@ -3919,7 +4132,7 @@ interface SessionDeps {
|
|
|
3919
4132
|
onNotice?: (notice: SessionNotice) => void;
|
|
3920
4133
|
/** Shared across sessions — sole producer of model catalogs and routing lists. */
|
|
3921
4134
|
modelResolver: ModelResolver;
|
|
3922
|
-
/** Live runtime settings (
|
|
4135
|
+
/** Live runtime settings (enabled runners). Read at each operation that needs them. */
|
|
3923
4136
|
settings: () => SessionRuntimeSettings;
|
|
3924
4137
|
/**
|
|
3925
4138
|
* Host-assigned session id. When set, every persist writes under this id so
|
|
@@ -3940,11 +4153,7 @@ interface SessionDeps {
|
|
|
3940
4153
|
* over the session's workspace root.
|
|
3941
4154
|
*/
|
|
3942
4155
|
skillsService?: SkillsService;
|
|
3943
|
-
/**
|
|
3944
|
-
* Where a task's output and final answer are read. Defaults to the agents'
|
|
3945
|
-
* own transcripts under the user's home; tests inject one that never
|
|
3946
|
-
* touches the disk.
|
|
3947
|
-
*/
|
|
4156
|
+
/** Where a task's output and final answer are read. */
|
|
3948
4157
|
taskOutput?: TaskOutputSource;
|
|
3949
4158
|
/**
|
|
3950
4159
|
* Git worktree isolation (ADR-0013). Defaults to git itself, gated by
|
|
@@ -3967,10 +4176,11 @@ declare function createSession(deps: SessionDeps): Session;
|
|
|
3967
4176
|
/** What {@link createSession} hands a Session: every collaborator, already built and wired. */
|
|
3968
4177
|
interface SessionParts {
|
|
3969
4178
|
config: IConfig;
|
|
3970
|
-
|
|
4179
|
+
catalog: SessionCatalog;
|
|
3971
4180
|
workspace: string;
|
|
3972
4181
|
fsAdapter: IFileSystem;
|
|
3973
4182
|
broadcast: SessionBroadcaster;
|
|
4183
|
+
notifications: INotification;
|
|
3974
4184
|
onNotice?: (notice: SessionNotice) => void;
|
|
3975
4185
|
modelResolver: ModelResolver;
|
|
3976
4186
|
settings: () => SessionRuntimeSettings;
|
|
@@ -3986,7 +4196,7 @@ interface SessionParts {
|
|
|
3986
4196
|
approvals: PendingApprovals;
|
|
3987
4197
|
approvalPolicy: ApprovalPolicy;
|
|
3988
4198
|
fetcher: IWebFetcher;
|
|
3989
|
-
skillsService: Pick<SkillsService, 'findSkill' | 'listSkills'>;
|
|
4199
|
+
skillsService: Pick<SkillsService, 'findSkill' | 'listSkills' | 'searchedDirs' | 'forRoot'>;
|
|
3990
4200
|
saveSession: SaveSession;
|
|
3991
4201
|
/** The conversation's host is the Session itself, so only the Session can make it. */
|
|
3992
4202
|
conversation: (host: PlannerConversationHost) => PlannerConversation;
|
|
@@ -4012,11 +4222,12 @@ declare class Session {
|
|
|
4012
4222
|
private readonly runs;
|
|
4013
4223
|
private readonly store;
|
|
4014
4224
|
private readonly config;
|
|
4015
|
-
private readonly
|
|
4225
|
+
private readonly catalog;
|
|
4016
4226
|
private plan;
|
|
4017
4227
|
private goal;
|
|
4018
4228
|
private workspace;
|
|
4019
4229
|
private readonly broadcast;
|
|
4230
|
+
private readonly notifications;
|
|
4020
4231
|
private readonly onNotice?;
|
|
4021
4232
|
private readonly modelResolver;
|
|
4022
4233
|
private readonly fsAdapter;
|
|
@@ -4025,8 +4236,12 @@ declare class Session {
|
|
|
4025
4236
|
private readonly fetcher;
|
|
4026
4237
|
private readonly settingsFn;
|
|
4027
4238
|
private readonly save;
|
|
4028
|
-
/**
|
|
4029
|
-
private
|
|
4239
|
+
/** The queue drain in flight, which a second call joins; see {@link processQueuedMessages}. */
|
|
4240
|
+
private queueDrain;
|
|
4241
|
+
/** The queued messages the planner has been given, no longer the user's to take back. */
|
|
4242
|
+
private drainingIds;
|
|
4243
|
+
/** User controls in flight; see {@link withSave}. */
|
|
4244
|
+
private controlsInFlight;
|
|
4030
4245
|
private unsubObserver;
|
|
4031
4246
|
private readonly hostSessionId?;
|
|
4032
4247
|
private currentSessionId;
|
|
@@ -4059,7 +4274,7 @@ declare class Session {
|
|
|
4059
4274
|
/**
|
|
4060
4275
|
* The relay announces every orchestrator event; this adds the saves some of
|
|
4061
4276
|
* them owe, each made before the announcement so no surface sees state the
|
|
4062
|
-
* disk lacks.
|
|
4277
|
+
* disk lacks, and drains the queue the scheduler parked behind.
|
|
4063
4278
|
*/
|
|
4064
4279
|
private observer;
|
|
4065
4280
|
/**
|
|
@@ -4094,43 +4309,8 @@ declare class Session {
|
|
|
4094
4309
|
* session.
|
|
4095
4310
|
*/
|
|
4096
4311
|
reset(): void;
|
|
4097
|
-
/**
|
|
4098
|
-
* What a planner may assign right now: every enabled runner, its modes, and
|
|
4099
|
-
* its allowlisted models — read as of this call, so a runner enabled or an
|
|
4100
|
-
* allowlist edited since planning started is in it (#69). Discovers a
|
|
4101
|
-
* runner's models the first time it is asked for.
|
|
4102
|
-
*/
|
|
4312
|
+
/** What a planner may assign right now; see {@link SessionCatalog.live}. */
|
|
4103
4313
|
liveCatalog(): Promise<TaskQueryCatalog>;
|
|
4104
|
-
private catalogOf;
|
|
4105
|
-
private runnerModesFor;
|
|
4106
|
-
/**
|
|
4107
|
-
* The catalog a model/task-mode edit is checked against — the same
|
|
4108
|
-
* discovered models and manifest modes the per-turn catalog block shows the
|
|
4109
|
-
* planner, so a refusal here can never name something invalid that the
|
|
4110
|
-
* planner was never told about. The catalog is not filtered by the
|
|
4111
|
-
* allowlist here — {@link checkModelAndModeValidity} narrows by
|
|
4112
|
-
* allowlist itself, the same way `coerceAssignments` does.
|
|
4113
|
-
*/
|
|
4114
|
-
private editCatalog;
|
|
4115
|
-
/** The runners enabled right now — a toggle made since the session was built counts (#69). */
|
|
4116
|
-
private enabledRunners;
|
|
4117
|
-
/**
|
|
4118
|
-
* The allowlist in force right now. Unset means no restriction — falling
|
|
4119
|
-
* back to the one planning started under would keep a restriction the user
|
|
4120
|
-
* has since cleared.
|
|
4121
|
-
*/
|
|
4122
|
-
private allowlist;
|
|
4123
|
-
/**
|
|
4124
|
-
* The discovered catalog as the resolver holds it now, per runner, with this
|
|
4125
|
-
* session's own discovery as the fallback where the resolver has nothing
|
|
4126
|
-
* cached. The resolver's cache outlives this session's snapshot in both
|
|
4127
|
-
* directions — an allowlist picker re-discovers into it mid-session — and a
|
|
4128
|
-
* model allowed after that must reach the planner with its real label and
|
|
4129
|
-
* variants, not as an id-only stub. Never triggers discovery itself.
|
|
4130
|
-
*/
|
|
4131
|
-
private models;
|
|
4132
|
-
/** What a runner offers, as `runnerAssignment` needs it. Spawns the runner's CLI to list models. */
|
|
4133
|
-
private catalogFor;
|
|
4134
4314
|
get planState(): LegacyPlanState | null;
|
|
4135
4315
|
/**
|
|
4136
4316
|
* The live plan in the shape a saved session is read back as. The disk
|
|
@@ -4146,24 +4326,16 @@ declare class Session {
|
|
|
4146
4326
|
* nothing executing, and reporting it as executing is what left the plan
|
|
4147
4327
|
* unstartable after its last live task was cancelled.
|
|
4148
4328
|
*/
|
|
4149
|
-
get isExecuting(): boolean;
|
|
4150
4329
|
/** See {@link TaskOrchestrator.hasLiveWork} — a spawned runner, not merely an armed scheduler. */
|
|
4151
|
-
get
|
|
4330
|
+
get isExecuting(): boolean;
|
|
4152
4331
|
get status(): 'approved' | 'running' | 'completed';
|
|
4332
|
+
/** Whether a planner turn — a reply, a compaction, plan generation — holds the conversation. */
|
|
4333
|
+
get isPlannerBusy(): boolean;
|
|
4153
4334
|
/**
|
|
4154
|
-
*
|
|
4155
|
-
*
|
|
4156
|
-
* waiting on has no one left to serve, and denying it unblocks the research
|
|
4157
|
-
* loop instead of stranding it. Without this the request sat out its
|
|
4158
|
-
* five-minute timeout and the loop then carried on as if nothing had
|
|
4159
|
-
* happened — the abort was real, but invisible until long after the user
|
|
4160
|
-
* pressed stop.
|
|
4161
|
-
*
|
|
4162
|
-
* The listener is returned as a disposer rather than left attached: callers
|
|
4163
|
-
* own the signal and may reuse it, and a leaked listener would deny the
|
|
4164
|
-
* *next* turn's prompts the moment that stale signal aborted.
|
|
4335
|
+
* Stop the planner turn in flight. It still settles — a backend hands back
|
|
4336
|
+
* what it had — and ends as stopped. False when no turn is in flight.
|
|
4165
4337
|
*/
|
|
4166
|
-
|
|
4338
|
+
abortPlannerTurn(): boolean;
|
|
4167
4339
|
generatePlan(goal: string, runners: RunnerId[], options?: GeneratePlanOptions): Promise<LegacyPlanState>;
|
|
4168
4340
|
/**
|
|
4169
4341
|
* Kick off the planner conversation (ADR-0002): research + the first planner
|
|
@@ -4225,21 +4397,20 @@ declare class Session {
|
|
|
4225
4397
|
/** Whether the planner conversation is live (started and not yet committed to a plan). */
|
|
4226
4398
|
get isConversationActive(): boolean;
|
|
4227
4399
|
/**
|
|
4228
|
-
*
|
|
4229
|
-
*
|
|
4230
|
-
*
|
|
4231
|
-
*
|
|
4232
|
-
* the planner as a notice naming what IS available, rather than passing a
|
|
4233
|
-
* bare /unknown through to be mis-resolved.
|
|
4400
|
+
* The skills a message's `/skill-name` tokens load, snapshotted here so the
|
|
4401
|
+
* planner gets Ordewell's skill rather than a runner (Claude Code, OpenCode)
|
|
4402
|
+
* resolving the token in its own skills directory. The message stays as
|
|
4403
|
+
* typed.
|
|
4234
4404
|
*/
|
|
4235
4405
|
private resolveSkillInvocation;
|
|
4236
4406
|
/**
|
|
4237
|
-
* The one
|
|
4238
|
-
*
|
|
4239
|
-
*
|
|
4240
|
-
* `modelsByRunner` stays whole because coercion needs real labels and variants.
|
|
4407
|
+
* The one catalog every planner path reads — its skill catalogs, `/name`,
|
|
4408
|
+
* and the check of what a plan or an edit attaches — over the folders the
|
|
4409
|
+
* workspace's tasks will read at spawn.
|
|
4241
4410
|
*/
|
|
4242
|
-
private
|
|
4411
|
+
private workspaceSkills;
|
|
4412
|
+
/** The catalog over workspace `roots`; the workspace root alone is the session's own. */
|
|
4413
|
+
private skillsAt;
|
|
4243
4414
|
private conversationOpening;
|
|
4244
4415
|
/**
|
|
4245
4416
|
* Load planner-produced tasks, coerced to the allowlist read live — it may
|
|
@@ -4276,7 +4447,19 @@ declare class Session {
|
|
|
4276
4447
|
cancelTask(taskId: string): Promise<void>;
|
|
4277
4448
|
markTaskComplete(taskId: string): Promise<void>;
|
|
4278
4449
|
markTaskIncomplete(taskId: string): Promise<void>;
|
|
4450
|
+
/**
|
|
4451
|
+
* Hand the queued edits to the planner. The Session does this itself each
|
|
4452
|
+
* time the scheduler parks behind the queue, so no surface has to; a caller
|
|
4453
|
+
* only needs it to await the drain. The messages stay queued until the
|
|
4454
|
+
* planner's answer is applied, so the scheduler stays paused behind them
|
|
4455
|
+
* meanwhile; one drain runs at a time, and a call made during it joins it.
|
|
4456
|
+
* Whatever was queued while it ran is drained after, before the run goes on.
|
|
4457
|
+
*/
|
|
4279
4458
|
processQueuedMessages(): Promise<void>;
|
|
4459
|
+
private drainQueue;
|
|
4460
|
+
/** Said through both channels: a host shows one or the other, never both (the daemon's toasts are no-ops). */
|
|
4461
|
+
private notice;
|
|
4462
|
+
private applyQueuedEdits;
|
|
4280
4463
|
/**
|
|
4281
4464
|
* Every finished task as the log records it: this run's own entries, plus
|
|
4282
4465
|
* the tasks earlier runs completed, which the log dropped when this run
|
|
@@ -4295,15 +4478,14 @@ declare class Session {
|
|
|
4295
4478
|
sendTaskMessage(taskId: string, text: string): string;
|
|
4296
4479
|
/**
|
|
4297
4480
|
* Force send (ADR-0023, F1): interrupt the task's running turn and deliver
|
|
4298
|
-
* this message next. Throws `TaskControlError` where a plain message would
|
|
4299
|
-
* and for a task on the terminal transport.
|
|
4481
|
+
* this message next. Throws `TaskControlError` where a plain message would.
|
|
4300
4482
|
*/
|
|
4301
4483
|
forceSendTaskMessage(taskId: string, text: string): string;
|
|
4302
4484
|
forceSendQueuedTaskMessage(taskId: string, id: string): boolean;
|
|
4303
4485
|
removeQueuedTaskMessage(taskId: string, id: string): boolean;
|
|
4304
4486
|
interruptTask(taskId: string): Promise<void>;
|
|
4305
4487
|
getQueuedMessages(): QueuedMessage[];
|
|
4306
|
-
/** Take back one unsent message; the plan's persisted queue follows so a reload cannot resurrect it. */
|
|
4488
|
+
/** Take back one unsent message — false once the planner has it; the plan's persisted queue follows so a reload cannot resurrect it. */
|
|
4307
4489
|
removeQueuedMessage(id: string): boolean;
|
|
4308
4490
|
setQueuedMessages(msgs: QueuedMessage[]): void;
|
|
4309
4491
|
/** Replay a run a dirty tree blocked, after stashing the tracked changes. */
|
|
@@ -4343,6 +4525,21 @@ declare class Session {
|
|
|
4343
4525
|
/** Add the task that merges a conflicted task's branch by hand; see {@link PlanEditor.addConflictResolver}. */
|
|
4344
4526
|
resolveConflictAsTask(taskId: string): Promise<LegacyPlanState | null>;
|
|
4345
4527
|
stopExecution(): void;
|
|
4528
|
+
/**
|
|
4529
|
+
* Run a user control and save what it changed before any surface hears of
|
|
4530
|
+
* it. Not a status hold, as {@link saved} is: these await spawns and git, so
|
|
4531
|
+
* a hold would stall every task's status for as long, and an
|
|
4532
|
+
* `execution_complete` the control triggers would overtake the status held
|
|
4533
|
+
* back — which a surface treats as the end of the stream. Instead each status
|
|
4534
|
+
* announced while one runs is saved first (see {@link observer}), as the
|
|
4535
|
+
* background save of an execution event: it may land mid planner turn. So
|
|
4536
|
+
* is the last one where the control is itself execution, not the user's
|
|
4537
|
+
* word on the plan (`background`).
|
|
4538
|
+
*/
|
|
4539
|
+
private withSave;
|
|
4540
|
+
private saveForControl;
|
|
4541
|
+
/** A control that finishes synchronously: its status is held until it is saved. */
|
|
4542
|
+
private saved;
|
|
4346
4543
|
/**
|
|
4347
4544
|
* The one mutation seam: every structural plan mutation runs the same
|
|
4348
4545
|
* ritual — store op → persist (which snapshots tasks from PlanStore) →
|
|
@@ -4399,9 +4596,261 @@ declare class PlanEditError extends Error {
|
|
|
4399
4596
|
constructor(message: string);
|
|
4400
4597
|
}
|
|
4401
4598
|
|
|
4599
|
+
/** What the user last picked for one planner backend. */
|
|
4600
|
+
interface PlannerModelChoice {
|
|
4601
|
+
model: string;
|
|
4602
|
+
effort?: string;
|
|
4603
|
+
}
|
|
4604
|
+
/**
|
|
4605
|
+
* A candidate model as this planner's catalog lists it. Deliberately plain
|
|
4606
|
+
* data: a harness planner's catalog is its runner's own model list and a
|
|
4607
|
+
* vendor's is a picker list (ADR-0009), and the rule below is the same for
|
|
4608
|
+
* both — so the caller normalizes, and this module never reaches for a
|
|
4609
|
+
* ModelResolver, a config or the network.
|
|
4610
|
+
*/
|
|
4611
|
+
interface PlannerModelCandidate {
|
|
4612
|
+
id: string;
|
|
4613
|
+
variants?: {
|
|
4614
|
+
id: string;
|
|
4615
|
+
}[];
|
|
4616
|
+
}
|
|
4617
|
+
interface PlannerModelRecall {
|
|
4618
|
+
model: string;
|
|
4619
|
+
effort: string;
|
|
4620
|
+
source: 'remembered' | 'catalog-default' | 'none';
|
|
4621
|
+
}
|
|
4622
|
+
/** The slice of `SettingsService` this needs, so tests can pass a plain object. */
|
|
4623
|
+
interface PlannerModelStore {
|
|
4624
|
+
getPlannerModel(provider: string): PlannerModelChoice | undefined;
|
|
4625
|
+
setPlannerModel(provider: string, entry: PlannerModelChoice | undefined): void;
|
|
4626
|
+
}
|
|
4627
|
+
/**
|
|
4628
|
+
* Remembers, per planner backend, the model the user last chose for it.
|
|
4629
|
+
*
|
|
4630
|
+
* Switching the planner has to clear the model — an id is scoped to the agent
|
|
4631
|
+
* that listed it, so an OpenRouter slug handed to Claude Code points it at
|
|
4632
|
+
* something it cannot spawn. That clear is correct and stays; what was missing
|
|
4633
|
+
* is that switching *back* then forced a re-pick of a model the user had
|
|
4634
|
+
* already chosen. Both surfaces' clears and the restore now read one rule from
|
|
4635
|
+
* here rather than three copies drifting apart.
|
|
4636
|
+
*/
|
|
4637
|
+
declare class PlannerModelMemory {
|
|
4638
|
+
private store;
|
|
4639
|
+
constructor(store: PlannerModelStore);
|
|
4640
|
+
/** Record what the user picked for `provider`; a blank model forgets it instead. */
|
|
4641
|
+
remember(provider: string, model: string, effort?: string): void;
|
|
4642
|
+
/**
|
|
4643
|
+
* What the model and effort should become when `provider` takes over the
|
|
4644
|
+
* planner, given the models it actually serves. The `source` is what the
|
|
4645
|
+
* three surfaces word their notice from — restored, defaulted, or nothing.
|
|
4646
|
+
*/
|
|
4647
|
+
recall(provider: string, catalog: PlannerModelCandidate[]): PlannerModelRecall;
|
|
4648
|
+
}
|
|
4649
|
+
|
|
4650
|
+
/**
|
|
4651
|
+
* The daemon contract: every HTTP body the local daemon sends, in one place.
|
|
4652
|
+
*
|
|
4653
|
+
* The daemon's routes build their bodies against these types and the CLI's
|
|
4654
|
+
* `ApiClient` reads them back, so a field added on one side is a compile error
|
|
4655
|
+
* on the other. Before this there were three hand-written copies — the routes'
|
|
4656
|
+
* inline `c.json`, the client's per-method generics, and the TUI's slice of the
|
|
4657
|
+
* client — and they had drifted (the client declared a `headless` field the
|
|
4658
|
+
* daemon never sent, and typed `GET /sessions/:id`'s plan as the wrong shape).
|
|
4659
|
+
*
|
|
4660
|
+
* Types only. Core is the one package both the daemon and its clients already
|
|
4661
|
+
* depend on; importing from the daemon would pull its runtime into the CLI.
|
|
4662
|
+
*/
|
|
4663
|
+
/**
|
|
4664
|
+
* Why a request was refused, as a stable code a client switches on instead of
|
|
4665
|
+
* reading the message. Absent on a refusal nobody needs to tell apart — a
|
|
4666
|
+
* missing field, say — where the message is all there is.
|
|
4667
|
+
*/
|
|
4668
|
+
type DaemonErrorCode = 'session_not_found' | 'task_not_found' | 'no_plan' | 'already_executing' | 'workspace_not_found' | 'workspace_not_a_project' | 'conversation_busy'
|
|
4669
|
+
/** The user stopped the planner turn: the turn ended as asked, so a client stays quiet. */
|
|
4670
|
+
| 'planner_turn_stopped'
|
|
4671
|
+
/** The planner turn settled after its plan was dropped; nothing it produced was kept. */
|
|
4672
|
+
| 'planner_turn_discarded'
|
|
4673
|
+
/** The request asked for something the plan, task or conversation does not allow. */
|
|
4674
|
+
| 'refused' | 'checkpoint_not_waiting' | 'approval_not_outstanding';
|
|
4675
|
+
/** The body of every non-2xx answer a route gives. */
|
|
4676
|
+
interface ErrorBody {
|
|
4677
|
+
error: string;
|
|
4678
|
+
code?: DaemonErrorCode;
|
|
4679
|
+
/** Set with `workspace_not_a_project`: the directory the daemon refused, so a client can offer to initialize it. */
|
|
4680
|
+
workspace?: string;
|
|
4681
|
+
}
|
|
4682
|
+
interface OkResponse {
|
|
4683
|
+
ok: boolean;
|
|
4684
|
+
}
|
|
4685
|
+
/**
|
|
4686
|
+
* A plan as the planner routes return it: the session's plan state, not the
|
|
4687
|
+
* `SerializedPlan` a websocket `plan_generated` carries. The two differ —
|
|
4688
|
+
* this one holds raw tasks and the dialogue's bookkeeping — and a client that
|
|
4689
|
+
* reads either reads only the fields it needs. Skill bodies stay in the
|
|
4690
|
+
* session: loads and attempt snapshots arrive as notices.
|
|
4691
|
+
*/
|
|
4692
|
+
interface PlanResponse {
|
|
4693
|
+
plan: SurfacePlan;
|
|
4694
|
+
}
|
|
4695
|
+
/** `POST /plans/:id/resolve-conflict`: `null` when the session had no conflict to hand a resolver task. */
|
|
4696
|
+
interface ResolveConflictResponse {
|
|
4697
|
+
plan: SurfacePlan | null;
|
|
4698
|
+
}
|
|
4699
|
+
/** What `GET /api/models` returns, and what the pool's provider discovery produces. */
|
|
4700
|
+
interface ModelsResponse {
|
|
4701
|
+
models: DiscoveredModel[];
|
|
4702
|
+
modelsByRunner: Record<string, DiscoveredModel[]>;
|
|
4703
|
+
/** Each runner's manifest modes, so a surface can offer a per-task mode picker. */
|
|
4704
|
+
modesByRunner: Record<string, RunnerModeInfo[]>;
|
|
4705
|
+
orchestratorModel: string;
|
|
4706
|
+
providers: AiProvider[];
|
|
4707
|
+
/** Full cross-provider catalog for the orchestrator (planner) model picker. */
|
|
4708
|
+
orchestratorModels: OrchestratorOption[];
|
|
4709
|
+
/** Per-provider catalog-fetch failures, keyed by provider id. */
|
|
4710
|
+
providerErrors: Record<string, string>;
|
|
4711
|
+
}
|
|
4712
|
+
/** One-shot planning answers in the phase-tagged shape a saved session is read back in. */
|
|
4713
|
+
interface GeneratePlanResponse extends Pick<ModelsResponse, 'models' | 'modelsByRunner'> {
|
|
4714
|
+
plan: SurfacePlanState;
|
|
4715
|
+
/** The host notes the plan's transcript records, a skill check's warnings among them, which the phase-tagged plan does not carry. */
|
|
4716
|
+
notes?: string[];
|
|
4717
|
+
}
|
|
4718
|
+
interface ExecuteResponse {
|
|
4719
|
+
status: 'running';
|
|
4720
|
+
}
|
|
4721
|
+
interface StopResponse {
|
|
4722
|
+
status: 'stopped';
|
|
4723
|
+
}
|
|
4724
|
+
interface CancelPlanningResponse {
|
|
4725
|
+
cancelled: boolean;
|
|
4726
|
+
}
|
|
4727
|
+
interface TaskMessageResponse {
|
|
4728
|
+
id: string;
|
|
4729
|
+
}
|
|
4730
|
+
interface ForceSendResponse {
|
|
4731
|
+
sent: boolean;
|
|
4732
|
+
}
|
|
4733
|
+
interface RemoveMessageResponse {
|
|
4734
|
+
removed: boolean;
|
|
4735
|
+
}
|
|
4736
|
+
interface MergeGateEntry {
|
|
4737
|
+
id: string;
|
|
4738
|
+
order: number;
|
|
4739
|
+
title: string;
|
|
4740
|
+
}
|
|
4741
|
+
interface MergeGateResponse {
|
|
4742
|
+
mergeGate: MergeGateEntry[];
|
|
4743
|
+
}
|
|
4744
|
+
interface IsolationDiffResponse {
|
|
4745
|
+
diff: string;
|
|
4746
|
+
}
|
|
4747
|
+
/** A merge that conflicts or is blocked is an outcome, not a refusal, so it answers 200 with the result. */
|
|
4748
|
+
type IsolationMergeResponse = IsolationMergeResult;
|
|
4749
|
+
/** A fork the daemon has already adopted. */
|
|
4750
|
+
interface ConversationForkResponse {
|
|
4751
|
+
sessionId: string;
|
|
4752
|
+
goal: string;
|
|
4753
|
+
plan: SurfacePlan;
|
|
4754
|
+
}
|
|
4755
|
+
/** A fork made by a rewind, with the full text of the message it was made just before. */
|
|
4756
|
+
interface ConversationRewindResponse extends ConversationForkResponse {
|
|
4757
|
+
rewoundMessage: string;
|
|
4758
|
+
}
|
|
4759
|
+
interface RewindTargetsResponse {
|
|
4760
|
+
targets: RewindTarget[];
|
|
4761
|
+
}
|
|
4762
|
+
interface ConversationCompactResponse extends ConversationCompaction, PlanResponse {
|
|
4763
|
+
}
|
|
4764
|
+
interface PrdResponse {
|
|
4765
|
+
prdMarkdown: string;
|
|
4766
|
+
}
|
|
4767
|
+
interface RunnerEntry {
|
|
4768
|
+
id: string;
|
|
4769
|
+
name: string;
|
|
4770
|
+
enabled: boolean;
|
|
4771
|
+
}
|
|
4772
|
+
interface RunnersResponse {
|
|
4773
|
+
runners: RunnerEntry[];
|
|
4774
|
+
orchestratorModel: string;
|
|
4775
|
+
}
|
|
4776
|
+
/** Sessions: a saved one comes off its file, a live one from the pool's store. */
|
|
4777
|
+
interface SessionResponse {
|
|
4778
|
+
meta: SessionMeta;
|
|
4779
|
+
plan: SurfacePlanState;
|
|
4780
|
+
}
|
|
4781
|
+
interface AdoptSessionResponse extends OkResponse {
|
|
4782
|
+
plan: SurfacePlan;
|
|
4783
|
+
goal: string;
|
|
4784
|
+
}
|
|
4785
|
+
interface TaskLogAttemptsResponse {
|
|
4786
|
+
attempts: number[];
|
|
4787
|
+
}
|
|
4788
|
+
interface TaskLogResponse {
|
|
4789
|
+
attempt: number;
|
|
4790
|
+
events: TaskLogEvent[];
|
|
4791
|
+
}
|
|
4792
|
+
type SessionListResponse = SessionMeta[];
|
|
4793
|
+
interface SettingsResponse {
|
|
4794
|
+
orchestratorModel: string;
|
|
4795
|
+
/** Who plans (ADR-0009) — a vendor id, or one of the three harness planners. */
|
|
4796
|
+
aiProvider: AiProvider;
|
|
4797
|
+
plannerThinkingEffort: string;
|
|
4798
|
+
maxParallel: number;
|
|
4799
|
+
modelAllowlist: UserSettings['modelAllowlist'];
|
|
4800
|
+
plannerModels: UserSettings['plannerModels'];
|
|
4801
|
+
}
|
|
4802
|
+
/** What `PATCH /api/settings` answers: the settings as they now stand, plus what the write itself decided. */
|
|
4803
|
+
interface SettingsUpdateResponse extends SettingsResponse {
|
|
4804
|
+
/**
|
|
4805
|
+
* Which model a planner switch landed on and why — remembered for that
|
|
4806
|
+
* backend, its catalog default, or none. Present only when the write changed
|
|
4807
|
+
* the planner; absent for every other write, where nothing was recalled.
|
|
4808
|
+
*/
|
|
4809
|
+
switchRecall?: PlannerModelRecall;
|
|
4810
|
+
/** Env keys the daemon refused to apply, so a client does not persist what the daemon would not. */
|
|
4811
|
+
rejectedEnvKeys?: string[];
|
|
4812
|
+
}
|
|
4813
|
+
interface CommandDescriptor {
|
|
4814
|
+
name: string;
|
|
4815
|
+
description: string;
|
|
4816
|
+
}
|
|
4817
|
+
interface CommandsResponse {
|
|
4818
|
+
commands: CommandDescriptor[];
|
|
4819
|
+
}
|
|
4820
|
+
interface WorkspacesResponse {
|
|
4821
|
+
workspaces: string[];
|
|
4822
|
+
}
|
|
4823
|
+
interface ApprovalsResponse {
|
|
4824
|
+
pending: PendingApproval[];
|
|
4825
|
+
approvedScopes: string[];
|
|
4826
|
+
}
|
|
4827
|
+
interface ApprovalAnswerResponse extends OkResponse {
|
|
4828
|
+
granted: boolean;
|
|
4829
|
+
decision: ApprovalDecision['decision'];
|
|
4830
|
+
}
|
|
4831
|
+
|
|
4832
|
+
/**
|
|
4833
|
+
* Why a call on a session could not be made. Each is a class rather than a
|
|
4834
|
+
* message so the daemon can map it to a status and a stable code in one place,
|
|
4835
|
+
* and a client can switch on that code instead of reading the wording. Like
|
|
4836
|
+
* `PlanEditError`, none carries a status: core is transport-agnostic.
|
|
4837
|
+
*/
|
|
4838
|
+
/** No session with that id is held — never planned in this process, or dropped by a restart. */
|
|
4839
|
+
declare class SessionNotFoundError extends Error {
|
|
4840
|
+
constructor();
|
|
4841
|
+
}
|
|
4842
|
+
/** The session holds no plan (or an empty one) for the operation to act on. */
|
|
4843
|
+
declare class NoPlanError extends Error {
|
|
4844
|
+
constructor(operation: 'execute' | 'review');
|
|
4845
|
+
}
|
|
4846
|
+
/** A run is already live, and starting another would reset the one in flight. */
|
|
4847
|
+
declare class AlreadyExecutingError extends Error {
|
|
4848
|
+
constructor();
|
|
4849
|
+
}
|
|
4850
|
+
|
|
4402
4851
|
/**
|
|
4403
4852
|
* Where Ordewell keeps machine-global data (settings, daemon tokens, caches,
|
|
4404
|
-
*
|
|
4853
|
+
* credentials). A single home for everything not tied to a project directory,
|
|
4405
4854
|
* so per-project state in `.ordewell/` and global state never collide.
|
|
4406
4855
|
*/
|
|
4407
4856
|
declare function globalDataDir(): string;
|
|
@@ -4428,22 +4877,14 @@ type CheckpointWithdrawnListener = (taskId: string) => void;
|
|
|
4428
4877
|
/** Fires on every idleSince transition (null→timestamp on silence, timestamp→null on resume/teardown). */
|
|
4429
4878
|
type IdleListener = (taskId: string, idleSince: string | null) => void;
|
|
4430
4879
|
declare class VerdictEngine {
|
|
4431
|
-
private markerSeen;
|
|
4432
4880
|
private pendingVerdicts;
|
|
4433
|
-
private
|
|
4434
|
-
private markerTails;
|
|
4435
|
-
private checkpointCarry;
|
|
4436
|
-
private pausedSessions;
|
|
4881
|
+
private sessions;
|
|
4437
4882
|
private listeners;
|
|
4438
4883
|
private checkpointListeners;
|
|
4439
4884
|
private withdrawnListeners;
|
|
4440
|
-
/**
|
|
4441
|
-
* The open `checkpoint` tool call per task (ADR-0022, V5): settling it is how
|
|
4442
|
-
* an answer reaches a runner that asked through the tool, where the marker's
|
|
4443
|
-
* answer is typed into the session instead.
|
|
4444
|
-
*/
|
|
4885
|
+
/** The open `checkpoint` tool call per task (ADR-0022, V5): settling it is how an answer reaches the runner. */
|
|
4445
4886
|
private toolCheckpoints;
|
|
4446
|
-
/** The question a task's checkpoint asks, whole, for as long as it waits
|
|
4887
|
+
/** The question a task's checkpoint asks, whole, for as long as it waits. */
|
|
4447
4888
|
private checkpointQuestions;
|
|
4448
4889
|
private idleListeners;
|
|
4449
4890
|
/**
|
|
@@ -4485,32 +4926,22 @@ declare class VerdictEngine {
|
|
|
4485
4926
|
private touchIdle;
|
|
4486
4927
|
/** Tear down idle tracking for a task; broadcasts the null transition if it was idle. */
|
|
4487
4928
|
private clearIdle;
|
|
4488
|
-
/**
|
|
4489
|
-
* Submit a synchronized resume token to the paused session. An interactive
|
|
4490
|
-
* TUI only accepts the Enter keystroke (`\r`) — a `\n` types the token into
|
|
4491
|
-
* its composer without sending it, leaving the agent paused until a human
|
|
4492
|
-
* presses Enter. A line-oriented piped session has no composer; it reads a
|
|
4493
|
-
* `\n`-terminated line, and the leading newline flushes a partial line.
|
|
4494
|
-
*/
|
|
4495
|
-
private resumeToken;
|
|
4496
4929
|
/** What a task's waiting checkpoint asks, untruncated; undefined when none waits. */
|
|
4497
4930
|
getCheckpointQuestion(taskId: string): string | undefined;
|
|
4498
4931
|
approveCheckpoint(taskId: string): void;
|
|
4499
4932
|
rejectCheckpoint(taskId: string, reason: string): void;
|
|
4500
4933
|
/**
|
|
4501
|
-
* Attach to a spawned session
|
|
4502
|
-
*
|
|
4503
|
-
*
|
|
4504
|
-
* when the marker was never observed. A structured session's `task_complete`
|
|
4505
|
-
* call is evidence too (ADR-0022, V2): whichever signal comes first decides.
|
|
4934
|
+
* Attach to a spawned session. The runner's `task_complete` call on the
|
|
4935
|
+
* attempt's token is the only completion evidence (ADR-0022, V2); a session
|
|
4936
|
+
* that exits before one gets a failed verdict.
|
|
4506
4937
|
*
|
|
4507
4938
|
* Returns the attempt's generation, what {@link signalComplete} is checked against.
|
|
4508
4939
|
*/
|
|
4509
|
-
watch(task: Task, session:
|
|
4940
|
+
watch(task: Task, session: IRunnerSession): number;
|
|
4510
4941
|
/**
|
|
4511
4942
|
* The runner's own `task_complete` call (ADR-0022, V1/V3): settles the
|
|
4512
|
-
* attempt
|
|
4513
|
-
*
|
|
4943
|
+
* attempt, unless that attempt is no longer the task's current one or an
|
|
4944
|
+
* earlier call already settled it.
|
|
4514
4945
|
*/
|
|
4515
4946
|
signalComplete(taskId: string, generation: number, report: TaskCompleteArgs): void;
|
|
4516
4947
|
/** The runner was told something after its evidence so far, so only what it reports from here counts. */
|
|
@@ -4518,9 +4949,8 @@ declare class VerdictEngine {
|
|
|
4518
4949
|
private acceptVerdict;
|
|
4519
4950
|
private publishVerdict;
|
|
4520
4951
|
/**
|
|
4521
|
-
* The runner's `checkpoint` call (ADR-0022, V5):
|
|
4522
|
-
*
|
|
4523
|
-
* settled by {@link approveCheckpoint} or {@link rejectCheckpoint}. It is
|
|
4952
|
+
* The runner's `checkpoint` call (ADR-0022, V5): the task waits on the
|
|
4953
|
+
* user until it is settled by {@link approveCheckpoint} or {@link rejectCheckpoint}. It is
|
|
4524
4954
|
* withdrawn, never left hanging, once the attempt is over or the call goes.
|
|
4525
4955
|
*/
|
|
4526
4956
|
raiseCheckpoint(taskId: string, generation: number, question: string, signal: AbortSignal): Promise<CheckpointAnswer>;
|
|
@@ -4529,64 +4959,33 @@ declare class VerdictEngine {
|
|
|
4529
4959
|
private withdrawToolCheckpoint;
|
|
4530
4960
|
private approvalOpened;
|
|
4531
4961
|
private approvalClosed;
|
|
4532
|
-
/** Scan only the new text plus the unmatched carry, so a long run stays linear. */
|
|
4533
|
-
private scanCheckpoints;
|
|
4534
4962
|
private bumpGeneration;
|
|
4535
4963
|
private forget;
|
|
4536
4964
|
/** Manual "Mark complete" override: a pass verdict that bypasses evidence. */
|
|
4537
4965
|
markComplete(task: Task): Verdict;
|
|
4538
4966
|
/** Clear verification state for a task (used on retry). */
|
|
4539
4967
|
clear(task: Task): void;
|
|
4968
|
+
/** Drop a task's verification state and invalidate any callbacks still holding its generation. */
|
|
4969
|
+
private ceaseTracking;
|
|
4540
4970
|
/** Drop all tracking state (used on stop / loadPlan). */
|
|
4541
4971
|
reset(): void;
|
|
4542
|
-
private decide;
|
|
4543
4972
|
}
|
|
4544
4973
|
|
|
4545
|
-
/**
|
|
4546
|
-
* Owns one bounded raw buffer per task attempt, fed from the attempt's
|
|
4547
|
-
* session, and reads final answers from the agent's transcript through an
|
|
4548
|
-
* injected {@link TranscriptReader}.
|
|
4549
|
-
*/
|
|
4974
|
+
/** Owns one bounded output buffer per task attempt, fed from the attempt's session. */
|
|
4550
4975
|
declare class BufferedTaskOutputSource implements TaskOutputSource {
|
|
4551
4976
|
private captures;
|
|
4552
|
-
private transcripts;
|
|
4553
4977
|
private maxBufferChars;
|
|
4554
4978
|
constructor(opts?: {
|
|
4555
|
-
transcripts?: TranscriptReader;
|
|
4556
4979
|
maxBufferChars?: number;
|
|
4557
4980
|
});
|
|
4558
|
-
attach(taskId: string, session:
|
|
4981
|
+
attach(taskId: string, session: IRunnerSession): void;
|
|
4559
4982
|
detach(taskId: string): void;
|
|
4560
4983
|
reset(): void;
|
|
4561
|
-
finalText(
|
|
4984
|
+
finalText(taskId: string): string;
|
|
4562
4985
|
liveTail(taskId: string, opts: LiveTailOptions): LiveTail | null;
|
|
4563
4986
|
private append;
|
|
4564
4987
|
}
|
|
4565
4988
|
|
|
4566
|
-
/**
|
|
4567
|
-
* Read a task's final answer from the agent's own session transcript — the
|
|
4568
|
-
* clean, structured record the agent writes about itself — instead of
|
|
4569
|
-
* reconstructing what a TUI painted (issue #16, built on #14's render).
|
|
4570
|
-
*
|
|
4571
|
-
* These stores are private and undocumented and DO rotate (OpenCode migrated
|
|
4572
|
-
* from files to SQLite mid-2026). Every reader is therefore defensive: any
|
|
4573
|
-
* missing file, unparseable line, or shape drift returns null and the caller
|
|
4574
|
-
* falls back to the terminal capture. Nothing here is a hard dependency.
|
|
4575
|
-
*
|
|
4576
|
-
* Directory and recency only narrow the candidates: with several attempts in
|
|
4577
|
-
* one cwd the newest session is whichever task finished last. A transcript is
|
|
4578
|
-
* accepted only when its content carries the task's completion marker.
|
|
4579
|
-
*/
|
|
4580
|
-
declare class HomeTranscriptReader implements TranscriptReader {
|
|
4581
|
-
private readonly home;
|
|
4582
|
-
private readonly claudeConfigDirs;
|
|
4583
|
-
constructor(opts?: {
|
|
4584
|
-
homeDir?: string;
|
|
4585
|
-
workspaceEnv?: (cwd: string) => Promise<Record<string, string>>;
|
|
4586
|
-
});
|
|
4587
|
-
finalAssistantText(query: TranscriptQuery, maxChars?: number): Promise<string | null>;
|
|
4588
|
-
}
|
|
4589
|
-
|
|
4590
4989
|
/**
|
|
4591
4990
|
* The ids a runner may actually run: the user's allowlist with the ids that
|
|
4592
4991
|
* provably belong to a *different* runner dropped. `undefined` means no
|
|
@@ -4596,7 +4995,7 @@ declare class HomeTranscriptReader implements TranscriptReader {
|
|
|
4596
4995
|
* allowlisted for Claude Code does not limit it — it points it at something it
|
|
4597
4996
|
* cannot spawn, and the plan only dies once a task is already running. But
|
|
4598
4997
|
* "this runner didn't list it" is not enough to call an id wrong: discovery can
|
|
4599
|
-
* be stale
|
|
4998
|
+
* be stale or return no list at all. What settles it is
|
|
4600
4999
|
* whether *another* runner listed the id. So:
|
|
4601
5000
|
*
|
|
4602
5001
|
* - listed for this runner → keep;
|
|
@@ -4623,45 +5022,6 @@ declare function clampThinkingEffort(effort: string | undefined, variants: {
|
|
|
4623
5022
|
}[]): string | undefined;
|
|
4624
5023
|
declare function coerceAssignments(tasks: readonly Task[], perRunnerAllowlist: Partial<Record<RunnerId, string[]>>, allowedRunners?: RunnerId[], modelsByRunner?: Partial<Record<RunnerId, DiscoveredModel[]>>): Task[];
|
|
4625
5024
|
|
|
4626
|
-
/** What a runner offers a task: the models discovered for it and the modes its manifest declares. */
|
|
4627
|
-
interface RunnerCatalog {
|
|
4628
|
-
models: DiscoveredModel[];
|
|
4629
|
-
modes: RunnerModeInfo[];
|
|
4630
|
-
/**
|
|
4631
|
-
* The mode a task lands on when it carries none this runner offers: the
|
|
4632
|
-
* manifest's `autonomous`/`safe`-tagged mode under the user's toggle
|
|
4633
|
-
* (ADR-0001). Absent, `modes[0]` stands in — which for Codex is its
|
|
4634
|
-
* workspace-write sandbox, not the full access an unattended run needs.
|
|
4635
|
-
*/
|
|
4636
|
-
defaultMode?: string;
|
|
4637
|
-
}
|
|
4638
|
-
/**
|
|
4639
|
-
* The model, thinking effort and mode a runner offers for a task.
|
|
4640
|
-
*
|
|
4641
|
-
* A task's model, effort and mode are all scoped to its runner:
|
|
4642
|
-
* `claude-sonnet-4-5` on Codex, or `acceptEdits` on OpenCode, are not degraded
|
|
4643
|
-
* choices but unspawnable ones. So this is where any task acquires a runnable
|
|
4644
|
-
* assignment — a runner change (below) and a hand-added task derive it the same
|
|
4645
|
-
* way. Each field in `current` is preserved when the runner also offers it, and
|
|
4646
|
-
* otherwise snapped to that runner's preferred entry (discovery already sorts
|
|
4647
|
-
* models by the manifest's `preferredPatterns`; the mode is the catalog's
|
|
4648
|
-
* `defaultMode`).
|
|
4649
|
-
*
|
|
4650
|
-
* An empty catalog means discovery failed or the runner is a plugin we have no
|
|
4651
|
-
* list for — not that the runner offers nothing. That field is left out of the
|
|
4652
|
-
* patch and the runner validates last, matching `coerceAssignments`.
|
|
4653
|
-
*/
|
|
4654
|
-
declare function runnerAssignment(catalog: RunnerCatalog, current?: Pick<Task, 'assignedModel' | 'taskMode'>): Partial<Task>;
|
|
4655
|
-
/**
|
|
4656
|
-
* Move a task onto a different runner, carrying its model, thinking effort and
|
|
4657
|
-
* mode over to values that runner actually offers. A runner change is never a
|
|
4658
|
-
* single-field edit — it either brings the other three with it or leaves the
|
|
4659
|
-
* task unrunnable.
|
|
4660
|
-
*
|
|
4661
|
-
* Returns the patch to apply, or `{}` when there is nothing to change.
|
|
4662
|
-
*/
|
|
4663
|
-
declare function retargetTaskRunner(task: Task, runner: RunnerId, catalog: RunnerCatalog): Partial<Task>;
|
|
4664
|
-
|
|
4665
5025
|
declare function buildResearchToolsPrompt(): string;
|
|
4666
5026
|
/**
|
|
4667
5027
|
* System prompt for one read-only research subagent (issue #34). The digest
|
|
@@ -4672,26 +5032,30 @@ declare function buildResearchToolsPrompt(): string;
|
|
|
4672
5032
|
declare function buildSubagentSystemPrompt(): string;
|
|
4673
5033
|
/**
|
|
4674
5034
|
* Facts about who plans and where tasks will run, as opposed to the user's
|
|
4675
|
-
*
|
|
5035
|
+
* choices: they change what the prompt can promise, not what it asks for.
|
|
4676
5036
|
*/
|
|
4677
5037
|
interface ConversationVariant {
|
|
4678
|
-
/**
|
|
5038
|
+
/**
|
|
5039
|
+
* Harness planner (ADR-0009): the agent owns its own tools and research
|
|
5040
|
+
* budget, and reads the catalog and submits the plan through Ordewell's MCP
|
|
5041
|
+
* tools (ADR-0022). An API planner speaks the JSON envelopes instead.
|
|
5042
|
+
*/
|
|
4679
5043
|
harness?: boolean;
|
|
4680
|
-
/** The
|
|
4681
|
-
|
|
5044
|
+
/** The skill catalog: task skills it can attach on every path, planner skills it can load only with tools. */
|
|
5045
|
+
skills?: readonly SkillInfo[];
|
|
4682
5046
|
/** Every AI task gets its own worktree (ADR-0013), so file overlap no longer forces an order; of every repo of a group (ADR-0014). */
|
|
4683
5047
|
isolatedExecution?: IsolatedExecution;
|
|
4684
5048
|
}
|
|
4685
|
-
declare function buildConversationSystemPrompt(goal: string, context: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean,
|
|
5049
|
+
declare function buildConversationSystemPrompt(goal: string, context: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean, variant?: ConversationVariant): string;
|
|
4686
5050
|
/** The one-shot planner's core rules for tasks that share the workspace root. */
|
|
4687
5051
|
declare const CORE_PLANNER_PROMPT: string;
|
|
4688
5052
|
declare function buildResearchPrompt(userGoal: string, context: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: PlannerModes): string;
|
|
4689
|
-
declare function buildPlanWithResults(userGoal: string, context: string, researchResults: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: PlannerModes): string;
|
|
4690
|
-
declare function buildModifyPlanPrompt(existingPlan: LegacyPlanState, userRequest: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, aiflowContext?: string, runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean): string;
|
|
5053
|
+
declare function buildPlanWithResults(userGoal: string, context: string, researchResults: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: PlannerModes, tools?: boolean): string;
|
|
5054
|
+
declare function buildModifyPlanPrompt(existingPlan: LegacyPlanState, userRequest: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, aiflowContext?: string, runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean, tools?: boolean): string;
|
|
4691
5055
|
declare function modelContextBlock(modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean): string;
|
|
4692
5056
|
declare function executionLogBlock(executionLog: TaskSnapshot[]): string;
|
|
4693
5057
|
declare function pendingEditRulesBlock(): string;
|
|
4694
|
-
declare function buildModifyDuringExecutionPrompt(executionLog: TaskSnapshot[], pendingTasks: string, userMessage: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: Pick<PlannerModes, 'autonomousDefault' | 'isolatedExecution'
|
|
5058
|
+
declare function buildModifyDuringExecutionPrompt(executionLog: TaskSnapshot[], pendingTasks: string, userMessage: string, modelsByRunner: Partial<Record<RunnerId, DiscoveredModel[]>>, runners: RunnerId[], runnerModes?: Record<RunnerId, RunnerModeInfo[]>, modes?: Pick<PlannerModes, 'autonomousDefault' | 'isolatedExecution'>, tools?: boolean): string;
|
|
4695
5059
|
/**
|
|
4696
5060
|
* User-message prompt for a planner-driven merge: asks the model to combine the
|
|
4697
5061
|
* selected tasks into one. Routed through the conversation loop, so the
|
|
@@ -4795,6 +5159,14 @@ declare const JSON_REPAIR_INSTRUCTION: string;
|
|
|
4795
5159
|
declare const TRUNCATED_PLAN_REPAIR_INSTRUCTION: string;
|
|
4796
5160
|
/** A plan attempt was botched (invalid or truncated JSON): re-emit the whole plan. */
|
|
4797
5161
|
declare function reEmitPlanPrompt(detail: string): string;
|
|
5162
|
+
/**
|
|
5163
|
+
* A planner that submits through Ordewell's tools ended without an accepted
|
|
5164
|
+
* plan, or one it submitted was refused: call the tool again. A plan written
|
|
5165
|
+
* in its reply is never read (ADR-0025), so asking for JSON would be ignored.
|
|
5166
|
+
*/
|
|
5167
|
+
declare function resubmitPlanPrompt(errors: string[]): string;
|
|
5168
|
+
/** A tool planner's task edit was refused as its turn settled: correct it through edit_plan. */
|
|
5169
|
+
declare function resubmitEditPrompt(errors: string[]): string;
|
|
4798
5170
|
/** A plan emission was truncated mid-JSON; the caller may also have compacted the history to free input context. */
|
|
4799
5171
|
declare function truncatedPlanReEmitPrompt(historyCompacted: boolean): string;
|
|
4800
5172
|
/** A task-ops attempt was botched (unparseable JSON): re-emit the ops object. */
|
|
@@ -4803,8 +5175,8 @@ declare function reEmitTaskOpsPrompt(detail: string): string;
|
|
|
4803
5175
|
declare function reEmitTaskQueryPrompt(detail: string): string;
|
|
4804
5176
|
/** Task ops parsed but failed semantic validation (cycles, unknown refs, locked tasks). */
|
|
4805
5177
|
declare function taskOpsRejectedPrompt(errors: string[]): string;
|
|
4806
|
-
/** A modified plan failed validation during execution: full re-prompt feedback block. */
|
|
4807
|
-
declare function modifyValidationFeedback(errors: string[]): string;
|
|
5178
|
+
/** A modified plan failed validation during execution: full re-prompt feedback block, asking for the planner's own transport. */
|
|
5179
|
+
declare function modifyValidationFeedback(errors: string[], tools?: boolean): string;
|
|
4808
5180
|
type PlannerReplyClassification = {
|
|
4809
5181
|
kind: 'plan';
|
|
4810
5182
|
tasks: Task[];
|
|
@@ -4854,23 +5226,6 @@ declare function classifyPlannerReply(text: string, opts: {
|
|
|
4854
5226
|
*/
|
|
4855
5227
|
declare function generatePlanWithRepair(generate: (repairHint?: string) => Promise<string>, runners: RunnerId[], maxAttempts?: number, runnerModes?: Record<RunnerId, RunnerModeInfo[]>, autonomousDefault?: boolean): Promise<Task[]>;
|
|
4856
5228
|
|
|
4857
|
-
type RunnerMode = string;
|
|
4858
|
-
|
|
4859
|
-
declare function buildRunnerInvocation(opts: {
|
|
4860
|
-
runner: string;
|
|
4861
|
-
prompt: string;
|
|
4862
|
-
modelId?: string;
|
|
4863
|
-
thinkingEffort?: string;
|
|
4864
|
-
modelVariants?: string[];
|
|
4865
|
-
mode?: RunnerMode;
|
|
4866
|
-
headless?: boolean;
|
|
4867
|
-
interactive?: boolean;
|
|
4868
|
-
cwd?: string;
|
|
4869
|
-
/** The installed runner's `--version`, for a manifest whose command line differs by major version. */
|
|
4870
|
-
runnerVersion?: string;
|
|
4871
|
-
registry: RunnerRegistry;
|
|
4872
|
-
}): RunnerInvocation;
|
|
4873
|
-
|
|
4874
5229
|
interface PriorOutput {
|
|
4875
5230
|
order: number;
|
|
4876
5231
|
title: string;
|
|
@@ -4883,18 +5238,6 @@ declare function summarizeOutput(reviewReason: string | undefined, output: strin
|
|
|
4883
5238
|
capturedAt: string;
|
|
4884
5239
|
};
|
|
4885
5240
|
declare function collectDirectDependencyOutputs(task: Task, allTasks: readonly Task[]): PriorOutput[];
|
|
4886
|
-
/**
|
|
4887
|
-
* Break marker tokens carried in a predecessor's captured output. Interactive
|
|
4888
|
-
* runners echo the prompt they are given, and the watcher scans that terminal
|
|
4889
|
-
* output — a quoted marker would settle this task on the previous one's
|
|
4890
|
-
* evidence. Hyphenated rather than spaced: the scanner also reads a
|
|
4891
|
-
* whitespace-flattened view of the terminal, which would rejoin a space.
|
|
4892
|
-
*
|
|
4893
|
-
* A completion marker also loses its id: transcripts are bound to a task by
|
|
4894
|
-
* that id, and a dependent's transcript quoting it would answer for the
|
|
4895
|
-
* predecessor the next time the predecessor runs.
|
|
4896
|
-
*/
|
|
4897
|
-
declare function defuseMarkers(text: string): string;
|
|
4898
5241
|
declare function renderPriorOutputs(outputs: PriorOutput[]): string;
|
|
4899
5242
|
declare function augmentPromptWithPriorOutputs(task: Task, allTasks: readonly Task[]): string;
|
|
4900
5243
|
/**
|
|
@@ -4909,11 +5252,10 @@ declare function renderPlanMap(planTasks: readonly Task[], currentTaskId: string
|
|
|
4909
5252
|
interface ComposeOptions {
|
|
4910
5253
|
planMapEnabled?: boolean;
|
|
4911
5254
|
planMapMaxEntries?: number;
|
|
4912
|
-
|
|
5255
|
+
/** The task's skills as resolved where this attempt runs. */
|
|
5256
|
+
skills?: readonly TaskSkillSnapshot[];
|
|
4913
5257
|
/** An ops task's last attempt, as its output ended (ADR-0020); absent on a first attempt. */
|
|
4914
5258
|
previousAttempt?: string;
|
|
4915
|
-
/** The runner is given the `task_complete` and `checkpoint` tools (ADR-0022); the markers stay as their fallback. */
|
|
4916
|
-
completionTool?: boolean;
|
|
4917
5259
|
}
|
|
4918
5260
|
declare function composeAugmentedPrompt(task: Task, allTasks: readonly Task[], opts?: ComposeOptions): string;
|
|
4919
5261
|
/**
|
|
@@ -4924,143 +5266,44 @@ declare function composeAugmentedPrompt(task: Task, allTasks: readonly Task[], o
|
|
|
4924
5266
|
*/
|
|
4925
5267
|
declare function composeContinuationPrompt(task: Task, message: string, opts?: {
|
|
4926
5268
|
ops?: boolean;
|
|
4927
|
-
completionTool?: boolean;
|
|
4928
5269
|
}): string;
|
|
4929
5270
|
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
* Runs the invocation in a fresh tmux window, tailed via `pipe-pane` into a
|
|
4967
|
-
* log file rather than polling `capture-pane` snapshots — a byte-exact
|
|
4968
|
-
* stream needs no diff/resync heuristics. The command is wrapped so the
|
|
4969
|
-
* window survives its own exit (an `exec`'d login shell), which is what
|
|
4970
|
-
* lets the user keep poking at a finished task's terminal.
|
|
4971
|
-
*/
|
|
4972
|
-
start(command: string, args: string[], cwd: string, env?: Record<string, string>): Promise<void>;
|
|
4973
|
-
private poll;
|
|
4974
|
-
/** Emit what the log gained since the last read; false when it gained nothing. */
|
|
4975
|
-
private readLog;
|
|
4976
|
-
/**
|
|
4977
|
-
* The sentinel is printed by the wrapper shell, so a window closed from
|
|
4978
|
-
* outside — killed by the user, or with the whole tmux server — never prints
|
|
4979
|
-
* it, and the session would count as running forever. A silent window is
|
|
4980
|
-
* therefore looked up by exact name (a `-t` target falls back to another
|
|
4981
|
-
* window once its own is gone), and once it is confirmed missing the session
|
|
4982
|
-
* ends as a kill does. Whatever the log still held is read first, so a
|
|
4983
|
-
* completion marker printed just before the close still counts.
|
|
4984
|
-
*/
|
|
4985
|
-
private checkWindow;
|
|
4986
|
-
/**
|
|
4987
|
-
* A task finishing (or being killed) stops observation, but never the
|
|
4988
|
-
* window itself on the sentinel path — only `kill()` closes the window.
|
|
4989
|
-
* Piping is turned off and the log file removed either way, so a finished
|
|
4990
|
-
* task doesn't leave a `cat` process appending to it for the rest of the
|
|
4991
|
-
* daemon's life.
|
|
4992
|
-
*/
|
|
4993
|
-
private finish;
|
|
4994
|
-
kill(): void;
|
|
4995
|
-
getOutput(): string;
|
|
4996
|
-
write(text: string): void;
|
|
4997
|
-
}
|
|
4998
|
-
/**
|
|
4999
|
-
* Runs tasks in a real tmux window instead of a piped subprocess, so a user
|
|
5000
|
-
* can open a genuine, interactive terminal on any task (running or
|
|
5001
|
-
* finished) from outside Ordewell's own process. `ITerminalSession` hides the
|
|
5002
|
-
* transport from `VerdictEngine`/`PoolAwareRunner`, so orchestration is
|
|
5003
|
-
* unchanged — this is a drop-in replacement for `HeadlessRunner`.
|
|
5004
|
-
*/
|
|
5005
|
-
declare class TmuxRunner extends AbstractRunner<TmuxSession> {
|
|
5006
|
-
private sessionName;
|
|
5007
|
-
private socket;
|
|
5008
|
-
private execFileImpl;
|
|
5009
|
-
private resolvePath;
|
|
5010
|
-
private pollIntervalMs;
|
|
5011
|
-
private logDir;
|
|
5012
|
-
private clipboardCommand;
|
|
5013
|
-
private runnerVersion;
|
|
5014
|
-
/** Retries get a freshly named window so a failed attempt's output stays inspectable. */
|
|
5015
|
-
private attempts;
|
|
5016
|
-
private ready;
|
|
5017
|
-
constructor(deps: TmuxRunnerDeps);
|
|
5018
|
-
/**
|
|
5019
|
-
* Reaps a session orphaned by a crashed prior daemon on the same port, then
|
|
5020
|
-
* creates a fresh one. Memoized: `spawn` awaits it too, so a task spawned
|
|
5021
|
-
* before startup's own call has settled never lands in a missing session —
|
|
5022
|
-
* and a settled failure clears the memo so the next spawn can retry.
|
|
5023
|
-
*/
|
|
5024
|
-
ensureSession(): Promise<void>;
|
|
5025
|
-
/** Every tmux call must name this daemon's socket; see `tmuxSocketName`. */
|
|
5026
|
-
private tmux;
|
|
5027
|
-
private createFreshSession;
|
|
5028
|
-
/**
|
|
5029
|
-
* Gives an attached runner terminal wheel/PageUp scrolling over a deep
|
|
5030
|
-
* scrollback, and a mouse selection that reaches the system clipboard — none
|
|
5031
|
-
* of which a default tmux session does. Server-wide scoping is harmless: the
|
|
5032
|
-
* daemon owns a private socket (`tmuxSocketName`).
|
|
5033
|
-
*
|
|
5034
|
-
* `mouse on` is what costs the emulator's own drag-select, so tmux must hand
|
|
5035
|
-
* the selection back out itself: via a clipboard binary when there is one,
|
|
5036
|
-
* and via OSC 52 (`set-clipboard`) for what that cannot cover, such as
|
|
5037
|
-
* viewing over SSH. Naming the binary on the binding as well as in
|
|
5038
|
-
* `copy-command` keeps drag-to-copy working on tmux older than 3.2, which has
|
|
5039
|
-
* no `copy-command`.
|
|
5040
|
-
*/
|
|
5041
|
-
private configureScrolling;
|
|
5042
|
-
/**
|
|
5043
|
-
* Called on daemon shutdown — the one guarantee against leaked tmux
|
|
5044
|
-
* processes. Kills the whole server, not just the session: the socket
|
|
5045
|
-
* belongs to this daemon alone, so nothing else can be on it, and a runner
|
|
5046
|
-
* that somehow escaped its session would otherwise keep running (and keep
|
|
5047
|
-
* billing) unattached for as long as the server lived.
|
|
5048
|
-
*/
|
|
5049
|
-
killSession(): Promise<void>;
|
|
5050
|
-
spawn(opts: {
|
|
5051
|
-
taskId: string;
|
|
5052
|
-
runner: string;
|
|
5053
|
-
prompt: string;
|
|
5054
|
-
modelId?: string;
|
|
5055
|
-
thinkingEffort?: string;
|
|
5056
|
-
modelVariants?: string[];
|
|
5057
|
-
mode?: string;
|
|
5058
|
-
headless?: boolean;
|
|
5059
|
-
cwd: string;
|
|
5060
|
-
registry?: RunnerRegistry;
|
|
5061
|
-
planSessionId?: string;
|
|
5062
|
-
env?: Record<string, string>;
|
|
5063
|
-
}): Promise<ITerminalSession>;
|
|
5271
|
+
/** One source for the spawn options, so a runner built on this base cannot drift from the interface. */
|
|
5272
|
+
type RunnerSpawnOptions = Parameters<IRunner['spawn']>[0];
|
|
5273
|
+
declare abstract class AbstractRunnerSession implements IRunnerSession {
|
|
5274
|
+
id: string;
|
|
5275
|
+
taskId: string;
|
|
5276
|
+
protected exited: boolean;
|
|
5277
|
+
protected outputEmitter: EventEmitter<any>;
|
|
5278
|
+
protected exitEmitter: EventEmitter<any>;
|
|
5279
|
+
constructor(id: string, taskId: string);
|
|
5280
|
+
protected baseHandleExit(code: number): void;
|
|
5281
|
+
onOutput(callback: (text: string) => void): void;
|
|
5282
|
+
onExit(callback: (code: number) => void): void;
|
|
5283
|
+
abstract kill(): void;
|
|
5284
|
+
abstract getOutput(): string;
|
|
5285
|
+
abstract write(text: string): void;
|
|
5286
|
+
abstract turnState(): 'working' | 'idle';
|
|
5287
|
+
abstract onTurnEnd(listener: (reason: StructuredTurnEnd) => void): void;
|
|
5288
|
+
abstract onEvent(listener: (event: StructuredEvent) => void): void;
|
|
5289
|
+
abstract sendMessage(text: string): string;
|
|
5290
|
+
abstract forceSend(text: string): string;
|
|
5291
|
+
abstract forceSendQueued(id: string): boolean;
|
|
5292
|
+
abstract removeQueued(id: string): boolean;
|
|
5293
|
+
abstract queued(): QueuedTaskMessage[];
|
|
5294
|
+
abstract interrupt(): Promise<void>;
|
|
5295
|
+
abstract nativeSessionId(): string | null;
|
|
5296
|
+
abstract answerPermission(id: string, decision: ApprovalDecision): boolean;
|
|
5297
|
+
abstract onTaskComplete(listener: (report: TaskCompleteArgs) => void): void;
|
|
5298
|
+
abstract onToolCheckpoint(handler: (question: string, signal: AbortSignal) => Promise<CheckpointAnswer>): void;
|
|
5299
|
+
}
|
|
5300
|
+
declare abstract class AbstractRunner<S extends IRunnerSession> implements IRunner {
|
|
5301
|
+
protected sessions: Map<string, S>;
|
|
5302
|
+
get activeCount(): number;
|
|
5303
|
+
stop(sessionId: string): void;
|
|
5304
|
+
stopAll(): void;
|
|
5305
|
+
protected registerSession(id: string, session: S): void;
|
|
5306
|
+
abstract spawn(opts: RunnerSpawnOptions): Promise<IRunnerSession>;
|
|
5064
5307
|
}
|
|
5065
5308
|
|
|
5066
5309
|
interface StructuredRunnerDeps {
|
|
@@ -5078,26 +5321,27 @@ interface SessionLaunch {
|
|
|
5078
5321
|
createAdapter: (runner: string, deps: AgentProcessDeps) => TaskModeAgentAdapter;
|
|
5079
5322
|
startOptions: TaskStartOptions;
|
|
5080
5323
|
interruptGraceMs: number;
|
|
5081
|
-
/** Where this attempt's task tools are served
|
|
5082
|
-
tools
|
|
5324
|
+
/** Where this attempt's task tools are served (ADR-0022). */
|
|
5325
|
+
tools: {
|
|
5083
5326
|
server: OrdewellMcpServer;
|
|
5084
5327
|
scope: TaskTokenScope;
|
|
5085
5328
|
};
|
|
5329
|
+
onNotice?: (message: string) => void;
|
|
5086
5330
|
}
|
|
5087
5331
|
/**
|
|
5088
5332
|
* One task driven over its runner's programmatic protocol (ADR-0018). It *is*
|
|
5089
|
-
* an `
|
|
5090
|
-
* what a terminal cannot do sits on {@link StructuredSessionCapability}.
|
|
5333
|
+
* an `IRunnerSession`, with plain output and structured events.
|
|
5091
5334
|
*
|
|
5092
5335
|
* Ordewell owns the message queue (M1). A message sent mid-turn is handed to a
|
|
5093
5336
|
* runner that can take one at its next step (ADR-0023); otherwise it waits for
|
|
5094
5337
|
* the turn to end rather than being typed into a runner that is busy.
|
|
5095
5338
|
*/
|
|
5096
|
-
declare class StructuredSession extends
|
|
5339
|
+
declare class StructuredSession extends AbstractRunnerSession {
|
|
5097
5340
|
private readonly launch;
|
|
5098
|
-
readonly transport: "structured";
|
|
5099
5341
|
private adapter;
|
|
5100
5342
|
private adapterStarted;
|
|
5343
|
+
private adapterAttached;
|
|
5344
|
+
private startupExit;
|
|
5101
5345
|
/** Bumped whenever the adapter is replaced, so the old one's late events and exit are ignored. */
|
|
5102
5346
|
private generation;
|
|
5103
5347
|
private output;
|
|
@@ -5123,16 +5367,25 @@ declare class StructuredSession extends AbstractTerminalSession implements Struc
|
|
|
5123
5367
|
private toolToken;
|
|
5124
5368
|
private checkpointHandler;
|
|
5125
5369
|
constructor(id: string, taskId: string, launch: SessionLaunch);
|
|
5126
|
-
/**
|
|
5370
|
+
/**
|
|
5371
|
+
* Start the runner with the attempt's tools attached and send the task's
|
|
5372
|
+
* prompt as its first turn. `task_complete` is the only way a task reports
|
|
5373
|
+
* it is done, so a runner without the tools is never sent the task: it is
|
|
5374
|
+
* killed and respawned once, and a second failure fails the start.
|
|
5375
|
+
*/
|
|
5127
5376
|
start(prompt: string): Promise<void>;
|
|
5128
5377
|
getOutput(): string;
|
|
5129
5378
|
onTaskComplete(listener: (report: TaskCompleteArgs) => void): void;
|
|
5130
5379
|
onToolCheckpoint(handler: (question: string, signal: AbortSignal) => Promise<CheckpointAnswer>): void;
|
|
5131
5380
|
/**
|
|
5132
|
-
*
|
|
5133
|
-
*
|
|
5381
|
+
* One spawn of the runner on a fresh token. Null once the runner reports
|
|
5382
|
+
* the server connected — or once the session ended meanwhile, which leaves
|
|
5383
|
+
* nothing to start; otherwise why not, with the process killed and the
|
|
5384
|
+
* token revoked. A runner that cannot be spawned at all throws instead:
|
|
5385
|
+
* spawning it again would fail the same way.
|
|
5134
5386
|
*/
|
|
5135
|
-
private
|
|
5387
|
+
private startAttached;
|
|
5388
|
+
private startWithTools;
|
|
5136
5389
|
private revokeTools;
|
|
5137
5390
|
protected baseHandleExit(code: number): void;
|
|
5138
5391
|
/**
|
|
@@ -5222,8 +5475,7 @@ declare class StructuredSession extends AbstractTerminalSession implements Struc
|
|
|
5222
5475
|
/**
|
|
5223
5476
|
* The structured transport (ADR-0018): a task's runner as a plain child
|
|
5224
5477
|
* process speaking its protocol — no tmux, no `script` (W2). Only runners
|
|
5225
|
-
* with a task-mode connector can be spawned here
|
|
5226
|
-
* terminal transport is the caller's decision, not a silent downgrade here.
|
|
5478
|
+
* with a task-mode connector can be spawned here.
|
|
5227
5479
|
*/
|
|
5228
5480
|
declare class StructuredRunner extends AbstractRunner<StructuredSession> {
|
|
5229
5481
|
private spawnCount;
|
|
@@ -5232,44 +5484,7 @@ declare class StructuredRunner extends AbstractRunner<StructuredSession> {
|
|
|
5232
5484
|
private readonly interruptGraceMs;
|
|
5233
5485
|
private readonly mcp;
|
|
5234
5486
|
constructor(deps?: StructuredRunnerDeps);
|
|
5235
|
-
spawn(opts: RunnerSpawnOptions): Promise<
|
|
5236
|
-
}
|
|
5237
|
-
|
|
5238
|
-
interface TransportRoute {
|
|
5239
|
-
transport: RunnerTransport;
|
|
5240
|
-
/** Why a structured request runs on the terminal instead, in words a surface shows as is. */
|
|
5241
|
-
fallback?: string;
|
|
5242
|
-
}
|
|
5243
|
-
/**
|
|
5244
|
-
* Where one task runs (ADR-0018, S3): structured only when the plan asks for
|
|
5245
|
-
* it and the task's runner has a task-mode connector. Anything else runs on
|
|
5246
|
-
* the terminal, and a structured request says why.
|
|
5247
|
-
*/
|
|
5248
|
-
declare function routeTransport(requested: RunnerTransport | undefined, runner: string, registry?: RunnerRegistry | null): TransportRoute;
|
|
5249
|
-
/**
|
|
5250
|
-
* The runner a host hands the orchestrator: its own terminal runner (tmux,
|
|
5251
|
-
* headless, the VS Code terminal) and the structured one behind a single
|
|
5252
|
-
* `ITerminalRunner`, picking per spawn by {@link routeTransport}.
|
|
5253
|
-
*
|
|
5254
|
-
* `stopAll` and `activeCount` reach both inner runners, so a host that shares
|
|
5255
|
-
* one across plans (the daemon's tmux) keeps its per-plan wrapper above this.
|
|
5256
|
-
*/
|
|
5257
|
-
declare class TransportRouter implements ITerminalRunner {
|
|
5258
|
-
private readonly runners;
|
|
5259
|
-
/**
|
|
5260
|
-
* Session ids the structured runner owns; every other id is the terminal's.
|
|
5261
|
-
* Kept past exit, so a stop that arrives late never reaches the terminal
|
|
5262
|
-
* runner with an id it does not know.
|
|
5263
|
-
*/
|
|
5264
|
-
private readonly structuredIds;
|
|
5265
|
-
constructor(runners: {
|
|
5266
|
-
terminal: ITerminalRunner;
|
|
5267
|
-
structured: ITerminalRunner;
|
|
5268
|
-
});
|
|
5269
|
-
get activeCount(): number;
|
|
5270
|
-
spawn(opts: RunnerSpawnOptions): Promise<ITerminalSession>;
|
|
5271
|
-
stop(sessionId: string): void;
|
|
5272
|
-
stopAll(): void;
|
|
5487
|
+
spawn(opts: RunnerSpawnOptions): Promise<IRunnerSession>;
|
|
5273
5488
|
}
|
|
5274
5489
|
|
|
5275
5490
|
/** Whether a task can be continued in its saved runner session (ADR-0018, K1), and in which. */
|
|
@@ -5282,9 +5497,8 @@ type Continuability = {
|
|
|
5282
5497
|
};
|
|
5283
5498
|
/**
|
|
5284
5499
|
* The rule every surface offers Continue by and the orchestrator enforces: a
|
|
5285
|
-
* completed or failed task whose last attempt
|
|
5286
|
-
*
|
|
5287
|
-
* a terminal task has no session Ordewell can reach — Retry covers both.
|
|
5500
|
+
* completed or failed task whose last attempt left a session id behind. A
|
|
5501
|
+
* conflict is resolved by its repair, not a new turn — Retry covers it.
|
|
5288
5502
|
*/
|
|
5289
5503
|
declare function continuability(task: Task): Continuability;
|
|
5290
5504
|
declare function canContinue(task: Task): boolean;
|
|
@@ -5304,8 +5518,7 @@ interface TaskLogRecorderDeps {
|
|
|
5304
5518
|
* batches, so what a surface saw live and what it reloads are one sequence.
|
|
5305
5519
|
*
|
|
5306
5520
|
* It sits around the runner rather than inside the orchestrator, which stays
|
|
5307
|
-
* unaware of logs
|
|
5308
|
-
* passed through untouched.
|
|
5521
|
+
* unaware of logs.
|
|
5309
5522
|
*/
|
|
5310
5523
|
declare class TaskLogRecorder {
|
|
5311
5524
|
private readonly deps;
|
|
@@ -5313,10 +5526,130 @@ declare class TaskLogRecorder {
|
|
|
5313
5526
|
private readonly flushMs;
|
|
5314
5527
|
private readonly logger;
|
|
5315
5528
|
constructor(deps: TaskLogRecorderDeps);
|
|
5316
|
-
wrap(runner:
|
|
5317
|
-
/** Start a new attempt's log for `session
|
|
5318
|
-
record(taskId: string, session:
|
|
5529
|
+
wrap(runner: IRunner): IRunner;
|
|
5530
|
+
/** Start a new attempt's log for `session`, opening with the skills it was given, and keep it until the session exits. */
|
|
5531
|
+
record(taskId: string, session: IRunnerSession, skills?: readonly TaskSkillSnapshot[]): void;
|
|
5532
|
+
}
|
|
5533
|
+
|
|
5534
|
+
declare function stripAnsi(text: string): string;
|
|
5535
|
+
|
|
5536
|
+
/**
|
|
5537
|
+
* cmd.exe's command-line buffer. A longer line is truncated rather than
|
|
5538
|
+
* rejected, which would corrupt a planner's system prompt or a task's prompt
|
|
5539
|
+
* mid-sentence and produce a confident answer to half a question — so the
|
|
5540
|
+
* batch route refuses instead. See {@link CommandLineTooLongError}.
|
|
5541
|
+
*/
|
|
5542
|
+
declare const CMD_EXE_MAX_COMMAND_LINE = 8191;
|
|
5543
|
+
/**
|
|
5544
|
+
* CreateProcess's own ceiling, which the native and PowerShell routes are
|
|
5545
|
+
* bounded by instead. Windows truncates here too, so the same refusal applies —
|
|
5546
|
+
* it is simply four times further away.
|
|
5547
|
+
*/
|
|
5548
|
+
declare const WINDOWS_MAX_COMMAND_LINE = 32767;
|
|
5549
|
+
interface LaunchPlan {
|
|
5550
|
+
/** The executable handed to `spawn()`. */
|
|
5551
|
+
file: string;
|
|
5552
|
+
/** Arguments for `file`. Pass verbatim when {@link verbatim} is set. */
|
|
5553
|
+
args: string[];
|
|
5554
|
+
/**
|
|
5555
|
+
* Windows batch route only: `args` is already a quoted command line and must
|
|
5556
|
+
* not be re-quoted. Maps to `windowsVerbatimArguments` for `spawn`.
|
|
5557
|
+
*/
|
|
5558
|
+
verbatim?: boolean;
|
|
5319
5559
|
}
|
|
5560
|
+
/** Test seam: every OS touchpoint is injectable, and production uses the defaults. */
|
|
5561
|
+
interface LaunchDeps {
|
|
5562
|
+
platform?: NodeJS.Platform;
|
|
5563
|
+
/** The PATH executables are looked up on. Defaults to the augmented PATH. */
|
|
5564
|
+
resolvePath?: () => Promise<string>;
|
|
5565
|
+
/** True when `candidate` names an existing file. */
|
|
5566
|
+
exists?: (candidate: string) => boolean;
|
|
5567
|
+
/** Absolute path to the Windows command interpreter. */
|
|
5568
|
+
comSpec?: () => string;
|
|
5569
|
+
/** Absolute path to Windows PowerShell. */
|
|
5570
|
+
powerShell?: () => string;
|
|
5571
|
+
/** PATHEXT, as the environment reports it. */
|
|
5572
|
+
pathExt?: () => string;
|
|
5573
|
+
}
|
|
5574
|
+
/**
|
|
5575
|
+
* Thrown when a command's arguments do not fit the buffer of the only
|
|
5576
|
+
* interpreter that can start it. Windows truncates rather than rejecting, and a
|
|
5577
|
+
* system prompt cut off mid-sentence makes the planner answer half a question
|
|
5578
|
+
* confidently — the silent success this repo refuses — so this is raised
|
|
5579
|
+
* instead. `TaskOrchestrator.startTask` catches it and holds the task, so the
|
|
5580
|
+
* message is what the user reads: it names the fix, because they cannot infer
|
|
5581
|
+
* it from a truncated prompt.
|
|
5582
|
+
*/
|
|
5583
|
+
declare class CommandLineTooLongError extends Error {
|
|
5584
|
+
readonly command: string;
|
|
5585
|
+
readonly length: number;
|
|
5586
|
+
readonly limit: number;
|
|
5587
|
+
constructor(command: string, length: number, limit?: number);
|
|
5588
|
+
}
|
|
5589
|
+
/**
|
|
5590
|
+
* Thrown when only a batch shim resolved for a multi-line argument. cmd.exe
|
|
5591
|
+
* reads up to the first CR/LF and discards the rest with no error and exit code
|
|
5592
|
+
* 0 — quoting does not help — so the agent would get the first paragraph of its
|
|
5593
|
+
* prompt without the instruction to report through `task_complete`, then exit looking successful.
|
|
5594
|
+
*/
|
|
5595
|
+
declare class EmbeddedNewlineError extends Error {
|
|
5596
|
+
readonly command: string;
|
|
5597
|
+
constructor(command: string);
|
|
5598
|
+
}
|
|
5599
|
+
/**
|
|
5600
|
+
* Thrown when `command` cannot be resolved to a real file. Kept distinguishable
|
|
5601
|
+
* from `WorkspaceNotFoundError` (utils/workspace) even though both a missing
|
|
5602
|
+
* cwd and a missing binary surface as the same `spawn` ENOENT to Node — the two
|
|
5603
|
+
* are checked, and named, separately so the failure names the actual cause.
|
|
5604
|
+
*/
|
|
5605
|
+
declare class ExecutableNotFoundError extends Error {
|
|
5606
|
+
readonly command: string;
|
|
5607
|
+
readonly searchedPath: string;
|
|
5608
|
+
constructor(command: string, searchedPath: string);
|
|
5609
|
+
}
|
|
5610
|
+
/**
|
|
5611
|
+
* Whether `command` actually resolves to a file, given the plan
|
|
5612
|
+
* {@link planDirectLaunch} produced for it and the PATH it was resolved
|
|
5613
|
+
* against.
|
|
5614
|
+
*
|
|
5615
|
+
* POSIX is deliberately identity in `planDirectLaunch` (execvp does its own
|
|
5616
|
+
* PATH search), so the search is repeated here instead. Windows already did
|
|
5617
|
+
* the search inside `planDirectLaunch` — signalled by the returned file
|
|
5618
|
+
* differing from the bare command name it was given; an unresolved command
|
|
5619
|
+
* comes back unchanged.
|
|
5620
|
+
*/
|
|
5621
|
+
declare function isExecutableResolved(command: string, plan: LaunchPlan, PATH: string, deps?: LaunchDeps): boolean;
|
|
5622
|
+
/** The verbatim command line cmd.exe receives after `/d /s /c`, before wrapping. */
|
|
5623
|
+
declare function windowsCommandLine(file: string, args: string[]): string;
|
|
5624
|
+
/**
|
|
5625
|
+
* How to start `command` with `args` through `spawn()`, with no shell.
|
|
5626
|
+
*
|
|
5627
|
+
* POSIX returns its input unchanged — execvp already searches PATH, and adding
|
|
5628
|
+
* a resolution step there would be a new way for a working setup to break.
|
|
5629
|
+
*
|
|
5630
|
+
* Windows resolves the command against PATH × PATHEXT, preferring a native
|
|
5631
|
+
* executable (spawned directly) over a batch shim (through cmd.exe) over a
|
|
5632
|
+
* PowerShell script shim (through `powershell.exe -File`). A command that
|
|
5633
|
+
* resolves to nothing is returned unchanged, so the caller's existing ENOENT —
|
|
5634
|
+
* which names what the user typed — is what surfaces rather than a second,
|
|
5635
|
+
* vaguer error from here.
|
|
5636
|
+
*
|
|
5637
|
+
* The tiers are tried in preference order and the first that *fits* wins, with
|
|
5638
|
+
* one deliberate exception: an overflowing batch shim does not fall through to
|
|
5639
|
+
* PowerShell. Overflow means a very large prompt, which is precisely where
|
|
5640
|
+
* `-File` argument fidelity is least worth betting on, and where a clear held
|
|
5641
|
+
* task beats a plausibly-mangled one. So capacity does not reorder the tiers —
|
|
5642
|
+
* a `.ps1` beside a too-long `.cmd` still raises.
|
|
5643
|
+
*
|
|
5644
|
+
* A line break does reorder them: cmd.exe cannot carry one at any length, so a
|
|
5645
|
+
* `.ps1` beside a `.cmd` wins, and a lone `.cmd` raises.
|
|
5646
|
+
*
|
|
5647
|
+
* @throws {CommandLineTooLongError} when the selected route's buffer cannot
|
|
5648
|
+
* carry the arguments.
|
|
5649
|
+
* @throws {EmbeddedNewlineError} when the arguments span lines and only the
|
|
5650
|
+
* batch route resolved.
|
|
5651
|
+
*/
|
|
5652
|
+
declare function planDirectLaunch(command: string, args: string[], deps?: LaunchDeps): Promise<LaunchPlan>;
|
|
5320
5653
|
|
|
5321
5654
|
/**
|
|
5322
5655
|
* A workspace path that does not exist, or exists but is not a directory.
|
|
@@ -5435,6 +5768,8 @@ interface KillTreeDeps {
|
|
|
5435
5768
|
unref?: () => void;
|
|
5436
5769
|
};
|
|
5437
5770
|
clearTimeoutImpl?: (handle: unknown) => void;
|
|
5771
|
+
/** Signals a pid, or a process group as its negated id. Injected so the group path needs no real processes. */
|
|
5772
|
+
killImpl?: (pid: number, signal: NodeJS.Signals | 0) => void;
|
|
5438
5773
|
}
|
|
5439
5774
|
/**
|
|
5440
5775
|
* Terminate `proc` and everything it started.
|
|
@@ -5481,137 +5816,42 @@ declare function clearAugmentedPathCache(): void;
|
|
|
5481
5816
|
*/
|
|
5482
5817
|
declare function withPath(base: NodeJS.ProcessEnv, resolvedPath: string, overrides?: Record<string, string>): NodeJS.ProcessEnv;
|
|
5483
5818
|
|
|
5484
|
-
/** One shared tmux session per daemon, scoped by port so multiple daemons never collide. */
|
|
5485
|
-
declare function tmuxSessionName(port: number): string;
|
|
5486
|
-
/**
|
|
5487
|
-
* Each daemon gets its own tmux *server*, not just its own session name.
|
|
5488
|
-
*
|
|
5489
|
-
* A plain `tmux new-session` attaches to whatever server already owns the
|
|
5490
|
-
* default socket, and a session created on an existing server inherits that
|
|
5491
|
-
* **server's** environment — not the environment of the process that asked for
|
|
5492
|
-
* it (tmux only refreshes `update-environment` vars, and only on attach). So a
|
|
5493
|
-
* daemon started with, say, a particular provider API key would silently hand
|
|
5494
|
-
* its runners a stale key left behind by whoever started the server first,
|
|
5495
|
-
* possibly hours earlier under a different configuration entirely.
|
|
5496
|
-
*
|
|
5497
|
-
* A private socket makes the server a child of this daemon, so the runner
|
|
5498
|
-
* inherits the daemon's environment the way any child process would, and
|
|
5499
|
-
* `kill-server` at shutdown is authoritative — a runner cannot outlive the
|
|
5500
|
-
* daemon by hiding on a shared server. Users attaching by hand need the same
|
|
5501
|
-
* flag: `tmux -L ordewell-<port> attach -t ordewell-<port>`.
|
|
5502
|
-
*/
|
|
5503
|
-
declare function tmuxSocketName(port: number): string;
|
|
5504
|
-
/**
|
|
5505
|
-
* tmux window targeting breaks on `:` and other punctuation, so ids are
|
|
5506
|
-
* slugged. Task ids are only unique within one plan ("task-1" is every
|
|
5507
|
-
* planner's favourite), so the window is also scoped by the plan session id —
|
|
5508
|
-
* without it, the second plan run in a daemon's lifetime would collide with
|
|
5509
|
-
* the first plan's still-open windows and pipe its output into the wrong one.
|
|
5510
|
-
*/
|
|
5511
|
-
declare function tmuxWindowName(taskId: string, planSessionId?: string): string;
|
|
5512
|
-
type ProbeFn = () => void;
|
|
5513
|
-
/** Feature-detects tmux the same way `HeadlessRunner` detects `script`. */
|
|
5514
|
-
declare function hasTmux(probe?: ProbeFn): boolean;
|
|
5515
5819
|
type HasBinFn = (bin: string) => boolean;
|
|
5516
5820
|
/**
|
|
5517
5821
|
* Shell command tmux should pipe a copy-mode selection into, so selecting text
|
|
5518
|
-
* in a
|
|
5822
|
+
* in a tmux pane puts it on the *system* clipboard rather than in a tmux
|
|
5519
5823
|
* paste buffer no other application can read. Preferred over tmux's OSC 52
|
|
5520
5824
|
* bridge, which plenty of emulators (VTE before 0.76, xterm without
|
|
5521
5825
|
* `allowWindowOps`) drop on the floor.
|
|
5522
5826
|
*/
|
|
5523
5827
|
declare function clipboardCopyCommand(hasBin?: HasBinFn, platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string | null;
|
|
5524
5828
|
|
|
5525
|
-
declare
|
|
5526
|
-
getUserPluginsDir(): string;
|
|
5527
|
-
listUserPluginDirs(): string[];
|
|
5528
|
-
listDir(dir: string): string[];
|
|
5529
|
-
loadManifest(pluginDir: string): RunnerPluginManifest | null;
|
|
5530
|
-
copyDir(sourceDir: string, destDir: string): void;
|
|
5531
|
-
removeDir(dir: string): void;
|
|
5532
|
-
ensureDir(dir: string): void;
|
|
5533
|
-
writeFile(filePath: string, content: string): void;
|
|
5534
|
-
readFile(filePath: string): string | null;
|
|
5535
|
-
dirExists(path: string): boolean;
|
|
5536
|
-
exists(path: string): boolean;
|
|
5537
|
-
}
|
|
5538
|
-
|
|
5539
|
-
/**
|
|
5540
|
-
* Shape check for a manifest read off disk or out of a cloned repository. The
|
|
5541
|
-
* name is constrained here rather than at each install route, so every store
|
|
5542
|
-
* implementation gets the same guarantee that a manifest name is a plain
|
|
5543
|
-
* segment and never a traversal sequence.
|
|
5544
|
-
*/
|
|
5545
|
-
declare function isValidManifest(obj: unknown): obj is RunnerPluginManifest;
|
|
5829
|
+
declare function removedPluginNotice(dataDir?: string): string | undefined;
|
|
5546
5830
|
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
*/
|
|
5553
|
-
declare const PLUGIN_NAME_PATTERN: RegExp;
|
|
5554
|
-
declare function isPlainPluginName(name: unknown): name is string;
|
|
5555
|
-
declare function assertPlainPluginName(name: unknown): asserts name is string;
|
|
5556
|
-
/**
|
|
5557
|
-
* Resolve where a plugin of this name installs, and assert the result is still
|
|
5558
|
-
* a direct child of the plugins directory. Validation and use share this one
|
|
5559
|
-
* call so they cannot disagree about the path being checked.
|
|
5560
|
-
*/
|
|
5561
|
-
declare function resolvePluginInstallDir(pluginsDir: string, name: unknown): string;
|
|
5562
|
-
|
|
5563
|
-
/** Hosts a plugin may be cloned from. Exact hostname match, case-insensitive. */
|
|
5564
|
-
declare const ALLOWED_PLUGIN_HOSTS: readonly string[];
|
|
5565
|
-
type PluginSource = {
|
|
5566
|
-
kind: 'git';
|
|
5567
|
-
url: string;
|
|
5568
|
-
} | {
|
|
5569
|
-
kind: 'path';
|
|
5570
|
-
path: string;
|
|
5571
|
-
};
|
|
5572
|
-
/**
|
|
5573
|
-
* Validate a plugin repository URL. Requires an ordinary HTTPS repository on an
|
|
5574
|
-
* allowed host, which is also what rejects git's transport helpers (`ext::`,
|
|
5575
|
-
* `git://`, `ssh://`, `file://`) — they never reach the clone because they are
|
|
5576
|
-
* not the https scheme.
|
|
5577
|
-
*
|
|
5578
|
-
* Returns the parsed URL so callers clone the normalised form they validated.
|
|
5579
|
-
*/
|
|
5580
|
-
declare function assertInstallablePluginUrl(url: unknown): URL;
|
|
5581
|
-
/**
|
|
5582
|
-
* Decide whether an install source names a remote repository or a local
|
|
5583
|
-
* directory. Anything that carries a scheme or looks like an scp-style remote
|
|
5584
|
-
* goes down the URL route so it is rejected as a bad URL rather than silently
|
|
5585
|
-
* retried as a (nonexistent) directory.
|
|
5586
|
-
*/
|
|
5587
|
-
declare function classifyPluginSource(source: string): PluginSource;
|
|
5588
|
-
|
|
5589
|
-
declare function resolveArgs(manifest: RunnerPluginManifest, ctx: ResolveContext): RunnerInvocation;
|
|
5590
|
-
/**
|
|
5591
|
-
* The manifest's meaning of a task's mode and effort, for a runner driven over
|
|
5592
|
-
* its programmatic protocol rather than a command line built from
|
|
5593
|
-
* `argsTemplate` (ADR-0018, C1). The effort stays a raw id behind the same
|
|
5594
|
-
* `{{if thinking}}` gate as the template path: how an effort reaches the
|
|
5595
|
-
* runner is protocol, which each adapter owns.
|
|
5596
|
-
*/
|
|
5597
|
-
declare function resolveTaskRunnerFlags(manifest: RunnerPluginManifest, ctx: Pick<ResolveContext, 'mode' | 'model' | 'thinkingEffort'>): TaskRunnerFlags;
|
|
5831
|
+
declare function resolveTaskRunnerFlags(manifest: RunnerManifest, ctx: {
|
|
5832
|
+
mode: string;
|
|
5833
|
+
model?: string;
|
|
5834
|
+
thinkingEffort?: string;
|
|
5835
|
+
}): TaskRunnerFlags;
|
|
5598
5836
|
|
|
5599
|
-
declare const CLAUDE_CODE_MANIFEST:
|
|
5837
|
+
declare const CLAUDE_CODE_MANIFEST: RunnerManifest;
|
|
5600
5838
|
|
|
5601
|
-
declare const OPENCODE_MANIFEST:
|
|
5839
|
+
declare const OPENCODE_MANIFEST: RunnerManifest;
|
|
5602
5840
|
|
|
5603
5841
|
declare const STATE_DIR = ".ordewell";
|
|
5604
5842
|
declare function ensureDir(dir: string): void;
|
|
5605
5843
|
declare function getStateDir(baseDir?: string): string;
|
|
5606
5844
|
/**
|
|
5607
|
-
*
|
|
5608
|
-
*
|
|
5609
|
-
*
|
|
5610
|
-
*
|
|
5611
|
-
*
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5845
|
+
* Ignores the state directory's contents except this file and `skills/`, so a
|
|
5846
|
+
* project's skills are committed and reach every task worktree through git —
|
|
5847
|
+
* the bootstrap never links `.ordewell/` (ADR-0013). Plans and sessions stay
|
|
5848
|
+
* uncommittable without touching a file the developer wrote; editing their
|
|
5849
|
+
* root `.gitignore` would be the intrusive version of this.
|
|
5850
|
+
*/
|
|
5851
|
+
declare const STATE_DIR_IGNORE = "*\n!.gitignore\n!skills/\n!skills/**\n";
|
|
5852
|
+
/**
|
|
5853
|
+
* Idempotent, and never overwrites a file the developer customised (to commit
|
|
5854
|
+
* their plans deliberately, say). Only the exact legacy rule is upgraded.
|
|
5615
5855
|
*/
|
|
5616
5856
|
declare function ensureStateDirIgnored(baseDir?: string): void;
|
|
5617
5857
|
|
|
@@ -5664,57 +5904,6 @@ declare function sanitizeSlug(raw: string): string;
|
|
|
5664
5904
|
/** Save the PRD to `<workspace>/.scratch/<slug>/PRD.md` (to-prd native convention). */
|
|
5665
5905
|
declare function savePrdMarkdown(workspace: string, slug: string, markdown: string): string;
|
|
5666
5906
|
|
|
5667
|
-
/** What the user last picked for one planner backend. */
|
|
5668
|
-
interface PlannerModelChoice {
|
|
5669
|
-
model: string;
|
|
5670
|
-
effort?: string;
|
|
5671
|
-
}
|
|
5672
|
-
/**
|
|
5673
|
-
* A candidate model as this planner's catalog lists it. Deliberately plain
|
|
5674
|
-
* data: a harness planner's catalog is its runner's own model list and a
|
|
5675
|
-
* vendor's is a picker list (ADR-0009), and the rule below is the same for
|
|
5676
|
-
* both — so the caller normalizes, and this module never reaches for a
|
|
5677
|
-
* ModelResolver, a config or the network.
|
|
5678
|
-
*/
|
|
5679
|
-
interface PlannerModelCandidate {
|
|
5680
|
-
id: string;
|
|
5681
|
-
variants?: {
|
|
5682
|
-
id: string;
|
|
5683
|
-
}[];
|
|
5684
|
-
}
|
|
5685
|
-
interface PlannerModelRecall {
|
|
5686
|
-
model: string;
|
|
5687
|
-
effort: string;
|
|
5688
|
-
source: 'remembered' | 'catalog-default' | 'none';
|
|
5689
|
-
}
|
|
5690
|
-
/** The slice of `SettingsService` this needs, so tests can pass a plain object. */
|
|
5691
|
-
interface PlannerModelStore {
|
|
5692
|
-
getPlannerModel(provider: string): PlannerModelChoice | undefined;
|
|
5693
|
-
setPlannerModel(provider: string, entry: PlannerModelChoice | undefined): void;
|
|
5694
|
-
}
|
|
5695
|
-
/**
|
|
5696
|
-
* Remembers, per planner backend, the model the user last chose for it.
|
|
5697
|
-
*
|
|
5698
|
-
* Switching the planner has to clear the model — an id is scoped to the agent
|
|
5699
|
-
* that listed it, so an OpenRouter slug handed to Claude Code points it at
|
|
5700
|
-
* something it cannot spawn. That clear is correct and stays; what was missing
|
|
5701
|
-
* is that switching *back* then forced a re-pick of a model the user had
|
|
5702
|
-
* already chosen. Both surfaces' clears and the restore now read one rule from
|
|
5703
|
-
* here rather than three copies drifting apart.
|
|
5704
|
-
*/
|
|
5705
|
-
declare class PlannerModelMemory {
|
|
5706
|
-
private store;
|
|
5707
|
-
constructor(store: PlannerModelStore);
|
|
5708
|
-
/** Record what the user picked for `provider`; a blank model forgets it instead. */
|
|
5709
|
-
remember(provider: string, model: string, effort?: string): void;
|
|
5710
|
-
/**
|
|
5711
|
-
* What the model and effort should become when `provider` takes over the
|
|
5712
|
-
* planner, given the models it actually serves. The `source` is what the
|
|
5713
|
-
* three surfaces word their notice from — restored, defaulted, or nothing.
|
|
5714
|
-
*/
|
|
5715
|
-
recall(provider: string, catalog: PlannerModelCandidate[]): PlannerModelRecall;
|
|
5716
|
-
}
|
|
5717
|
-
|
|
5718
5907
|
/** How many AI tasks may run at once: `ORDEWELL_MAX_PARALLEL`, `/parallel`, `ordewell.maxParallelSessions`. */
|
|
5719
5908
|
declare const DEFAULT_MAX_PARALLEL = 3;
|
|
5720
5909
|
/**
|
|
@@ -5725,4 +5914,4 @@ declare const DEFAULT_MAX_PARALLEL = 3;
|
|
|
5725
5914
|
*/
|
|
5726
5915
|
declare function parseMaxParallel(value: unknown): number | null;
|
|
5727
5916
|
|
|
5728
|
-
export {
|
|
5917
|
+
export { ALL_PROVIDERS, AUTO_COMMANDS, AbstractRunner, AbstractRunnerSession, ActiveTaskSession, type AdoptSessionResponse, type Adr0013IsolationRun, type Adr0013PlanIsolation, type Adr0013TaskRecord, AgentAdapter, AgentEvent, AgentProcessDeps, AgentStartOptions, AiProvider, AlreadyExecutingError, ApplyTaskOpsResult, ApprovalAnswer, type ApprovalAnswerResponse, ApprovalDecision, ApprovalMode, ApprovalPolicy, ApprovalRequest, type ApprovalsResponse, type AskOptions, AwaitingReason, BaseAiService, BaseConfig, BaseFileSystem, BufferedTaskOutputSource, CLAUDE_CODE_MANIFEST, CLI_PROVIDERS, CMD_EXE_MAX_COMMAND_LINE, CORE_PLANNER_PROMPT, type CancelPlanningResponse, type CappedRows, CheckpointAnswer, type CheckpointListener, ClaudeCodeAdapter, CliAgentAiService, type CliAgentAiServiceDeps, CodexAdapter, type CommandClassification, type CommandDescriptor, CommandLineTooLongError, type CommandTier, type CommandsResponse, type ComposeOptions, ConsoleLogger, ContextCollector, type Continuability, ConversationBusyError, type ConversationCompactResponse, type ConversationCompaction, ConversationEditError, type ConversationFork, type ConversationForkResponse, ConversationMessage, type ConversationRequest, type ConversationRewind, type ConversationRewindResponse, type ConversationTurn, type ConversationVariant, DAEMON_SUBPROTOCOL, DAEMON_TOKEN_SUBPROTOCOL_PREFIX, DEFAULT_MAX_PARALLEL, type DaemonErrorCode, DiscoveredModel, EmbeddedNewlineError, type EnvAdmission, EnvConfig, type ErrorBody, type ExecImpl, ExecutableNotFoundError, type ExecuteResponse, FindSymbolOptions, type ForceSendResponse, GIT_READONLY_SUBCOMMANDS, GREP_PCRE_PROBE_ARGS, GeminiService, type GeneratePlanResponse, type GitExecFn, GlobOptions, type GrepInvocation, GrepOptions, type GrepRegex, HARNESS_PLANNER_REASON, type HasBinFn, type IAiService, IApproval, IConfig, IFileSystem, type ILogger, type INotification, IRunner, IRunnerSession, IWorktreeIsolation, type IsolationDiffResponse, IsolationHandoff, IsolationLandedTask, type IsolationMergeResponse, IsolationMergeResult, IsolationOutcome, IsolationRun, IsolationTaskRecord, IsolationTaskStatus, IsolationView, JSON_REPAIR_INSTRUCTION, type KillTreeDeps, type LaunchDeps, type LaunchPlan, LegacyPlanState, type LiveOutputLookup, type LiveTail, type LiveTailOptions, type MappedTool, type MergeGateEntry, type MergeGateResponse, MergeGateView, ModelResolver, type ModelResolverDeps, type ModelsResponse, type ModifyPlanRequest, NoPlanError, type NotificationAction, OPENCODE_MANIFEST, ORDEWELL_SETTABLE_ENV, OUTPUT_LINES_DEFAULT, OUTPUT_LINES_MAX, type OkResponse, OpenAiService, OpenCodeAdapter, type OrchestratorObserver, OrchestratorOption, OrdewellMcpServer, PROVIDER_CREDENTIAL_ENV, PROVIDER_DETECT_PRIORITY, PROVIDER_LABEL, PROVIDER_PRIORITY, PROVIDER_SHORT_LABEL, type PendingApproval, PendingApprovals, type PendingApprovalsOptions, PlanEditError, PlanIsolation, PlanParseError, type PlanRequest, type PlanResponse, PlanState, PlanStatus, PlanStore, Planner, type PlannerBackendEntry, type PlannerModelCandidate, type PlannerModelChoice, PlannerModelMemory, type PlannerModelRecall, type PlannerModelStore, type PlannerReplyClassification, type PlannerSubmission, PlannerToolHandler, PlannerTurnDiscardedError, PlannerTurnStoppedError, type PlannerUsability, PlannerUsage, type PrdBlock, type PrdResponse, type PriorOutput, ProviderModelLists, type ProviderRegistration, QueuedMessage, QueuedTaskMessage, REFUSED_COMMANDS, ReadFileOpts, type RemoveMessageResponse, RepairEvidence, type RepairLoopOpts, type RepairVerdict, RepoGroupLayout, type ResearchChat, ResearchLogEntry, ResearchProgress, type ResearchShell, type ResearchShellDeps, ResearchToolType, type ResearchTurn, type ResolveConflictResponse, type RewindTarget, type RewindTargetsResponse, RunnerApprovals, type RunnerCatalog, RunnerId, RunnerInstallation, RunnerManifest, RunnerModeInfo, RunnerRegistry, type RunnerSpawnOptions, type RunnersResponse, SETTINGS_ENV_ALLOWLIST, SETTINGS_ENV_REFUSED, STATE_DIR, STATE_DIR_IGNORE, STOPPED_TOOL_RESULT, SYMBOL_LANGUAGES, type SaveSession, Session, SessionBroadcaster, type SessionData, type SessionDeps, type SessionListResponse, SessionMessage, type SessionMeta, SessionNotFoundError, SessionNotice, type SessionPlanner, type SessionResponse, type SessionRuntimeSettings, type SettingsResponse, SettingsService, type SettingsUpdateResponse, type ShellDialect, SkillInfo, type SkillInvocation, SkillLoad, SkillsService, type SpawnSpec, StdioAgentAdapter, type StopResponse, StructuredEvent, StructuredRunner, type StructuredRunnerDeps, StructuredSession, StructuredTurnEnd, SurfacePlan, SurfacePlanState, TASK_QUERY_ANSWER_MAX_CHARS, TASK_QUERY_ANSWER_OR_OPS, TASK_QUERY_FIELDS, TASK_QUERY_PROTOCOL, TASK_QUERY_REMINDER, TRUNCATED_PLAN_REPAIR_INSTRUCTION, Task, type TaskAttemptSnapshot, TaskCompleteArgs, TaskControlError, TaskIsolation, type TaskLogAttemptsResponse, TaskLogEvent, type TaskLogFile, type TaskLogLocation, TaskLogRecorder, type TaskLogRecorderDeps, type TaskLogResponse, type TaskMessageResponse, TaskModeAgentAdapter, TaskOp, TaskOrchestrator, type TaskOrchestratorDeps, type TaskOrchestratorOptions, type TaskOutputSource, type TaskQuery, type TaskQueryCatalog, type TaskQueryField, TaskRunnerFlags, TaskSkillSnapshot, TaskSnapshot, TaskStartOptions, TaskTokenScope, type TokenCarriers, type ToolCall, ToolOutcome, type ToolResult, TreeSnapshot, UsageRecord, type UserSettings, Verdict, VerdictEngine, type VerdictListener, WINDOWS_MAX_COMMAND_LINE, type WorkspaceCheckDeps, WorkspaceNotAProjectError, WorkspaceNotFoundError, type WorkspaceProjectCheckDeps, type WorkspacesResponse, type WorktreeIsolationDeps, abbreviateHome, admitSettingsEnv, applyHeadLimit, assertWorkspaceExists, assertWorkspaceIsProject, augmentPromptWithPriorOutputs, augmentedPath, bearerHeaderValue, buildConflictRepairPrompt, buildConflictResolutionPrompt, buildConversationSystemPrompt, buildFallbackGrepArgs, buildGlobArgs, buildGrepArgs, buildMergePrompt, buildModifyDuringExecutionPrompt, buildModifyPlanPrompt, buildPlanWithResults, buildResearchPrompt, buildResearchToolsPrompt, buildSplitPrompt, buildSubagentSystemPrompt, canContinue, clampThinkingEffort, classifyCommand, classifyPlannerReply, clearAugmentedPathCache, clearDaemonToken, clearResearchShellCache, clearState, clipboardCopyCommand, coerceAssignments, collectDirectDependencyOutputs, composeAugmentedPrompt, composeContinuationPrompt, configuredProviders, continuability, createAiService, createSession, createTaskAdapter, createWorktreeIsolation, daemonTokenPath, defaultLogger, definitionPattern, deleteSession, describeMergeResult, discoverGeminiModels, effectiveAllowlist, ensureDir, ensurePrivateDir, ensureStateDirIgnored, executionLogBlock, extractPrdBlock, extractPresentedToken, filterFallbackByAnchoredInclude, filterModelsForPrompt, formatSearchOutput, generatePlanWithRepair, getLatestSession, getProviderMeta, getSettingsPath, getStateDir, globalDataDir, grantScopeFor, grepRegexFromProbe, idSegment, includeGlobFor, isCliProvider, isExecutableResolved, isOpenAiProvider, killTree, languageForId, listSessions, listTaskLogAttempts, loadSession, loadSessionPlanState, loadState, mapAgentTool, migrateOldConfigDir, migratePlanIsolation, mintDaemonToken, mintSessionId, modelContextBlock, modifyValidationFeedback, normalizeAgentArgs, normalizeGeminiModel, openTaskLog, parseMaxParallel, parseTaskQueryJson, pendingEditRulesBlock, planDirectLaunch, plannerBackendEntries, plannerMessage, plannerTranscript, prefixModelId, providerForRunner, reEmitPlanPrompt, reEmitTaskOpsPrompt, reEmitTaskQueryPrompt, readDaemonToken, readTaskLog, referencePattern, removedPluginNotice, renderPlanMap, renderPriorOutputs, renderTaskQueryAnswer, repairLoop, researchShellWarning, researchToolsPath, resolveProviderFromPrefix, resolveResearchShell, resolveSkillInvocation, resolveTaskRunnerFlags, resolveWithin, resubmitEditPrompt, resubmitPlanPrompt, retargetTaskRunner, runnerAssignment, runnerForProvider, sanitizeSlug, savePrdMarkdown, saveSession, saveState, sessionDataDir, sessionRuntimeSettings, stateExists, stripAnsi, stripModelPrefix, summarizeOutput, supportsTaskMode, taskOpsRejectedPrompt, taskQuerySignature, textHasTaskQuery, tokenSubprotocols, tokensMatch, truncatedPlanReEmitPrompt, wellKnownBinDirs, windowsCommandLine, withPath, writePrivateFile };
|