@ordewell/core 0.4.10 → 0.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ApprovalPolicy-BVhGdECT.d.mts +79 -0
- package/dist/ApprovalPolicy-BVhGdECT.d.ts +79 -0
- package/dist/{ITerminalRunner-CbE6gKLI.d.ts → ITerminalRunner-D_RBDoHa.d.mts} +10 -81
- package/dist/{ITerminalRunner-1NAv8wCC.d.mts → ITerminalRunner-DqAs12sy.d.ts} +10 -81
- package/dist/{ModeResolver-F5wnlSz1.d.mts → ModeResolver-CCKYqdZC.d.mts} +1 -1
- package/dist/{ModeResolver-Dx5gzNPC.d.ts → ModeResolver-CzZd-i6T.d.ts} +1 -1
- package/dist/{Task-1NwmUImI.d.mts → Task-cGrfYRXK.d.mts} +8 -1
- package/dist/{Task-1NwmUImI.d.ts → Task-cGrfYRXK.d.ts} +8 -1
- package/dist/chunk-HPNUFBIT.mjs +19 -0
- package/dist/chunk-HPNUFBIT.mjs.map +1 -0
- package/dist/{chunk-IO6PEEN6.mjs → chunk-N6HTBUKG.mjs} +11 -1
- package/dist/chunk-N6HTBUKG.mjs.map +1 -0
- package/dist/{chunk-TUGJXD4G.mjs → chunk-UEJ3SZQ7.mjs} +2 -2
- package/dist/{chunk-YI4ZDZEE.mjs → chunk-YTJ7EOV6.mjs} +62 -3
- package/dist/chunk-YTJ7EOV6.mjs.map +1 -0
- package/dist/index.d.mts +187 -235
- package/dist/index.d.ts +187 -235
- package/dist/index.js +643 -439
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +611 -486
- package/dist/index.mjs.map +1 -1
- package/dist/order-labels.d.mts +17 -0
- package/dist/order-labels.d.ts +17 -0
- package/dist/order-labels.js +44 -0
- package/dist/order-labels.js.map +1 -0
- package/dist/order-labels.mjs +9 -0
- package/dist/order-labels.mjs.map +1 -0
- package/dist/{parsing-BqbJySeo.d.mts → parsing-BT-dvFcu.d.mts} +2 -2
- package/dist/{parsing-X0Gvuz-q.d.ts → parsing-D87zKtTe.d.ts} +2 -2
- package/dist/parsing.d.mts +3 -3
- package/dist/parsing.d.ts +3 -3
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +3 -2
- package/dist/{plan-utils-DtsfHnn_.d.ts → plan-utils-BbC9KdK4.d.ts} +139 -3
- package/dist/{plan-utils-B5rVXNVI.d.mts → plan-utils-DHBIvkiT.d.mts} +139 -3
- package/dist/plan-utils.d.mts +4 -3
- package/dist/plan-utils.d.ts +4 -3
- package/dist/plan-utils.js +14 -2
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +9 -4
- package/dist/testing.d.mts +3 -2
- package/dist/testing.d.ts +3 -2
- package/package.json +12 -2
- package/skills/grilling/SKILL.md +31 -0
- package/skills/to-spec/SKILL.md +64 -0
- package/dist/chunk-IO6PEEN6.mjs.map +0 -1
- package/dist/chunk-YI4ZDZEE.mjs.map +0 -1
- /package/dist/{chunk-TUGJXD4G.mjs.map → chunk-UEJ3SZQ7.mjs.map} +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The planner's single approval seam. Every capability that reaches beyond the
|
|
3
|
+
* default read-only, in-workspace envelope — a path outside the workspace root,
|
|
4
|
+
* a shell command outside the auto-allowed set, a URL fetch — routes through
|
|
5
|
+
* one `request()` so the policy has exactly one owner (the same "one repair
|
|
6
|
+
* owner" shape as PlanRepair).
|
|
7
|
+
*
|
|
8
|
+
* Surfaces supply the human channel. VS Code answers with a modal; the web
|
|
9
|
+
* server currently has no prompt UI, so it denies unless the scope was
|
|
10
|
+
* pre-approved through config. Denial is always a visible, actionable tool
|
|
11
|
+
* result — never a silent success.
|
|
12
|
+
*/
|
|
13
|
+
type ApprovalKind = 'external_path' | 'shell_command' | 'url_fetch';
|
|
14
|
+
interface ApprovalRequest {
|
|
15
|
+
kind: ApprovalKind;
|
|
16
|
+
/** The concrete thing being asked about: an absolute path, a command line, a URL. */
|
|
17
|
+
subject: string;
|
|
18
|
+
/**
|
|
19
|
+
* What a grant covers. Approving remembers this, not `subject`, so reading a
|
|
20
|
+
* second file from an already-approved directory does not prompt again.
|
|
21
|
+
*/
|
|
22
|
+
scope: string;
|
|
23
|
+
/** One-line context for the prompt. */
|
|
24
|
+
detail?: string;
|
|
25
|
+
}
|
|
26
|
+
interface IApproval {
|
|
27
|
+
request(req: ApprovalRequest): Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
/** Denies everything. The safe default when a surface wires no approval channel. */
|
|
30
|
+
declare const DENY_ALL: IApproval;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Decides whether one out-of-envelope capability may run, and remembers the
|
|
34
|
+
* answer for the rest of the session.
|
|
35
|
+
*
|
|
36
|
+
* Grants are keyed on {@link ApprovalRequest.scope}, never on the concrete
|
|
37
|
+
* subject: approving a read of `/tmp/foo/a.log` grants `/tmp/foo/*`, and
|
|
38
|
+
* approving `az group list` grants `az group`. Without that, a planner doing
|
|
39
|
+
* real research would prompt on every single call and the feature would be
|
|
40
|
+
* unusable.
|
|
41
|
+
*
|
|
42
|
+
* `mode` is the policy floor:
|
|
43
|
+
* ask consult the human channel; no channel means deny (headless, web)
|
|
44
|
+
* allow grant everything the tier system did not already refuse
|
|
45
|
+
* deny grant nothing beyond `preApproved`
|
|
46
|
+
*
|
|
47
|
+
* Note the ordering: `preApproved` is honored under every mode including
|
|
48
|
+
* `deny`, because it is an explicit operator decision rather than a default.
|
|
49
|
+
*/
|
|
50
|
+
type ApprovalMode = 'ask' | 'allow' | 'deny';
|
|
51
|
+
interface ApprovalPolicyOptions {
|
|
52
|
+
mode?: ApprovalMode;
|
|
53
|
+
/** Scopes granted up front from config. A trailing `*` matches by prefix. */
|
|
54
|
+
preApproved?: string[];
|
|
55
|
+
/** The human channel. Absent means there is nobody to ask. */
|
|
56
|
+
ask?: (req: ApprovalRequest) => Promise<boolean>;
|
|
57
|
+
/** Called whenever a decision is reached, for surfacing in a UI or a log. */
|
|
58
|
+
onDecision?: (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
|
|
59
|
+
}
|
|
60
|
+
type ApprovalSource = 'pre-approved' | 'remembered' | 'mode' | 'asked' | 'no-channel';
|
|
61
|
+
declare class ApprovalPolicy implements IApproval {
|
|
62
|
+
private readonly mode;
|
|
63
|
+
private readonly preApproved;
|
|
64
|
+
private readonly asker?;
|
|
65
|
+
private readonly onDecision?;
|
|
66
|
+
private readonly granted;
|
|
67
|
+
private readonly refused;
|
|
68
|
+
/** One in-flight ask per scope: a parallel tool round must not prompt twice for the same thing. */
|
|
69
|
+
private readonly inFlight;
|
|
70
|
+
private generation;
|
|
71
|
+
constructor(opts?: ApprovalPolicyOptions);
|
|
72
|
+
request(req: ApprovalRequest): Promise<boolean>;
|
|
73
|
+
/** Scopes the user has granted this session — for display and for persistence. */
|
|
74
|
+
grantedScopes(): string[];
|
|
75
|
+
/** Drop every session-scoped decision. Called on session reset. */
|
|
76
|
+
reset(): void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { type ApprovalKind as A, DENY_ALL as D, type IApproval as I, type ApprovalMode as a, ApprovalPolicy as b, type ApprovalPolicyOptions as c, type ApprovalRequest as d, type ApprovalSource as e };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The planner's single approval seam. Every capability that reaches beyond the
|
|
3
|
+
* default read-only, in-workspace envelope — a path outside the workspace root,
|
|
4
|
+
* a shell command outside the auto-allowed set, a URL fetch — routes through
|
|
5
|
+
* one `request()` so the policy has exactly one owner (the same "one repair
|
|
6
|
+
* owner" shape as PlanRepair).
|
|
7
|
+
*
|
|
8
|
+
* Surfaces supply the human channel. VS Code answers with a modal; the web
|
|
9
|
+
* server currently has no prompt UI, so it denies unless the scope was
|
|
10
|
+
* pre-approved through config. Denial is always a visible, actionable tool
|
|
11
|
+
* result — never a silent success.
|
|
12
|
+
*/
|
|
13
|
+
type ApprovalKind = 'external_path' | 'shell_command' | 'url_fetch';
|
|
14
|
+
interface ApprovalRequest {
|
|
15
|
+
kind: ApprovalKind;
|
|
16
|
+
/** The concrete thing being asked about: an absolute path, a command line, a URL. */
|
|
17
|
+
subject: string;
|
|
18
|
+
/**
|
|
19
|
+
* What a grant covers. Approving remembers this, not `subject`, so reading a
|
|
20
|
+
* second file from an already-approved directory does not prompt again.
|
|
21
|
+
*/
|
|
22
|
+
scope: string;
|
|
23
|
+
/** One-line context for the prompt. */
|
|
24
|
+
detail?: string;
|
|
25
|
+
}
|
|
26
|
+
interface IApproval {
|
|
27
|
+
request(req: ApprovalRequest): Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
/** Denies everything. The safe default when a surface wires no approval channel. */
|
|
30
|
+
declare const DENY_ALL: IApproval;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Decides whether one out-of-envelope capability may run, and remembers the
|
|
34
|
+
* answer for the rest of the session.
|
|
35
|
+
*
|
|
36
|
+
* Grants are keyed on {@link ApprovalRequest.scope}, never on the concrete
|
|
37
|
+
* subject: approving a read of `/tmp/foo/a.log` grants `/tmp/foo/*`, and
|
|
38
|
+
* approving `az group list` grants `az group`. Without that, a planner doing
|
|
39
|
+
* real research would prompt on every single call and the feature would be
|
|
40
|
+
* unusable.
|
|
41
|
+
*
|
|
42
|
+
* `mode` is the policy floor:
|
|
43
|
+
* ask consult the human channel; no channel means deny (headless, web)
|
|
44
|
+
* allow grant everything the tier system did not already refuse
|
|
45
|
+
* deny grant nothing beyond `preApproved`
|
|
46
|
+
*
|
|
47
|
+
* Note the ordering: `preApproved` is honored under every mode including
|
|
48
|
+
* `deny`, because it is an explicit operator decision rather than a default.
|
|
49
|
+
*/
|
|
50
|
+
type ApprovalMode = 'ask' | 'allow' | 'deny';
|
|
51
|
+
interface ApprovalPolicyOptions {
|
|
52
|
+
mode?: ApprovalMode;
|
|
53
|
+
/** Scopes granted up front from config. A trailing `*` matches by prefix. */
|
|
54
|
+
preApproved?: string[];
|
|
55
|
+
/** The human channel. Absent means there is nobody to ask. */
|
|
56
|
+
ask?: (req: ApprovalRequest) => Promise<boolean>;
|
|
57
|
+
/** Called whenever a decision is reached, for surfacing in a UI or a log. */
|
|
58
|
+
onDecision?: (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
|
|
59
|
+
}
|
|
60
|
+
type ApprovalSource = 'pre-approved' | 'remembered' | 'mode' | 'asked' | 'no-channel';
|
|
61
|
+
declare class ApprovalPolicy implements IApproval {
|
|
62
|
+
private readonly mode;
|
|
63
|
+
private readonly preApproved;
|
|
64
|
+
private readonly asker?;
|
|
65
|
+
private readonly onDecision?;
|
|
66
|
+
private readonly granted;
|
|
67
|
+
private readonly refused;
|
|
68
|
+
/** One in-flight ask per scope: a parallel tool round must not prompt twice for the same thing. */
|
|
69
|
+
private readonly inFlight;
|
|
70
|
+
private generation;
|
|
71
|
+
constructor(opts?: ApprovalPolicyOptions);
|
|
72
|
+
request(req: ApprovalRequest): Promise<boolean>;
|
|
73
|
+
/** Scopes the user has granted this session — for display and for persistence. */
|
|
74
|
+
grantedScopes(): string[];
|
|
75
|
+
/** Drop every session-scoped decision. Called on session reset. */
|
|
76
|
+
reset(): void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { type ApprovalKind as A, DENY_ALL as D, type IApproval as I, type ApprovalMode as a, ApprovalPolicy as b, type ApprovalPolicyOptions as c, type ApprovalRequest as d, type ApprovalSource as e };
|
|
@@ -1,35 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The planner's single approval seam. Every capability that reaches beyond the
|
|
5
|
-
* default read-only, in-workspace envelope — a path outside the workspace root,
|
|
6
|
-
* a shell command outside the auto-allowed set, a URL fetch — routes through
|
|
7
|
-
* one `request()` so the policy has exactly one owner (the same "one repair
|
|
8
|
-
* owner" shape as PlanRepair).
|
|
9
|
-
*
|
|
10
|
-
* Surfaces supply the human channel. VS Code answers with a modal; the web
|
|
11
|
-
* server currently has no prompt UI, so it denies unless the scope was
|
|
12
|
-
* pre-approved through config. Denial is always a visible, actionable tool
|
|
13
|
-
* result — never a silent success.
|
|
14
|
-
*/
|
|
15
|
-
type ApprovalKind = 'external_path' | 'shell_command' | 'url_fetch';
|
|
16
|
-
interface ApprovalRequest {
|
|
17
|
-
kind: ApprovalKind;
|
|
18
|
-
/** The concrete thing being asked about: an absolute path, a command line, a URL. */
|
|
19
|
-
subject: string;
|
|
20
|
-
/**
|
|
21
|
-
* What a grant covers. Approving remembers this, not `subject`, so reading a
|
|
22
|
-
* second file from an already-approved directory does not prompt again.
|
|
23
|
-
*/
|
|
24
|
-
scope: string;
|
|
25
|
-
/** One-line context for the prompt. */
|
|
26
|
-
detail?: string;
|
|
27
|
-
}
|
|
28
|
-
interface IApproval {
|
|
29
|
-
request(req: ApprovalRequest): Promise<boolean>;
|
|
30
|
-
}
|
|
31
|
-
/** Denies everything. The safe default when a surface wires no approval channel. */
|
|
32
|
-
declare const DENY_ALL: IApproval;
|
|
1
|
+
import { I as IApproval, a as ApprovalMode } from './ApprovalPolicy-BVhGdECT.mjs';
|
|
2
|
+
import { h as RunnerId } from './Task-cGrfYRXK.mjs';
|
|
33
3
|
|
|
34
4
|
interface ToolOutcome {
|
|
35
5
|
success: boolean;
|
|
@@ -104,53 +74,6 @@ interface IFileSystem {
|
|
|
104
74
|
setApproval?(approval: IApproval): void;
|
|
105
75
|
}
|
|
106
76
|
|
|
107
|
-
/**
|
|
108
|
-
* Decides whether one out-of-envelope capability may run, and remembers the
|
|
109
|
-
* answer for the rest of the session.
|
|
110
|
-
*
|
|
111
|
-
* Grants are keyed on {@link ApprovalRequest.scope}, never on the concrete
|
|
112
|
-
* subject: approving a read of `/tmp/foo/a.log` grants `/tmp/foo/*`, and
|
|
113
|
-
* approving `az group list` grants `az group`. Without that, a planner doing
|
|
114
|
-
* real research would prompt on every single call and the feature would be
|
|
115
|
-
* unusable.
|
|
116
|
-
*
|
|
117
|
-
* `mode` is the policy floor:
|
|
118
|
-
* ask consult the human channel; no channel means deny (headless, web)
|
|
119
|
-
* allow grant everything the tier system did not already refuse
|
|
120
|
-
* deny grant nothing beyond `preApproved`
|
|
121
|
-
*
|
|
122
|
-
* Note the ordering: `preApproved` is honored under every mode including
|
|
123
|
-
* `deny`, because it is an explicit operator decision rather than a default.
|
|
124
|
-
*/
|
|
125
|
-
type ApprovalMode = 'ask' | 'allow' | 'deny';
|
|
126
|
-
interface ApprovalPolicyOptions {
|
|
127
|
-
mode?: ApprovalMode;
|
|
128
|
-
/** Scopes granted up front from config. A trailing `*` matches by prefix. */
|
|
129
|
-
preApproved?: string[];
|
|
130
|
-
/** The human channel. Absent means there is nobody to ask. */
|
|
131
|
-
ask?: (req: ApprovalRequest) => Promise<boolean>;
|
|
132
|
-
/** Called whenever a decision is reached, for surfacing in a UI or a log. */
|
|
133
|
-
onDecision?: (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
|
|
134
|
-
}
|
|
135
|
-
type ApprovalSource = 'pre-approved' | 'remembered' | 'mode' | 'asked' | 'no-channel';
|
|
136
|
-
declare class ApprovalPolicy implements IApproval {
|
|
137
|
-
private readonly mode;
|
|
138
|
-
private readonly preApproved;
|
|
139
|
-
private readonly asker?;
|
|
140
|
-
private readonly onDecision?;
|
|
141
|
-
private readonly granted;
|
|
142
|
-
private readonly refused;
|
|
143
|
-
/** One in-flight ask per scope: a parallel tool round must not prompt twice for the same thing. */
|
|
144
|
-
private readonly inFlight;
|
|
145
|
-
private generation;
|
|
146
|
-
constructor(opts?: ApprovalPolicyOptions);
|
|
147
|
-
request(req: ApprovalRequest): Promise<boolean>;
|
|
148
|
-
/** Scopes the user has granted this session — for display and for persistence. */
|
|
149
|
-
grantedScopes(): string[];
|
|
150
|
-
/** Drop every session-scoped decision. Called on session reset. */
|
|
151
|
-
reset(): void;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
77
|
interface CatalogModel {
|
|
155
78
|
id: string;
|
|
156
79
|
name: string;
|
|
@@ -474,7 +397,7 @@ interface RunnerInvocation {
|
|
|
474
397
|
* testable without real I/O.
|
|
475
398
|
*/
|
|
476
399
|
interface IPluginStore {
|
|
477
|
-
/** Path to the user plugins directory (~/.
|
|
400
|
+
/** Path to the user plugins directory (~/.ordewell/plugins/). */
|
|
478
401
|
getUserPluginsDir(): string;
|
|
479
402
|
/** List subdirectory names inside the user plugins directory. */
|
|
480
403
|
listUserPluginDirs(): string[];
|
|
@@ -535,6 +458,12 @@ interface ITerminalSession {
|
|
|
535
458
|
kill(): void;
|
|
536
459
|
getOutput(): string;
|
|
537
460
|
write(text: string): void;
|
|
461
|
+
/**
|
|
462
|
+
* Optional transport-level control channel: PTY resize requests for a session
|
|
463
|
+
* whose runner renders a TUI. Absent on transports without a resizable PTY
|
|
464
|
+
* (a plain piped subprocess); surfaces must feature-detect before calling.
|
|
465
|
+
*/
|
|
466
|
+
writeControl?(text: string): void;
|
|
538
467
|
}
|
|
539
468
|
|
|
540
469
|
interface ITerminalRunner {
|
|
@@ -564,4 +493,4 @@ interface ITerminalRunner {
|
|
|
564
493
|
activeCount: number;
|
|
565
494
|
}
|
|
566
495
|
|
|
567
|
-
export { type AiProvider as A,
|
|
496
|
+
export { type AiProvider as A, isReservedRunnerName as B, type CatalogModel as C, type DiscoveryCommand as D, knownModelId as E, type FetchAllProviderModelsOptions as F, GREP_DEFAULT_HEAD_LIMIT as G, resolveModelShortcut as H, type IConfig as I, resolveProvider as J, toOrchestratorOptions as K, ModelCatalog as M, ORCHESTRATOR_SHORTCUTS as O, type PluginCloneFn as P, type ReadFileOpts as R, SEARCH_EXCLUSIONS as S, type ToolOutcome as T, type AllProviderModels as a, type FindSymbolOptions as b, type GlobOptions as c, type GrepOptions as d, type GrepOutputMode as e, type IFileSystem as f, type IPluginStore as g, type ITerminalRunner as h, type ITerminalSession as i, type ModelShortcut as j, type OrchestratorOption as k, type PluginEntry as l, type PluginFeatures as m, type PluginMode as n, type PluginModelDiscovery as o, type PluginRunnerDef as p, type ProviderCredentialSource as q, type ProviderModelLists as r, type ProviderModelsResult as s, type ResolveContext as t, type RunnerInvocation as u, type RunnerPluginManifest as v, RunnerRegistry as w, collectProviderCredentials as x, enabledRunners as y, fetchAllProviderModels as z };
|
|
@@ -1,35 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The planner's single approval seam. Every capability that reaches beyond the
|
|
5
|
-
* default read-only, in-workspace envelope — a path outside the workspace root,
|
|
6
|
-
* a shell command outside the auto-allowed set, a URL fetch — routes through
|
|
7
|
-
* one `request()` so the policy has exactly one owner (the same "one repair
|
|
8
|
-
* owner" shape as PlanRepair).
|
|
9
|
-
*
|
|
10
|
-
* Surfaces supply the human channel. VS Code answers with a modal; the web
|
|
11
|
-
* server currently has no prompt UI, so it denies unless the scope was
|
|
12
|
-
* pre-approved through config. Denial is always a visible, actionable tool
|
|
13
|
-
* result — never a silent success.
|
|
14
|
-
*/
|
|
15
|
-
type ApprovalKind = 'external_path' | 'shell_command' | 'url_fetch';
|
|
16
|
-
interface ApprovalRequest {
|
|
17
|
-
kind: ApprovalKind;
|
|
18
|
-
/** The concrete thing being asked about: an absolute path, a command line, a URL. */
|
|
19
|
-
subject: string;
|
|
20
|
-
/**
|
|
21
|
-
* What a grant covers. Approving remembers this, not `subject`, so reading a
|
|
22
|
-
* second file from an already-approved directory does not prompt again.
|
|
23
|
-
*/
|
|
24
|
-
scope: string;
|
|
25
|
-
/** One-line context for the prompt. */
|
|
26
|
-
detail?: string;
|
|
27
|
-
}
|
|
28
|
-
interface IApproval {
|
|
29
|
-
request(req: ApprovalRequest): Promise<boolean>;
|
|
30
|
-
}
|
|
31
|
-
/** Denies everything. The safe default when a surface wires no approval channel. */
|
|
32
|
-
declare const DENY_ALL: IApproval;
|
|
1
|
+
import { I as IApproval, a as ApprovalMode } from './ApprovalPolicy-BVhGdECT.js';
|
|
2
|
+
import { h as RunnerId } from './Task-cGrfYRXK.js';
|
|
33
3
|
|
|
34
4
|
interface ToolOutcome {
|
|
35
5
|
success: boolean;
|
|
@@ -104,53 +74,6 @@ interface IFileSystem {
|
|
|
104
74
|
setApproval?(approval: IApproval): void;
|
|
105
75
|
}
|
|
106
76
|
|
|
107
|
-
/**
|
|
108
|
-
* Decides whether one out-of-envelope capability may run, and remembers the
|
|
109
|
-
* answer for the rest of the session.
|
|
110
|
-
*
|
|
111
|
-
* Grants are keyed on {@link ApprovalRequest.scope}, never on the concrete
|
|
112
|
-
* subject: approving a read of `/tmp/foo/a.log` grants `/tmp/foo/*`, and
|
|
113
|
-
* approving `az group list` grants `az group`. Without that, a planner doing
|
|
114
|
-
* real research would prompt on every single call and the feature would be
|
|
115
|
-
* unusable.
|
|
116
|
-
*
|
|
117
|
-
* `mode` is the policy floor:
|
|
118
|
-
* ask consult the human channel; no channel means deny (headless, web)
|
|
119
|
-
* allow grant everything the tier system did not already refuse
|
|
120
|
-
* deny grant nothing beyond `preApproved`
|
|
121
|
-
*
|
|
122
|
-
* Note the ordering: `preApproved` is honored under every mode including
|
|
123
|
-
* `deny`, because it is an explicit operator decision rather than a default.
|
|
124
|
-
*/
|
|
125
|
-
type ApprovalMode = 'ask' | 'allow' | 'deny';
|
|
126
|
-
interface ApprovalPolicyOptions {
|
|
127
|
-
mode?: ApprovalMode;
|
|
128
|
-
/** Scopes granted up front from config. A trailing `*` matches by prefix. */
|
|
129
|
-
preApproved?: string[];
|
|
130
|
-
/** The human channel. Absent means there is nobody to ask. */
|
|
131
|
-
ask?: (req: ApprovalRequest) => Promise<boolean>;
|
|
132
|
-
/** Called whenever a decision is reached, for surfacing in a UI or a log. */
|
|
133
|
-
onDecision?: (req: ApprovalRequest, granted: boolean, source: ApprovalSource) => void;
|
|
134
|
-
}
|
|
135
|
-
type ApprovalSource = 'pre-approved' | 'remembered' | 'mode' | 'asked' | 'no-channel';
|
|
136
|
-
declare class ApprovalPolicy implements IApproval {
|
|
137
|
-
private readonly mode;
|
|
138
|
-
private readonly preApproved;
|
|
139
|
-
private readonly asker?;
|
|
140
|
-
private readonly onDecision?;
|
|
141
|
-
private readonly granted;
|
|
142
|
-
private readonly refused;
|
|
143
|
-
/** One in-flight ask per scope: a parallel tool round must not prompt twice for the same thing. */
|
|
144
|
-
private readonly inFlight;
|
|
145
|
-
private generation;
|
|
146
|
-
constructor(opts?: ApprovalPolicyOptions);
|
|
147
|
-
request(req: ApprovalRequest): Promise<boolean>;
|
|
148
|
-
/** Scopes the user has granted this session — for display and for persistence. */
|
|
149
|
-
grantedScopes(): string[];
|
|
150
|
-
/** Drop every session-scoped decision. Called on session reset. */
|
|
151
|
-
reset(): void;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
77
|
interface CatalogModel {
|
|
155
78
|
id: string;
|
|
156
79
|
name: string;
|
|
@@ -474,7 +397,7 @@ interface RunnerInvocation {
|
|
|
474
397
|
* testable without real I/O.
|
|
475
398
|
*/
|
|
476
399
|
interface IPluginStore {
|
|
477
|
-
/** Path to the user plugins directory (~/.
|
|
400
|
+
/** Path to the user plugins directory (~/.ordewell/plugins/). */
|
|
478
401
|
getUserPluginsDir(): string;
|
|
479
402
|
/** List subdirectory names inside the user plugins directory. */
|
|
480
403
|
listUserPluginDirs(): string[];
|
|
@@ -535,6 +458,12 @@ interface ITerminalSession {
|
|
|
535
458
|
kill(): void;
|
|
536
459
|
getOutput(): string;
|
|
537
460
|
write(text: string): void;
|
|
461
|
+
/**
|
|
462
|
+
* Optional transport-level control channel: PTY resize requests for a session
|
|
463
|
+
* whose runner renders a TUI. Absent on transports without a resizable PTY
|
|
464
|
+
* (a plain piped subprocess); surfaces must feature-detect before calling.
|
|
465
|
+
*/
|
|
466
|
+
writeControl?(text: string): void;
|
|
538
467
|
}
|
|
539
468
|
|
|
540
469
|
interface ITerminalRunner {
|
|
@@ -564,4 +493,4 @@ interface ITerminalRunner {
|
|
|
564
493
|
activeCount: number;
|
|
565
494
|
}
|
|
566
495
|
|
|
567
|
-
export { type AiProvider as A,
|
|
496
|
+
export { type AiProvider as A, isReservedRunnerName as B, type CatalogModel as C, type DiscoveryCommand as D, knownModelId as E, type FetchAllProviderModelsOptions as F, GREP_DEFAULT_HEAD_LIMIT as G, resolveModelShortcut as H, type IConfig as I, resolveProvider as J, toOrchestratorOptions as K, ModelCatalog as M, ORCHESTRATOR_SHORTCUTS as O, type PluginCloneFn as P, type ReadFileOpts as R, SEARCH_EXCLUSIONS as S, type ToolOutcome as T, type AllProviderModels as a, type FindSymbolOptions as b, type GlobOptions as c, type GrepOptions as d, type GrepOutputMode as e, type IFileSystem as f, type IPluginStore as g, type ITerminalRunner as h, type ITerminalSession as i, type ModelShortcut as j, type OrchestratorOption as k, type PluginEntry as l, type PluginFeatures as m, type PluginMode as n, type PluginModelDiscovery as o, type PluginRunnerDef as p, type ProviderCredentialSource as q, type ProviderModelLists as r, type ProviderModelsResult as s, type ResolveContext as t, type RunnerInvocation as u, type RunnerPluginManifest as v, RunnerRegistry as w, collectProviderCredentials as x, enabledRunners as y, fetchAllProviderModels as z };
|
|
@@ -235,9 +235,16 @@ type PlanState = {
|
|
|
235
235
|
};
|
|
236
236
|
declare function migratePlanState(raw: unknown): PlanState;
|
|
237
237
|
declare function migrateLegacyPlan(legacy: LegacyPlanState): PlanState;
|
|
238
|
+
|
|
238
239
|
declare function createTask(overrides?: Partial<Task>): Task;
|
|
239
240
|
declare function createEmptyPlan(): LegacyPlanState;
|
|
240
241
|
declare function flattenTasks(tasks: Task[]): Task[];
|
|
242
|
+
/** A flattened task with the parent it hangs under, null for a top-level task. */
|
|
243
|
+
interface TaskWithParent {
|
|
244
|
+
task: Task;
|
|
245
|
+
parent: Task | null;
|
|
246
|
+
}
|
|
247
|
+
declare function flattenTasksWithParents(tasks: Task[]): TaskWithParent[];
|
|
241
248
|
declare function migrateTask(task: Record<string, unknown>): Task;
|
|
242
249
|
declare function addTaskToPlan(tasks: Task[], partial: Partial<Task>): Task[];
|
|
243
250
|
declare function removeTaskFromPlan(tasks: Task[], taskId: string): Task[];
|
|
@@ -261,4 +268,4 @@ interface ValidationContext {
|
|
|
261
268
|
type ValidationCheck = (ctx: ValidationContext) => ValidationResult;
|
|
262
269
|
declare function warningsText(w: PlanModificationWarnings): string | null;
|
|
263
270
|
|
|
264
|
-
export { type ActiveTaskSession as A,
|
|
271
|
+
export { type ActiveTaskSession as A, emptyWarnings as B, type ConversationMessage as C, type DiscoveredMode as D, flattenTasks as E, flattenTasksWithParents as F, migrateLegacyPlan as G, migratePlanState as H, migrateTask as I, removeTaskFromPlan as J, renumberTasks as K, type LegacyPlanState as L, type Message as M, updateTaskInPlan as N, validateModifiedPlan as O, type PlanModificationWarnings as P, type QueuedMessage as Q, type ResearchLogEntry as R, type StreamEvent as S, type Task as T, type UserPromptEntry as U, type ValidationCheck as V, warningsText as W, type DiscoveredModel as a, type PlanState as b, type PlanStatus as c, type ResearchProgress as d, type ResearchStep as e, type ResearchStepOutcome as f, type ResearchToolType as g, type RunnerId as h, type StreamStepEvent as i, type StreamThinkingEvent as j, type TaskMode as k, type TaskModelAssignment as l, type TaskOutputSummary as m, type TaskSnapshot as n, type TaskStatus as o, type TaskType as p, type TaskWithParent as q, type ThinkingBlock as r, type UserStep as s, type ValidationContext as t, type ValidationResult as u, type Verdict as v, type VerificationCheck as w, addTaskToPlan as x, createEmptyPlan as y, createTask as z };
|
|
@@ -235,9 +235,16 @@ type PlanState = {
|
|
|
235
235
|
};
|
|
236
236
|
declare function migratePlanState(raw: unknown): PlanState;
|
|
237
237
|
declare function migrateLegacyPlan(legacy: LegacyPlanState): PlanState;
|
|
238
|
+
|
|
238
239
|
declare function createTask(overrides?: Partial<Task>): Task;
|
|
239
240
|
declare function createEmptyPlan(): LegacyPlanState;
|
|
240
241
|
declare function flattenTasks(tasks: Task[]): Task[];
|
|
242
|
+
/** A flattened task with the parent it hangs under, null for a top-level task. */
|
|
243
|
+
interface TaskWithParent {
|
|
244
|
+
task: Task;
|
|
245
|
+
parent: Task | null;
|
|
246
|
+
}
|
|
247
|
+
declare function flattenTasksWithParents(tasks: Task[]): TaskWithParent[];
|
|
241
248
|
declare function migrateTask(task: Record<string, unknown>): Task;
|
|
242
249
|
declare function addTaskToPlan(tasks: Task[], partial: Partial<Task>): Task[];
|
|
243
250
|
declare function removeTaskFromPlan(tasks: Task[], taskId: string): Task[];
|
|
@@ -261,4 +268,4 @@ interface ValidationContext {
|
|
|
261
268
|
type ValidationCheck = (ctx: ValidationContext) => ValidationResult;
|
|
262
269
|
declare function warningsText(w: PlanModificationWarnings): string | null;
|
|
263
270
|
|
|
264
|
-
export { type ActiveTaskSession as A,
|
|
271
|
+
export { type ActiveTaskSession as A, emptyWarnings as B, type ConversationMessage as C, type DiscoveredMode as D, flattenTasks as E, flattenTasksWithParents as F, migrateLegacyPlan as G, migratePlanState as H, migrateTask as I, removeTaskFromPlan as J, renumberTasks as K, type LegacyPlanState as L, type Message as M, updateTaskInPlan as N, validateModifiedPlan as O, type PlanModificationWarnings as P, type QueuedMessage as Q, type ResearchLogEntry as R, type StreamEvent as S, type Task as T, type UserPromptEntry as U, type ValidationCheck as V, warningsText as W, type DiscoveredModel as a, type PlanState as b, type PlanStatus as c, type ResearchProgress as d, type ResearchStep as e, type ResearchStepOutcome as f, type ResearchToolType as g, type RunnerId as h, type StreamStepEvent as i, type StreamThinkingEvent as j, type TaskMode as k, type TaskModelAssignment as l, type TaskOutputSummary as m, type TaskSnapshot as n, type TaskStatus as o, type TaskType as p, type TaskWithParent as q, type ThinkingBlock as r, type UserStep as s, type ValidationContext as t, type ValidationResult as u, type Verdict as v, type VerificationCheck as w, addTaskToPlan as x, createEmptyPlan as y, createTask as z };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/order-labels.ts
|
|
2
|
+
function taskOrderLabel(task, parent) {
|
|
3
|
+
return parent ? `${parent.order}.${task.order}` : String(task.order);
|
|
4
|
+
}
|
|
5
|
+
function resolveOrderLabel(tasks, label) {
|
|
6
|
+
const parts = label.split(".");
|
|
7
|
+
if (parts.length > 2 || parts.some((p) => !/^\d+$/.test(p))) return void 0;
|
|
8
|
+
const [topOrder, childOrder] = parts.map(Number);
|
|
9
|
+
const top = tasks.find((t) => t.order === topOrder);
|
|
10
|
+
if (!top) return void 0;
|
|
11
|
+
if (childOrder === void 0) return top;
|
|
12
|
+
return top.subtasks.find((s) => s.order === childOrder);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
taskOrderLabel,
|
|
17
|
+
resolveOrderLabel
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=chunk-HPNUFBIT.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/order-labels.ts"],"sourcesContent":["import type { Task } from './models/Task';\n\n/**\n * Parent-scoped dotted order label for a task, e.g. \"2.1\" for the first subtask\n * of task 2. Kept in its own module (no Node imports) so a browser-bundled\n * surface — the VS Code webview — can import it via `@ordewell/core/order-labels`\n * without dragging the rest of core in.\n */\nexport function taskOrderLabel(task: { order: number }, parent?: { order: number }): string {\n return parent ? `${parent.order}.${task.order}` : String(task.order);\n}\n\n/** Resolve a dotted label to a task in a plan's top-level task list. */\nexport function resolveOrderLabel(tasks: Task[], label: string): Task | undefined {\n const parts = label.split('.');\n if (parts.length > 2 || parts.some((p) => !/^\\d+$/.test(p))) return undefined;\n const [topOrder, childOrder] = parts.map(Number);\n const top = tasks.find((t) => t.order === topOrder);\n if (!top) return undefined;\n if (childOrder === undefined) return top;\n return top.subtasks.find((s) => s.order === childOrder);\n}"],"mappings":";AAQO,SAAS,eAAe,MAAyB,QAAoC;AAC1F,SAAO,SAAS,GAAG,OAAO,KAAK,IAAI,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK;AACrE;AAGO,SAAS,kBAAkB,OAAe,OAAiC;AAChF,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,MAAI,MAAM,SAAS,KAAK,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,EAAG,QAAO;AACpE,QAAM,CAAC,UAAU,UAAU,IAAI,MAAM,IAAI,MAAM;AAC/C,QAAM,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,QAAQ;AAClD,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,eAAe,OAAW,QAAO;AACrC,SAAO,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,UAAU;AACxD;","names":[]}
|
|
@@ -184,6 +184,15 @@ function createEmptyPlan() {
|
|
|
184
184
|
function flattenTasks(tasks) {
|
|
185
185
|
return tasks.flatMap((t) => [t, ...flattenTasks(t.subtasks ?? [])]);
|
|
186
186
|
}
|
|
187
|
+
function flattenTasksWithParents(tasks) {
|
|
188
|
+
const rows = [];
|
|
189
|
+
const walk = (t, parent) => {
|
|
190
|
+
rows.push({ task: t, parent });
|
|
191
|
+
for (const sub of t.subtasks ?? []) walk(sub, t);
|
|
192
|
+
};
|
|
193
|
+
for (const t of tasks) walk(t, null);
|
|
194
|
+
return rows;
|
|
195
|
+
}
|
|
187
196
|
function migrateTask(task) {
|
|
188
197
|
if (!task.assignedModel) {
|
|
189
198
|
task.assignedModel = void 0;
|
|
@@ -444,6 +453,7 @@ export {
|
|
|
444
453
|
createTask,
|
|
445
454
|
createEmptyPlan,
|
|
446
455
|
flattenTasks,
|
|
456
|
+
flattenTasksWithParents,
|
|
447
457
|
migrateTask,
|
|
448
458
|
addTaskToPlan,
|
|
449
459
|
removeTaskFromPlan,
|
|
@@ -462,4 +472,4 @@ export {
|
|
|
462
472
|
stripTrailingCommas,
|
|
463
473
|
escapeControlCharsInStrings
|
|
464
474
|
};
|
|
465
|
-
//# sourceMappingURL=chunk-
|
|
475
|
+
//# sourceMappingURL=chunk-N6HTBUKG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/models/Task.ts","../src/services/JsonExtractor.ts"],"sourcesContent":["import { v4 as uuidv4 } from 'uuid';\n\nexport interface UserStep {\n order: number;\n instruction: string;\n completed: boolean;\n}\n\n/** One deterministic signal gathered while verifying a completed task. */\nexport interface VerificationCheck {\n name: 'exit_code' | 'completion_marker' | 'manual';\n passed: boolean;\n /** A check that did not apply. Skipped checks don't affect the verdict. */\n skipped: boolean;\n detail: string;\n}\n\n/** Evidence-based verdict for a completed task. Single end-to-end outcome produced by verification. */\nexport interface Verdict {\n outcome: 'pass' | 'fail';\n reason: string;\n checks: VerificationCheck[];\n decidedAt: string;\n}\n\nexport interface TaskOutputSummary {\n reviewReason: string;\n logTail: string;\n capturedAt: string;\n}\n\nexport type TaskType = 'ai' | 'user';\nexport type TaskStatus = 'pending' | 'approved' | 'in_progress' | 'completed' | 'failed' | 'blocked' | 'awaiting_user';\nexport type TaskMode = string;\n\nexport interface TaskModelAssignment {\n modelId: string;\n modelLabel: string;\n thinkingEffort?: string;\n /**\n * All variant ids the model offered when this assignment was made. Carried\n * on the assignment because runners need it at spawn time (opencode's TUI\n * only honors an assigned variant when the others are config-disabled) and\n * the discovery catalog isn't available there.\n */\n availableVariants?: string[];\n}\n\nexport type RunnerId = string;\n\nexport interface Task {\n id: string;\n order: number;\n title: string;\n description: string;\n type: TaskType;\n status: TaskStatus;\n dependencies: string[];\n prompt?: string;\n userSteps?: UserStep[];\n subtasks: Task[];\n verdict?: Verdict;\n outputSummary?: TaskOutputSummary;\n assignedModel?: TaskModelAssignment;\n assignedRunner: RunnerId;\n thinkingEffort?: string;\n taskMode?: TaskMode;\n completionMarker: string;\n autonomy?: 'AFK' | 'HITL';\n sliceType?: 'HITL' | 'AFK';\n userStoriesCovered?: string[];\n}\n\nexport interface DiscoveredMode {\n id: string;\n label: string;\n description: string;\n}\n\nexport type ResearchToolType =\n | 'read_file' | 'read_files' | 'glob' | 'grep' | 'find_symbol' | 'list_dir'\n | 'bash' | 'fetch' | 'web_search' | 'spawn_research_agent'\n /**\n * A tool belonging to a harness planner's own toolbox (ADR-0009) that has no\n * Ordewell equivalent — Edit, WebFetch, TodoWrite, whatever a coding agent\n * ships next. The real name travels in `toolLabel` rather than being\n * relabelled as a tool it is not; the union stays closed so the\n * exhaustiveness checks in every surface's icon/label switch survive.\n */\n | 'agent_tool';\n\n/**\n * What happened when a research tool call ran, for honest per-surface\n * rendering. The broadcast seam carries this on every `research_step_done` so\n * surfaces do not have to pattern-match refusal text to tell a refused `rm`\n * from a successful `rm` — the old render path flipped a `✓` for both.\n */\nexport type ResearchStepOutcome = 'success' | 'failure' | 'refused' | 'denied' | 'not_executed';\n\nexport interface ResearchStep {\n id: string;\n tool: ResearchToolType;\n /** The tool's own name when it came from a harness planner — always set for `agent_tool`. */\n toolLabel?: string;\n args: string;\n result: string;\n success: boolean;\n outcome: ResearchStepOutcome;\n /** The model's tool_call id, so a surface can match `tool_result` to the\n * pending `tool_call` it announced — robust under parallel same-tool rounds. */\n toolCallId?: string;\n timestamp: string;\n thinkingText?: string;\n}\n\nexport interface UserPromptEntry {\n id: string;\n type: 'user_prompt' | 'system';\n content: string;\n timestamp: string;\n}\n\nexport type ResearchLogEntry = ResearchStep | UserPromptEntry;\n\nexport interface ResearchProgress {\n type: 'thinking' | 'tool_call' | 'tool_result' | 'plan_token' | 'interrupted';\n text?: string;\n tool?: string;\n /** Harness planners (ADR-0009): the agent's own name for a tool Ordewell has no member for. */\n toolLabel?: string;\n toolArgs?: string;\n toolResult?: string;\n planToken?: string;\n step?: ResearchStep;\n /** The model's tool_call id, threaded on tool_call and tool_result so a\n * surface can match the result to its pending call — robust under parallel\n * same-tool rounds where LIFO-by-name matching mislabels summaries. */\n toolCallId?: string;\n /** Present when this event originates from (or reports on) one spawned research subagent (issue #34). */\n subagentId?: string;\n}\n\nexport interface ThinkingBlock {\n id: string;\n text: string;\n}\n\nexport interface StreamThinkingEvent {\n type: 'thinking';\n block: ThinkingBlock;\n}\n\nexport interface StreamStepEvent {\n type: 'step';\n step: ResearchStep;\n}\n\nexport type StreamEvent = StreamThinkingEvent | StreamStepEvent;\n\nexport interface DiscoveredModel {\n modelId: string;\n modelLabel: string;\n runnerProvider?: string;\n /**\n * Human-facing provider name as the runner itself reports it (e.g.\n * \"OpenCode Zen\" for `runnerProvider: 'opencode'`). Populated from the\n * runner's own provider catalog when available; when absent the UI derives a\n * label from `runnerProvider` by title-casing.\n */\n runnerProviderLabel?: string;\n /**\n * The runner whose catalog listed this model. Stamped once, at the single\n * `ModelDiscovery.discover` choke point, so a flat cross-runner list can\n * still say where each entry came from — `runnerProvider` alone cannot:\n * OpenCode reports most of its catalog as `openrouter`, which names the\n * serving backend, not the agent Ordewell would spawn.\n */\n runnerId?: string;\n /** The runner's display name (`OpenCode`), from its manifest. */\n runnerLabel?: string;\n variants: { id: string; label: string }[];\n}\n\nexport type PlanStatus = 'draft' | 'approved' | 'rejected' | 'running' | 'completed';\n\n/**\n * One entry of the planner's persisted dialogue (ADR-0002). The single source\n * of truth for both UI redisplay and conversational context. Tool-call results\n * are NOT stored here — they live in the AI service's tool-use history;\n * `researchLog` remains the persisted tool trace for the UI.\n */\nexport interface ConversationMessage {\n role: 'user' | 'assistant';\n content: string;\n timestamp: string;\n /**\n * Timeline marker: 'plan_generated' records the point in the dialogue where\n * the plan was committed (the UI anchors the plan card there on restore);\n * 'system' is a host-injected notice. Absent for ordinary chat turns, so\n * sessions saved before markers existed degrade gracefully.\n */\n kind?: 'plan_generated' | 'system';\n}\n\nexport interface QueuedMessage {\n id: string;\n text: string;\n timestamp: string;\n}\n\nexport interface PlanModificationWarnings {\n deletedCompleted: string[];\n changedCompleted: string[];\n deletedInProgress: string[];\n modifiedInProgress: string[];\n brokenDependencies: string[];\n}\n\nexport function emptyWarnings(): PlanModificationWarnings {\n return { deletedCompleted: [], changedCompleted: [], deletedInProgress: [], modifiedInProgress: [], brokenDependencies: [] };\n}\n\nexport interface LegacyPlanState {\n tasks: Task[];\n generatedAt: string;\n status: PlanStatus;\n runners: RunnerId[];\n lastUpdated: string;\n researchLog?: ResearchLogEntry[];\n /** The planner dialogue — user messages and assistant messages, in order (ADR-0002). */\n conversationHistory?: ConversationMessage[];\n /** Full markdown PRD once written by the planner (PRD mode), also saved to .scratch/<slug>/PRD.md. */\n prdMarkdown?: string;\n /** Follow-ups queued while tasks execute — applied as plan modifications between batches. */\n queuedMessages?: QueuedMessage[];\n}\n\nexport interface Message {\n id: string;\n role: 'user' | 'planner' | 'system';\n content: string;\n timestamp: number;\n}\n\nexport interface TaskSnapshot extends Task {\n completedAt: number;\n verdict?: Verdict;\n retryCount: number;\n finalized: boolean;\n}\n\nexport type PlanState =\n | {\n phase: 'planning';\n history: Message[];\n message: string;\n pendingTasks: Task[];\n }\n | {\n phase: 'executing';\n history: Message[];\n message: string;\n executionLog: TaskSnapshot[];\n pendingTasks: Task[];\n goal: string;\n runners: string[];\n status: PlanStatus;\n };\n\nfunction hasPhase(raw: unknown): raw is PlanState {\n return typeof raw === 'object' && raw !== null && 'phase' in raw;\n}\n\nfunction hasTasks(raw: unknown): raw is LegacyPlanState {\n return typeof raw === 'object' && raw !== null && 'tasks' in raw && Array.isArray((raw as Record<string, unknown>).tasks);\n}\n\nfunction migrateHistory(raw: LegacyPlanState): Message[] {\n const messages: Message[] = [];\n\n if (raw.researchLog) {\n for (const entry of raw.researchLog) {\n if ('type' in entry && entry.type === 'user_prompt') {\n messages.push({\n id: entry.id,\n role: 'user',\n content: (entry as UserPromptEntry).content,\n timestamp: new Date(entry.timestamp).getTime(),\n });\n } else {\n const step = entry as ResearchStep;\n messages.push({\n id: step.id,\n role: 'system',\n content: JSON.stringify({ tool: step.tool, args: step.args, result: step.result }),\n timestamp: new Date(step.timestamp).getTime(),\n });\n }\n }\n }\n\n if (raw.queuedMessages) {\n for (const qm of raw.queuedMessages) {\n messages.push({\n id: qm.id,\n role: 'system',\n content: qm.text,\n timestamp: new Date(qm.timestamp).getTime(),\n });\n }\n }\n\n return messages;\n}\n\nexport function migratePlanState(raw: unknown): PlanState {\n if (hasPhase(raw)) return raw;\n\n if (!hasTasks(raw)) {\n return {\n phase: 'planning',\n history: [],\n message: '',\n pendingTasks: [],\n };\n }\n\n const hasExecution = raw.tasks.some(\n (t) => t.status === 'completed' || t.status === 'failed',\n );\n\n const messages = migrateHistory(raw);\n\n if (hasExecution) {\n const executionLog: TaskSnapshot[] = raw.tasks\n .filter((t) => t.status === 'completed' || t.status === 'failed')\n .map((t) => ({\n ...t,\n completedAt: new Date(raw.lastUpdated).getTime(),\n verdict: t.verdict,\n retryCount: 0,\n finalized: true,\n }));\n\n const pendingTasks = raw.tasks.filter(\n (t) => t.status !== 'completed' && t.status !== 'failed' && t.status !== 'blocked',\n );\n\n return {\n phase: 'executing',\n history: messages,\n message: '',\n executionLog,\n pendingTasks,\n goal: '',\n runners: raw.runners,\n status: raw.status,\n };\n }\n\n return {\n phase: 'planning',\n history: messages,\n message: '',\n pendingTasks: raw.tasks,\n };\n}\n\nexport function migrateLegacyPlan(legacy: LegacyPlanState): PlanState {\n const messages: Message[] = [];\n\n if (legacy.researchLog) {\n for (const entry of legacy.researchLog) {\n if ('type' in entry && entry.type === 'user_prompt') {\n messages.push({\n id: entry.id,\n role: 'user',\n content: (entry as UserPromptEntry).content,\n timestamp: new Date(entry.timestamp).getTime(),\n });\n } else {\n const step = entry as ResearchStep;\n messages.push({\n id: step.id,\n role: 'system',\n content: JSON.stringify({ tool: step.tool, args: step.args, result: step.result }),\n timestamp: new Date(step.timestamp).getTime(),\n });\n }\n }\n }\n\n if (legacy.queuedMessages) {\n for (const qm of legacy.queuedMessages) {\n messages.push({\n id: qm.id,\n role: 'system',\n content: qm.text,\n timestamp: new Date(qm.timestamp).getTime(),\n });\n }\n }\n\n const isPlanning = legacy.status === 'draft' || legacy.status === 'approved' || legacy.status === 'rejected';\n\n if (isPlanning) {\n return {\n phase: 'planning',\n history: messages,\n message: 'Plan generation',\n pendingTasks: legacy.tasks.filter((t) => t.status === 'pending' || t.status === ('draft' as never)),\n };\n }\n\n const nonCompletedTasks = legacy.tasks.filter(\n (t) => t.status !== 'completed' && t.status !== 'failed' && t.status !== 'blocked'\n );\n\n const completedSnapshot: TaskSnapshot[] = legacy.tasks\n .filter((t) => t.status === 'completed' || t.status === 'failed')\n .map((t) => ({\n ...t,\n completedAt: new Date(legacy.lastUpdated).getTime(),\n verdict: t.verdict,\n retryCount: 0,\n finalized: true,\n }));\n\n return {\n phase: 'executing',\n history: messages,\n message: 'Plan migration',\n executionLog: completedSnapshot,\n pendingTasks: nonCompletedTasks,\n goal: 'Plan migration',\n runners: legacy.runners,\n status: legacy.status,\n };\n}\n\nexport { taskOrderLabel, resolveOrderLabel } from '../order-labels';\n\nexport function createTask(overrides: Partial<Task> = {}): Task {\n return {\n id: overrides.id ?? uuidv4(),\n order: overrides.order ?? 0,\n title: overrides.title ?? '',\n description: overrides.description ?? '',\n type: overrides.type ?? 'ai',\n status: overrides.status ?? 'pending',\n dependencies: overrides.dependencies ?? [],\n prompt: overrides.prompt,\n userSteps: overrides.userSteps,\n subtasks: overrides.subtasks ?? [],\n verdict: overrides.verdict,\n outputSummary: overrides.outputSummary,\n assignedModel: overrides.assignedModel,\n assignedRunner: overrides.assignedRunner ?? 'claude-code',\n thinkingEffort: overrides.thinkingEffort,\n taskMode: overrides.taskMode ?? 'build',\n completionMarker: overrides.completionMarker ?? uuidv4(),\n autonomy: overrides.autonomy,\n sliceType: overrides.sliceType,\n userStoriesCovered: overrides.userStoriesCovered,\n };\n}\n\nexport function createEmptyPlan(): LegacyPlanState {\n return {\n tasks: [],\n generatedAt: new Date().toISOString(),\n status: 'draft',\n runners: ['claude-code'],\n lastUpdated: new Date().toISOString(),\n };\n}\n\nexport function flattenTasks(tasks: Task[]): Task[] {\n return tasks.flatMap((t) => [t, ...flattenTasks(t.subtasks ?? [])]);\n}\n\n/** A flattened task with the parent it hangs under, null for a top-level task. */\nexport interface TaskWithParent {\n task: Task;\n parent: Task | null;\n}\n\nexport function flattenTasksWithParents(tasks: Task[]): TaskWithParent[] {\n const rows: TaskWithParent[] = [];\n const walk = (t: Task, parent: Task | null) => {\n rows.push({ task: t, parent });\n for (const sub of t.subtasks ?? []) walk(sub, t);\n };\n for (const t of tasks) walk(t, null);\n return rows;\n}\n\nexport function migrateTask(task: Record<string, unknown>): Task {\n if (!task.assignedModel) {\n task.assignedModel = undefined;\n }\n if (!task.assignedRunner) {\n task.assignedRunner = 'claude-code';\n }\n if (!task.thinkingEffort) {\n task.thinkingEffort = undefined;\n }\n if (!task.completionMarker) {\n task.completionMarker = uuidv4();\n }\n if (task.verdict && task.verification) {\n delete task.verification;\n }\n if (!task.autonomy) {\n task.autonomy = undefined;\n }\n if (!task.sliceType) {\n task.sliceType = undefined;\n }\n if (!task.userStoriesCovered) {\n task.userStoriesCovered = undefined;\n }\n return task as unknown as Task;\n}\n\nexport function addTaskToPlan(tasks: Task[], partial: Partial<Task>): Task[] {\n const maxOrder = tasks.reduce((max, t) => Math.max(max, t.order), 0);\n const newTask = createTask({\n ...partial,\n order: partial.order ?? maxOrder + 1,\n status: 'pending',\n });\n return renumberTasks([...tasks, newTask]);\n}\n\nexport function removeTaskFromPlan(tasks: Task[], taskId: string): Task[] {\n const result = tasks\n .filter((t) => t.id !== taskId)\n .map((t) => ({\n ...t,\n dependencies: t.dependencies.filter((depId) => depId !== taskId),\n subtasks: removeTaskFromPlan(t.subtasks, taskId),\n }));\n return renumberTasks(result);\n}\n\nexport function updateTaskInPlan(tasks: Task[], taskId: string, changes: Partial<Task>): Task[] {\n return renumberTasks(\n tasks.map((t) => {\n if (t.id === taskId) return { ...t, ...changes, id: t.id };\n return { ...t, subtasks: updateTaskInPlan(t.subtasks, taskId, changes) };\n })\n );\n}\n\nexport function renumberTasks(tasks: Task[]): Task[] {\n return tasks.map((t, i) => ({\n ...t,\n order: i + 1,\n subtasks: renumberTasks(t.subtasks),\n }));\n}\n\nexport function validateModifiedPlan(original: Task[], modified: Task[]): PlanModificationWarnings {\n const allOriginal = flattenTasks(original);\n const allModified = flattenTasks(modified);\n const warnings = emptyWarnings();\n const originalMap = new Map(allOriginal.map((t) => [t.id, t]));\n const modifiedIds = new Set(allModified.map((t) => t.id));\n\n for (const ot of originalMap.values()) {\n if (ot.status === 'completed' && !modifiedIds.has(ot.id)) {\n warnings.deletedCompleted.push(ot.title);\n } else if (ot.status === 'in_progress' && !modifiedIds.has(ot.id)) {\n warnings.deletedInProgress.push(ot.title);\n }\n }\n\n for (const mt of allModified) {\n const orig = originalMap.get(mt.id);\n if (orig) {\n if (orig.status === 'completed' && mt.status !== 'completed') {\n warnings.changedCompleted.push(orig.title);\n }\n if (orig.status === 'in_progress' && (mt.status !== 'in_progress' || mt.prompt !== orig.prompt)) {\n warnings.modifiedInProgress.push(orig.title);\n }\n if (orig.status === 'failed' && mt.status === 'pending') {\n for (const dt of allModified) {\n if (dt.dependencies.includes(mt.id) && dt.status === 'blocked') {\n dt.status = 'pending';\n }\n }\n }\n }\n }\n\n for (const t of allModified) {\n for (const depId of t.dependencies) {\n if (!modifiedIds.has(depId)) {\n warnings.brokenDependencies.push(`${t.title} → ${depId}`);\n }\n }\n }\n\n return warnings;\n}\n\nexport interface ActiveTaskSession {\n id: string;\n taskId: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport interface ValidationContext {\n executionLog: TaskSnapshot[];\n oldPending: Task[];\n newPending: Task[];\n activeSessions: Map<string, ActiveTaskSession>;\n}\n\nexport type ValidationCheck = (ctx: ValidationContext) => ValidationResult;\n\nexport function warningsText(w: PlanModificationWarnings): string | null {\n const lines: string[] = [];\n if (w.deletedCompleted.length) lines.push(`Completed tasks deleted: ${w.deletedCompleted.join(', ')}`);\n if (w.changedCompleted.length) lines.push(`Completed tasks modified: ${w.changedCompleted.join(', ')}`);\n if (w.deletedInProgress.length) lines.push(`In-progress tasks deleted: ${w.deletedInProgress.join(', ')}`);\n if (w.modifiedInProgress.length) lines.push(`In-progress tasks modified: ${w.modifiedInProgress.join(', ')}`);\n if (w.brokenDependencies.length) lines.push(`Broken dependencies: ${w.brokenDependencies.join(', ')}`);\n return lines.length > 0 ? lines.join('\\n') : null;\n}\n","/** The envelope key a full plan reply is keyed by: `{\"tasks\":[...]}`. */\nexport const PLAN_ENVELOPE_KEY = 'tasks';\n/** The envelope key a targeted-edits reply is keyed by: `{\"taskOps\":[...]}`. */\nexport const TASK_OPS_ENVELOPE_KEY = 'taskOps';\n/** The envelope key a read-only detail request is keyed by: `{\"taskQuery\":{...}}`. */\nexport const TASK_QUERY_ENVELOPE_KEY = 'taskQuery';\n\n/** Thrown when an LLM plan response cannot be parsed into a valid plan. Carries the raw text so callers can log it or retry. */\nexport class PlanParseError extends Error {\n readonly raw: string;\n /**\n * True when the reply was cut off mid-object (output-token limit) rather\n * than malformed — the two need different repairs: a truncated emission will\n * be cut at the same point again unless the retry frees context or asks for\n * terser output.\n */\n readonly truncated: boolean;\n /**\n * True when the JSON parsed fine and a *shape* rule rejected it. The generic\n * \"could not be parsed as JSON\" corrective is a lie for these, so the model\n * re-sends the same object; a semantic rejection must be repaired by naming\n * the rule it broke.\n */\n readonly semantic: boolean;\n constructor(message: string, raw: string, opts?: { truncated?: boolean; semantic?: boolean }) {\n super(message);\n this.name = 'PlanParseError';\n this.raw = raw;\n this.truncated = opts?.truncated ?? false;\n this.semantic = opts?.semantic ?? false;\n }\n}\n/**\n * Strip the noise reasoning models wrap around their answer: markdown code\n * fences and `<think>…</think>` chain-of-thought blocks (which routinely contain\n * stray braces that would otherwise derail brace-balancing). Reasoning captured\n * out-of-band by the service never reaches here, but a model that inlines its\n * thinking in the content channel still must not corrupt parsing.\n */\nexport function stripModelNoise(raw: string): string {\n return raw\n .replace(/<think>[\\s\\S]*?<\\/think>/gi, '')\n .replace(/```json\\s*/gi, '')\n .replace(/```\\s*/g, '')\n .trim();\n}\n\n/**\n * Scan from `start` (which must point at a `{`) for the matching balanced close,\n * ignoring braces inside strings. Returns the object substring and whether it was\n * balanced; an unbalanced result means the input was truncated mid-object.\n */\nfunction balancedObjectAt(text: string, start: number): { json: string; balanced: boolean } {\n let depth = 0;\n let inString = false;\n let escaped = false;\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') inString = true;\n else if (ch === '{') depth++;\n else if (ch === '}') {\n depth--;\n if (depth === 0) return { json: text.slice(start, i + 1), balanced: true };\n }\n }\n return { json: text.slice(start), balanced: false };\n}\n\n/**\n * Scan an LLM response for every balanced `{…}` object carrying a `\"<key>\":`\n * entry. Strips fences and `<think>` blocks first. A matching object is\n * skipped over wholesale, so its nested braces don't produce fragment\n * candidates; non-matching objects are descended into, so a match wrapped in\n * an unrelated outer object is still found. `fallback` preserves the legacy\n * behavior for callers with no keyed match: the first balanced object, else\n * the stripped text so a JSON.parse error still surfaces.\n */\nexport function extractObjectsWithKey(raw: string, key: string): {\n matches: string[];\n fallback: { json: string; balanced: boolean };\n sawBrace: boolean;\n /** An object ran to EOF unclosed — the classic signature of truncated output. */\n sawUnbalanced: boolean;\n} {\n const stripped = stripModelNoise(raw);\n const keyRe = new RegExp(`\"${key}\"\\\\s*:`);\n\n const matches: string[] = [];\n let firstObject: string | null = null;\n let sawBrace = false;\n let sawUnbalanced = false;\n let inString = false;\n let escaped = false;\n for (let i = 0; i < stripped.length; i++) {\n const ch = stripped[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') { inString = true; continue; }\n if (ch !== '{') continue;\n\n sawBrace = true;\n const obj = balancedObjectAt(stripped, i);\n // A stray brace in a reasoning preamble produces an unbalanced candidate,\n // which we skip so it can't swallow the real object that follows.\n if (obj.balanced && keyRe.test(obj.json)) {\n matches.push(obj.json);\n i += obj.json.length - 1;\n continue;\n }\n if (!obj.balanced) sawUnbalanced = true;\n if (!firstObject && obj.balanced) firstObject = obj.json;\n }\n\n return {\n matches,\n fallback: firstObject !== null ? { json: firstObject, balanced: true } : { json: stripped, balanced: false },\n sawBrace,\n sawUnbalanced,\n };\n}\n\n/**\n * Pull the JSON object out of an LLM response and report whether it was balanced.\n * Strips fences and `<think>` blocks, then walks every top-level `{…}` and\n * returns the FIRST one that contains a `\"tasks\"` key — so a brace appearing\n * earlier in reasoning (or an unrelated preamble object) can't make us parse the\n * wrong thing. Falls back to the first balanced object and, failing that, the\n * first `{` onwards so a genuine `JSON.parse` error still surfaces.\n */\nexport function extractObjectWithBalance(raw: string): { json: string; balanced: boolean; sawBrace: boolean } {\n const { matches, fallback, sawBrace } = extractObjectsWithKey(raw, PLAN_ENVELOPE_KEY);\n if (matches.length > 0) return { json: matches[0], balanced: true, sawBrace };\n return { ...fallback, sawBrace };\n}\n\n/**\n * Pull the JSON object out of an LLM response. Strips markdown code fences and\n * `<think>` blocks, prefers the object containing a `tasks` key, and tolerates a\n * prose preamble and trailing prose. Returns the fence-stripped text unchanged\n * if no `{` is present so the caller's JSON.parse produces a clear failure.\n */\nexport function extractJsonObject(raw: string): string {\n return extractObjectWithBalance(raw).json;\n}\n\n/** Drop trailing commas before a closing `}` or `]` — a common model quirk. */\nexport function stripTrailingCommas(json: string): string {\n return json.replace(/,(\\s*[}\\]])/g, '$1');\n}\n\n/**\n * Escape raw control characters that appear INSIDE string literals — budget\n * models routinely emit multi-line `prompt` strings with literal newlines,\n * which strict JSON.parse rejects (\"bad control character\"). Characters\n * outside strings (formatting whitespace) are left untouched.\n */\nexport function escapeControlCharsInStrings(json: string): string {\n let out = '';\n let inString = false;\n let escaped = false;\n for (const ch of json) {\n if (inString) {\n if (escaped) { out += ch; escaped = false; continue; }\n if (ch === '\\\\') { out += ch; escaped = true; continue; }\n if (ch === '\"') { out += ch; inString = false; continue; }\n if (ch === '\\n') { out += '\\\\n'; continue; }\n if (ch === '\\r') { out += '\\\\r'; continue; }\n if (ch === '\\t') { out += '\\\\t'; continue; }\n out += ch;\n continue;\n }\n if (ch === '\"') inString = true;\n out += ch;\n }\n return out;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
extractObjectsWithKey,
|
|
7
7
|
stripModelNoise,
|
|
8
8
|
stripTrailingCommas
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-N6HTBUKG.mjs";
|
|
10
10
|
|
|
11
11
|
// src/services/ModeResolver.ts
|
|
12
12
|
function runnerModesFrom(registry, runners) {
|
|
@@ -395,4 +395,4 @@ export {
|
|
|
395
395
|
validatePlanModification,
|
|
396
396
|
parsePartialPlan
|
|
397
397
|
};
|
|
398
|
-
//# sourceMappingURL=chunk-
|
|
398
|
+
//# sourceMappingURL=chunk-UEJ3SZQ7.mjs.map
|