@wrongstack/core 0.1.2 → 0.1.3
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/defaults/index.d.ts +738 -138
- package/dist/defaults/index.js +2507 -975
- package/dist/defaults/index.js.map +1 -1
- package/dist/index.d.ts +27 -8
- package/dist/index.js +3271 -1057
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +5 -3
- package/dist/kernel/index.js +89 -11
- package/dist/kernel/index.js.map +1 -1
- package/dist/provider-DovtyuM8.d.ts +813 -0
- package/dist/{secret-scrubber-Dax_Ou_o.d.ts → secret-scrubber-qU3AwEiI.d.ts} +126 -457
- package/dist/{tool-executor-DjnMELMV.d.ts → session-reader-DR4u3bu9.d.ts} +445 -59
- package/dist/{system-prompt-BG3nks8P.d.ts → system-prompt--mzZnenv.d.ts} +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.js +153 -5
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +42 -1
- package/dist/utils/index.js +122 -3
- package/dist/utils/index.js.map +1 -1
- package/package.json +5 -4
package/dist/defaults/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { g as Logger, f as LogLevel, P as PathResolver, n as ModelsRegistry, B as EventBus, u as ResolvedModel, j as MemoryStore, i as MemoryScope, S as SecretScrubber, p as PermissionPolicy, I as InputReader, o as PermissionDecision, w as RetryPolicy, E as ErrorHandler, a as Compactor, x as SkillLoader, y as SkillManifest, b as Config, c as ConfigLoader, d as ConfigStore, C as CompactReport, U as MiddlewareHandler, l as ModelsDevPayload, v as ResolvedProvider, W as WireFamily, M as MCPServerConfig } from '../secret-scrubber-qU3AwEiI.js';
|
|
2
|
+
import { u as TokenCounter, U as Usage, C as CacheStats, p as SessionStore, o as SessionMetadata, r as SessionWriter, l as ResumedSession, S as SessionData, q as SessionSummary, c as ContentBlock, v as Tool, a0 as Context, i as ProviderError, k as Response, h as Provider, M as Message, F as ToolUseBlock, B as ToolResultBlock, n as SessionEvent } from '../provider-DovtyuM8.js';
|
|
3
|
+
import { h as AttachmentStore, A as AddAttachmentInput, g as AttachmentRef, d as Attachment, S as SecretVault, F as ModeStore, y as ModeConfig, x as Mode, I as MultiAgentCoordinator, G as MultiAgentConfig, ae as SubagentRunner, aa as SubagentConfig, a0 as SpawnResult, aq as TaskSpec, B as BridgeMessage, a as AgentBridge, l as CoordinatorStatus, ao as TaskResult, aH as Agent, aJ as AgentInput, j as BridgeTransport, b as AgentBridgeConfig, p as DoneCondition, aR as RunResult, a9 as Specification, a1 as SpecAnalysis, a8 as SpecValidationResult, ak as TaskGraph, al as TaskNode, aj as TaskFilter, ap as TaskSort, an as TaskProgress, as as TaskType, am as TaskPriority, ay as ToolExecutorOptions, az as ToolExecutorStrategy, at as ToolBatchResult, V as SessionReader, o as DefaultSessionReaderOptions, U as SessionQuery, Y as SessionSummaryLite, X as SessionSearchQuery, W as SessionSearchHit, T as SessionExportOptions, v as MetricsSink, t as MetricLabels, w as MetricsSnapshot, r as HealthRegistry, H as HealthCheck, c as AggregateHealth, aB as Tracer, $ as Span } from '../session-reader-DR4u3bu9.js';
|
|
4
|
+
export { aL as BudgetExceededError, aM as BudgetKind, aN as BudgetLimits, aO as BudgetUsage, aS as SubagentBudget } from '../session-reader-DR4u3bu9.js';
|
|
3
5
|
import { a as WstackPaths } from '../wstack-paths-D24ynAz1.js';
|
|
4
6
|
import { EventEmitter } from 'node:events';
|
|
5
7
|
|
|
@@ -34,39 +36,6 @@ declare class DefaultPathResolver implements PathResolver {
|
|
|
34
36
|
ensureInsideRoot(absPath: string): string;
|
|
35
37
|
}
|
|
36
38
|
|
|
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
39
|
/**
|
|
71
40
|
* Token counter that derives pricing from the ModelsRegistry instead of a
|
|
72
41
|
* hardcoded table. If a model is unknown to the registry (or the registry is
|
|
@@ -125,79 +94,6 @@ declare class DefaultSessionStore implements SessionStore {
|
|
|
125
94
|
private replay;
|
|
126
95
|
}
|
|
127
96
|
|
|
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
97
|
/**
|
|
202
98
|
* The persisted form of a single queued user message. The TUI's
|
|
203
99
|
* in-memory QueueItem has a render id; that's pure UI bookkeeping, so
|
|
@@ -258,6 +154,31 @@ declare class DefaultAttachmentStore implements AttachmentStore {
|
|
|
258
154
|
private toBlock;
|
|
259
155
|
}
|
|
260
156
|
|
|
157
|
+
interface MemoryStoreOptions {
|
|
158
|
+
paths: WstackPaths;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Three scopes:
|
|
162
|
+
* project-agents → <project>/.wrongstack/AGENTS.md (committed)
|
|
163
|
+
* project-memory → ~/.wrongstack/projects/<hash>/memory.md (per-project agent notes)
|
|
164
|
+
* user-memory → ~/.wrongstack/memory.md (global personal memory)
|
|
165
|
+
*/
|
|
166
|
+
declare class DefaultMemoryStore implements MemoryStore {
|
|
167
|
+
private readonly files;
|
|
168
|
+
constructor(opts: MemoryStoreOptions);
|
|
169
|
+
readAll(): Promise<string>;
|
|
170
|
+
read(scope: MemoryScope): Promise<string>;
|
|
171
|
+
remember(text: string, scope?: MemoryScope): Promise<void>;
|
|
172
|
+
forget(query: string, scope?: MemoryScope): Promise<number>;
|
|
173
|
+
consolidate(scope: MemoryScope): Promise<void>;
|
|
174
|
+
clear(scope?: MemoryScope): Promise<void>;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
declare class DefaultSecretScrubber implements SecretScrubber {
|
|
178
|
+
scrub(text: string): string;
|
|
179
|
+
scrubObject<T>(obj: T): T;
|
|
180
|
+
}
|
|
181
|
+
|
|
261
182
|
interface SecretVaultOptions {
|
|
262
183
|
/** Absolute path to the key file. Created with mode 0o600 if missing. */
|
|
263
184
|
keyFile: string;
|
|
@@ -302,26 +223,6 @@ declare function migratePlaintextSecrets(configPath: string, vault: SecretVault)
|
|
|
302
223
|
file: string;
|
|
303
224
|
}>;
|
|
304
225
|
|
|
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
226
|
interface PermissionPolicyOptions {
|
|
326
227
|
trustFile: string;
|
|
327
228
|
yolo?: boolean;
|
|
@@ -345,6 +246,34 @@ declare class DefaultPermissionPolicy implements PermissionPolicy {
|
|
|
345
246
|
private findNamespaceEntry;
|
|
346
247
|
}
|
|
347
248
|
|
|
249
|
+
declare class DefaultRetryPolicy implements RetryPolicy {
|
|
250
|
+
shouldRetry(err: Error | ProviderError, attempt: number): boolean;
|
|
251
|
+
maxAttempts(err: Error | ProviderError): number;
|
|
252
|
+
delayMs(attempt: number): number;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Tiered error recovery strategies.
|
|
257
|
+
* Each strategy is attempted in order until one succeeds.
|
|
258
|
+
*/
|
|
259
|
+
interface RecoveryStrategy {
|
|
260
|
+
/** Human-readable label for logs. */
|
|
261
|
+
label: string;
|
|
262
|
+
/** Optional compactor for context_overflow recovery. */
|
|
263
|
+
compactor?: Compactor;
|
|
264
|
+
/** Returns a substitute Response, or null to fall through to the next strategy. */
|
|
265
|
+
attempt: (err: unknown, ctx: Context) => Promise<Response | null>;
|
|
266
|
+
}
|
|
267
|
+
declare class DefaultErrorHandler implements ErrorHandler {
|
|
268
|
+
private readonly strategies;
|
|
269
|
+
constructor(strategies?: RecoveryStrategy[]);
|
|
270
|
+
classify(err: unknown): {
|
|
271
|
+
kind: 'rate_limit' | 'overloaded' | 'server' | 'client' | 'network' | 'abort' | 'context_overflow' | 'unknown';
|
|
272
|
+
retryable: boolean;
|
|
273
|
+
};
|
|
274
|
+
recover(err: unknown, ctx: Context): Promise<Response | null>;
|
|
275
|
+
}
|
|
276
|
+
|
|
348
277
|
interface SkillLoaderOptions {
|
|
349
278
|
paths: WstackPaths;
|
|
350
279
|
bundledDir?: string;
|
|
@@ -404,6 +333,114 @@ declare class DefaultConfigLoader implements ConfigLoader {
|
|
|
404
333
|
private validateIdentity;
|
|
405
334
|
}
|
|
406
335
|
|
|
336
|
+
/**
|
|
337
|
+
* Reference implementation of `ConfigStore`. Stores a single frozen Config
|
|
338
|
+
* and notifies watchers synchronously on every update. Updates use a deep
|
|
339
|
+
* clone so callers can mutate their `partial` argument freely without
|
|
340
|
+
* tainting state.
|
|
341
|
+
*
|
|
342
|
+
* For the CLI: instantiate once at boot, pass the store (not the Config)
|
|
343
|
+
* to subsystems that care about runtime changes (provider switching,
|
|
344
|
+
* extension reload).
|
|
345
|
+
*/
|
|
346
|
+
declare class DefaultConfigStore implements ConfigStore {
|
|
347
|
+
private current;
|
|
348
|
+
private watchers;
|
|
349
|
+
constructor(initial: Config);
|
|
350
|
+
get(): Readonly<Config>;
|
|
351
|
+
getSection<K extends keyof Config>(key: K): Readonly<Config[K]>;
|
|
352
|
+
getExtension(pluginName: string): Readonly<Record<string, unknown>>;
|
|
353
|
+
update(partial: Partial<Config>): Readonly<Config>;
|
|
354
|
+
watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* L2-D: Config version migration framework. Pure functions, decoupled
|
|
359
|
+
* from disk/CLI — caller passes a parsed JSON object and gets back the
|
|
360
|
+
* up-to-date `Config` shape (or a structured error explaining why
|
|
361
|
+
* migration failed).
|
|
362
|
+
*
|
|
363
|
+
* Migrations are registered as `{ from, to, migrate }` triples and run
|
|
364
|
+
* sequentially. Each migration is independently testable. Adding a new
|
|
365
|
+
* version means appending one migration; existing user configs are
|
|
366
|
+
* upgraded in place at load time.
|
|
367
|
+
*/
|
|
368
|
+
interface MigrationContext {
|
|
369
|
+
/**
|
|
370
|
+
* Original on-disk version of the input. Migrations may use this to
|
|
371
|
+
* decide between in-place patches and rewrites.
|
|
372
|
+
*/
|
|
373
|
+
fromVersion: number;
|
|
374
|
+
/**
|
|
375
|
+
* Set when the migration writes back to disk. Callers persist the
|
|
376
|
+
* migrated config when this is true so the user doesn't see the same
|
|
377
|
+
* migration banner on every boot.
|
|
378
|
+
*/
|
|
379
|
+
shouldPersist: boolean;
|
|
380
|
+
}
|
|
381
|
+
interface ConfigMigration {
|
|
382
|
+
/** Version of the input this migration accepts. */
|
|
383
|
+
from: number;
|
|
384
|
+
/** Version of the output it produces. */
|
|
385
|
+
to: number;
|
|
386
|
+
/** Pure transform — no I/O. */
|
|
387
|
+
migrate(input: Record<string, unknown>, ctx: MigrationContext): Record<string, unknown>;
|
|
388
|
+
/** Optional human-readable description for migration logs / banners. */
|
|
389
|
+
describe?: string;
|
|
390
|
+
}
|
|
391
|
+
interface MigrationResult {
|
|
392
|
+
/** Final config (still typed as `unknown`-keyed — caller validates). */
|
|
393
|
+
config: Record<string, unknown>;
|
|
394
|
+
/** Ordered list of `from→to` versions that ran. */
|
|
395
|
+
applied: string[];
|
|
396
|
+
/** True when at least one migration produced changes worth persisting. */
|
|
397
|
+
shouldPersist: boolean;
|
|
398
|
+
}
|
|
399
|
+
declare class ConfigMigrationError extends Error {
|
|
400
|
+
readonly fromVersion: number;
|
|
401
|
+
readonly targetVersion: number;
|
|
402
|
+
readonly missingStep: number | null;
|
|
403
|
+
constructor(opts: {
|
|
404
|
+
message: string;
|
|
405
|
+
fromVersion: number;
|
|
406
|
+
targetVersion: number;
|
|
407
|
+
missingStep: number | null;
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Run registered migrations until the input reaches `targetVersion`.
|
|
412
|
+
*
|
|
413
|
+
* Resolution rules:
|
|
414
|
+
* 1. If `input.version === targetVersion`, no migrations run; `shouldPersist`
|
|
415
|
+
* is false.
|
|
416
|
+
* 2. Otherwise walk the migration chain from `input.version` upward,
|
|
417
|
+
* picking the migration whose `from` matches the current version.
|
|
418
|
+
* 3. Stop when `current.version === targetVersion`.
|
|
419
|
+
* 4. If no migration matches at some point, throw `ConfigMigrationError`
|
|
420
|
+
* with the missing step recorded for diagnostics.
|
|
421
|
+
*
|
|
422
|
+
* Migrations may be downward (e.g. for staged rollouts), but `targetVersion`
|
|
423
|
+
* must be reachable strictly via the registered chain — there's no implicit
|
|
424
|
+
* "skip" or transitive resolution.
|
|
425
|
+
*/
|
|
426
|
+
declare function runConfigMigrations(input: Record<string, unknown>, targetVersion: number, migrations: readonly ConfigMigration[]): MigrationResult;
|
|
427
|
+
/**
|
|
428
|
+
* Default empty migration registry. Real migrations are appended as new
|
|
429
|
+
* Config versions are introduced. Example (when v2 lands):
|
|
430
|
+
*
|
|
431
|
+
* export const CONFIG_MIGRATIONS: readonly ConfigMigration[] = [
|
|
432
|
+
* {
|
|
433
|
+
* from: 1, to: 2, describe: 'rename `apiKey` → `auth.apiKey`',
|
|
434
|
+
* migrate(cfg) {
|
|
435
|
+
* const apiKey = cfg.apiKey;
|
|
436
|
+
* delete cfg.apiKey;
|
|
437
|
+
* return { ...cfg, auth: { ...(cfg.auth ?? {}), apiKey } };
|
|
438
|
+
* },
|
|
439
|
+
* },
|
|
440
|
+
* ];
|
|
441
|
+
*/
|
|
442
|
+
declare const DEFAULT_CONFIG_MIGRATIONS: readonly ConfigMigration[];
|
|
443
|
+
|
|
407
444
|
interface CompactorOptions {
|
|
408
445
|
preserveK?: number;
|
|
409
446
|
eliseThreshold?: number;
|
|
@@ -480,7 +517,6 @@ declare class IntelligentCompactor implements Compactor {
|
|
|
480
517
|
private eliseOldToolResults;
|
|
481
518
|
private hasTextContent;
|
|
482
519
|
private estimateTokens;
|
|
483
|
-
private roughTokenEstimate;
|
|
484
520
|
}
|
|
485
521
|
|
|
486
522
|
/**
|
|
@@ -732,37 +768,104 @@ interface ModeLoaderOptions {
|
|
|
732
768
|
declare function loadProjectModes(modesDir: string): Promise<Mode[]>;
|
|
733
769
|
declare function loadUserModes(modesDir: string): Promise<Mode[]>;
|
|
734
770
|
|
|
771
|
+
interface MultiAgentCoordinatorOptions {
|
|
772
|
+
/**
|
|
773
|
+
* Callback that executes a task on behalf of a subagent. Required for
|
|
774
|
+
* `assign()` to actually run anything — without it, tasks queue forever.
|
|
775
|
+
* The coordinator provides per-subagent isolation (own budget, own signal,
|
|
776
|
+
* own bridge) and enforces timeout + concurrency.
|
|
777
|
+
*/
|
|
778
|
+
runner?: SubagentRunner;
|
|
779
|
+
}
|
|
735
780
|
declare class DefaultMultiAgentCoordinator extends EventEmitter implements MultiAgentCoordinator {
|
|
736
781
|
readonly coordinatorId: string;
|
|
737
782
|
readonly config: MultiAgentConfig;
|
|
783
|
+
private readonly runner?;
|
|
738
784
|
private readonly subagents;
|
|
739
785
|
private pendingTasks;
|
|
740
786
|
private completedResults;
|
|
741
787
|
private totalIterations;
|
|
742
|
-
|
|
788
|
+
private inFlight;
|
|
789
|
+
constructor(config: MultiAgentConfig, options?: MultiAgentCoordinatorOptions);
|
|
743
790
|
spawn(subagent: SubagentConfig): Promise<SpawnResult>;
|
|
744
791
|
assign(task: TaskSpec): Promise<void>;
|
|
745
792
|
delegate(to: string, msg: BridgeMessage): Promise<void>;
|
|
746
793
|
/**
|
|
747
|
-
* Wire up the communication bridge for a subagent. Call
|
|
748
|
-
*
|
|
794
|
+
* Wire up the communication bridge for a subagent. Call after spawn() once
|
|
795
|
+
* the caller has created the bidirectional connection.
|
|
749
796
|
*/
|
|
750
797
|
setSubagentBridge(subagentId: string, bridge: AgentBridge): void;
|
|
751
798
|
stop(subagentId: string): Promise<void>;
|
|
752
799
|
stopAll(): Promise<void>;
|
|
753
800
|
getStatus(): CoordinatorStatus;
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
801
|
+
/** Expose snapshot of completed results — useful for callers awaiting all done. */
|
|
802
|
+
results(): readonly TaskResult[];
|
|
803
|
+
/**
|
|
804
|
+
* Manual completion — for callers that drive subagents without a runner
|
|
805
|
+
* (e.g. external orchestrators). When a runner is configured the coordinator
|
|
806
|
+
* calls this itself.
|
|
807
|
+
*/
|
|
757
808
|
completeTask(result: TaskResult): void;
|
|
809
|
+
private tryDispatchNext;
|
|
810
|
+
private canDispatch;
|
|
811
|
+
private findIdleSubagent;
|
|
812
|
+
private runDispatched;
|
|
813
|
+
private executeWithTimeout;
|
|
814
|
+
private recordCompletion;
|
|
815
|
+
private isDone;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Caller-supplied factory that builds an isolated `Agent` for a subagent.
|
|
820
|
+
* The factory MUST construct a fresh `Context` per call — sharing context
|
|
821
|
+
* between subagents defeats isolation. Each Agent should also use either
|
|
822
|
+
* its own `EventBus` or a forwarded view, so per-subagent metrics can be
|
|
823
|
+
* attributed correctly.
|
|
824
|
+
*/
|
|
825
|
+
type AgentFactory = (config: SubagentConfig) => Promise<AgentFactoryResult>;
|
|
826
|
+
interface AgentFactoryResult {
|
|
827
|
+
agent: Agent;
|
|
828
|
+
/** Event bus the factory wired to this agent — required for budget hookup. */
|
|
829
|
+
events: EventBus;
|
|
758
830
|
}
|
|
831
|
+
interface AgentRunnerOptions {
|
|
832
|
+
factory: AgentFactory;
|
|
833
|
+
/**
|
|
834
|
+
* Format a TaskSpec into the user input the agent will receive. Defaults
|
|
835
|
+
* to `task.description ?? ''`. Override when subagents expect structured
|
|
836
|
+
* input (e.g. JSON contracts, role-prefixed prompts).
|
|
837
|
+
*/
|
|
838
|
+
formatTaskInput?: (task: TaskSpec, config: SubagentConfig) => AgentInput;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Builds a `SubagentRunner` that drives a real `Agent` per task while honoring
|
|
842
|
+
* the coordinator's budget and abort signal. This is the production adapter —
|
|
843
|
+
* the coordinator's `runner` option in CLI/TUI assemblies points here.
|
|
844
|
+
*
|
|
845
|
+
* Lifecycle per task:
|
|
846
|
+
* 1. factory(config) → fresh Agent + EventBus.
|
|
847
|
+
* 2. Subscribe to events to feed the budget (tool calls, token usage).
|
|
848
|
+
* 3. Call agent.run(input, { signal }) — the coordinator's signal cancels.
|
|
849
|
+
* 4. Map RunResult.status onto a `SubagentRunOutcome` or throw on failure.
|
|
850
|
+
* 5. Unsubscribe and let the factory's resources be GC'd.
|
|
851
|
+
*
|
|
852
|
+
* The budget is checked synchronously from event handlers — a runaway agent
|
|
853
|
+
* that crosses its tool-call limit triggers `BudgetExceededError`, which the
|
|
854
|
+
* coordinator surfaces as `status: 'failed'` on the task result.
|
|
855
|
+
*/
|
|
856
|
+
declare function makeAgentSubagentRunner(opts: AgentRunnerOptions): SubagentRunner;
|
|
759
857
|
|
|
858
|
+
/**
|
|
859
|
+
* In-memory pub/sub transport for agent-to-agent messaging.
|
|
860
|
+
* Subscribers register by agentId and receive messages via callback.
|
|
861
|
+
*/
|
|
760
862
|
declare class InMemoryBridgeTransport implements BridgeTransport {
|
|
761
|
-
private subs;
|
|
863
|
+
private readonly subs;
|
|
762
864
|
send(msg: BridgeMessage, to: string): Promise<void>;
|
|
763
865
|
subscribe(agentId: string, handler: (msg: BridgeMessage) => void): () => void;
|
|
764
866
|
close(agentId: string): Promise<void>;
|
|
765
867
|
}
|
|
868
|
+
|
|
766
869
|
declare class InMemoryAgentBridge implements AgentBridge {
|
|
767
870
|
readonly agentId: string;
|
|
768
871
|
readonly coordinatorId: string;
|
|
@@ -1015,6 +1118,79 @@ declare class SpecDrivenDev {
|
|
|
1015
1118
|
}[];
|
|
1016
1119
|
}
|
|
1017
1120
|
|
|
1121
|
+
/**
|
|
1122
|
+
* Per-project lockfile used for crash detection. The CLI writes one of
|
|
1123
|
+
* these alongside the session JSONLs (`<projectSessions>/active.json`)
|
|
1124
|
+
* when an interactive run starts, and deletes it on clean exit. If we
|
|
1125
|
+
* find one on the next launch whose owning PID is dead (or whose host
|
|
1126
|
+
* doesn't match), we know the previous run was killed mid-flight and
|
|
1127
|
+
* the session it was writing to is a recovery candidate.
|
|
1128
|
+
*
|
|
1129
|
+
* The lockfile is intentionally per-project (already isolated by
|
|
1130
|
+
* `wpaths.projectSessions`), so two TUIs in two different repos do not
|
|
1131
|
+
* fight each other.
|
|
1132
|
+
*/
|
|
1133
|
+
interface RecoveryLockOptions {
|
|
1134
|
+
/** Directory the lockfile lives in. Usually `wpaths.projectSessions`. */
|
|
1135
|
+
dir: string;
|
|
1136
|
+
/** This process's PID. Default: `process.pid`. */
|
|
1137
|
+
pid?: number;
|
|
1138
|
+
/** Hostname recorded for the lock. Default: `os.hostname()`. */
|
|
1139
|
+
hostname?: string;
|
|
1140
|
+
/** Locks older than this are considered orphaned (disk wiped, etc.). Default 24h. */
|
|
1141
|
+
maxAgeMs?: number;
|
|
1142
|
+
/** Used to check whether the abandoned session was actually closed cleanly. */
|
|
1143
|
+
sessionStore?: SessionStore;
|
|
1144
|
+
/**
|
|
1145
|
+
* Override the PID-liveness probe. Default: `process.kill(pid, 0)` —
|
|
1146
|
+
* succeeds (or throws EPERM) when the PID is alive, throws ESRCH when
|
|
1147
|
+
* it is gone. Tests inject a deterministic stub.
|
|
1148
|
+
*/
|
|
1149
|
+
isPidAlive?: (pid: number) => boolean;
|
|
1150
|
+
}
|
|
1151
|
+
interface AbandonedSession {
|
|
1152
|
+
sessionId: string;
|
|
1153
|
+
pid: number;
|
|
1154
|
+
startedAt: string;
|
|
1155
|
+
/** Lockfile age in ms at the time of the check. */
|
|
1156
|
+
ageMs: number;
|
|
1157
|
+
/** Number of messages already on disk for this session. */
|
|
1158
|
+
messageCount: number;
|
|
1159
|
+
}
|
|
1160
|
+
declare class RecoveryLock {
|
|
1161
|
+
private readonly file;
|
|
1162
|
+
private readonly pid;
|
|
1163
|
+
private readonly hostname;
|
|
1164
|
+
private readonly maxAgeMs;
|
|
1165
|
+
private readonly sessionStore?;
|
|
1166
|
+
private readonly probe;
|
|
1167
|
+
constructor(opts: RecoveryLockOptions);
|
|
1168
|
+
/**
|
|
1169
|
+
* Examine the lockfile and decide whether it represents an abandoned
|
|
1170
|
+
* session. Returns `null` if the file is missing, points to a live
|
|
1171
|
+
* instance, references a clean-closed session, is too old, or is
|
|
1172
|
+
* malformed. Otherwise returns enough detail to prompt the user.
|
|
1173
|
+
*
|
|
1174
|
+
* Important: this is a read-only check. We never delete an active
|
|
1175
|
+
* lock from here — if another wstack instance is alive, the caller
|
|
1176
|
+
* should bail or run with a fresh session instead.
|
|
1177
|
+
*/
|
|
1178
|
+
checkAbandoned(): Promise<AbandonedSession | null>;
|
|
1179
|
+
/**
|
|
1180
|
+
* Claim the lock for the given session. Overwrites any existing lock
|
|
1181
|
+
* — the caller should have already handled abandonment (via
|
|
1182
|
+
* `checkAbandoned`) before calling this.
|
|
1183
|
+
*/
|
|
1184
|
+
write(sessionId: string): Promise<void>;
|
|
1185
|
+
/**
|
|
1186
|
+
* Release the lock. Idempotent — silently succeeds if the file is
|
|
1187
|
+
* already gone (e.g. someone else cleared it, or the directory was
|
|
1188
|
+
* wiped).
|
|
1189
|
+
*/
|
|
1190
|
+
clear(): Promise<void>;
|
|
1191
|
+
private readLock;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1018
1194
|
declare class ToolExecutor {
|
|
1019
1195
|
private readonly registry;
|
|
1020
1196
|
private readonly opts;
|
|
@@ -1037,11 +1213,377 @@ declare class ToolExecutor {
|
|
|
1037
1213
|
*/
|
|
1038
1214
|
executeTool(tool: Tool, use: ToolUseBlock, ctx: Context, budget: number): Promise<ToolResultBlock>;
|
|
1039
1215
|
private runWithTimeout;
|
|
1216
|
+
private runStreamedTool;
|
|
1040
1217
|
private unknownToolResult;
|
|
1041
1218
|
private deniedResult;
|
|
1042
|
-
private
|
|
1219
|
+
private decrementBudget;
|
|
1220
|
+
/**
|
|
1221
|
+
* Compute the suggestedPattern string for a tool+input pair.
|
|
1222
|
+
* Matches the logic in DefaultPermissionPolicy so the TUI shows the
|
|
1223
|
+
* same subject that the trust file would use.
|
|
1224
|
+
*/
|
|
1225
|
+
private subjectFor;
|
|
1043
1226
|
}
|
|
1044
1227
|
|
|
1228
|
+
/**
|
|
1229
|
+
* L2-A: read-only view over a `SessionStore` with query, replay, search,
|
|
1230
|
+
* and export helpers. Implemented on top of the public `SessionStore`
|
|
1231
|
+
* surface so any concrete store can be inspected without re-implementation.
|
|
1232
|
+
*
|
|
1233
|
+
* The heavy operations re-parse the JSONL stream on every call — fine for
|
|
1234
|
+
* /resume and one-off analytics. Wrap with a memoizing decorator if needed.
|
|
1235
|
+
*/
|
|
1236
|
+
declare class DefaultSessionReader implements SessionReader {
|
|
1237
|
+
private readonly store;
|
|
1238
|
+
constructor(opts: DefaultSessionReaderOptions);
|
|
1239
|
+
query(q?: SessionQuery): Promise<SessionSummaryLite[]>;
|
|
1240
|
+
replay(sessionId: string): AsyncIterable<SessionEvent>;
|
|
1241
|
+
search(q: SessionSearchQuery, sessionId?: string): Promise<SessionSearchHit[]>;
|
|
1242
|
+
export(sessionId: string, opts: SessionExportOptions): Promise<string>;
|
|
1243
|
+
metadata(sessionId: string): Promise<SessionMetadata>;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* In-memory metrics sink. Suitable for embedded use, tests, and /metrics
|
|
1248
|
+
* scrape over HTTP. For production push-based pipelines, write an adapter
|
|
1249
|
+
* that implements MetricsSink and forwards to OTLP/StatsD/Prometheus.
|
|
1250
|
+
*/
|
|
1251
|
+
declare class InMemoryMetricsSink implements MetricsSink {
|
|
1252
|
+
private counters;
|
|
1253
|
+
private gauges;
|
|
1254
|
+
private histograms;
|
|
1255
|
+
counter(name: string, value?: number, labels?: MetricLabels): void;
|
|
1256
|
+
gauge(name: string, value: number, labels?: MetricLabels): void;
|
|
1257
|
+
histogram(name: string, value: number, labels?: MetricLabels): void;
|
|
1258
|
+
snapshot(): MetricsSnapshot;
|
|
1259
|
+
reset(): void;
|
|
1260
|
+
private getOrCreate;
|
|
1261
|
+
}
|
|
1262
|
+
/** Cheap noop sink — drop-in default when observability is not configured. */
|
|
1263
|
+
declare class NoopMetricsSink implements MetricsSink {
|
|
1264
|
+
counter(): void;
|
|
1265
|
+
gauge(): void;
|
|
1266
|
+
histogram(): void;
|
|
1267
|
+
snapshot(): MetricsSnapshot;
|
|
1268
|
+
reset(): void;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
/**
|
|
1272
|
+
* Aggregates registered health checks. Worst status wins — one unhealthy check
|
|
1273
|
+
* makes the whole system unhealthy. Use timeouts so a slow probe can't stall
|
|
1274
|
+
* the response.
|
|
1275
|
+
*/
|
|
1276
|
+
declare class DefaultHealthRegistry implements HealthRegistry {
|
|
1277
|
+
private checks;
|
|
1278
|
+
private readonly timeoutMs;
|
|
1279
|
+
constructor(opts?: {
|
|
1280
|
+
timeoutMs?: number;
|
|
1281
|
+
});
|
|
1282
|
+
register(check: HealthCheck): void;
|
|
1283
|
+
unregister(name: string): void;
|
|
1284
|
+
run(): Promise<AggregateHealth>;
|
|
1285
|
+
private runOne;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
* Default tracer is a noop — zero overhead when observability is not wired up.
|
|
1290
|
+
* Replace at runtime with an OpenTelemetry-backed Tracer to enable real spans.
|
|
1291
|
+
*/
|
|
1292
|
+
declare class NoopTracer implements Tracer {
|
|
1293
|
+
startSpan(): Span;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
/**
|
|
1297
|
+
* Lightweight OTel adapter. Doesn't pull in `@opentelemetry/api` directly —
|
|
1298
|
+
* the user passes their already-initialized OTel Tracer through, and this
|
|
1299
|
+
* wrapper translates our minimal Span surface onto theirs.
|
|
1300
|
+
*
|
|
1301
|
+
* Usage:
|
|
1302
|
+
* import { trace } from '@opentelemetry/api';
|
|
1303
|
+
* const tracer = trace.getTracer('wrongstack', '1.0');
|
|
1304
|
+
* const wrappedTracer = new OTelTracer(tracer);
|
|
1305
|
+
* // pass `wrappedTracer` as Agent.tracer / ToolExecutor.tracer.
|
|
1306
|
+
*
|
|
1307
|
+
* The shape of the upstream Tracer is intentionally typed loosely so we
|
|
1308
|
+
* don't need a build-time dependency. Anything OTel-compatible works,
|
|
1309
|
+
* including OpenInference, Tempo, etc.
|
|
1310
|
+
*/
|
|
1311
|
+
|
|
1312
|
+
interface OTelLikeSpan {
|
|
1313
|
+
setAttribute(key: string, value: string | number | boolean): unknown;
|
|
1314
|
+
recordException(err: {
|
|
1315
|
+
message: string;
|
|
1316
|
+
stack?: string;
|
|
1317
|
+
name?: string;
|
|
1318
|
+
}): unknown;
|
|
1319
|
+
setStatus?(status: {
|
|
1320
|
+
code: number;
|
|
1321
|
+
message?: string;
|
|
1322
|
+
}): unknown;
|
|
1323
|
+
end(): unknown;
|
|
1324
|
+
}
|
|
1325
|
+
interface OTelLikeTracer {
|
|
1326
|
+
startSpan(name: string, options?: {
|
|
1327
|
+
attributes?: Record<string, string | number | boolean>;
|
|
1328
|
+
}): OTelLikeSpan;
|
|
1329
|
+
}
|
|
1330
|
+
declare class OTelTracer implements Tracer {
|
|
1331
|
+
private readonly upstream;
|
|
1332
|
+
constructor(upstream: OTelLikeTracer);
|
|
1333
|
+
startSpan(name: string, attrs?: Record<string, string | number | boolean>): Span;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
/**
|
|
1337
|
+
* Subscribes a MetricsSink to the EventBus. Returns an unsubscribe function
|
|
1338
|
+
* that detaches all listeners. This is the single integration point between
|
|
1339
|
+
* the agent's event stream and the observability layer — no metric calls
|
|
1340
|
+
* leak into core call sites.
|
|
1341
|
+
*/
|
|
1342
|
+
declare function wireMetricsToEvents(events: EventBus, sink: MetricsSink): () => void;
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* Render a `MetricsSnapshot` as Prometheus text-format bytes. The output
|
|
1346
|
+
* always ends with a trailing newline (Prometheus requires it).
|
|
1347
|
+
*/
|
|
1348
|
+
declare function renderPrometheus(snapshot: MetricsSnapshot): string;
|
|
1349
|
+
/** MIME type Prometheus servers must respond with on /metrics. */
|
|
1350
|
+
declare const PROMETHEUS_CONTENT_TYPE = "text/plain; version=0.0.4; charset=utf-8";
|
|
1351
|
+
interface MetricsServerOptions {
|
|
1352
|
+
port: number;
|
|
1353
|
+
/** Bind address. Defaults to 127.0.0.1 so we don't accidentally expose metrics publicly. */
|
|
1354
|
+
host?: string;
|
|
1355
|
+
sink: MetricsSink;
|
|
1356
|
+
/** Path to serve on. Defaults to /metrics. */
|
|
1357
|
+
path?: string;
|
|
1358
|
+
/**
|
|
1359
|
+
* V2-C: optional health registry. When provided, the server also responds
|
|
1360
|
+
* on `/healthz` (configurable via `healthPath`) with a JSON aggregate of
|
|
1361
|
+
* every registered health check. K8s probes expect a single HTTP server
|
|
1362
|
+
* exposing both `/metrics` and `/healthz`, so we mount them on the same
|
|
1363
|
+
* port rather than opening a sibling listener.
|
|
1364
|
+
*/
|
|
1365
|
+
healthRegistry?: HealthRegistry;
|
|
1366
|
+
/** Path to serve health JSON on. Defaults to /healthz. */
|
|
1367
|
+
healthPath?: string;
|
|
1368
|
+
}
|
|
1369
|
+
interface MetricsServerHandle {
|
|
1370
|
+
port: number;
|
|
1371
|
+
url: string;
|
|
1372
|
+
close(): Promise<void>;
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Start an HTTP server that exposes a Prometheus scrape endpoint.
|
|
1376
|
+
* Uses node:http directly to avoid pulling a framework into the core graph.
|
|
1377
|
+
*
|
|
1378
|
+
* Why bind to 127.0.0.1 by default: telemetry endpoints inside an agent
|
|
1379
|
+
* process can leak prompt content via metric labels (tool name, error
|
|
1380
|
+
* message, etc.). The default keeps that on the loopback interface;
|
|
1381
|
+
* operators who want network scraping opt in explicitly with host: '0.0.0.0'.
|
|
1382
|
+
*/
|
|
1383
|
+
declare function startMetricsServer(opts: MetricsServerOptions): Promise<MetricsServerHandle>;
|
|
1384
|
+
|
|
1385
|
+
/**
|
|
1386
|
+
* V2-A: OTLP/JSON metrics push exporter.
|
|
1387
|
+
*
|
|
1388
|
+
* Periodically POSTs `MetricsSink.snapshot()` to an OTLP HTTP receiver
|
|
1389
|
+
* (the OpenTelemetry Collector, vendor agents like Honeycomb, Datadog,
|
|
1390
|
+
* Grafana Cloud, etc.). The wire format is OTLP/JSON v1.0 — covered by
|
|
1391
|
+
* the spec at github.com/open-telemetry/opentelemetry-proto.
|
|
1392
|
+
*
|
|
1393
|
+
* Why no `@opentelemetry/*` dep: the core graph is intentionally
|
|
1394
|
+
* dependency-free. The JSON shape is well-defined and stable; bringing
|
|
1395
|
+
* in the official SDK would add ~3MB and pin us to its release cadence.
|
|
1396
|
+
* Operators who need the OTLP gRPC transport or vendor-specific quirks
|
|
1397
|
+
* can wrap an `@opentelemetry/exporter-metrics-otlp-grpc` in a custom
|
|
1398
|
+
* `MetricsSink` instead — the seam exists.
|
|
1399
|
+
*/
|
|
1400
|
+
interface OtlpMetricsExporterOptions {
|
|
1401
|
+
/** Source of metric data. The exporter reads `snapshot()` per interval. */
|
|
1402
|
+
sink: MetricsSink;
|
|
1403
|
+
/**
|
|
1404
|
+
* OTLP HTTP endpoint base URL. Path `/v1/metrics` is appended unless
|
|
1405
|
+
* the URL already ends with `/v1/metrics` (idempotent).
|
|
1406
|
+
* Example: `http://otel-collector:4318` or `https://otlp.example.com`.
|
|
1407
|
+
*/
|
|
1408
|
+
endpoint: string;
|
|
1409
|
+
/** Push interval in milliseconds. Defaults to 30s (Prometheus default). */
|
|
1410
|
+
intervalMs?: number;
|
|
1411
|
+
/** Optional bearer token / API key (sent as `Authorization`). */
|
|
1412
|
+
authorization?: string;
|
|
1413
|
+
/** Extra request headers (vendor-specific keys go here). */
|
|
1414
|
+
headers?: Record<string, string>;
|
|
1415
|
+
/** Resource attributes attached to every export. Defaults: `service.name=wrongstack`. */
|
|
1416
|
+
resourceAttributes?: Record<string, string>;
|
|
1417
|
+
/** Instrumentation scope. Default: `wrongstack`. */
|
|
1418
|
+
scopeName?: string;
|
|
1419
|
+
/** Per-request timeout. Defaults to 10s. */
|
|
1420
|
+
timeoutMs?: number;
|
|
1421
|
+
/** Override fetch (for tests). Defaults to global `fetch`. */
|
|
1422
|
+
fetchImpl?: typeof globalThis.fetch;
|
|
1423
|
+
/** Called when a push fails. Defaults to silent (telemetry must never crash the host). */
|
|
1424
|
+
onError?: (err: unknown) => void;
|
|
1425
|
+
}
|
|
1426
|
+
interface OtlpMetricsExporterHandle {
|
|
1427
|
+
/** Push immediately (in addition to the scheduled interval). */
|
|
1428
|
+
flush(): Promise<void>;
|
|
1429
|
+
/** Stop the timer, attempt a final flush, then resolve. */
|
|
1430
|
+
stop(): Promise<void>;
|
|
1431
|
+
}
|
|
1432
|
+
interface OtlpAttribute$1 {
|
|
1433
|
+
key: string;
|
|
1434
|
+
value: {
|
|
1435
|
+
stringValue: string;
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
interface OtlpDataPoint {
|
|
1439
|
+
attributes: OtlpAttribute$1[];
|
|
1440
|
+
timeUnixNano: string;
|
|
1441
|
+
asDouble?: number;
|
|
1442
|
+
asInt?: string;
|
|
1443
|
+
count?: string;
|
|
1444
|
+
sum?: number;
|
|
1445
|
+
quantileValues?: {
|
|
1446
|
+
quantile: number;
|
|
1447
|
+
value: number;
|
|
1448
|
+
}[];
|
|
1449
|
+
}
|
|
1450
|
+
interface OtlpMetric {
|
|
1451
|
+
name: string;
|
|
1452
|
+
description?: string;
|
|
1453
|
+
unit?: string;
|
|
1454
|
+
sum?: {
|
|
1455
|
+
dataPoints: OtlpDataPoint[];
|
|
1456
|
+
aggregationTemporality: 2;
|
|
1457
|
+
isMonotonic: true;
|
|
1458
|
+
};
|
|
1459
|
+
gauge?: {
|
|
1460
|
+
dataPoints: OtlpDataPoint[];
|
|
1461
|
+
};
|
|
1462
|
+
summary?: {
|
|
1463
|
+
dataPoints: OtlpDataPoint[];
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
interface OtlpExportRequest {
|
|
1467
|
+
resourceMetrics: {
|
|
1468
|
+
resource: {
|
|
1469
|
+
attributes: OtlpAttribute$1[];
|
|
1470
|
+
};
|
|
1471
|
+
scopeMetrics: {
|
|
1472
|
+
scope: {
|
|
1473
|
+
name: string;
|
|
1474
|
+
version?: string;
|
|
1475
|
+
};
|
|
1476
|
+
metrics: OtlpMetric[];
|
|
1477
|
+
}[];
|
|
1478
|
+
}[];
|
|
1479
|
+
}
|
|
1480
|
+
/**
|
|
1481
|
+
* Build the OTLP/JSON export body from a sink snapshot. Exported for tests
|
|
1482
|
+
* and for callers that want to ship via their own transport.
|
|
1483
|
+
*/
|
|
1484
|
+
declare function buildOtlpMetricsRequest(sink: MetricsSink, opts?: {
|
|
1485
|
+
resourceAttributes?: Record<string, string>;
|
|
1486
|
+
scopeName?: string;
|
|
1487
|
+
}): OtlpExportRequest;
|
|
1488
|
+
/**
|
|
1489
|
+
* Start pushing metrics to an OTLP HTTP receiver. Returns a handle with
|
|
1490
|
+
* `flush()` and `stop()`.
|
|
1491
|
+
*/
|
|
1492
|
+
declare function startOtlpMetricsExporter(opts: OtlpMetricsExporterOptions): OtlpMetricsExporterHandle;
|
|
1493
|
+
|
|
1494
|
+
type SpanAttrValue = string | number | boolean;
|
|
1495
|
+
interface RecordedSpan {
|
|
1496
|
+
traceId: string;
|
|
1497
|
+
spanId: string;
|
|
1498
|
+
name: string;
|
|
1499
|
+
startTimeUnixNano: bigint;
|
|
1500
|
+
endTimeUnixNano?: bigint;
|
|
1501
|
+
attributes: Record<string, SpanAttrValue>;
|
|
1502
|
+
status: {
|
|
1503
|
+
code: number;
|
|
1504
|
+
message?: string;
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
interface OtlpTraceExporterOptions {
|
|
1508
|
+
/** OTLP HTTP endpoint base URL. `/v1/traces` is appended unless already present. */
|
|
1509
|
+
endpoint: string;
|
|
1510
|
+
/** Push interval in milliseconds. Defaults to 5s (traces are bursty). */
|
|
1511
|
+
intervalMs?: number;
|
|
1512
|
+
/** Hard cap on buffered spans. When exceeded, oldest are dropped. Defaults to 2048. */
|
|
1513
|
+
maxBufferedSpans?: number;
|
|
1514
|
+
/** Authorization header. */
|
|
1515
|
+
authorization?: string;
|
|
1516
|
+
/** Extra request headers. */
|
|
1517
|
+
headers?: Record<string, string>;
|
|
1518
|
+
/** Resource attributes. Defaults to `service.name=wrongstack`. */
|
|
1519
|
+
resourceAttributes?: Record<string, string>;
|
|
1520
|
+
/** Instrumentation scope name. Default `wrongstack`. */
|
|
1521
|
+
scopeName?: string;
|
|
1522
|
+
/** Per-request timeout in ms. Default 10s. */
|
|
1523
|
+
timeoutMs?: number;
|
|
1524
|
+
/** Override fetch (for tests). */
|
|
1525
|
+
fetchImpl?: typeof globalThis.fetch;
|
|
1526
|
+
/** Called on push failure. Defaults to silent. */
|
|
1527
|
+
onError?: (err: unknown) => void;
|
|
1528
|
+
}
|
|
1529
|
+
interface OtlpTraceExporterHandle {
|
|
1530
|
+
/** The Tracer to install on Agent / ToolExecutor. */
|
|
1531
|
+
readonly tracer: Tracer;
|
|
1532
|
+
/** Push buffered spans immediately. */
|
|
1533
|
+
flush(): Promise<void>;
|
|
1534
|
+
/** Stop the timer, push remaining spans, resolve. */
|
|
1535
|
+
stop(): Promise<void>;
|
|
1536
|
+
/** Test helper: snapshot of spans currently in the buffer (not yet pushed). */
|
|
1537
|
+
readonly buffered: () => readonly RecordedSpan[];
|
|
1538
|
+
}
|
|
1539
|
+
interface OtlpAttribute {
|
|
1540
|
+
key: string;
|
|
1541
|
+
value: {
|
|
1542
|
+
stringValue: string;
|
|
1543
|
+
} | {
|
|
1544
|
+
boolValue: boolean;
|
|
1545
|
+
} | {
|
|
1546
|
+
doubleValue: number;
|
|
1547
|
+
} | {
|
|
1548
|
+
intValue: string;
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
interface OtlpSpan {
|
|
1552
|
+
traceId: string;
|
|
1553
|
+
spanId: string;
|
|
1554
|
+
name: string;
|
|
1555
|
+
kind: 1;
|
|
1556
|
+
startTimeUnixNano: string;
|
|
1557
|
+
endTimeUnixNano: string;
|
|
1558
|
+
attributes: OtlpAttribute[];
|
|
1559
|
+
status: {
|
|
1560
|
+
code: number;
|
|
1561
|
+
message?: string;
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
interface OtlpTracesRequest {
|
|
1565
|
+
resourceSpans: {
|
|
1566
|
+
resource: {
|
|
1567
|
+
attributes: OtlpAttribute[];
|
|
1568
|
+
};
|
|
1569
|
+
scopeSpans: {
|
|
1570
|
+
scope: {
|
|
1571
|
+
name: string;
|
|
1572
|
+
};
|
|
1573
|
+
spans: OtlpSpan[];
|
|
1574
|
+
}[];
|
|
1575
|
+
}[];
|
|
1576
|
+
}
|
|
1577
|
+
declare function buildOtlpTracesRequest(spans: readonly RecordedSpan[], opts?: {
|
|
1578
|
+
resourceAttributes?: Record<string, string>;
|
|
1579
|
+
scopeName?: string;
|
|
1580
|
+
}): OtlpTracesRequest;
|
|
1581
|
+
/**
|
|
1582
|
+
* Start the OTLP trace exporter. Returns a `Tracer` to install on the
|
|
1583
|
+
* runtime (`Agent.run` etc.) and `flush()`/`stop()` controls.
|
|
1584
|
+
*/
|
|
1585
|
+
declare function startOtlpTraceExporter(opts: OtlpTraceExporterOptions): OtlpTraceExporterHandle;
|
|
1586
|
+
|
|
1045
1587
|
type ContextManagerAction = 'check' | 'summary' | 'prune' | 'add_note' | 'compact';
|
|
1046
1588
|
interface ContextManagerInput {
|
|
1047
1589
|
action: ContextManagerAction;
|
|
@@ -1079,4 +1621,62 @@ declare function createContextManagerTool(opts?: ContextManagerToolOptions): Too
|
|
|
1079
1621
|
/** Pre-built instance with no compactor — compact action will return an error. */
|
|
1080
1622
|
declare const contextManagerTool: Tool<ContextManagerInput, ContextManagerResult>;
|
|
1081
1623
|
|
|
1082
|
-
|
|
1624
|
+
/**
|
|
1625
|
+
* Built-in MCP server presets available to all WrongStack users out of the box.
|
|
1626
|
+
* These servers must be explicitly enabled in config (disabled by default).
|
|
1627
|
+
*
|
|
1628
|
+
* To enable: set `mcpServers: { serverName: { enabled: true } }` in your config.
|
|
1629
|
+
*
|
|
1630
|
+
* Some servers require environment variables or additional config — see notes below.
|
|
1631
|
+
*
|
|
1632
|
+
* Transport types:
|
|
1633
|
+
* stdio — spawns a local npm package binary via child_process
|
|
1634
|
+
* sse — HTTP SSE endpoint (client POSTs requests)
|
|
1635
|
+
* streamable-http — session-based HTTP with NDJSON responses
|
|
1636
|
+
*/
|
|
1637
|
+
/** Filesystem access: read, write, list, search, tree. Good for exploring projects. */
|
|
1638
|
+
declare const filesystemServer: () => MCPServerConfig;
|
|
1639
|
+
/** GitHub API: issues, PRs, repos, search, file operations. Requires GITHUB_PERSONAL_ACCESS_TOKEN. */
|
|
1640
|
+
declare const githubServer: () => MCPServerConfig;
|
|
1641
|
+
/**
|
|
1642
|
+
* Context7 — codebase-aware documentation and Q&A using context from your code.
|
|
1643
|
+
* Live documentation for any library, grounded in your actual versions.
|
|
1644
|
+
*/
|
|
1645
|
+
declare const context7Server: () => MCPServerConfig;
|
|
1646
|
+
/**
|
|
1647
|
+
* Brave Search — web search via Brave Browser's API.
|
|
1648
|
+
* Requires BRAVE_SEARCH_API_KEY. Free tier: 2,000 queries/month.
|
|
1649
|
+
* Sign up at https://api.search.brave.com/
|
|
1650
|
+
*/
|
|
1651
|
+
declare const braveSearchServer: () => MCPServerConfig;
|
|
1652
|
+
/**
|
|
1653
|
+
* Block (Block, Inc.) — Postgres database access via SQL.
|
|
1654
|
+
* Useful for running queries against a connected database during development.
|
|
1655
|
+
*/
|
|
1656
|
+
declare const blockServer: () => MCPServerConfig;
|
|
1657
|
+
/**
|
|
1658
|
+
* EverArt — AI image generation via various providers.
|
|
1659
|
+
* Requires EVERART_API_KEY.
|
|
1660
|
+
*/
|
|
1661
|
+
declare const everArtServer: () => MCPServerConfig;
|
|
1662
|
+
/**
|
|
1663
|
+
* Slack — messaging, channels, search.
|
|
1664
|
+
* Requires SLACK_BOT_TOKEN and either SLACK_TEAM_ID or SLACK_USER_TOKEN.
|
|
1665
|
+
*/
|
|
1666
|
+
declare const slackServer: () => MCPServerConfig;
|
|
1667
|
+
/**
|
|
1668
|
+
* AWS knowledge base — EC2, S3, Lambda, IAM, CloudFormation, cost management.
|
|
1669
|
+
* Requires AWS access key + secret in environment.
|
|
1670
|
+
*/
|
|
1671
|
+
declare const awsServer: () => MCPServerConfig;
|
|
1672
|
+
/**
|
|
1673
|
+
* Google Maps — directions, distance matrix, geocoding, places.
|
|
1674
|
+
* Requires GOOGLE_MAPS_API_KEY.
|
|
1675
|
+
*/
|
|
1676
|
+
declare const googleMapsServer: () => MCPServerConfig;
|
|
1677
|
+
/** Sentinel — security vulnerability scanning (sentinel-labs). */
|
|
1678
|
+
declare const sentinelServer: () => MCPServerConfig;
|
|
1679
|
+
/** Everything bundled — full set of built-in servers. Useful for `wstack mcp add --all`. */
|
|
1680
|
+
declare const allServers: () => Record<string, MCPServerConfig>;
|
|
1681
|
+
|
|
1682
|
+
export { type AbandonedSession, type AgentFactory, type AgentFactoryResult, type AgentRunnerOptions, type AttachmentStoreOptions, AutoCompactionMiddleware, AutonomousRunner, type AutonomousRunnerOptions, type CompactorOptions, type ConfigLoaderOptions, type ConfigMigration, ConfigMigrationError, type ConfigSource, type ContextManagerAction, type ContextManagerInput, type ContextManagerResult, type ContextManagerToolOptions, DEFAULT_CONFIG_MIGRATIONS, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, type DefaultLoggerOptions, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, type DefaultModelsRegistryOptions, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultTaskStore, DefaultTokenCounter, type DoneCheckResult, DoneConditionChecker, type GeneratedTask, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, IntelligentCompactor, type IntelligentCompactorOptions, LLMSelector, type LLMSelectorOptions, type MemoryStoreOptions, type MetricsServerHandle, type MetricsServerOptions, type MigrationContext, type MigrationResult, type ModeLoaderOptions, type MultiAgentCoordinatorOptions, NoopMetricsSink, NoopTracer, OTelTracer, type OtlpMetricsExporterHandle, type OtlpMetricsExporterOptions, type OtlpTraceExporterHandle, type OtlpTraceExporterOptions, PROMETHEUS_CONTENT_TYPE, 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, allServers, awsServer, blockServer, braveSearchServer, buildOtlpMetricsRequest, buildOtlpTracesRequest, classifyFamily, context7Server, contextManagerTool, createContextManagerTool, createMessage, decryptConfigSecrets, encryptConfigSecrets, everArtServer, filesystemServer, githubServer, googleMapsServer, loadProjectModes, loadUserModes, makeAgentSubagentRunner, migratePlaintextSecrets, renderPrometheus, rewriteConfigEncrypted, runConfigMigrations, sentinelServer, slackServer, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, wireMetricsToEvents };
|