@wrongstack/core 0.1.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/LICENSE +17 -0
- package/dist/defaults/index.d.ts +1082 -0
- package/dist/defaults/index.js +4549 -0
- package/dist/defaults/index.js.map +1 -0
- package/dist/index.d.ts +180 -0
- package/dist/index.js +6410 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/index.d.ts +71 -0
- package/dist/kernel/index.js +361 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/secret-scrubber-Dax_Ou_o.d.ts +1055 -0
- package/dist/system-prompt-BG3nks8P.d.ts +16 -0
- package/dist/tool-executor-DjnMELMV.d.ts +689 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +296 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +88 -0
- package/dist/utils/index.js +461 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/wstack-paths-D24ynAz1.d.ts +56 -0
- package/package.json +46 -0
- package/skills/git-flow/SKILL.md +32 -0
- package/skills/multi-agent/SKILL.md +62 -0
- package/skills/node-modern/SKILL.md +41 -0
- package/skills/prompt-engineering/SKILL.md +28 -0
- package/skills/react-modern/SKILL.md +34 -0
- package/skills/sdd/SKILL.md +78 -0
- package/skills/typescript-strict/SKILL.md +50 -0
|
@@ -0,0 +1,1082 @@
|
|
|
1
|
+
import { j as Logger, i as LogLevel, P as PathResolver, S as SecretScrubber, O as RetryPolicy, A as ProviderError, E as ErrorHandler, c as Compactor, ag as Context, K as Response, a1 as TokenCounter, s as ModelsRegistry, ai as EventBus, a8 as Usage, G as ResolvedModel, C as CacheStats, V as SessionStore, U as SessionMetadata, X as SessionWriter, N as ResumedSession, Q as SessionData, W as SessionSummary, f as ContentBlock, m as MemoryStore, l as MemoryScope, v as PermissionPolicy, a2 as Tool, h as InputReader, u as PermissionDecision, Y as SkillLoader, Z as SkillManifest, d as Config, e as ConfigLoader, b as CompactReport, y as Provider, n as Message, as as MiddlewareHandler, q as ModelsDevPayload, H as ResolvedProvider, a9 as WireFamily, a5 as ToolUseBlock, a4 as ToolResultBlock } from '../secret-scrubber-Dax_Ou_o.js';
|
|
2
|
+
import { g as AttachmentStore, A as AddAttachmentInput, f as AttachmentRef, c as Attachment, S as SecretVault, q as ModeStore, o as ModeConfig, n as Mode, s as MultiAgentCoordinator, r as MultiAgentConfig, Q as SubagentConfig, z as SpawnResult, a2 as TaskSpec, B as BridgeMessage, a as AgentBridge, j as CoordinatorStatus, a0 as TaskResult, b as AgentBridgeConfig, i as BridgeTransport, ah as Agent, m as DoneCondition, an as RunResult, O as Specification, F as SpecAnalysis, N as SpecValidationResult, Y as TaskGraph, Z as TaskNode, X as TaskFilter, a1 as TaskSort, $ as TaskProgress, a4 as TaskType, _ as TaskPriority, a9 as ToolExecutorOptions, aa as ToolExecutorStrategy, a5 as ToolBatchResult } from '../tool-executor-DjnMELMV.js';
|
|
3
|
+
import { a as WstackPaths } from '../wstack-paths-D24ynAz1.js';
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
|
|
6
|
+
interface DefaultLoggerOptions {
|
|
7
|
+
level?: LogLevel;
|
|
8
|
+
file?: string;
|
|
9
|
+
pretty?: boolean;
|
|
10
|
+
bindings?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
declare class DefaultLogger implements Logger {
|
|
13
|
+
level: LogLevel;
|
|
14
|
+
private readonly file?;
|
|
15
|
+
private readonly bindings;
|
|
16
|
+
private readonly pretty;
|
|
17
|
+
constructor(opts?: DefaultLoggerOptions);
|
|
18
|
+
error(msg: string, ctx?: unknown): void;
|
|
19
|
+
warn(msg: string, ctx?: unknown): void;
|
|
20
|
+
info(msg: string, ctx?: unknown): void;
|
|
21
|
+
debug(msg: string, ctx?: unknown): void;
|
|
22
|
+
trace(msg: string, ctx?: unknown): void;
|
|
23
|
+
child(bindings: Record<string, unknown>): Logger;
|
|
24
|
+
private log;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare class DefaultPathResolver implements PathResolver {
|
|
28
|
+
readonly projectRoot: string;
|
|
29
|
+
readonly cwd: string;
|
|
30
|
+
constructor(cwd?: string);
|
|
31
|
+
detectProjectRoot(start: string): string;
|
|
32
|
+
resolve(input: string): string;
|
|
33
|
+
isInsideRoot(absPath: string): boolean;
|
|
34
|
+
ensureInsideRoot(absPath: string): string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
declare class DefaultSecretScrubber implements SecretScrubber {
|
|
38
|
+
scrub(text: string): string;
|
|
39
|
+
scrubObject<T>(obj: T): T;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
declare class DefaultRetryPolicy implements RetryPolicy {
|
|
43
|
+
shouldRetry(err: Error | ProviderError, attempt: number): boolean;
|
|
44
|
+
maxAttempts(err: Error | ProviderError): number;
|
|
45
|
+
delayMs(attempt: number): number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Tiered error recovery strategies.
|
|
50
|
+
* Each strategy is attempted in order until one succeeds.
|
|
51
|
+
*/
|
|
52
|
+
interface RecoveryStrategy {
|
|
53
|
+
/** Human-readable label for logs. */
|
|
54
|
+
label: string;
|
|
55
|
+
/** Optional compactor for context_overflow recovery. */
|
|
56
|
+
compactor?: Compactor;
|
|
57
|
+
/** Returns a substitute Response, or null to fall through to the next strategy. */
|
|
58
|
+
attempt: (err: unknown, ctx: Context) => Promise<Response | null>;
|
|
59
|
+
}
|
|
60
|
+
declare class DefaultErrorHandler implements ErrorHandler {
|
|
61
|
+
private readonly strategies;
|
|
62
|
+
constructor(strategies?: RecoveryStrategy[]);
|
|
63
|
+
classify(err: unknown): {
|
|
64
|
+
kind: 'rate_limit' | 'overloaded' | 'server' | 'client' | 'network' | 'abort' | 'context_overflow' | 'unknown';
|
|
65
|
+
retryable: boolean;
|
|
66
|
+
};
|
|
67
|
+
recover(err: unknown, ctx: Context): Promise<Response | null>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Token counter that derives pricing from the ModelsRegistry instead of a
|
|
72
|
+
* hardcoded table. If a model is unknown to the registry (or the registry is
|
|
73
|
+
* unavailable) the counter still tracks token totals but reports zero cost.
|
|
74
|
+
*/
|
|
75
|
+
declare class DefaultTokenCounter implements TokenCounter {
|
|
76
|
+
private input;
|
|
77
|
+
private output;
|
|
78
|
+
private cacheRead;
|
|
79
|
+
private cacheWrite;
|
|
80
|
+
private costInput;
|
|
81
|
+
private costOutput;
|
|
82
|
+
private readonly registry?;
|
|
83
|
+
private readonly providerId?;
|
|
84
|
+
private readonly events?;
|
|
85
|
+
private priceCache;
|
|
86
|
+
constructor(opts?: {
|
|
87
|
+
registry?: ModelsRegistry;
|
|
88
|
+
providerId?: string;
|
|
89
|
+
events?: EventBus;
|
|
90
|
+
});
|
|
91
|
+
account(usage: Usage, model?: string): void;
|
|
92
|
+
/** Synchronous variant for code paths that have already resolved the model. */
|
|
93
|
+
accountWithModel(usage: Usage, resolved: ResolvedModel): void;
|
|
94
|
+
total(): Usage;
|
|
95
|
+
estimateCost(): {
|
|
96
|
+
input: number;
|
|
97
|
+
output: number;
|
|
98
|
+
total: number;
|
|
99
|
+
currency: 'USD';
|
|
100
|
+
};
|
|
101
|
+
cacheStats(): CacheStats;
|
|
102
|
+
/** Invalidate cached prices so the next account() call fetches fresh data. */
|
|
103
|
+
invalidateCache(): void;
|
|
104
|
+
reset(): void;
|
|
105
|
+
private applyPrice;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
interface SessionStoreOptions {
|
|
109
|
+
dir: string;
|
|
110
|
+
/** Optional EventBus for emitting session diagnostics. */
|
|
111
|
+
events?: EventBus;
|
|
112
|
+
}
|
|
113
|
+
declare class DefaultSessionStore implements SessionStore {
|
|
114
|
+
private readonly dir;
|
|
115
|
+
private readonly events?;
|
|
116
|
+
constructor(opts: SessionStoreOptions);
|
|
117
|
+
create(meta: Omit<SessionMetadata, 'startedAt'>): Promise<SessionWriter>;
|
|
118
|
+
resume(id: string): Promise<ResumedSession>;
|
|
119
|
+
load(id: string): Promise<SessionData>;
|
|
120
|
+
list(limit?: number): Promise<SessionSummary[]>;
|
|
121
|
+
private summaryFor;
|
|
122
|
+
delete(id: string): Promise<void>;
|
|
123
|
+
private summarize;
|
|
124
|
+
private metaFromEvents;
|
|
125
|
+
private replay;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Per-project lockfile used for crash detection. The CLI writes one of
|
|
130
|
+
* these alongside the session JSONLs (`<projectSessions>/active.json`)
|
|
131
|
+
* when an interactive run starts, and deletes it on clean exit. If we
|
|
132
|
+
* find one on the next launch whose owning PID is dead (or whose host
|
|
133
|
+
* doesn't match), we know the previous run was killed mid-flight and
|
|
134
|
+
* the session it was writing to is a recovery candidate.
|
|
135
|
+
*
|
|
136
|
+
* The lockfile is intentionally per-project (already isolated by
|
|
137
|
+
* `wpaths.projectSessions`), so two TUIs in two different repos do not
|
|
138
|
+
* fight each other.
|
|
139
|
+
*/
|
|
140
|
+
interface RecoveryLockOptions {
|
|
141
|
+
/** Directory the lockfile lives in. Usually `wpaths.projectSessions`. */
|
|
142
|
+
dir: string;
|
|
143
|
+
/** This process's PID. Default: `process.pid`. */
|
|
144
|
+
pid?: number;
|
|
145
|
+
/** Hostname recorded for the lock. Default: `os.hostname()`. */
|
|
146
|
+
hostname?: string;
|
|
147
|
+
/** Locks older than this are considered orphaned (disk wiped, etc.). Default 24h. */
|
|
148
|
+
maxAgeMs?: number;
|
|
149
|
+
/** Used to check whether the abandoned session was actually closed cleanly. */
|
|
150
|
+
sessionStore?: SessionStore;
|
|
151
|
+
/**
|
|
152
|
+
* Override the PID-liveness probe. Default: `process.kill(pid, 0)` —
|
|
153
|
+
* succeeds (or throws EPERM) when the PID is alive, throws ESRCH when
|
|
154
|
+
* it is gone. Tests inject a deterministic stub.
|
|
155
|
+
*/
|
|
156
|
+
isPidAlive?: (pid: number) => boolean;
|
|
157
|
+
}
|
|
158
|
+
interface AbandonedSession {
|
|
159
|
+
sessionId: string;
|
|
160
|
+
pid: number;
|
|
161
|
+
startedAt: string;
|
|
162
|
+
/** Lockfile age in ms at the time of the check. */
|
|
163
|
+
ageMs: number;
|
|
164
|
+
/** Number of messages already on disk for this session. */
|
|
165
|
+
messageCount: number;
|
|
166
|
+
}
|
|
167
|
+
declare class RecoveryLock {
|
|
168
|
+
private readonly file;
|
|
169
|
+
private readonly pid;
|
|
170
|
+
private readonly hostname;
|
|
171
|
+
private readonly maxAgeMs;
|
|
172
|
+
private readonly sessionStore?;
|
|
173
|
+
private readonly probe;
|
|
174
|
+
constructor(opts: RecoveryLockOptions);
|
|
175
|
+
/**
|
|
176
|
+
* Examine the lockfile and decide whether it represents an abandoned
|
|
177
|
+
* session. Returns `null` if the file is missing, points to a live
|
|
178
|
+
* instance, references a clean-closed session, is too old, or is
|
|
179
|
+
* malformed. Otherwise returns enough detail to prompt the user.
|
|
180
|
+
*
|
|
181
|
+
* Important: this is a read-only check. We never delete an active
|
|
182
|
+
* lock from here — if another wstack instance is alive, the caller
|
|
183
|
+
* should bail or run with a fresh session instead.
|
|
184
|
+
*/
|
|
185
|
+
checkAbandoned(): Promise<AbandonedSession | null>;
|
|
186
|
+
/**
|
|
187
|
+
* Claim the lock for the given session. Overwrites any existing lock
|
|
188
|
+
* — the caller should have already handled abandonment (via
|
|
189
|
+
* `checkAbandoned`) before calling this.
|
|
190
|
+
*/
|
|
191
|
+
write(sessionId: string): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Release the lock. Idempotent — silently succeeds if the file is
|
|
194
|
+
* already gone (e.g. someone else cleared it, or the directory was
|
|
195
|
+
* wiped).
|
|
196
|
+
*/
|
|
197
|
+
clear(): Promise<void>;
|
|
198
|
+
private readLock;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* The persisted form of a single queued user message. The TUI's
|
|
203
|
+
* in-memory QueueItem has a render id; that's pure UI bookkeeping, so
|
|
204
|
+
* we drop it when serializing — fresh ids are assigned on rehydrate.
|
|
205
|
+
*/
|
|
206
|
+
interface PersistedQueueItem {
|
|
207
|
+
displayText: string;
|
|
208
|
+
blocks: ContentBlock[];
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Side-file storage for a session's pending input queue. Lives at
|
|
212
|
+
* `<sessionDir>/queue.json` next to the attachment spool. Reads are
|
|
213
|
+
* tolerant (missing/malformed file → empty array); writes are atomic
|
|
214
|
+
* (tmp + rename) so a crash mid-write can never leave a partial file
|
|
215
|
+
* the next launch would choke on.
|
|
216
|
+
*
|
|
217
|
+
* The contract is "snapshot replacement": every mutation hands the
|
|
218
|
+
* full queue and we rewrite the file. The queue is small (rarely more
|
|
219
|
+
* than a handful of messages), so this is cheaper than delta logging
|
|
220
|
+
* and avoids the replay complexity.
|
|
221
|
+
*/
|
|
222
|
+
declare class QueueStore {
|
|
223
|
+
private readonly file;
|
|
224
|
+
constructor(opts: {
|
|
225
|
+
dir: string;
|
|
226
|
+
});
|
|
227
|
+
write(items: PersistedQueueItem[]): Promise<void>;
|
|
228
|
+
read(): Promise<PersistedQueueItem[]>;
|
|
229
|
+
clear(): Promise<void>;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
interface AttachmentStoreOptions {
|
|
233
|
+
/**
|
|
234
|
+
* Directory for spooling payloads larger than `spoolThresholdBytes`.
|
|
235
|
+
* When omitted, all payloads stay in memory.
|
|
236
|
+
*/
|
|
237
|
+
spoolDir?: string;
|
|
238
|
+
spoolThresholdBytes?: number;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* In-memory attachment store with optional disk spool. Placeholder syntax
|
|
242
|
+
* is `[<kind> #<seq>]` where kind is `pasted` / `image` / `file`. Unknown
|
|
243
|
+
* placeholders are passed through as-is so users can write that literal
|
|
244
|
+
* text without losing it.
|
|
245
|
+
*/
|
|
246
|
+
declare class DefaultAttachmentStore implements AttachmentStore {
|
|
247
|
+
private readonly items;
|
|
248
|
+
private readonly refs;
|
|
249
|
+
private nextSeq;
|
|
250
|
+
private readonly spoolDir;
|
|
251
|
+
private readonly spoolThreshold;
|
|
252
|
+
constructor(opts?: AttachmentStoreOptions);
|
|
253
|
+
add(input: AddAttachmentInput): Promise<AttachmentRef>;
|
|
254
|
+
get(id: string): Promise<Attachment | undefined>;
|
|
255
|
+
list(): AttachmentRef[];
|
|
256
|
+
expand(text: string): Promise<ContentBlock[]>;
|
|
257
|
+
clear(): Promise<void>;
|
|
258
|
+
private toBlock;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
interface SecretVaultOptions {
|
|
262
|
+
/** Absolute path to the key file. Created with mode 0o600 if missing. */
|
|
263
|
+
keyFile: string;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Default vault: AES-256-GCM with a key stored at `keyFile` (mode 0o600).
|
|
267
|
+
* The key is loaded lazily on first encrypt/decrypt; if it does not exist,
|
|
268
|
+
* a fresh one is generated. Decryption of plaintext values is a no-op so
|
|
269
|
+
* legacy configs continue to work.
|
|
270
|
+
*/
|
|
271
|
+
declare class DefaultSecretVault implements SecretVault {
|
|
272
|
+
private readonly keyFile;
|
|
273
|
+
private key?;
|
|
274
|
+
constructor(opts: SecretVaultOptions);
|
|
275
|
+
isEncrypted(value: string): boolean;
|
|
276
|
+
encrypt(plaintext: string): string;
|
|
277
|
+
decrypt(value: string): string;
|
|
278
|
+
private loadOrCreateKey;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Walk a Config-shaped object and decrypt any apiKey-like fields in place,
|
|
282
|
+
* returning a new object. Used by the config loader so the rest of the
|
|
283
|
+
* system never has to know about the wire format.
|
|
284
|
+
*/
|
|
285
|
+
declare function decryptConfigSecrets<T>(cfg: T, vault: SecretVault): T;
|
|
286
|
+
declare function encryptConfigSecrets<T>(cfg: T, vault: SecretVault): T;
|
|
287
|
+
/**
|
|
288
|
+
* Re-write `~/.wrongstack/config.json` (or any path) with all secret-bearing
|
|
289
|
+
* fields encrypted. Used by the `wstack auth` subcommand.
|
|
290
|
+
*/
|
|
291
|
+
declare function rewriteConfigEncrypted(configPath: string, vault: SecretVault, patch?: Record<string, unknown>): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Scan a config file on disk for plaintext secret-bearing fields and
|
|
294
|
+
* rewrite the file with them encrypted in place. Returns a count of how
|
|
295
|
+
* many fields were migrated. Idempotent — calling on a fully-encrypted
|
|
296
|
+
* file is a no-op and writes nothing. Used by the CLI on every boot so
|
|
297
|
+
* users who had plaintext keys before the vault landed are upgraded
|
|
298
|
+
* transparently.
|
|
299
|
+
*/
|
|
300
|
+
declare function migratePlaintextSecrets(configPath: string, vault: SecretVault): Promise<{
|
|
301
|
+
migrated: number;
|
|
302
|
+
file: string;
|
|
303
|
+
}>;
|
|
304
|
+
|
|
305
|
+
interface MemoryStoreOptions {
|
|
306
|
+
paths: WstackPaths;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Three scopes:
|
|
310
|
+
* project-agents → <project>/.wrongstack/AGENTS.md (committed)
|
|
311
|
+
* project-memory → ~/.wrongstack/projects/<hash>/memory.md (per-project agent notes)
|
|
312
|
+
* user-memory → ~/.wrongstack/memory.md (global personal memory)
|
|
313
|
+
*/
|
|
314
|
+
declare class DefaultMemoryStore implements MemoryStore {
|
|
315
|
+
private readonly files;
|
|
316
|
+
constructor(opts: MemoryStoreOptions);
|
|
317
|
+
readAll(): Promise<string>;
|
|
318
|
+
read(scope: MemoryScope): Promise<string>;
|
|
319
|
+
remember(text: string, scope?: MemoryScope): Promise<void>;
|
|
320
|
+
forget(query: string, scope?: MemoryScope): Promise<number>;
|
|
321
|
+
consolidate(scope: MemoryScope): Promise<void>;
|
|
322
|
+
clear(scope?: MemoryScope): Promise<void>;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface PermissionPolicyOptions {
|
|
326
|
+
trustFile: string;
|
|
327
|
+
yolo?: boolean;
|
|
328
|
+
promptDelegate?: (tool: Tool, input: unknown, suggestedPattern: string) => Promise<'yes' | 'no' | 'always' | 'deny'>;
|
|
329
|
+
inputReader?: InputReader;
|
|
330
|
+
}
|
|
331
|
+
declare class DefaultPermissionPolicy implements PermissionPolicy {
|
|
332
|
+
private policy;
|
|
333
|
+
private loaded;
|
|
334
|
+
private readonly trustFile;
|
|
335
|
+
private readonly yolo;
|
|
336
|
+
private readonly promptDelegate?;
|
|
337
|
+
constructor(opts: PermissionPolicyOptions);
|
|
338
|
+
reload(): Promise<void>;
|
|
339
|
+
evaluate(tool: Tool, input: unknown, _ctx: Context): Promise<PermissionDecision>;
|
|
340
|
+
trust(rule: {
|
|
341
|
+
tool: string;
|
|
342
|
+
pattern: string;
|
|
343
|
+
}): Promise<void>;
|
|
344
|
+
private subjectFor;
|
|
345
|
+
private findNamespaceEntry;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
interface SkillLoaderOptions {
|
|
349
|
+
paths: WstackPaths;
|
|
350
|
+
bundledDir?: string;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Discovery order (later layers shadow earlier ones at boot, but we walk
|
|
354
|
+
* highest priority first and skip names already seen):
|
|
355
|
+
* 1. Project-committed: <project>/.wrongstack/skills/
|
|
356
|
+
* 2. User-global: ~/.wrongstack/skills/
|
|
357
|
+
* 3. Bundled with build: packages/core/skills/
|
|
358
|
+
*/
|
|
359
|
+
declare class DefaultSkillLoader implements SkillLoader {
|
|
360
|
+
private readonly dirs;
|
|
361
|
+
private cache?;
|
|
362
|
+
constructor(opts: SkillLoaderOptions);
|
|
363
|
+
list(): Promise<SkillManifest[]>;
|
|
364
|
+
find(name: string): Promise<SkillManifest | undefined>;
|
|
365
|
+
manifestText(): Promise<string>;
|
|
366
|
+
readBody(name: string): Promise<string>;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* A single config source. Higher priority wins in merges.
|
|
371
|
+
* Sources are applied in priority order (lowest first), so a source
|
|
372
|
+
* with priority=10 overrides one with priority=1.
|
|
373
|
+
*/
|
|
374
|
+
interface ConfigSource {
|
|
375
|
+
/** Unique name for debugging and error messages. */
|
|
376
|
+
name: string;
|
|
377
|
+
/** Lower numbers merge first, higher numbers override lower. Default: 50. */
|
|
378
|
+
priority?: number;
|
|
379
|
+
/**
|
|
380
|
+
* Read the raw config patch. Return an empty object if unavailable.
|
|
381
|
+
* Errors are surfaced but do not abort loading — the source is skipped.
|
|
382
|
+
*/
|
|
383
|
+
read(): Promise<Partial<Config>>;
|
|
384
|
+
}
|
|
385
|
+
interface ConfigLoaderOptions {
|
|
386
|
+
paths: WstackPaths;
|
|
387
|
+
strict?: boolean;
|
|
388
|
+
vault?: SecretVault;
|
|
389
|
+
/** Extra sources merged after the built-in layers. */
|
|
390
|
+
sources?: ConfigSource[];
|
|
391
|
+
}
|
|
392
|
+
declare class DefaultConfigLoader implements ConfigLoader {
|
|
393
|
+
private readonly paths;
|
|
394
|
+
private readonly strict;
|
|
395
|
+
private readonly vault;
|
|
396
|
+
private readonly extraSources;
|
|
397
|
+
constructor(opts: ConfigLoaderOptions);
|
|
398
|
+
load(opts?: {
|
|
399
|
+
cliFlags?: Partial<Config>;
|
|
400
|
+
cwd?: string;
|
|
401
|
+
}): Promise<Config>;
|
|
402
|
+
private readJson;
|
|
403
|
+
private validateBehavior;
|
|
404
|
+
private validateIdentity;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
interface CompactorOptions {
|
|
408
|
+
preserveK?: number;
|
|
409
|
+
eliseThreshold?: number;
|
|
410
|
+
estimator?: (text: string) => number;
|
|
411
|
+
}
|
|
412
|
+
declare class HybridCompactor implements Compactor {
|
|
413
|
+
private readonly preserveK;
|
|
414
|
+
private readonly eliseThreshold;
|
|
415
|
+
private readonly estimator;
|
|
416
|
+
constructor(opts?: CompactorOptions);
|
|
417
|
+
compact(ctx: Context, opts?: {
|
|
418
|
+
aggressive?: boolean;
|
|
419
|
+
}): Promise<CompactReport>;
|
|
420
|
+
private eliseOldToolResults;
|
|
421
|
+
private collapseAncientTurns;
|
|
422
|
+
private estimateMessages;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Options for IntelligentCompactor.
|
|
427
|
+
*/
|
|
428
|
+
interface IntelligentCompactorOptions {
|
|
429
|
+
/** Provider to use for LLM-assisted summarization. Required. */
|
|
430
|
+
provider: Provider;
|
|
431
|
+
/** Fraction of maxContext that triggers a warning (default 0.6). */
|
|
432
|
+
warnThreshold?: number;
|
|
433
|
+
/** Fraction of maxContext that triggers soft compaction (default 0.75). */
|
|
434
|
+
softThreshold?: number;
|
|
435
|
+
/** Fraction of maxContext that triggers hard compaction (default 0.9). */
|
|
436
|
+
hardThreshold?: number;
|
|
437
|
+
/** Max context window in tokens (used only for threshold fraction math). */
|
|
438
|
+
maxContext?: number;
|
|
439
|
+
/** How many recent (user+assistant) pairs to always preserve (default 4). */
|
|
440
|
+
preserveK?: number;
|
|
441
|
+
/** Token threshold below which tool results are not elided (default 500). */
|
|
442
|
+
eliseThreshold?: number;
|
|
443
|
+
/** System prompt for the summarizer sub-LLM. */
|
|
444
|
+
summarizerPrompt?: string;
|
|
445
|
+
/**
|
|
446
|
+
* Model ID to use for summarization. When not set, the same model as the
|
|
447
|
+
* agent is used (which risks cascading failure on context overflow). Set to
|
|
448
|
+
* a fast/cheap model like `claude-3-5-haiku-20240620` for resilience.
|
|
449
|
+
*/
|
|
450
|
+
summarizerModel?: string;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* IntelligentCompactor uses an LLM to:
|
|
454
|
+
* - Analyze message importance and preserve critical context
|
|
455
|
+
* - Generate semantic summaries for old message ranges
|
|
456
|
+
* - Make intelligent decisions about what to compact
|
|
457
|
+
*
|
|
458
|
+
* It extends HybridCompactor's elision logic with LLM-assisted summarization.
|
|
459
|
+
*/
|
|
460
|
+
declare class IntelligentCompactor implements Compactor {
|
|
461
|
+
private readonly provider;
|
|
462
|
+
private readonly warnThreshold;
|
|
463
|
+
private readonly softThreshold;
|
|
464
|
+
private readonly hardThreshold;
|
|
465
|
+
private readonly maxContext;
|
|
466
|
+
private readonly preserveK;
|
|
467
|
+
private readonly eliseThreshold;
|
|
468
|
+
private readonly summarizerPrompt;
|
|
469
|
+
private readonly summarizerModel?;
|
|
470
|
+
constructor(opts: IntelligentCompactorOptions);
|
|
471
|
+
compact(ctx: Context, opts?: {
|
|
472
|
+
aggressive?: boolean;
|
|
473
|
+
}): Promise<CompactReport>;
|
|
474
|
+
private summarizeAncientTurns;
|
|
475
|
+
private findSafeBoundary;
|
|
476
|
+
private findExchangeStart;
|
|
477
|
+
private callSummarizer;
|
|
478
|
+
private messagesToText;
|
|
479
|
+
private lightweightCompact;
|
|
480
|
+
private eliseOldToolResults;
|
|
481
|
+
private hasTextContent;
|
|
482
|
+
private estimateTokens;
|
|
483
|
+
private roughTokenEstimate;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Result of LLM-driven message importance analysis.
|
|
488
|
+
* The selector marks each message range with an importance tier,
|
|
489
|
+
* and optionally provides a natural-language summary for collapsed ranges.
|
|
490
|
+
*/
|
|
491
|
+
interface SelectorResult {
|
|
492
|
+
/**
|
|
493
|
+
* Ordered list of kept message ranges. Each entry describes a
|
|
494
|
+
* message range that should be preserved verbatim in the context.
|
|
495
|
+
*/
|
|
496
|
+
kept: Array<{
|
|
497
|
+
from: number;
|
|
498
|
+
to: number;
|
|
499
|
+
importance: 'critical' | 'high' | 'medium';
|
|
500
|
+
}>;
|
|
501
|
+
/**
|
|
502
|
+
* Collapsed ranges — either replaced by the compactor or omitted.
|
|
503
|
+
* Each entry may carry a summary text produced by the LLM.
|
|
504
|
+
*/
|
|
505
|
+
collapsed: Array<{
|
|
506
|
+
from: number;
|
|
507
|
+
to: number;
|
|
508
|
+
summary?: string;
|
|
509
|
+
}>;
|
|
510
|
+
/**
|
|
511
|
+
* Raw reasoning from the selector LLM (for debugging / audit).
|
|
512
|
+
*/
|
|
513
|
+
reasoning: string;
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Message selector that uses an LLM to decide which message ranges
|
|
517
|
+
* to keep vs collapse/summarize. The selector runs as a separate API
|
|
518
|
+
* call before compaction, making it more surgical than fixed-window
|
|
519
|
+
* or rules-based approaches.
|
|
520
|
+
*/
|
|
521
|
+
interface MessageSelector {
|
|
522
|
+
/**
|
|
523
|
+
* Analyze `messages` and return a structured plan for what to keep
|
|
524
|
+
* vs collapse. May modify the messages array in-place if needed,
|
|
525
|
+
* or return a plan that the caller (Compactor) executes.
|
|
526
|
+
*
|
|
527
|
+
* @param messages Current message history (may be modified in-place)
|
|
528
|
+
* @param maxToKeep Token budget — selector should aim to keep total
|
|
529
|
+
* retained message content under this threshold
|
|
530
|
+
*/
|
|
531
|
+
select(messages: Message[], maxToKeep: number): Promise<SelectorResult>;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Options for SelectiveCompactor — the most configurable compactor.
|
|
536
|
+
*/
|
|
537
|
+
interface SelectiveCompactorOptions {
|
|
538
|
+
/** Provider for LLM calls (selector + summarizer). Required. */
|
|
539
|
+
provider: Provider;
|
|
540
|
+
/** Selector for LLM-driven importance analysis. */
|
|
541
|
+
selector?: MessageSelector;
|
|
542
|
+
/** Fraction of maxContext that triggers a warning (default 0.6). */
|
|
543
|
+
warnThreshold?: number;
|
|
544
|
+
/** Fraction of maxContext that triggers soft compaction (default 0.75). */
|
|
545
|
+
softThreshold?: number;
|
|
546
|
+
/** Fraction of maxContext that triggers hard compaction (default 0.9). */
|
|
547
|
+
hardThreshold?: number;
|
|
548
|
+
/** Max context window in tokens (used for threshold fraction math). */
|
|
549
|
+
maxContext?: number;
|
|
550
|
+
/** How many recent (user+assistant) pairs to always preserve (default 4). */
|
|
551
|
+
preserveK?: number;
|
|
552
|
+
/** Token threshold below which tool results are not elided (default 500). */
|
|
553
|
+
eliseThreshold?: number;
|
|
554
|
+
/** Model for selector LLM calls (default: same as provider default). */
|
|
555
|
+
selectorModel?: string;
|
|
556
|
+
/** Summarizer model for collapsed ranges (default: same as selectorModel). */
|
|
557
|
+
summarizerModel?: string;
|
|
558
|
+
/** Prompt for the summarizer sub-LLM. */
|
|
559
|
+
summarizerPrompt?: string;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* SelectiveCompactor uses an LLM-driven MessageSelector to make
|
|
563
|
+
* surgical decisions about which message ranges to keep vs collapse.
|
|
564
|
+
*
|
|
565
|
+
* Compared to HybridCompactor / IntelligentCompactor:
|
|
566
|
+
* - HybridCompactor: rule-based (preserveK + elision), no LLM calls
|
|
567
|
+
* - IntelligentCompactor: LLM summarization but no structured selection
|
|
568
|
+
* - SelectiveCompactor: full LLM-driven selection + optional summarization
|
|
569
|
+
*/
|
|
570
|
+
declare class SelectiveCompactor implements Compactor {
|
|
571
|
+
private readonly provider;
|
|
572
|
+
private readonly selector;
|
|
573
|
+
private readonly warnThreshold;
|
|
574
|
+
private readonly softThreshold;
|
|
575
|
+
private readonly hardThreshold;
|
|
576
|
+
private readonly maxContext;
|
|
577
|
+
private readonly preserveK;
|
|
578
|
+
private readonly eliseThreshold;
|
|
579
|
+
private readonly summarizerModel;
|
|
580
|
+
private readonly summarizerPrompt;
|
|
581
|
+
constructor(opts: SelectiveCompactorOptions);
|
|
582
|
+
compact(ctx: Context, opts?: {
|
|
583
|
+
aggressive?: boolean;
|
|
584
|
+
}): Promise<CompactReport>;
|
|
585
|
+
/**
|
|
586
|
+
* Run the LLM selector to decide what to keep vs collapse.
|
|
587
|
+
* Returns the token savings achieved.
|
|
588
|
+
*/
|
|
589
|
+
private runSelector;
|
|
590
|
+
/**
|
|
591
|
+
* Execute a SelectorResult plan: collapse/remove ranges and
|
|
592
|
+
* insert summaries where the selector provided them.
|
|
593
|
+
*/
|
|
594
|
+
private executePlan;
|
|
595
|
+
private summarizeRange;
|
|
596
|
+
private messagePreview;
|
|
597
|
+
/**
|
|
598
|
+
* Fallback when selector fails: aggressively trim from the oldest end
|
|
599
|
+
* until we hit targetBudget.
|
|
600
|
+
*/
|
|
601
|
+
private aggressiveRecencyTrim;
|
|
602
|
+
private computeTargetBudget;
|
|
603
|
+
private eliseOldToolResults;
|
|
604
|
+
private hasTextContent;
|
|
605
|
+
private estimateTokens;
|
|
606
|
+
private roughTokenEstimate;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
interface LLMSelectorOptions {
|
|
610
|
+
/** Provider used for the selector LLM call. Required. */
|
|
611
|
+
provider: Provider;
|
|
612
|
+
/** Model for the selector. Defaults to the provider's default model. */
|
|
613
|
+
model?: string;
|
|
614
|
+
/**
|
|
615
|
+
* Maximum tokens to keep in context (target budget).
|
|
616
|
+
* Selector will aim to keep total content below this.
|
|
617
|
+
*/
|
|
618
|
+
maxContextTokens?: number;
|
|
619
|
+
/**
|
|
620
|
+
* Prompt instructing the selector how to behave.
|
|
621
|
+
* Should guide the LLM on importance tiers and output format.
|
|
622
|
+
*/
|
|
623
|
+
systemPrompt?: string;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* LLM-powered message selector. Calls a sub-LLM to analyze the
|
|
627
|
+
* message history and produce a keep/collapse plan — more surgical
|
|
628
|
+
* than fixed-window rules.
|
|
629
|
+
*/
|
|
630
|
+
declare class LLMSelector implements MessageSelector {
|
|
631
|
+
private readonly provider;
|
|
632
|
+
private readonly model;
|
|
633
|
+
private readonly maxContextTokens;
|
|
634
|
+
private readonly systemPrompt;
|
|
635
|
+
constructor(opts: LLMSelectorOptions);
|
|
636
|
+
select(messages: Message[], maxToKeep: number): Promise<SelectorResult>;
|
|
637
|
+
private fallbackSelect;
|
|
638
|
+
private parseSelectorOutput;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Pipeline middleware that monitors context token load and
|
|
643
|
+
* automatically triggers compaction when the warn/soft/hard
|
|
644
|
+
* thresholds are crossed. Runs before the next agent iteration.
|
|
645
|
+
*/
|
|
646
|
+
declare class AutoCompactionMiddleware {
|
|
647
|
+
readonly name = "AutoCompaction";
|
|
648
|
+
private readonly compactor;
|
|
649
|
+
private readonly warnThreshold;
|
|
650
|
+
private readonly softThreshold;
|
|
651
|
+
private readonly hardThreshold;
|
|
652
|
+
private readonly maxContext;
|
|
653
|
+
private readonly estimator;
|
|
654
|
+
private readonly aggressiveOn;
|
|
655
|
+
/**
|
|
656
|
+
* @param compactor Compactor to use for compaction
|
|
657
|
+
* @param maxContext Provider's max context window in tokens
|
|
658
|
+
* @param estimator Token estimation function (ctx → token count)
|
|
659
|
+
* @param thresholds Threshold fractions (0-1) of maxContext
|
|
660
|
+
* @param aggressiveOn Which threshold triggers aggressive (full LLM summarization)
|
|
661
|
+
*/
|
|
662
|
+
constructor(compactor: Compactor, maxContext: number, estimator: (ctx: Context) => number, thresholds: {
|
|
663
|
+
warn: number;
|
|
664
|
+
soft: number;
|
|
665
|
+
hard: number;
|
|
666
|
+
}, aggressiveOn?: 'hard' | 'soft' | 'warn');
|
|
667
|
+
handler(): MiddlewareHandler<Context>;
|
|
668
|
+
private compact;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
interface DefaultModelsRegistryOptions {
|
|
672
|
+
cacheFile: string;
|
|
673
|
+
url?: string;
|
|
674
|
+
ttlSeconds?: number;
|
|
675
|
+
fetchImpl?: typeof fetch;
|
|
676
|
+
/** Pre-seeded payload — useful for offline scenarios and tests. */
|
|
677
|
+
seed?: ModelsDevPayload;
|
|
678
|
+
/**
|
|
679
|
+
* Maximum age in seconds for stale cache fallback when network fails.
|
|
680
|
+
* Defaults to 7 days. Set to `Infinity` for full offline resilience
|
|
681
|
+
* (risk: deprecated models, wrong pricing). Set to `0` to disable
|
|
682
|
+
* stale fallback entirely.
|
|
683
|
+
*/
|
|
684
|
+
maxStaleAgeSeconds?: number;
|
|
685
|
+
}
|
|
686
|
+
declare function classifyFamily(npm: string | undefined): WireFamily;
|
|
687
|
+
declare class DefaultModelsRegistry implements ModelsRegistry {
|
|
688
|
+
private payload?;
|
|
689
|
+
private fetchedAt?;
|
|
690
|
+
private readonly cacheFile;
|
|
691
|
+
private readonly url;
|
|
692
|
+
private readonly ttlMs;
|
|
693
|
+
private readonly fetchImpl;
|
|
694
|
+
private readonly seed?;
|
|
695
|
+
private readonly maxStaleAgeMs;
|
|
696
|
+
constructor(opts: DefaultModelsRegistryOptions);
|
|
697
|
+
load(opts?: {
|
|
698
|
+
force?: boolean;
|
|
699
|
+
}): Promise<ModelsDevPayload>;
|
|
700
|
+
refresh(): Promise<ModelsDevPayload>;
|
|
701
|
+
listProviders(): Promise<ResolvedProvider[]>;
|
|
702
|
+
getProvider(id: string): Promise<ResolvedProvider | undefined>;
|
|
703
|
+
getModel(providerId: string, modelId: string): Promise<ResolvedModel | undefined>;
|
|
704
|
+
suggestModel(providerId: string): Promise<string | undefined>;
|
|
705
|
+
ageSeconds(): Promise<number>;
|
|
706
|
+
private resolveProvider;
|
|
707
|
+
private isFresh;
|
|
708
|
+
private isWithinMaxStaleAge;
|
|
709
|
+
private readCache;
|
|
710
|
+
/** Used by `wstack models refresh` to expose where the cache lives. */
|
|
711
|
+
cacheLocation(): string;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
declare class DefaultModeStore implements ModeStore {
|
|
715
|
+
private activeModeId;
|
|
716
|
+
private modes;
|
|
717
|
+
private configDir;
|
|
718
|
+
constructor(config: ModeConfig);
|
|
719
|
+
getActiveMode(): Promise<Mode | null>;
|
|
720
|
+
setActiveMode(modeId: string | null): Promise<void>;
|
|
721
|
+
listModes(): Promise<Mode[]>;
|
|
722
|
+
getMode(modeId: string): Promise<Mode | null>;
|
|
723
|
+
addMode(mode: Mode): Promise<void>;
|
|
724
|
+
removeMode(modeId: string): Promise<void>;
|
|
725
|
+
private loadActiveMode;
|
|
726
|
+
private saveActiveMode;
|
|
727
|
+
}
|
|
728
|
+
interface ModeLoaderOptions {
|
|
729
|
+
projectModesDir?: string;
|
|
730
|
+
userModesDir?: string;
|
|
731
|
+
}
|
|
732
|
+
declare function loadProjectModes(modesDir: string): Promise<Mode[]>;
|
|
733
|
+
declare function loadUserModes(modesDir: string): Promise<Mode[]>;
|
|
734
|
+
|
|
735
|
+
declare class DefaultMultiAgentCoordinator extends EventEmitter implements MultiAgentCoordinator {
|
|
736
|
+
readonly coordinatorId: string;
|
|
737
|
+
readonly config: MultiAgentConfig;
|
|
738
|
+
private readonly subagents;
|
|
739
|
+
private pendingTasks;
|
|
740
|
+
private completedResults;
|
|
741
|
+
private totalIterations;
|
|
742
|
+
constructor(config: MultiAgentConfig);
|
|
743
|
+
spawn(subagent: SubagentConfig): Promise<SpawnResult>;
|
|
744
|
+
assign(task: TaskSpec): Promise<void>;
|
|
745
|
+
delegate(to: string, msg: BridgeMessage): Promise<void>;
|
|
746
|
+
/**
|
|
747
|
+
* Wire up the communication bridge for a subagent. Call this after `spawn()`
|
|
748
|
+
* once the caller has created the bidirectional bridge connection.
|
|
749
|
+
*/
|
|
750
|
+
setSubagentBridge(subagentId: string, bridge: AgentBridge): void;
|
|
751
|
+
stop(subagentId: string): Promise<void>;
|
|
752
|
+
stopAll(): Promise<void>;
|
|
753
|
+
getStatus(): CoordinatorStatus;
|
|
754
|
+
private getAvailableSubagent;
|
|
755
|
+
private dispatch;
|
|
756
|
+
private isDone;
|
|
757
|
+
completeTask(result: TaskResult): void;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
declare class InMemoryBridgeTransport implements BridgeTransport {
|
|
761
|
+
private subs;
|
|
762
|
+
send(msg: BridgeMessage, to: string): Promise<void>;
|
|
763
|
+
subscribe(agentId: string, handler: (msg: BridgeMessage) => void): () => void;
|
|
764
|
+
close(agentId: string): Promise<void>;
|
|
765
|
+
}
|
|
766
|
+
declare class InMemoryAgentBridge implements AgentBridge {
|
|
767
|
+
readonly agentId: string;
|
|
768
|
+
readonly coordinatorId: string;
|
|
769
|
+
private readonly transport;
|
|
770
|
+
private readonly subscriptions;
|
|
771
|
+
private pendingRequests;
|
|
772
|
+
private stopped;
|
|
773
|
+
private timeoutMs;
|
|
774
|
+
constructor(config: AgentBridgeConfig, transport: BridgeTransport);
|
|
775
|
+
send(msg: BridgeMessage): Promise<void>;
|
|
776
|
+
broadcast(msg: BridgeMessage): Promise<void>;
|
|
777
|
+
subscribe(handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
778
|
+
request<T>(msg: BridgeMessage, timeoutMs?: number): Promise<BridgeMessage<T>>;
|
|
779
|
+
stop(): Promise<void>;
|
|
780
|
+
}
|
|
781
|
+
declare function createMessage<T = unknown>(type: BridgeMessage['type'], from: string, payload: T, to?: string): BridgeMessage<T>;
|
|
782
|
+
|
|
783
|
+
interface DoneCheckResult {
|
|
784
|
+
done: boolean;
|
|
785
|
+
reason?: string;
|
|
786
|
+
iterations: number;
|
|
787
|
+
toolCalls: number;
|
|
788
|
+
}
|
|
789
|
+
declare class DoneConditionChecker {
|
|
790
|
+
private readonly condition;
|
|
791
|
+
constructor(condition: DoneCondition);
|
|
792
|
+
check(state: {
|
|
793
|
+
iterations: number;
|
|
794
|
+
toolCalls: number;
|
|
795
|
+
lastOutput?: string;
|
|
796
|
+
}): DoneCheckResult;
|
|
797
|
+
}
|
|
798
|
+
interface AutonomousRunnerOptions {
|
|
799
|
+
agent: Agent;
|
|
800
|
+
context: Context;
|
|
801
|
+
doneCondition: DoneCondition;
|
|
802
|
+
iterationTimeoutMs?: number;
|
|
803
|
+
onIteration?: (state: {
|
|
804
|
+
iteration: number;
|
|
805
|
+
toolCalls: number;
|
|
806
|
+
}) => void;
|
|
807
|
+
onDone?: (result: RunResult & {
|
|
808
|
+
toolCalls: number;
|
|
809
|
+
reason?: string;
|
|
810
|
+
}) => void;
|
|
811
|
+
}
|
|
812
|
+
declare class AutonomousRunner {
|
|
813
|
+
private readonly opts;
|
|
814
|
+
private iterations;
|
|
815
|
+
private toolCalls;
|
|
816
|
+
private lastOutput?;
|
|
817
|
+
private stopped;
|
|
818
|
+
private readonly doneChecker;
|
|
819
|
+
constructor(opts: AutonomousRunnerOptions);
|
|
820
|
+
run(): Promise<RunResult & {
|
|
821
|
+
toolCalls: number;
|
|
822
|
+
reason?: string;
|
|
823
|
+
}>;
|
|
824
|
+
stop(): void;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
interface SpecParserOptions {
|
|
828
|
+
strict?: boolean;
|
|
829
|
+
}
|
|
830
|
+
declare class SpecParser {
|
|
831
|
+
private readonly opts;
|
|
832
|
+
constructor(opts?: SpecParserOptions);
|
|
833
|
+
parse(content: string): Specification;
|
|
834
|
+
private extractTitle;
|
|
835
|
+
private extractVersion;
|
|
836
|
+
private extractOverview;
|
|
837
|
+
private extractSections;
|
|
838
|
+
private extractRequirements;
|
|
839
|
+
private parseRequirementLine;
|
|
840
|
+
private mapSectionType;
|
|
841
|
+
analyze(spec: Specification): SpecAnalysis;
|
|
842
|
+
validate(spec: Specification): SpecValidationResult;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
interface TaskStore {
|
|
846
|
+
saveGraph(graph: TaskGraph): Promise<void>;
|
|
847
|
+
loadGraph(id: string): Promise<TaskGraph | null>;
|
|
848
|
+
listGraphs(): Promise<{
|
|
849
|
+
id: string;
|
|
850
|
+
title: string;
|
|
851
|
+
updatedAt: number;
|
|
852
|
+
}[]>;
|
|
853
|
+
deleteGraph(id: string): Promise<void>;
|
|
854
|
+
}
|
|
855
|
+
interface TaskTrackerOptions {
|
|
856
|
+
store: TaskStore;
|
|
857
|
+
}
|
|
858
|
+
interface TaskTransition {
|
|
859
|
+
from: TaskNode['status'];
|
|
860
|
+
to: TaskNode['status'];
|
|
861
|
+
timestamp: number;
|
|
862
|
+
reason?: string;
|
|
863
|
+
}
|
|
864
|
+
declare class TaskTracker {
|
|
865
|
+
private readonly opts;
|
|
866
|
+
private graph;
|
|
867
|
+
private transitions;
|
|
868
|
+
constructor(opts: TaskTrackerOptions);
|
|
869
|
+
createGraph(specId: string, title: string): Promise<TaskGraph>;
|
|
870
|
+
loadGraph(id: string): Promise<TaskGraph | null>;
|
|
871
|
+
addNode(node: Omit<TaskNode, 'id' | 'createdAt' | 'updatedAt'>): TaskNode;
|
|
872
|
+
addEdge(from: string, to: string, type?: TaskGraph['edges'][0]['type']): void;
|
|
873
|
+
updateNodeStatus(id: string, status: TaskNode['status'], reason?: string): void;
|
|
874
|
+
getNode(id: string): TaskNode | undefined;
|
|
875
|
+
getAllNodes(filter?: TaskFilter, sort?: TaskSort): TaskNode[];
|
|
876
|
+
getChildren(parentId: string): TaskNode[];
|
|
877
|
+
getDependents(taskId: string): string[];
|
|
878
|
+
getBlockers(taskId: string): string[];
|
|
879
|
+
canStart(taskId: string): boolean;
|
|
880
|
+
getProgress(): TaskProgress;
|
|
881
|
+
getTransitions(taskId?: string): TaskTransition[];
|
|
882
|
+
private unblockDependents;
|
|
883
|
+
private checkAndBlockIfNeeded;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
interface TaskGeneratorOptions {
|
|
887
|
+
taskTracker: TaskTracker;
|
|
888
|
+
}
|
|
889
|
+
interface GeneratedTask {
|
|
890
|
+
specRequirementId?: string;
|
|
891
|
+
title: string;
|
|
892
|
+
description: string;
|
|
893
|
+
type: TaskType;
|
|
894
|
+
priority: TaskPriority;
|
|
895
|
+
estimateHours?: number;
|
|
896
|
+
tags?: string[];
|
|
897
|
+
}
|
|
898
|
+
declare class TaskGenerator {
|
|
899
|
+
private readonly opts;
|
|
900
|
+
constructor(opts: TaskGeneratorOptions);
|
|
901
|
+
generateFromSpec(spec: Specification): Promise<TaskGraph>;
|
|
902
|
+
private createTaskFromRequirement;
|
|
903
|
+
private createTaskFromEndpoint;
|
|
904
|
+
private buildDescription;
|
|
905
|
+
private mapRequirementType;
|
|
906
|
+
private mapPriority;
|
|
907
|
+
private estimateHours;
|
|
908
|
+
private estimateForEndpoint;
|
|
909
|
+
generateSubtasks(parentTaskId: string, spec: Specification): Promise<void>;
|
|
910
|
+
}
|
|
911
|
+
declare class DefaultTaskStore implements TaskStore {
|
|
912
|
+
private graphs;
|
|
913
|
+
saveGraph(graph: TaskGraph): Promise<void>;
|
|
914
|
+
loadGraph(id: string): Promise<TaskGraph | null>;
|
|
915
|
+
listGraphs(): Promise<{
|
|
916
|
+
id: string;
|
|
917
|
+
title: string;
|
|
918
|
+
updatedAt: number;
|
|
919
|
+
}[]>;
|
|
920
|
+
deleteGraph(id: string): Promise<void>;
|
|
921
|
+
private cloneGraph;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Extended event map used internally by TaskFlow and multi-agent components.
|
|
926
|
+
* These events are emitted on the injected EventBus and are a subset of
|
|
927
|
+
* the full EventMap — they do not require a separate registration.
|
|
928
|
+
*/
|
|
929
|
+
interface TaskFlowEventMap {
|
|
930
|
+
'phase.change': {
|
|
931
|
+
from: TaskFlowPhase;
|
|
932
|
+
to: TaskFlowPhase;
|
|
933
|
+
};
|
|
934
|
+
'task.started': {
|
|
935
|
+
taskId: string;
|
|
936
|
+
};
|
|
937
|
+
'task.completed': {
|
|
938
|
+
taskId: string;
|
|
939
|
+
result?: unknown;
|
|
940
|
+
};
|
|
941
|
+
'task.failed': {
|
|
942
|
+
taskId: string;
|
|
943
|
+
error: string;
|
|
944
|
+
};
|
|
945
|
+
'task.review': {
|
|
946
|
+
taskId: string;
|
|
947
|
+
};
|
|
948
|
+
'spec.analyzed': {
|
|
949
|
+
analysis: SpecAnalysis;
|
|
950
|
+
};
|
|
951
|
+
'progress': {
|
|
952
|
+
percent: number;
|
|
953
|
+
message: string;
|
|
954
|
+
};
|
|
955
|
+
'done': {
|
|
956
|
+
graph: TaskGraph;
|
|
957
|
+
};
|
|
958
|
+
'error': {
|
|
959
|
+
phase: TaskFlowPhase;
|
|
960
|
+
error: Error;
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
type TaskFlowPhase = 'idle' | 'parsing' | 'analyzing' | 'generating' | 'executing' | 'reviewing' | 'completing' | 'done' | 'failed';
|
|
964
|
+
type TaskFlowEventName = keyof TaskFlowEventMap;
|
|
965
|
+
interface TaskFlowOptions {
|
|
966
|
+
tracker: TaskTracker;
|
|
967
|
+
events: EventBus;
|
|
968
|
+
doneCondition?: DoneCondition;
|
|
969
|
+
maxConcurrent?: number;
|
|
970
|
+
}
|
|
971
|
+
interface TaskFlowExecutionContext {
|
|
972
|
+
executeTask: (task: TaskNode) => Promise<unknown>;
|
|
973
|
+
onTaskComplete?: (task: TaskNode, result: unknown) => void;
|
|
974
|
+
onTaskFail?: (task: TaskNode, error: Error) => void;
|
|
975
|
+
}
|
|
976
|
+
declare class TaskFlow {
|
|
977
|
+
private readonly opts;
|
|
978
|
+
private phase;
|
|
979
|
+
private spec;
|
|
980
|
+
private graph;
|
|
981
|
+
private stopped;
|
|
982
|
+
constructor(opts: TaskFlowOptions);
|
|
983
|
+
private emit;
|
|
984
|
+
fromSpec(specContent: string): Promise<TaskGraph>;
|
|
985
|
+
execute(ctx: TaskFlowExecutionContext): Promise<TaskGraph>;
|
|
986
|
+
reviewTask(taskId: string, approved: boolean, comment?: string): Promise<void>;
|
|
987
|
+
stop(): void;
|
|
988
|
+
getPhase(): TaskFlowPhase;
|
|
989
|
+
getGraph(): TaskGraph | null;
|
|
990
|
+
getSpec(): Specification | null;
|
|
991
|
+
private setPhase;
|
|
992
|
+
private getExecutableTasks;
|
|
993
|
+
private executeSingleTask;
|
|
994
|
+
private checkDoneCondition;
|
|
995
|
+
private emitProgress;
|
|
996
|
+
}
|
|
997
|
+
interface SpecDrivenDevOptions {
|
|
998
|
+
workingDirectory: string;
|
|
999
|
+
events: EventBus;
|
|
1000
|
+
doneCondition?: DoneCondition;
|
|
1001
|
+
}
|
|
1002
|
+
declare class SpecDrivenDev {
|
|
1003
|
+
private store;
|
|
1004
|
+
private tracker;
|
|
1005
|
+
private readonly events;
|
|
1006
|
+
private flows;
|
|
1007
|
+
constructor(opts: SpecDrivenDevOptions);
|
|
1008
|
+
createFlow(specContent: string, options?: Partial<TaskFlowOptions>): Promise<TaskFlow>;
|
|
1009
|
+
getTracker(): TaskTracker;
|
|
1010
|
+
getFlow(graphId: string): TaskFlow | undefined;
|
|
1011
|
+
listFlows(): {
|
|
1012
|
+
id: string;
|
|
1013
|
+
title: string;
|
|
1014
|
+
phase: TaskFlowPhase;
|
|
1015
|
+
}[];
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
declare class ToolExecutor {
|
|
1019
|
+
private readonly registry;
|
|
1020
|
+
private readonly opts;
|
|
1021
|
+
private readonly serializer;
|
|
1022
|
+
private readonly iterationTimeoutMs;
|
|
1023
|
+
constructor(registry: {
|
|
1024
|
+
get(name: string): Tool | undefined;
|
|
1025
|
+
list(): Tool[];
|
|
1026
|
+
}, opts: ToolExecutorOptions);
|
|
1027
|
+
/**
|
|
1028
|
+
* Execute a batch of tool uses using the configured strategy.
|
|
1029
|
+
* Returns the execution results and the remaining output budget.
|
|
1030
|
+
*/
|
|
1031
|
+
executeBatch(toolUses: ToolUseBlock[], ctx: Context, strategy: ToolExecutorStrategy): Promise<ToolBatchResult>;
|
|
1032
|
+
/**
|
|
1033
|
+
* Execute a single tool with timeout, permission check, and output capping.
|
|
1034
|
+
* Emits `tool.started` via the injected EventBus (if any) right before
|
|
1035
|
+
* invoking the tool — closes the observability gap between "model decided
|
|
1036
|
+
* to call a tool" and "tool.executed".
|
|
1037
|
+
*/
|
|
1038
|
+
executeTool(tool: Tool, use: ToolUseBlock, ctx: Context, budget: number): Promise<ToolResultBlock>;
|
|
1039
|
+
private runWithTimeout;
|
|
1040
|
+
private unknownToolResult;
|
|
1041
|
+
private deniedResult;
|
|
1042
|
+
private confirmResult;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
type ContextManagerAction = 'check' | 'summary' | 'prune' | 'add_note' | 'compact';
|
|
1046
|
+
interface ContextManagerInput {
|
|
1047
|
+
action: ContextManagerAction;
|
|
1048
|
+
/** 0-based message indices for prune/summary (inclusive). */
|
|
1049
|
+
from?: number;
|
|
1050
|
+
to?: number;
|
|
1051
|
+
/** Text for add_note / summary actions. For summary, this is the LLM-provided summary text. */
|
|
1052
|
+
text?: string;
|
|
1053
|
+
/** Inject after which index (for add_note). Defaults to prepend (0). */
|
|
1054
|
+
afterIndex?: number;
|
|
1055
|
+
}
|
|
1056
|
+
interface ContextManagerResult {
|
|
1057
|
+
action: ContextManagerAction;
|
|
1058
|
+
beforeTokens: number;
|
|
1059
|
+
afterTokens?: number;
|
|
1060
|
+
removedCount?: number;
|
|
1061
|
+
messageCount: number;
|
|
1062
|
+
summary?: string;
|
|
1063
|
+
notes?: string;
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Options for creating a context manager tool.
|
|
1067
|
+
* `compactor` is required for the "compact" action; without it the action returns an error.
|
|
1068
|
+
*/
|
|
1069
|
+
interface ContextManagerToolOptions {
|
|
1070
|
+
compactor?: Compactor;
|
|
1071
|
+
/**
|
|
1072
|
+
* Optional sub-LLM summarizer. When provided, the "summary" action calls this
|
|
1073
|
+
* to produce real summaries of message ranges instead of placeholder text.
|
|
1074
|
+
* (signature matches Provider.complete — return the summary text in result.content[0].text)
|
|
1075
|
+
*/
|
|
1076
|
+
summarizer?: (messages: Message[]) => Promise<string>;
|
|
1077
|
+
}
|
|
1078
|
+
declare function createContextManagerTool(opts?: ContextManagerToolOptions): Tool<ContextManagerInput, ContextManagerResult>;
|
|
1079
|
+
/** Pre-built instance with no compactor — compact action will return an error. */
|
|
1080
|
+
declare const contextManagerTool: Tool<ContextManagerInput, ContextManagerResult>;
|
|
1081
|
+
|
|
1082
|
+
export { type AbandonedSession, type AttachmentStoreOptions, AutoCompactionMiddleware, AutonomousRunner, type AutonomousRunnerOptions, type CompactorOptions, type ConfigLoaderOptions, type ConfigSource, type ContextManagerAction, type ContextManagerInput, type ContextManagerResult, type ContextManagerToolOptions, DefaultAttachmentStore, DefaultConfigLoader, DefaultErrorHandler, DefaultLogger, type DefaultLoggerOptions, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, type DefaultModelsRegistryOptions, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionStore, DefaultSkillLoader, DefaultTaskStore, DefaultTokenCounter, type DoneCheckResult, DoneConditionChecker, type GeneratedTask, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, IntelligentCompactor, type IntelligentCompactorOptions, LLMSelector, type LLMSelectorOptions, type MemoryStoreOptions, type ModeLoaderOptions, type PermissionPolicyOptions, type PersistedQueueItem, QueueStore, RecoveryLock, type RecoveryLockOptions, type SecretVaultOptions, SelectiveCompactor, type SelectiveCompactorOptions, type SessionStoreOptions, type SkillLoaderOptions, SpecDrivenDev, type SpecDrivenDevOptions, SpecParser, type SpecParserOptions, TaskFlow, type TaskFlowEventMap, type TaskFlowEventName, type TaskFlowExecutionContext, type TaskFlowOptions, type TaskFlowPhase, TaskGenerator, type TaskGeneratorOptions, type TaskStore, TaskTracker, type TaskTrackerOptions, type TaskTransition, ToolExecutor, classifyFamily, contextManagerTool, createContextManagerTool, createMessage, decryptConfigSecrets, encryptConfigSecrets, loadProjectModes, loadUserModes, migratePlaintextSecrets, rewriteConfigEncrypted };
|