@wrongstack/core 0.63.4 → 0.68.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.
Files changed (57) hide show
  1. package/dist/{agent-bridge-B5rxWrg3.d.ts → agent-bridge-D-j6OOBT.d.ts} +1 -1
  2. package/dist/agent-subagent-runner-DRZ9-NnR.d.ts +1042 -0
  3. package/dist/{compactor-0vjZ8KTk.d.ts → compactor-D_ExJajC.d.ts} +1 -1
  4. package/dist/{config-BdDuaZmB.d.ts → config--86aHSln.d.ts} +1 -1
  5. package/dist/{context-iFMEO2rN.d.ts → context-y87Jc5ei.d.ts} +3 -3
  6. package/dist/coordination/index.d.ts +12 -12
  7. package/dist/coordination/index.js +265 -275
  8. package/dist/coordination/index.js.map +1 -1
  9. package/dist/defaults/index.d.ts +22 -22
  10. package/dist/defaults/index.js +181 -180
  11. package/dist/defaults/index.js.map +1 -1
  12. package/dist/{events-k8CHjcrN.d.ts → events-CIplI98R.d.ts} +1 -1
  13. package/dist/execution/index.d.ts +16 -385
  14. package/dist/execution/index.js +124 -146
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/extension/index.d.ts +6 -6
  17. package/dist/goal-store-C7jcumEh.d.ts +96 -0
  18. package/dist/{index-Bc6BiP5q.d.ts → index-DKUvyTvV.d.ts} +28 -442
  19. package/dist/{index-CWdW_CJt.d.ts → index-b5uhfTSl.d.ts} +8 -8
  20. package/dist/index.d.ts +34 -32
  21. package/dist/index.js +692 -750
  22. package/dist/index.js.map +1 -1
  23. package/dist/infrastructure/index.d.ts +6 -6
  24. package/dist/kernel/index.d.ts +9 -9
  25. package/dist/{mcp-servers-CwqQDMYy.d.ts → mcp-servers-DwoNBf6r.d.ts} +3 -3
  26. package/dist/models/index.d.ts +2 -2
  27. package/dist/{multi-agent-coordinator-CNUJYq7U.d.ts → multi-agent-coordinator-CWnH-CiX.d.ts} +10 -2
  28. package/dist/{null-fleet-bus-DRoJ0uOY.d.ts → null-fleet-bus-CuN0ObJr.d.ts} +24 -31
  29. package/dist/observability/index.d.ts +2 -2
  30. package/dist/parallel-eternal-engine-0UwotoSx.d.ts +483 -0
  31. package/dist/{path-resolver-C5sPVne8.d.ts → path-resolver-DVkEcIw8.d.ts} +2 -2
  32. package/dist/{permission-Ld-i5ugf.d.ts → permission-C1A5whY5.d.ts} +5 -1
  33. package/dist/{permission-policy-CL-mPufp.d.ts → permission-policy-B2dK-T5N.d.ts} +19 -5
  34. package/dist/{plan-templates-ThBHOjaM.d.ts → plan-templates-Bprrzhbu.d.ts} +4 -4
  35. package/dist/{provider-runner-DJQa211J.d.ts → provider-runner-mXvXGSIw.d.ts} +3 -3
  36. package/dist/{retry-policy-BfBScewS.d.ts → retry-policy-CG3qvH_e.d.ts} +1 -1
  37. package/dist/sdd/index.d.ts +8 -8
  38. package/dist/sdd/index.js +123 -146
  39. package/dist/sdd/index.js.map +1 -1
  40. package/dist/security/index.d.ts +3 -3
  41. package/dist/security/index.js +31 -22
  42. package/dist/security/index.js.map +1 -1
  43. package/dist/{selector-DxhW7ML3.d.ts → selector-RvBR_YRW.d.ts} +1 -1
  44. package/dist/session-event-bridge-CDHxcmQU.d.ts +93 -0
  45. package/dist/{session-reader-q2ThszgG.d.ts → session-reader-BIpwM60D.d.ts} +1 -1
  46. package/dist/storage/index.d.ts +7 -6
  47. package/dist/{system-prompt-7LHyBbIf.d.ts → system-prompt-b61lOd49.d.ts} +2 -2
  48. package/dist/types/index.d.ts +23 -14
  49. package/dist/types/index.js.map +1 -1
  50. package/dist/utils/index.d.ts +2 -2
  51. package/dist/utils/index.js.map +1 -1
  52. package/package.json +1 -1
  53. package/skills/multi-agent/SKILL.md +0 -2
  54. package/dist/agent-subagent-runner-Zc3f37Sg.d.ts +0 -182
  55. package/dist/goal-store-iHltMi5n.d.ts +0 -188
  56. package/dist/multi-agent-SASYOrWA.d.ts +0 -554
  57. package/dist/tool-executor-CIjpGaRA.d.ts +0 -111
@@ -1,10 +1,10 @@
1
- export { A as AfterIterationHook, a as AfterRunHook, b as AfterToolExecutionHook, d as AgentExtension, B as BeforeIterationHook, h as BeforeRunHook, i as BeforeToolExecutionHook, E as ExtensionRegistry, O as OnErrorHook, w as ProviderRunnerFn, x as ProviderRunnerWrapper } from '../index-Bc6BiP5q.js';
2
- import '../context-iFMEO2rN.js';
1
+ export { A as AfterIterationHook, a as AfterRunHook, b as AfterToolExecutionHook, c as AgentExtension, B as BeforeIterationHook, g as BeforeRunHook, h as BeforeToolExecutionHook, E as ExtensionRegistry, O as OnErrorHook, n as ProviderRunnerFn, o as ProviderRunnerWrapper } from '../index-DKUvyTvV.js';
2
+ import '../context-y87Jc5ei.js';
3
3
  import '../logger-DDd5C--Z.js';
4
- import '../system-prompt-7LHyBbIf.js';
5
- import '../config-BdDuaZmB.js';
4
+ import '../system-prompt-b61lOd49.js';
5
+ import '../config--86aHSln.js';
6
6
  import '../models-registry-BcYJDKLm.js';
7
7
  import '../observability-BhnVLBLS.js';
8
- import '../events-k8CHjcrN.js';
8
+ import '../events-CIplI98R.js';
9
9
  import '../secret-scrubber-3MHDDAtm.js';
10
- import '../permission-Ld-i5ugf.js';
10
+ import '../permission-C1A5whY5.js';
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Long-running autonomous mission. A goal survives across sessions and
3
+ * drives the EternalAutonomyEngine — every iteration of the engine
4
+ * consults the goal to choose what to do next.
5
+ *
6
+ * Storage: `~/.wrongstack/projects/<hash>/goal.json`. Persistent and
7
+ * project-scoped on purpose: the goal belongs to the codebase, not the
8
+ * REPL session.
9
+ */
10
+ interface JournalEntry {
11
+ /** ISO timestamp of the iteration. */
12
+ at: string;
13
+ /** Sequential iteration counter (1-based, monotonically increasing). */
14
+ iteration: number;
15
+ /** Source that produced the action ('todo' | 'git' | 'brainstorm' | 'resume' | 'manual' | 'parallel'). */
16
+ source: 'todo' | 'git' | 'brainstorm' | 'resume' | 'manual' | 'parallel';
17
+ /** Short one-line description of what the iteration set out to do. */
18
+ task: string;
19
+ /** Outcome status. */
20
+ status: 'success' | 'failure' | 'aborted' | 'skipped';
21
+ /** Optional free-form note (error message, summary, etc.). */
22
+ note?: string;
23
+ /** Optional token usage delta for this iteration. */
24
+ tokens?: {
25
+ input: number;
26
+ output: number;
27
+ };
28
+ /** Optional USD cost delta for this iteration (provider-estimated). */
29
+ costUsd?: number;
30
+ }
31
+ interface GoalFile {
32
+ version: 1;
33
+ /** The mission statement. */
34
+ goal: string;
35
+ /** When the goal was first set or last replaced. */
36
+ setAt: string;
37
+ /** Updated on every iteration completion. */
38
+ lastActivityAt: string;
39
+ /** Total iterations the engine has run against this goal (cumulative). */
40
+ iterations: number;
41
+ /** Engine lifecycle state — 'running' means another process owns this goal. */
42
+ engineState: 'idle' | 'running' | 'stopped';
43
+ /**
44
+ * Mission-level lifecycle. `active` is the default; `completed` is set
45
+ * when the engine detects `[GOAL_COMPLETE]` in a successful iteration's
46
+ * final text AND a verification pass agrees; `abandoned` is set by the
47
+ * user (e.g. `/goal abandon`) or when the engine exceeds a configured
48
+ * failure ceiling. Once not `active`, the engine refuses to run further
49
+ * iterations against this goal — protects against accidental restarts
50
+ * burning through API quota after the work is done.
51
+ *
52
+ * Optional for backward compatibility — pre-existing `goal.json` files
53
+ * without this field load as `active`.
54
+ */
55
+ goalState?: 'active' | 'paused' | 'completed' | 'abandoned';
56
+ /**
57
+ * Per-todo attempt counter. Keyed by TodoItem id. Used by the engine
58
+ * to skip a todo that has failed N times rather than spinning on it
59
+ * forever. Persisted so attempt counts survive restarts (`/autonomy
60
+ * stop` + resume should not reset progress against a stuck task).
61
+ */
62
+ todoAttempts?: Record<string, number>;
63
+ /** Bounded ring buffer of recent iterations (newest last). */
64
+ journal: JournalEntry[];
65
+ }
66
+ /** Cap on persisted journal entries — older entries are evicted FIFO. */
67
+ declare const MAX_JOURNAL_ENTRIES = 500;
68
+ /**
69
+ * Resolve the goal file path for a given project root.
70
+ * Exposed so the engine and CLI use one canonical path.
71
+ * Uses `~/.wrongstack/projects/<hash>/goal.json` .<hash>/`.
72
+ */
73
+ declare function goalFilePath(projectRoot: string): string;
74
+ declare function loadGoal(filePath: string): Promise<GoalFile | null>;
75
+ declare function saveGoal(filePath: string, goal: GoalFile): Promise<void>;
76
+ declare function emptyGoal(goal: string): GoalFile;
77
+ /**
78
+ * Append a journal entry, bumping iteration counters and trimming the
79
+ * ring buffer. Returns a new GoalFile — does not mutate the argument.
80
+ */
81
+ declare function appendJournal(goal: GoalFile, entry: Omit<JournalEntry, 'iteration' | 'at'>): GoalFile;
82
+ /**
83
+ * Aggregate cumulative cost + tokens across all journal entries. Entries
84
+ * without telemetry are skipped (legacy entries from before the field
85
+ * was added still load cleanly).
86
+ */
87
+ declare function summarizeUsage(goal: GoalFile): {
88
+ totalCostUsd: number;
89
+ totalInputTokens: number;
90
+ totalOutputTokens: number;
91
+ iterationsWithUsage: number;
92
+ };
93
+ /** Format the goal + recent journal as a human-readable status block. */
94
+ declare function formatGoal(goal: GoalFile, journalLimit?: number): string;
95
+
96
+ export { type GoalFile as G, type JournalEntry as J, MAX_JOURNAL_ENTRIES as M, appendJournal as a, summarizeUsage as b, emptyGoal as e, formatGoal as f, goalFilePath as g, loadGoal as l, saveGoal as s };
@@ -1,13 +1,31 @@
1
- import { Q as Tool, Y as ToolResultBlock, _ as ToolUseBlock, d as Context, T as TextBlock, p as Request, q as Response, m as Provider, a0 as WrongStackError, c as ContentBlock, u as RunOptions, J as JSONSchema } from './context-iFMEO2rN.js';
1
+ import { T as TextBlock, Q as Tool, Y as ToolResultBlock, _ as ToolUseBlock, d as Context, p as Request, q as Response, m as Provider, a0 as WrongStackError, c as ContentBlock } from './context-y87Jc5ei.js';
2
2
  import { a as Logger } from './logger-DDd5C--Z.js';
3
- import { H as HookRegistry, e as Renderer, a as BuildContext, C as Container, P as Pipeline, R as ReadonlyPipeline } from './system-prompt-7LHyBbIf.js';
4
- import { l as HookEvent, r as ProviderConfig, n as HookMatcher, I as InProcessHook, a as Config } from './config-BdDuaZmB.js';
3
+ import { a as BuildContext, H as HookRegistry, e as Renderer, P as Pipeline, C as Container } from './system-prompt-b61lOd49.js';
4
+ import { l as HookEvent, r as ProviderConfig } from './config--86aHSln.js';
5
5
  import { T as Tracer } from './observability-BhnVLBLS.js';
6
- import { E as EventBus, k as EventName, L as Listener } from './events-k8CHjcrN.js';
6
+ import { E as EventBus } from './events-CIplI98R.js';
7
7
  import { S as SecretScrubber } from './secret-scrubber-3MHDDAtm.js';
8
- import { a as PermissionPolicy } from './permission-Ld-i5ugf.js';
8
+ import { a as PermissionPolicy } from './permission-C1A5whY5.js';
9
9
  import { W as WireFamily } from './models-registry-BcYJDKLm.js';
10
10
 
11
+ /**
12
+ * A contributor that injects additional TextBlocks into the system prompt.
13
+ *
14
+ * Contributors are called on every `build()` in registration order.
15
+ * Their output is inserted after the core blocks (identity, tool usage,
16
+ * environment) but before the mode and plan blocks. This lets plugins
17
+ * inject ephemeral context — current state, recent events, plugin-specific
18
+ * instructions — without replacing the entire system prompt builder.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * api.extensions.registerSystemPromptContributor(async (ctx) => {
23
+ * return [{ type: 'text', text: '## My Plugin Context\n...' }];
24
+ * });
25
+ * ```
26
+ */
27
+ type SystemPromptContributor = (ctx: BuildContext) => Promise<TextBlock[]>;
28
+
11
29
  /**
12
30
  * A function that wraps (decorates) an existing tool. Receives the
13
31
  * original tool and returns a modified version — typically the same
@@ -243,24 +261,6 @@ interface ToolExecutorLike {
243
261
  executeTool(tool: Tool, use: ToolUseBlock, ctx: Context, budget: number): Promise<ToolResultBlock>;
244
262
  }
245
263
 
246
- /**
247
- * A contributor that injects additional TextBlocks into the system prompt.
248
- *
249
- * Contributors are called on every `build()` in registration order.
250
- * Their output is inserted after the core blocks (identity, tool usage,
251
- * environment) but before the mode and plan blocks. This lets plugins
252
- * inject ephemeral context — current state, recent events, plugin-specific
253
- * instructions — without replacing the entire system prompt builder.
254
- *
255
- * @example
256
- * ```ts
257
- * api.extensions.registerSystemPromptContributor(async (ctx) => {
258
- * return [{ type: 'text', text: '## My Plugin Context\n...' }];
259
- * });
260
- * ```
261
- */
262
- type SystemPromptContributor = (ctx: BuildContext) => Promise<TextBlock[]>;
263
-
264
264
  /**
265
265
  * Extension points for the Agent lifecycle.
266
266
  *
@@ -467,7 +467,7 @@ declare class ExtensionRegistry {
467
467
  * the returned instance. The `type` is the registry key (e.g. a
468
468
  * provider's models.dev id or a user-chosen alias).
469
469
  */
470
- interface ProviderFactory$1 {
470
+ interface ProviderFactory {
471
471
  /**
472
472
  * Unique identifier used as the registry key. When registered via
473
473
  * a plugin, this becomes `cfg.type` in `ProviderRegistry.create(cfg)`.
@@ -488,17 +488,17 @@ declare class ProviderRegistry {
488
488
  * exists, it is replaced. Use this for both initial registration and
489
489
  * runtime overrides (e.g. from plugins or CLI flags).
490
490
  */
491
- register(f: ProviderFactory$1): void;
491
+ register(f: ProviderFactory): void;
492
492
  /**
493
493
  * Bulk-register multiple provider factories at once.
494
494
  */
495
- registerAll(factories: ProviderFactory$1[]): void;
495
+ registerAll(factories: ProviderFactory[]): void;
496
496
  /**
497
497
  * Override an existing factory. Throws if no factory is registered
498
498
  * for the given type. Use this to safely replace a provider at runtime
499
499
  * (e.g. in tests or when a plugin provides a custom implementation).
500
500
  */
501
- override(type: string, f: ProviderFactory$1): void;
501
+ override(type: string, f: ProviderFactory): void;
502
502
  has(type: string): boolean;
503
503
  create(cfg: ProviderConfig): Provider;
504
504
  list(): string[];
@@ -508,22 +508,9 @@ declare class ProviderRegistry {
508
508
  declare const DEFAULT_MAX_ITERATIONS = 100;
509
509
  interface RunResult {
510
510
  status: 'done' | 'failed' | 'max_iterations' | 'aborted';
511
- /**
512
- * Set when `status === 'failed'` (always) or `'aborted'` (when the abort
513
- * carried an error context). Always a `WrongStackError` so callers can
514
- * branch on `code`, `severity`, and `recoverable` without parsing strings.
515
- * Raw throws are wrapped into an `AgentError` with code `AGENT_RUN_FAILED`
516
- * by `Agent.run` before they reach this field.
517
- */
518
511
  error?: WrongStackError;
519
512
  finalText?: string;
520
513
  iterations: number;
521
- /**
522
- * Subagent delegate summaries collected during the run. Populated by the
523
- * `delegate` tool — each entry is the `summary` + `ok` fields returned
524
- * when a subagent finishes. Callers (e.g. TUI/CLI renderer) use this to
525
- * surface flashy completion banners in the terminal.
526
- */
527
514
  delegateSummaries?: Array<{
528
515
  summary: string;
529
516
  ok: boolean;
@@ -540,58 +527,12 @@ interface AgentInit {
540
527
  iterationTimeoutMs?: number;
541
528
  executionStrategy?: 'parallel' | 'sequential' | 'smart';
542
529
  perIterationOutputCapBytes?: number;
543
- /**
544
- * When true (default), the agent automatically extends its iteration
545
- * limit by 100 when hit, without asking the user. Set to false to
546
- * emit `iteration.limit_reached` and wait for a listener to grant/deny.
547
- */
548
530
  autoExtendLimit?: boolean;
549
- /**
550
- * When true, the agent supports autonomous continuation — the model
551
- * can signal "keep going" either via the `continue_to_next_iteration()`
552
- * tool or by placing a `[continue]` / `[next step]` / `[proceed]` /
553
- * `[done]` marker on its own line in the final text output. The agent
554
- * loop re-runs without returning to the caller when `continue` is
555
- * signalled, or exits with `status: 'done'` when `stop` is signalled.
556
- *
557
- * The text-marker parser runs in `processResponse()` before the
558
- * loop-exit check so markers in the final text block are honoured
559
- * even when no tool was called.
560
- */
561
531
  autonomousContinue?: boolean;
562
- /**
563
- * Optional confirm handler. When set, the executor calls it synchronously
564
- * when a tool needs user confirmation (CLI path). When omitted, the
565
- * executor returns a `ToolConfirmPendingResult` and the agent emits
566
- * `tool.confirm_needed` for the TUI to resolve.
567
- */
568
532
  confirmAwaiter?: ConfirmAwaiter | undefined;
569
- /**
570
- * Override the PermissionPolicy resolved from the container. Subagents
571
- * use this to force auto-approval — they cannot respond to interactive
572
- * permission prompts, so inheriting the leader's non-YOLO policy would
573
- * silently hang the entire delegated run on the first tool call.
574
- */
575
533
  permissionPolicy?: PermissionPolicy;
576
- /**
577
- * Optional tracer. When provided, `Agent.run` opens an `agent.run` span,
578
- * per-iteration `agent.iteration` spans, and `provider.complete` spans
579
- * inside the retry loop. Tool spans are opened by the ToolExecutor.
580
- * Default is `NoopTracer` (zero overhead).
581
- */
582
534
  tracer?: Tracer | undefined;
583
- /**
584
- * Optional extension registry. Plugins and host applications register
585
- * extensions here to hook into the agent lifecycle (beforeRun, afterRun,
586
- * beforeIteration, onError, wrapProviderRunner, etc.).
587
- * When not provided, the agent creates an empty registry internally —
588
- * no overhead, zero breakage.
589
- */
590
535
  extensions?: ExtensionRegistry | undefined;
591
- /**
592
- * Mandatory tool executor. Callers (e.g. CLI wiring) inject a pre-built
593
- * instance so `core/` does not need a runtime import of `execution/`.
594
- */
595
536
  toolExecutor: ToolExecutorLike;
596
537
  }
597
538
  interface AgentPipelines {
@@ -604,7 +545,6 @@ interface AgentPipelines {
604
545
  }
605
546
  interface UserInputPayload {
606
547
  content: ContentBlock[];
607
- /** Concatenation of text blocks — convenience for middleware that only cares about text. */
608
548
  text: string;
609
549
  ctx: Context;
610
550
  }
@@ -613,362 +553,8 @@ interface ToolCallPipelinePayload {
613
553
  toolUse: ToolUseBlock;
614
554
  result: ToolResultBlock;
615
555
  ctx: Context;
616
- /** Undefined when the model invoked a tool name we don't know. */
617
556
  tool?: Tool;
618
557
  }
619
558
  declare function createDefaultPipelines(): AgentPipelines;
620
- declare class Agent {
621
- readonly container: Container;
622
- readonly tools: ToolRegistry;
623
- readonly providers: ProviderRegistry;
624
- readonly events: EventBus;
625
- readonly pipelines: AgentPipelines;
626
- readonly ctx: Context;
627
- private readonly maxIterations;
628
- private readonly executionStrategy;
629
- private readonly perIterationOutputCapBytes;
630
- private readonly plugins;
631
- private readonly toolExecutor;
632
- private readonly autoExtendLimit;
633
- /** Enables autonomous continue: model can signal `[continue]` or call continue_to_next_iteration() to re-run. */
634
- private readonly autonomousContinue;
635
- private readonly tracer;
636
- readonly extensions: ExtensionRegistry;
637
- constructor(init: AgentInit);
638
- private get logger();
639
- private get retry();
640
- private get errorHandler();
641
- private get permission();
642
- private get renderer();
643
- /**
644
- * Switch from inline CLI prompts to event-driven confirmation.
645
- * Clears both the ToolExecutor's confirmAwaiter (so it returns
646
- * `ToolConfirmPendingResult`) and the permission policy's
647
- * promptDelegate (so `evaluate()` returns `confirm`).
648
- *
649
- * Call this before entering TUI or any mode where stdin is owned
650
- * by a UI framework (Ink, WebUI WS bridge). Without this, the
651
- * inline prompt writes to stdout and blocks on stdin — both of
652
- * which are owned by the framework — making the prompt invisible
653
- * and the input deadlocked.
654
- */
655
- disableInteractiveConfirmation(): void;
656
- register(tool: Tool): void;
657
- use(plugin: Plugin, api: PluginAPI): Promise<void>;
658
- /** Tear down all plugins in reverse order, calling their teardown hooks. */
659
- teardown(): Promise<void>;
660
- run(userInput: AgentInput, opts?: RunOptions): Promise<RunResult>;
661
- private runInner;
662
- /**
663
- * Check if iteration limit has been reached and request extension if needed.
664
- * Returns the new effective limit (possibly extended) and a RunResult if
665
- * the loop should exit. Returns `{ limit }` with no result when the
666
- * iteration may proceed.
667
- */
668
- private checkIterationLimit;
669
- /**
670
- * Build request and run through request pipeline.
671
- */
672
- private buildAndRunRequestPipeline;
673
- /**
674
- * Process the provider response: run response pipeline, emit events,
675
- * update session, render text, handle abort.
676
- */
677
- private processResponse;
678
- /**
679
- * Execute tools and append tool results to context.
680
- * When a tool returns `tool_confirm_pending` (no confirmAwaiter set),
681
- * we pause and emit `tool.confirm_needed`. The run is blocked until
682
- * the event listener resolves the confirmation, then we re-run the
683
- * single tool.
684
- */
685
- private executeTools;
686
- /**
687
- * Fold any pending `/btw` notes into the conversation. Called at the top of
688
- * each iteration so a note set mid-run reaches the model on its next turn.
689
- *
690
- * To stay valid across all provider wire families we never create two
691
- * consecutive user messages: if the last message is a user turn (e.g. the
692
- * tool_result block from the previous iteration) we append the note as an
693
- * extra text block on that turn; otherwise we add a fresh user message.
694
- */
695
- private injectPendingBtwNotes;
696
- private waitForConfirm;
697
- private executeSingleWithDecision;
698
- /**
699
- * Run context window pipeline. The pipeline may be empty, or it may contain
700
- * middleware with its own injected dependencies.
701
- */
702
- private compactContextIfNeeded;
703
- /**
704
- * Emit the current context window load as a `ctx.pct` event so subscribers
705
- * (FleetBus → TUI) can render a live fill bar per agent.
706
- */
707
- private emitContextPct;
708
- }
709
-
710
- /**
711
- * A slash command registered with the CLI or available to plugins.
712
- * Plugins receive a view of the registry via PluginAPI.slashCommands.
713
- *
714
- * Commands registered by plugins use a namespaced name: `pluginName:commandName`.
715
- * This prevents collisions with built-in commands and other plugins.
716
- */
717
- interface SlashCommand {
718
- /** Unique command name. For plugins: `pluginName:commandName`. */
719
- name: string;
720
- /** Short aliases — also prefixed automatically: `pluginName:alias`. */
721
- aliases?: string[];
722
- description: string;
723
- /**
724
- * Optional compact argument hint for interactive menus. This is not parsed
725
- * by the registry; it only helps TUI/REPL surfaces show the expected shape,
726
- * for example `[list|install <alias>|disable <name>]`.
727
- */
728
- argsHint?: string;
729
- /**
730
- * Optional detailed help shown by `/help <name>`. Use this for usage,
731
- * arguments, examples, side-effects — anything that doesn't fit in
732
- * `description`. Renders verbatim, so format with line breaks.
733
- * If absent, `/help <name>` falls back to `description`.
734
- */
735
- help?: string;
736
- /**
737
- * Execute the command.
738
- * @param args Everything after the command name (trimmed by dispatch).
739
- * @param ctx The current agent context.
740
- * @returns `{ exit: true }` to quit the REPL. `{ message }` to print and
741
- * continue. `{ runText }` to send a follow-up user-role message to the
742
- * model immediately (e.g. `/steer <text>` builds a STEERING preamble
743
- * here and asks the TUI to run it as the next turn). The TUI prints
744
- * `message` first (if any) so the user sees the slash result before
745
- * the model's response starts streaming. `{ metadata }` carries
746
- * structured data for the REPL/TUI to act on (e.g. SDD session state).
747
- */
748
- run(args: string, ctx: Context): Promise<{
749
- exit?: boolean;
750
- message?: string;
751
- runText?: string;
752
- metadata?: Record<string, unknown>;
753
- } | void>;
754
- }
755
-
756
- interface ToolRegistryView {
757
- register(t: Tool): void;
758
- unregister(name: string): void;
759
- /** Wrap (decorate) an existing tool. The wrapper gets the current tool and returns the decorated version. */
760
- wrap(name: string, wrapper: ToolWrapper): void;
761
- get(name: string): Tool | undefined;
762
- list(): Tool[];
763
- }
764
- interface ProviderFactory {
765
- type: string;
766
- family: WireFamily;
767
- create(cfg: unknown): Provider;
768
- }
769
- interface ProviderRegistryView {
770
- register(f: ProviderFactory): void;
771
- create(cfg: {
772
- type: string;
773
- } & Record<string, unknown>): Provider;
774
- list(): string[];
775
- }
776
- interface MCPRegistryView {
777
- start(cfg: unknown): Promise<void>;
778
- stop(name: string): Promise<void>;
779
- restart(name: string): Promise<void>;
780
- list(): {
781
- name: string;
782
- state: string;
783
- toolCount: number;
784
- }[];
785
- }
786
- interface SlashCommandRegistryView {
787
- register(cmd: SlashCommand): void;
788
- unregister(name: string): boolean;
789
- get(name: string): SlashCommand | undefined;
790
- list(): SlashCommand[];
791
- }
792
- /**
793
- * Read-only view of the session writer. Plugins can append custom events
794
- * to the JSONL session log and read the transcript path.
795
- *
796
- * The `append` method accepts any JSON-serializable payload — custom
797
- * event types are persisted verbatim next to the built-in events.
798
- */
799
- interface SessionWriterView {
800
- readonly transcriptPath?: string;
801
- append(event: Record<string, unknown> & {
802
- type: string;
803
- ts: string;
804
- }): Promise<void>;
805
- }
806
- /**
807
- * Metrics sink scoped to a plugin. The host auto-prefixes metric names
808
- * with `plugin.<pluginName>.` so plugins don't need to namespace
809
- * manually. Plugins call counter/histogram/gauge directly; the values
810
- * flow to the host's MetricsSink (Prometheus, OTLP, or noop).
811
- */
812
- interface MetricsSinkView {
813
- counter(name: string, value?: number, labels?: Record<string, string>): void;
814
- histogram(name: string, value: number, labels?: Record<string, string>): void;
815
- gauge(name: string, value: number, labels?: Record<string, string>): void;
816
- }
817
- interface PluginPipelines {
818
- request: ReadonlyPipeline<Request>;
819
- response: ReadonlyPipeline<Response>;
820
- toolCall: ReadonlyPipeline<ToolCallPipelinePayload>;
821
- userInput: ReadonlyPipeline<{
822
- content: ContentBlock[];
823
- text: string;
824
- ctx: Context;
825
- }>;
826
- assistantOutput: ReadonlyPipeline<TextBlock>;
827
- contextWindow: ReadonlyPipeline<Context>;
828
- [k: string]: ReadonlyPipeline<any>;
829
- }
830
- interface PluginAPI {
831
- container: Container;
832
- pipelines: PluginPipelines;
833
- events: EventBus;
834
- tools: ToolRegistryView;
835
- providers: ProviderRegistryView;
836
- mcp: MCPRegistryView;
837
- slashCommands: SlashCommandRegistryView;
838
- /** Live session writer — plugins can append custom events here. */
839
- session: SessionWriterView;
840
- /** Scoped metrics sink — counters/histograms/gauges auto-namespaced under `plugin.<name>.` */
841
- metrics: MetricsSinkView;
842
- /** Registry for agent lifecycle extensions — hooks like beforeRun, beforeIteration, onError, etc. */
843
- extensions: ExtensionRegistry;
844
- /**
845
- * Register a system prompt contributor. Plugins call this to inject
846
- * ephemeral TextBlocks into the system prompt on every build.
847
- * Returns an unregister function.
848
- */
849
- registerSystemPromptContributor(c: SystemPromptContributor): () => void;
850
- /**
851
- * Register an in-process lifecycle hook. `matcher` is a tool-name filter for
852
- * `PreToolUse`/`PostToolUse` (`"Bash"`, `"edit|write"`, `"*"`) and ignored
853
- * for other events. The hook can block, rewrite tool input, or inject extra
854
- * context — see `HookOutcome`. Automatically removed when the plugin is
855
- * uninstalled. Returns an unregister function.
856
- */
857
- registerHook(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook): () => void;
858
- config: Config;
859
- log: Logger;
860
- /**
861
- * Register a one-time event listener. The handler is automatically removed
862
- * after the first emission, or when the plugin is uninstalled — whichever
863
- * comes first.
864
- */
865
- onEvent<K extends EventName>(event: K, handler: Listener<K>): () => void;
866
- /**
867
- * Subscribe to all events matching a glob-style pattern.
868
- * `'tool.*'` matches all tool events. `'*'` matches everything.
869
- * Returns an unsubscribe function.
870
- */
871
- onPattern(pattern: string, handler: (event: string, payload: unknown) => void): () => void;
872
- /**
873
- * Emit a custom event on the agent's EventBus. Use for inter-plugin
874
- * communication or to surface plugin-specific state to the host.
875
- *
876
- * Custom events use a `pluginName:eventName` convention to avoid
877
- * collisions with built-in events (e.g. `my-plugin:cache_hit`).
878
- * The payload is passed through to all subscribers.
879
- */
880
- emitCustom(event: string, payload: unknown): void;
881
- /**
882
- * Register a callback that fires when the configuration changes at
883
- * runtime (e.g. via `/config` slash command or programmatic update).
884
- * The handler receives the new and previous config snapshots.
885
- * Returns an unsubscribe function.
886
- */
887
- onConfigChange(handler: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
888
- }
889
- /**
890
- * Capability declaration — informs the host which subsystems a plugin
891
- * intends to touch. Used for diagnostics and per-plugin enable/disable UX
892
- * (e.g. "this plugin registers tools — disable to remove them"). Not
893
- * enforced at runtime: a plugin that declares `tools: false` can still
894
- * call `api.tools.register()`, but the host can flag the discrepancy.
895
- */
896
- interface PluginCapabilities {
897
- /** Will register tools via `api.tools.register()`. */
898
- tools?: boolean;
899
- /** Will register provider factories via `api.providers.register()`. */
900
- providers?: boolean;
901
- /**
902
- * Pipelines the plugin hooks into. Use the standard names
903
- * (`request | response | toolCall | userInput | assistantOutput | contextWindow`)
904
- * or custom pipeline names exposed by other plugins.
905
- */
906
- pipelines?: string[];
907
- /** Will register slash commands via `api.slashCommands.register()`. */
908
- slashCommands?: boolean;
909
- /** Will start MCP servers via `api.mcp.start()`. */
910
- mcp?: boolean;
911
- }
912
- /**
913
- * Structured dependency declaration. The string form (`dependsOn: ['foo']`)
914
- * is shorthand for `[{ name: 'foo' }]` — both work. Use the structured form
915
- * when you need a version constraint:
916
- *
917
- * dependsOn: [{ name: 'wstack-auth', version: '^1.2.0' }]
918
- */
919
- interface PluginDependency {
920
- name: string;
921
- /** npm-style semver range. Supports `^`, `~`, exact, and unprefixed. */
922
- version?: string;
923
- }
924
- interface Plugin {
925
- name: string;
926
- version?: string;
927
- /** One-line summary for `wstack plugins list` and error messages. */
928
- description?: string;
929
- /** Semver range against the kernel API version (KERNEL_API_VERSION). */
930
- apiVersion: string;
931
- /**
932
- * Capability hints — what subsystems the plugin will register against.
933
- * Optional; provided for diagnostics and UX. The loader does not enforce
934
- * these, but mismatch is surfaced via logger at warn level.
935
- */
936
- capabilities?: PluginCapabilities;
937
- /**
938
- * JSON Schema for the options under `Config.plugins[<name>].options`.
939
- * When present, the loader validates that section before calling `setup`
940
- * and rejects the plugin with a clear error path on failure.
941
- */
942
- configSchema?: JSONSchema;
943
- /**
944
- * Mandatory plugin dependencies — loading fails if any are absent or
945
- * version-incompatible. Accepts both the legacy string-array form and
946
- * the structured form with version constraints.
947
- */
948
- dependsOn?: (string | PluginDependency)[];
949
- /** Optional plugin dependencies — silently skipped if absent. */
950
- optionalDeps?: (string | PluginDependency)[];
951
- conflictsWith?: string[];
952
- /**
953
- * Default configuration values, deep-merged under the plugin's options
954
- * key before `configSchema` validation. User-provided values take
955
- * precedence over defaults — this is a fallback, not an override.
956
- *
957
- * @example
958
- * defaultConfig: { ttl: 3600, maxSize: 100 }
959
- */
960
- defaultConfig?: Record<string, unknown>;
961
- setup(api: PluginAPI): void | Promise<void>;
962
- teardown?(api: PluginAPI): void | Promise<void>;
963
- /**
964
- * Optional health check. Called by the host (e.g. `/diag plugins` slash
965
- * command or health endpoint) to surface plugin status. Return
966
- * `{ ok: false, message: '...' }` when the plugin is degraded.
967
- */
968
- health?(): Promise<{
969
- ok: boolean;
970
- message?: string;
971
- }>;
972
- }
973
559
 
974
- export { type AfterIterationHook as A, type BeforeIterationHook as B, type SystemPromptContributor as C, DEFAULT_MAX_ITERATIONS as D, ExtensionRegistry as E, type ToolCallPipelinePayload as F, type ToolExecutorOptions as G, type HookRunEnv as H, type ToolExecutorStrategy as I, ToolRegistry as J, type ToolRegistryView as K, type ToolWrapper as L, type MCPRegistryView as M, createDefaultPipelines as N, type OnErrorHook as O, type Plugin as P, type RunResult as R, type SessionWriterView as S, type ToolBatchResult as T, type UserInputPayload as U, type AfterRunHook as a, type AfterToolExecutionHook as b, Agent as c, type AgentExtension as d, type AgentInit as e, type AgentInput as f, type AgentPipelines as g, type BeforeRunHook as h, type BeforeToolExecutionHook as i, HookRunner as j, type HookRunnerOptions as k, type MetricsSinkView as l, type PluginAPI as m, type PluginCapabilities as n, type PluginDependency as o, type PluginPipelines as p, type PreToolUseResult as q, type PromptResult as r, type ProviderFactory as s, type ProviderFactory$1 as t, ProviderRegistry as u, type ProviderRegistryView as v, type ProviderRunnerFn as w, type ProviderRunnerWrapper as x, type SlashCommand as y, type SlashCommandRegistryView as z };
560
+ export { type AfterIterationHook as A, type BeforeIterationHook as B, DEFAULT_MAX_ITERATIONS as D, ExtensionRegistry as E, type HookRunEnv as H, type OnErrorHook as O, type PreToolUseResult as P, type RunResult as R, type SystemPromptContributor as S, type ToolBatchResult as T, type UserInputPayload as U, type AfterRunHook as a, type AfterToolExecutionHook as b, type AgentExtension as c, type AgentInit as d, type AgentInput as e, type AgentPipelines as f, type BeforeRunHook as g, type BeforeToolExecutionHook as h, HookRunner as i, type HookRunnerOptions as j, type PromptResult as k, type ProviderFactory as l, ProviderRegistry as m, type ProviderRunnerFn as n, type ProviderRunnerWrapper as o, type ToolCallPipelinePayload as p, type ToolExecutorLike as q, type ToolExecutorOptions as r, type ToolExecutorStrategy as s, ToolRegistry as t, type ToolWrapper as u, createDefaultPipelines as v };