@wrongstack/core 0.275.0 → 0.276.2

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 (83) hide show
  1. package/dist/{agent-bridge-D9JkPvJ0.d.ts → agent-bridge-D7A-eu3C.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-CArSFKFl.d.ts → agent-subagent-runner-CEuw4ATz.d.ts} +16 -10
  3. package/dist/{brain-DCkB5_e7.d.ts → brain-BLOyN5ZP.d.ts} +127 -1
  4. package/dist/{compactor-CzSvxM1g.d.ts → compactor-DcBpaJsI.d.ts} +1 -1
  5. package/dist/{config-BzFRKkg7.d.ts → config-Bf5mj-ad.d.ts} +20 -2
  6. package/dist/{context-BrLe8pJy.d.ts → context-CLnUMW5g.d.ts} +40 -2
  7. package/dist/coordination/index.d.ts +43 -24
  8. package/dist/coordination/index.js +849 -648
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +28 -28
  11. package/dist/defaults/index.js +1636 -845
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +16 -16
  14. package/dist/execution/index.js +218 -49
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/execution/prompt-enhancer.d.ts +1 -1
  17. package/dist/extension/index.d.ts +7 -7
  18. package/dist/extension/index.js.map +1 -1
  19. package/dist/{global-mailbox-CXkugtNQ.d.ts → global-mailbox-Iqfkgmwu.d.ts} +3 -3
  20. package/dist/{goal-store-DUwdbdoY.d.ts → goal-store-DGb6b5Ed.d.ts} +1 -1
  21. package/dist/hq/index.d.ts +6 -6
  22. package/dist/hq/index.js +178 -75
  23. package/dist/hq/index.js.map +1 -1
  24. package/dist/{index-CtlizLTK.d.ts → index-Cn0NOshr.d.ts} +10 -5
  25. package/dist/{index-neOCEy6q.d.ts → index-L4RZN9jJ.d.ts} +2 -2
  26. package/dist/index.d.ts +56 -48
  27. package/dist/index.js +2789 -1546
  28. package/dist/index.js.map +1 -1
  29. package/dist/infrastructure/index.d.ts +6 -6
  30. package/dist/infrastructure/index.js +26 -7
  31. package/dist/infrastructure/index.js.map +1 -1
  32. package/dist/kernel/index.d.ts +20 -12
  33. package/dist/kernel/index.js +55 -9
  34. package/dist/kernel/index.js.map +1 -1
  35. package/dist/{mailbox-types-_7gaY0Rl.d.ts → mailbox-types-DTl7bRH3.d.ts} +3 -1
  36. package/dist/{mcp-servers-MLL6bMlv.d.ts → mcp-servers-CuZGf9fI.d.ts} +4 -4
  37. package/dist/models/index.d.ts +5 -5
  38. package/dist/models/index.js +223 -139
  39. package/dist/models/index.js.map +1 -1
  40. package/dist/{models-registry-CrkcxQ-g.d.ts → models-registry-8XOdxWQu.d.ts} +16 -1
  41. package/dist/{multi-agent-coordinator-Dc_HuG9p.d.ts → multi-agent-coordinator-CiRtKVTk.d.ts} +8 -1
  42. package/dist/{null-fleet-bus-BMZwMin7.d.ts → null-fleet-bus-d9G-bVy9.d.ts} +26 -22
  43. package/dist/observability/index.d.ts +2 -2
  44. package/dist/{path-resolver-uVK4BatM.d.ts → path-resolver-BhIb6mtd.d.ts} +8 -3
  45. package/dist/{permission-CJR1qfOi.d.ts → permission-BCbQDR2s.d.ts} +1 -1
  46. package/dist/{permission-policy-DLVKKk4w.d.ts → permission-policy-C0ikndX_.d.ts} +2 -18
  47. package/dist/{pipeline-BYR-Vdau.d.ts → pipeline-Dl6XbfE7.d.ts} +10 -6
  48. package/dist/{provider-model-resolve-iREK_1lG.d.ts → provider-model-resolve-B70epO19.d.ts} +3 -3
  49. package/dist/{provider-runner-i7SQXZuC.d.ts → provider-runner-DZ808MSM.d.ts} +3 -3
  50. package/dist/{retry-policy-BmY5ooh3.d.ts → retry-policy-Dt3_z8Aj.d.ts} +1 -1
  51. package/dist/sdd/index.d.ts +19 -10
  52. package/dist/sdd/index.js +411 -240
  53. package/dist/sdd/index.js.map +1 -1
  54. package/dist/{secret-vault-C9leEMzr.d.ts → secret-vault-BUJ2d1gB.d.ts} +1 -1
  55. package/dist/security/index.d.ts +5 -5
  56. package/dist/security/index.js +30 -6
  57. package/dist/security/index.js.map +1 -1
  58. package/dist/{selector-qjpee9BF.d.ts → selector-BCkWgdwy.d.ts} +1 -1
  59. package/dist/{session-event-bridge-m7y--I-H.d.ts → session-event-bridge-CMvIO59_.d.ts} +1 -1
  60. package/dist/{session-reader-BjLH4V9n.d.ts → session-reader-C8aiChUu.d.ts} +1 -1
  61. package/dist/skills/index.js +1 -0
  62. package/dist/skills/index.js.map +1 -1
  63. package/dist/storage/index.d.ts +68 -30
  64. package/dist/storage/index.js +839 -528
  65. package/dist/storage/index.js.map +1 -1
  66. package/dist/{strategy-compactor-C2bmlWYg.d.ts → strategy-compactor-DI1OHVbB.d.ts} +10 -10
  67. package/dist/{todos-checkpoint-oDS9IBNS.d.ts → todos-checkpoint-Ddd2CGr0.d.ts} +56 -9
  68. package/dist/{tool-executor-D4YdaJ-M.d.ts → tool-executor-Bmd5Ygoo.d.ts} +45 -10
  69. package/dist/tools/index.d.ts +2 -2
  70. package/dist/tools/index.js.map +1 -1
  71. package/dist/types/index.d.ts +20 -20
  72. package/dist/types/index.js +331 -98
  73. package/dist/types/index.js.map +1 -1
  74. package/dist/utils/index.d.ts +16 -3
  75. package/dist/utils/index.js +159 -83
  76. package/dist/utils/index.js.map +1 -1
  77. package/dist/{worktree-manager-A1Efnvs0.d.ts → worktree-manager-DBdl_5rs.d.ts} +4 -1
  78. package/instructions/agents/shadow-agent.md +3 -3
  79. package/instructions/coordination/director-preamble.md +3 -3
  80. package/instructions/modes/research-web.md +4 -4
  81. package/package.json +1 -1
  82. package/skills/research-web/SKILL.md +26 -26
  83. package/skills/research-web/SKILL.save.md +1 -1
@@ -1,13 +1,13 @@
1
- import { C as Context, c as Request, P as Provider } from './context-BrLe8pJy.js';
2
- import { E as EventBus } from './brain-DCkB5_e7.js';
3
- import { M as MiddlewareHandler, b as Middleware } from './pipeline-BYR-Vdau.js';
4
- import { S as SessionEventBridge } from './session-event-bridge-m7y--I-H.js';
5
- import { C as Compactor, a as CompactReport } from './compactor-CzSvxM1g.js';
6
- import { h as ContextWindowAggressiveOn, i as ContextWindowPolicy } from './config-BzFRKkg7.js';
7
- import { g as Agent, D as DoneCondition } from './agent-subagent-runner-CArSFKFl.js';
8
- import { R as RunResult, S as SystemPromptContributor, A as AgentPipelines, c as ToolCallPipelinePayload, U as UserInputPayload } from './index-CtlizLTK.js';
9
- import { D as DesignStack, a as DesignStudioState, b as DesignKitLoader, c as DesignKitManifest, d as DesignKitEntry, e as DesignKitTokens } from './tool-executor-D4YdaJ-M.js';
10
- import { M as MessageSelector } from './selector-qjpee9BF.js';
1
+ import { C as Context, c as Request, P as Provider } from './context-CLnUMW5g.js';
2
+ import { E as EventBus } from './brain-BLOyN5ZP.js';
3
+ import { M as MiddlewareHandler, b as Middleware } from './pipeline-Dl6XbfE7.js';
4
+ import { S as SessionEventBridge } from './session-event-bridge-CMvIO59_.js';
5
+ import { C as Compactor, a as CompactReport } from './compactor-DcBpaJsI.js';
6
+ import { h as ContextWindowAggressiveOn, i as ContextWindowPolicy } from './config-Bf5mj-ad.js';
7
+ import { h as Agent, D as DoneCondition } from './agent-subagent-runner-CEuw4ATz.js';
8
+ import { R as RunResult, S as SystemPromptContributor, A as AgentPipelines, c as ToolCallPipelinePayload, U as UserInputPayload } from './index-Cn0NOshr.js';
9
+ import { D as DesignStack, a as DesignStudioState, b as DesignKitLoader, c as DesignKitManifest, d as DesignKitEntry, e as DesignKitTokens } from './tool-executor-Bmd5Ygoo.js';
10
+ import { M as MessageSelector } from './selector-BCkWgdwy.js';
11
11
  import { S as SkillLoader, a as SkillManifest, b as SkillEntry } from './skill-DGIXCtdv.js';
12
12
  import { W as WstackPaths } from './wstack-paths-_NrRovdr.js';
13
13
  import { P as PromptLoader, a as PromptEntry, b as PromptSearchOptions, c as PromptCategoryCount } from './prompt-DLd35n4Q.js';
@@ -1,10 +1,10 @@
1
- import { A as AttachmentStore, a as AddAttachmentInput, b as AttachmentRef, c as Attachment } from './session-reader-BjLH4V9n.js';
2
- import { i as ContentBlock, u as ConversationState, k as SessionStore, S as SessionEvent, j as SessionMetadata, b as SessionWriter, v as ResumedSession, w as SessionData, x as SessionSummary, y as TodoItem } from './context-BrLe8pJy.js';
3
- import { C as Config, j as ConfigLoader, k as SyncConfig, l as ConfigStore } from './config-BzFRKkg7.js';
1
+ import { A as AttachmentStore, a as AddAttachmentInput, b as AttachmentRef, c as Attachment } from './session-reader-C8aiChUu.js';
2
+ import { i as ContentBlock, v as ConversationState, k as SessionStore, S as SessionEvent, j as SessionMetadata, b as SessionWriter, w as ResumedSession, x as SessionData, y as SessionSummary, z as TodoItem } from './context-CLnUMW5g.js';
3
+ import { C as Config, j as ConfigLoader, k as SyncConfig, l as ConfigStore } from './config-Bf5mj-ad.js';
4
4
  import { S as SecretVault } from './secret-vault-BAKpgFw_.js';
5
5
  import { W as WstackPaths } from './wstack-paths-_NrRovdr.js';
6
- import { E as EventBus, M as MemoryScope, b as MemoryEntry, c as MemoryStore, d as MemoryRelevanceContext, S as ScoredEntry } from './brain-DCkB5_e7.js';
7
- import { S as SecretScrubber } from './permission-CJR1qfOi.js';
6
+ import { E as EventBus, M as MemoryScope, b as MemoryEntry, c as MemoryStore, d as MemoryRelevanceContext, S as ScoredEntry } from './brain-BLOyN5ZP.js';
7
+ import { S as SecretScrubber } from './permission-BCbQDR2s.js';
8
8
 
9
9
  interface AttachmentStoreOptions {
10
10
  /**
@@ -218,8 +218,23 @@ interface FileMemoryBackendOptions {
218
218
  declare class FileMemoryBackend implements MemoryBackend {
219
219
  readonly kind = "file";
220
220
  private readonly files;
221
+ /** Cache of parsed entries per file path. */
222
+ private readonly entryCache;
223
+ /** Inverted index per file path. */
224
+ private readonly indexCache;
225
+ /** File mtime cache for invalidation. */
226
+ private readonly mtimeCache;
221
227
  constructor(opts: FileMemoryBackendOptions);
222
228
  private resolveFile;
229
+ private getMtime;
230
+ private invalidateCache;
231
+ /**
232
+ * Load (and cache) the parsed entries for a file. Callers that have already
233
+ * stat'd the file this tick (e.g. `getIndex`) can pass the known `mtime` to
234
+ * avoid a redundant `fs.stat` — otherwise it's fetched here.
235
+ */
236
+ private loadEntries;
237
+ private getIndex;
223
238
  remember(scope: MemoryScope, entry: MemoryEntry, filePath: string): Promise<void>;
224
239
  forget(scope: MemoryScope, query: string, filePath: string): Promise<number>;
225
240
  readAll(scope: MemoryScope, filePath: string): Promise<string>;
@@ -288,9 +303,10 @@ declare class DefaultMemoryStore implements MemoryStore {
288
303
  /** Result cache for scoreRelevant() — keyed by scope + context hash, TTL 30s. */
289
304
  private readonly _scoreCache;
290
305
  /**
291
- * Per-entry cached lowercase strings — computed once per scoreRelevant() call,
292
- * stored here so repeated scoring of the same entries avoids re-computation.
293
- * Cleared on every mutation (remember/forget/consolidate/clear).
306
+ * Per-entry cached lowercase strings — lazily allocated once and reused
307
+ * across scoreRelevant() calls so repeated scoring of the same entries skips
308
+ * re-lowercasing. Keyed by entry object identity; cleared (set to null) on
309
+ * every mutation (remember/forget/consolidate/clear) via invalidateScoreCaches().
294
310
  */
295
311
  private _cachedLower;
296
312
  constructor(opts: MemoryStoreOptions);
@@ -317,6 +333,12 @@ declare class DefaultMemoryStore implements MemoryStore {
317
333
  findRelated(text: string, scope?: MemoryScope, limit?: number): Promise<MemoryEntry[]>;
318
334
  search(query: string, scope?: MemoryScope, limit?: number): Promise<MemoryEntry[]>;
319
335
  remember(text: string, scope?: MemoryScope, metadata?: Omit<Partial<MemoryEntry>, 'scope' | 'text' | 'ts'>): Promise<void>;
336
+ /**
337
+ * Drop the relevance caches after a mutation. Both the per-context score
338
+ * cache and the per-entry lowercase cache are keyed on entry objects that a
339
+ * mutation invalidates, so they must be cleared together when entries change.
340
+ */
341
+ private invalidateScoreCaches;
320
342
  /**
321
343
  * Score and rank memories by relevance to the current context.
322
344
  * Returns entries with score >= MIN_RELEVANCE_SCORE, sorted highest first.
@@ -640,6 +662,22 @@ declare class DefaultSessionStore implements SessionStore {
640
662
  create(meta: Omit<SessionMetadata, 'startedAt'>): Promise<SessionWriter>;
641
663
  resume(id: string): Promise<ResumedSession>;
642
664
  load(id: string): Promise<SessionData>;
665
+ /**
666
+ * Fast-path loader that skips message reconstruction and adjacency repair.
667
+ *
668
+ * Use this for callers that only need the raw event stream + session
669
+ * metadata — e.g. session listers, analytics, audit, and the TUI's
670
+ * "events only" views. It avoids the message array build and
671
+ * repairToolUseAdjacency cost on large session files (a long agent
672
+ * run can have 50k+ events; rebuilding messages is O(events) and
673
+ * allocates per-block, so skipping it is a meaningful win).
674
+ *
675
+ * The returned data.messages is an empty array; data.toolCallEnds
676
+ * is computed from the raw events. usage is the sum across all
677
+ * llm_response events — same as full load().
678
+ */
679
+ loadEventsOnly(id: string): Promise<SessionData>;
680
+ private loadInternal;
643
681
  /**
644
682
  * Streaming search over a session's JSONL. Walks the file once, parses
645
683
  * each event lazily, and yields only the events that match `predicate`.
@@ -693,9 +731,18 @@ declare class DefaultSessionStore implements SessionStore {
693
731
  private writeTombstone;
694
732
  /**
695
733
  * Compact the index: read all entries, drop tombstones, deduplicate
696
- * (keep latest per session), and rewrite. Atomic via temp+rename.
734
+ * (keep latest per session), and rewrite atomically. Acquires the index
735
+ * file lock so a concurrent append (this process or another wstack in the
736
+ * same project) can't be overwritten by the rewrite.
697
737
  */
698
738
  private compactIndex;
739
+ /**
740
+ * Lock-free compaction body. The caller MUST already hold the index file
741
+ * lock (via withFileLock(this.indexFile, ...)). Uses atomicWrite for the
742
+ * rewrite so the temp file gets a random suffix (no collision between two
743
+ * compactions) and the Windows transient-EPERM rename retry.
744
+ */
745
+ private compactIndexInner;
699
746
  /**
700
747
  * Read the index file and return deduplicated session summaries.
701
748
  * Entries with a matching tombstone are filtered out.
@@ -1,12 +1,12 @@
1
- import { C as Context, g as ProviderError, T as Tool, r as ToolUseBlock, s as ToolResultBlock } from './context-BrLe8pJy.js';
2
- import { C as Compactor, a as CompactReport } from './compactor-CzSvxM1g.js';
3
- import { E as ErrorHandler, a as RecoveryDecision, R as RetryPolicy } from './retry-policy-BmY5ooh3.js';
4
- import { M as ModelsRegistry, C as Config } from './config-BzFRKkg7.js';
5
- import { g as Agent, h as AgentFactory } from './agent-subagent-runner-CArSFKFl.js';
6
- import { B as BrainArbiter, E as EventBus } from './brain-DCkB5_e7.js';
7
- import { J as JournalEntry } from './goal-store-DUwdbdoY.js';
8
- import { D as DispatchClassifier, a as DefaultMultiAgentCoordinator } from './multi-agent-coordinator-Dc_HuG9p.js';
9
- import { T as ToolExecutorOptions, a as ToolExecutorStrategy, b as ToolBatchResult } from './index-CtlizLTK.js';
1
+ import { C as Context, g as ProviderError, T as Tool, s as ToolUseBlock, t as ToolResultBlock, l as ToolErrorCategory } from './context-CLnUMW5g.js';
2
+ import { C as Compactor, a as CompactReport } from './compactor-DcBpaJsI.js';
3
+ import { E as ErrorHandler, a as RecoveryDecision, R as RetryPolicy } from './retry-policy-Dt3_z8Aj.js';
4
+ import { M as ModelsRegistry, C as Config } from './config-Bf5mj-ad.js';
5
+ import { h as Agent, i as AgentFactory } from './agent-subagent-runner-CEuw4ATz.js';
6
+ import { B as BrainArbiter, E as EventBus } from './brain-BLOyN5ZP.js';
7
+ import { J as JournalEntry } from './goal-store-DGb6b5Ed.js';
8
+ import { D as DispatchClassifier, a as DefaultMultiAgentCoordinator } from './multi-agent-coordinator-CiRtKVTk.js';
9
+ import { T as ToolExecutorOptions, a as ToolExecutorStrategy, b as ToolBatchResult } from './index-Cn0NOshr.js';
10
10
 
11
11
  interface CompactorOptions {
12
12
  preserveK?: number | undefined;
@@ -611,6 +611,9 @@ declare class ToolExecutor {
611
611
  * `setResultRenderMode` (e.g. headless/test renderers).
612
612
  */
613
613
  private hintRenderMode;
614
+ private toolLogBase;
615
+ private logToolSuccess;
616
+ private logToolFailure;
614
617
  /**
615
618
  * Execute a batch of tool uses using the configured strategy.
616
619
  * Returns the execution results and the remaining output budget.
@@ -626,6 +629,29 @@ declare class ToolExecutor {
626
629
  block: ToolResultBlock;
627
630
  bytes: number;
628
631
  }>;
632
+ /**
633
+ * Async "produce" phase: run the tool, serialize, scrub, and spill an
634
+ * oversized output to a disk artifact. Returns the pre-cap text. This is
635
+ * the long-running, concurrency-safe part — it touches NO shared budget
636
+ * state, so multiple invocations can run in parallel without racing.
637
+ *
638
+ * The `budgetHint` only gates the disk-spill threshold (a heuristic for
639
+ * "is this output large enough to persist"); it is NOT the output cap.
640
+ * The authoritative cap is applied synchronously in settleToolOutput()
641
+ * against the live budget.
642
+ */
643
+ private produceToolOutput;
644
+ /**
645
+ * Synchronous "settle" phase: enforce the output cap against the CURRENT
646
+ * budget, render, and build the result block. This MUST stay synchronous
647
+ * (no awaits) so that, in the parallel/smart strategies, two tools settling
648
+ * one after another against the shared closure budget can't interleave a
649
+ * stale read with a write. The first to settle consumes its bytes; the next
650
+ * settles against the reduced budget; once the budget hits 0, enforceCap
651
+ * truncates — making the per-iteration cap genuinely CUMULATIVE across
652
+ * parallel tools instead of degrading into a per-tool cap.
653
+ */
654
+ private settleToolOutput;
629
655
  private runWithTimeout;
630
656
  /** Best-effort tool cleanup; never let it mask the original error. */
631
657
  private runToolCleanup;
@@ -647,5 +673,14 @@ declare class ToolExecutor {
647
673
  */
648
674
  private budgetForString;
649
675
  }
676
+ /**
677
+ * Classify a tool execution error into a structured ToolErrorCategory.
678
+ * Used for observability (span attributes) and retry strategy decisions.
679
+ */
680
+ declare function classifyToolError(err: unknown): {
681
+ category: ToolErrorCategory;
682
+ retryable: boolean;
683
+ detail?: string;
684
+ };
650
685
 
651
- export { type CompactorOptions as C, type DesignStack as D, EternalAutonomyEngine as E, HybridCompactor as H, type IterationStage as I, type ParallelEngineState as P, type RecoveryStrategy as R, ToolExecutor as T, type DesignStudioState as a, type DesignKitLoader as b, type DesignKitManifest as c, type DesignKitEntry as d, type DesignKitTokens as e, DEFAULT_RECOVERY_STRATEGIES as f, DESIGN_STACKS as g, DefaultErrorHandler as h, DefaultRetryPolicy as i, type DesignTokenSet as j, type EternalAutonomyOptions as k, type EternalEngineState as l, ParallelEternalEngine as m, type ParallelEternalOptions as n, type ParallelIterationStage as o, buildRecoveryStrategies as p, isDesignStack as q };
686
+ export { type CompactorOptions as C, type DesignStack as D, EternalAutonomyEngine as E, HybridCompactor as H, type IterationStage as I, type ParallelEngineState as P, type RecoveryStrategy as R, ToolExecutor as T, type DesignStudioState as a, type DesignKitLoader as b, type DesignKitManifest as c, type DesignKitEntry as d, type DesignKitTokens as e, DEFAULT_RECOVERY_STRATEGIES as f, DESIGN_STACKS as g, DefaultErrorHandler as h, DefaultRetryPolicy as i, type DesignTokenSet as j, type EternalAutonomyOptions as k, type EternalEngineState as l, ParallelEternalEngine as m, type ParallelEternalOptions as n, type ParallelIterationStage as o, buildRecoveryStrategies as p, classifyToolError as q, isDesignStack as r };
@@ -1,5 +1,5 @@
1
- import { T as Tool } from '../context-BrLe8pJy.js';
2
- import { c as MCPServerConfig, C as Config } from '../config-BzFRKkg7.js';
1
+ import { T as Tool } from '../context-CLnUMW5g.js';
2
+ import { c as MCPServerConfig, C as Config } from '../config-Bf5mj-ad.js';
3
3
  import '../dispatcher-types.d-BBeXBQgS.js';
4
4
  import 'node:https';
5
5
  import 'undici';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/expect-defined.ts","../../src/utils/error.ts","../../src/security/capabilities.ts","../../src/infrastructure/mcp-servers.ts","../../src/utils/atomic-write.ts","../../src/utils/config-json.ts","../../src/tools/mcp-control.ts"],"names":["stat","fs2","path"],"mappings":"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","file":"index.js","sourcesContent":["/** Assert a value is neither null nor undefined. Throws if it is.\n * Useful after optional chaining and indexed access when the\n * control flow guarantees the value exists but TypeScript can't\n * prove it (e.g. after a check on a related field). */\nexport function expectDefined<T>(value: T | null | undefined, label?: string): T {\n if (value === null || value === undefined) {\n const err = new Error(label ? `Expected ${label} to be defined` : 'Expected value to be defined');\n err.name = 'ExpectDefinedError';\n throw err;\n }\n return value;\n}\n","/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","/**\n * Well-known tool capabilities used for authorization decisions.\n *\n * These are the preferred values for `Tool.capabilities`.\n * New capabilities should be added here with clear documentation.\n *\n * Philosophy (2026-06+):\n * - Prefer capabilities over exact tool name matching.\n * - Subagent guards and future policies should primarily key off capabilities.\n * - Name-based denylists are legacy and will be phased down.\n */\nexport const ToolCapabilities = {\n /** Can execute arbitrary commands in the user's shell (the `bash` tool). */\n SHELL_ARBITRARY: 'shell.arbitrary',\n\n /** Can execute a restricted set of commands (the `exec` tool). */\n SHELL_RESTRICTED: 'shell.restricted',\n\n /** Can read files inside the project (and possibly outside via symlinks if not guarded). */\n FS_READ: 'fs.read',\n\n /** Can write / modify / delete files inside the project. */\n FS_WRITE: 'fs.write',\n\n /** Can write files outside the current project root (very high risk). */\n FS_WRITE_OUTSIDE_PROJECT: 'fs.write.outside-project',\n\n /** Can perform outbound network requests. */\n NET_OUTBOUND: 'net.outbound',\n\n /** Proxies tools from external MCP servers (unknown capability). */\n MCP_PROXY: 'mcp.proxy',\n\n /** Can spawn or manage subagents / multi-agent tasks. */\n SUBAGENT_SPAWN: 'subagent.spawn',\n\n /** Can inspect fleet/subagent coordination state without mutating it. */\n COORDINATION_FLEET_READ: 'coordination.fleet.read',\n\n /** Can read or write inter-agent mailbox messages. */\n COORDINATION_MAIL: 'coordination.mail',\n\n /** Can schedule, inspect, or cancel in-session cron jobs. */\n COORDINATION_CRON: 'coordination.cron',\n\n /** Can mutate global or session configuration / trust state. */\n CONFIG_MUTATE: 'config.mutate',\n\n /** Can install packages or run package managers with side effects. */\n PACKAGE_INSTALL: 'package.install',\n} as const;\n\nexport type ToolCapability = (typeof ToolCapabilities)[keyof typeof ToolCapabilities];\n\n/**\n * Set of capabilities that are considered dangerous for subagents by default.\n * Subagents should not receive these capabilities unless the leader explicitly\n * allows the specific tool at spawn time.\n */\nexport const DANGEROUS_FOR_SUBAGENTS: readonly ToolCapability[] = [\n ToolCapabilities.SHELL_ARBITRARY,\n ToolCapabilities.SHELL_RESTRICTED,\n ToolCapabilities.FS_WRITE,\n ToolCapabilities.FS_WRITE_OUTSIDE_PROJECT,\n ToolCapabilities.MCP_PROXY,\n ToolCapabilities.SUBAGENT_SPAWN,\n ToolCapabilities.CONFIG_MUTATE,\n ToolCapabilities.PACKAGE_INSTALL,\n];\n\n/**\n * Wide capability allowlist for subagents that the user has authorized to act\n * with full developer power (the CLI fleet host applies this to any subagent\n * that isn't given an explicit, narrower grant). It covers everything needed to\n * do real work end-to-end — read, write/edit inside the project, outbound\n * network, and shell/build/install — so a delegated coding or build agent runs\n * the same toolchain the leader would, without per-tool confirmation it cannot\n * answer.\n *\n * Deliberately EXCLUDED (require an explicit per-spawn `allowedCapabilities`\n * grant, because they escape the task's blast radius rather than perform it):\n * - `fs.write.outside-project` — writing outside the repo (e.g. ~/.ssh).\n * - `mcp.proxy` — third-party MCP tools (also hard-blocked by name).\n * - `subagent.spawn` — recursive delegation (the baseline prompt forbids it).\n * - `config.mutate` — rewriting trust/config is privilege escalation, not work.\n */\nexport const WIDE_SUBAGENT_CAPABILITIES: readonly ToolCapability[] = [\n ToolCapabilities.FS_READ,\n ToolCapabilities.FS_WRITE,\n ToolCapabilities.NET_OUTBOUND,\n ToolCapabilities.SHELL_ARBITRARY,\n ToolCapabilities.SHELL_RESTRICTED,\n ToolCapabilities.PACKAGE_INSTALL,\n];\n\n/**\n * Check if a tool (or its capabilities array) includes any dangerous capability\n * for subagent execution.\n */\nexport function hasDangerousCapabilityForSubagents(\n toolOrCaps: { capabilities?: readonly string[] | undefined } | readonly string[] | undefined,\n): boolean {\n if (!toolOrCaps) return false;\n const input = toolOrCaps as never as { capabilities?: readonly string[] | undefined };\n const caps: readonly string[] = Array.isArray(toolOrCaps) ? toolOrCaps : (input.capabilities ?? []);\n return caps.some((c) => DANGEROUS_FOR_SUBAGENTS.includes(c as ToolCapability));\n}\n\n/**\n * Check if a tool declares a specific capability (or any of the provided ones).\n */\nexport function hasCapability(\n toolOrCaps: { capabilities?: readonly string[] | undefined } | readonly string[] | undefined,\n capability: ToolCapability | ToolCapability[],\n): boolean {\n if (!toolOrCaps) return false;\n const input = toolOrCaps as never as { capabilities?: readonly string[] | undefined };\n const caps: readonly string[] = Array.isArray(toolOrCaps) ? toolOrCaps : (input.capabilities ?? []);\n const toCheck = Array.isArray(capability) ? capability : [capability];\n return toCheck.some((c) => caps.includes(c));\n}\n\n/**\n * Returns the intersection of a tool's capabilities with the dangerous set.\n * Useful for logging and audit trails.\n */\nexport function getDangerousCapabilities(\n toolOrCaps: { capabilities?: readonly string[] | undefined } | readonly string[] | undefined,\n): ToolCapability[] {\n if (!toolOrCaps) return [];\n const input = toolOrCaps as never as { capabilities?: readonly string[] | undefined };\n const caps: readonly string[] = Array.isArray(toolOrCaps) ? toolOrCaps : (input.capabilities ?? []);\n return caps.filter((c): c is ToolCapability =>\n DANGEROUS_FOR_SUBAGENTS.includes(c as ToolCapability),\n );\n}\n","import type { MCPServerConfig } from '../types/config.js';\n\n/**\n * Built-in MCP server presets available to all WrongStack users out of the box.\n * These servers must be explicitly enabled in config (disabled by default).\n *\n * To enable: set `mcpServers: { serverName: { enabled: true } }` in your config.\n *\n * Some servers require environment variables or additional config — see notes below.\n *\n * Transport types:\n * stdio — spawns a local npm package binary via child_process\n * sse — HTTP SSE endpoint (client POSTs requests)\n * streamable-http — session-based HTTP with NDJSON responses\n */\n\n/** Filesystem access: read, write, list, search, tree. Good for exploring projects. */\nexport const filesystemServer = (): MCPServerConfig => ({\n name: 'filesystem',\n description: 'Read, write, and navigate the local filesystem (read-heavy tools)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-filesystem', '.'],\n permission: 'confirm',\n});\n\n/** GitHub API: issues, PRs, repos, search, file operations. Requires GITHUB_PERSONAL_ACCESS_TOKEN. */\nexport const githubServer = (): MCPServerConfig => ({\n name: 'github',\n description:\n 'GitHub API — issues, PRs, repos, search, file ops (requires GITHUB_PERSONAL_ACCESS_TOKEN)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-github'],\n permission: 'confirm',\n});\n\n/**\n * Context7 — codebase-aware documentation and Q&A using context from your code.\n * Live documentation for any library, grounded in your actual versions.\n */\nexport const context7Server = (): MCPServerConfig => ({\n name: 'context7',\n description: 'Codebase-aware documentation and Q&A (context7.ai)',\n transport: 'streamable-http',\n url: 'https://mcp.context7.com/mcp',\n permission: 'confirm',\n});\n\n/**\n * Brave Search — web search via Brave Browser's API.\n * Requires BRAVE_SEARCH_API_KEY. Free tier: 2,000 queries/month.\n * Sign up at https://api.search.brave.com/\n */\nexport const braveSearchServer = (): MCPServerConfig => ({\n name: 'brave-search',\n description: 'Web search (Brave). Requires BRAVE_SEARCH_API_KEY — free tier 2k queries/month',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-brave-search'],\n permission: 'confirm',\n});\n\n/**\n * Block (Block, Inc.) — Postgres database access via SQL.\n * Useful for running queries against a connected database during development.\n */\nexport const blockServer = (): MCPServerConfig => ({\n name: 'block',\n description: 'Postgres database access via SQL (Block MCP server)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-block'],\n permission: 'confirm',\n});\n\n/**\n * EverArt — AI image generation via various providers.\n * Requires EVERART_API_KEY.\n */\nexport const everArtServer = (): MCPServerConfig => ({\n name: 'everart',\n description: 'AI image generation (EverArt). Requires EVERART_API_KEY',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-everart'],\n permission: 'confirm',\n});\n\n/**\n * Slack — messaging, channels, search.\n * Requires SLACK_BOT_TOKEN and either SLACK_TEAM_ID or SLACK_USER_TOKEN.\n */\nexport const slackServer = (): MCPServerConfig => ({\n name: 'slack',\n description: 'Slack — messaging, channels, search. Requires SLACK_BOT_TOKEN + SLACK_TEAM_ID',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-slack'],\n permission: 'confirm',\n});\n\n/**\n * AWS knowledge base — EC2, S3, Lambda, IAM, CloudFormation, cost management.\n * Requires AWS access key + secret in environment.\n */\nexport const awsServer = (): MCPServerConfig => ({\n name: 'aws',\n description: 'AWS — EC2, S3, Lambda, IAM, CloudFormation, costs. Requires AWS credentials',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-aws'],\n permission: 'confirm',\n});\n\n/**\n * Google Maps — directions, distance matrix, geocoding, places.\n * Requires GOOGLE_MAPS_API_KEY.\n */\nexport const googleMapsServer = (): MCPServerConfig => ({\n name: 'google-maps',\n description: 'Google Maps — directions, geocoding, places. Requires GOOGLE_MAPS_API_KEY',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-google-maps'],\n permission: 'confirm',\n});\n\n/** Sentinel — security vulnerability scanning (sentinel-labs). */\nexport const sentinelServer = (): MCPServerConfig => ({\n name: 'sentinel',\n description: 'Security vulnerability scanning (Sentinel)',\n transport: 'streamable-http',\n url: 'https://mcp.sentinel.ai',\n permission: 'deny', // security tool — require explicit confirmation\n});\n\n/**\n * Z.AI Vision MCP — image understanding fallback for text-only models.\n * Requires Z_AI_API_KEY. Tools are read-only and safe to run automatically.\n */\nexport const zaiVisionServer = (): MCPServerConfig => ({\n name: 'zai-vision',\n description: 'Z.AI Vision MCP — image analysis and screenshot understanding',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@z_ai/mcp-server@latest'],\n env: { Z_AI_MODE: 'ZAI' },\n allowedTools: [\n 'image_analysis',\n 'extract_text_from_screenshot',\n 'diagnose_error_screenshot',\n 'understand_technical_diagram',\n 'analyze_data_visualization',\n 'ui_diff_check',\n ],\n permission: 'auto',\n});\n\n/**\n * Playwright — browser automation: navigate, click, type, screenshot, evaluate JS.\n * Spawns a headless Chromium browser via @modelcontextprotocol/server-playwright.\n * Tools can read and interact with live web pages — permission defaults to\n * `confirm` because form submission / DOM mutation is possible.\n */\nexport const playwrightServer = (): MCPServerConfig => ({\n name: 'playwright',\n description:\n 'Browser automation — navigate, screenshot, click, type, evaluate JS (headless Chromium)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-playwright'],\n permission: 'confirm',\n});\n\n/**\n * MiniMax Token Plan MCP — web_search + understand_image.\n * This preset exposes only the read-only image understanding tool by default.\n * Requires MINIMAX_API_KEY and uvx on PATH.\n */\nexport const miniMaxVisionServer = (): MCPServerConfig => ({\n name: 'minimax-vision',\n description: 'MiniMax MCP — image understanding via understand_image',\n transport: 'stdio',\n command: 'uvx',\n args: ['minimax-coding-plan-mcp', '-y'],\n env: {\n MINIMAX_MCP_BASE_PATH: './.wrongstack/minimax-output',\n MINIMAX_API_HOST: 'https://api.minimax.io',\n MINIMAX_API_RESOURCE_MODE: 'url',\n },\n allowedTools: ['understand_image'],\n permission: 'auto',\n});\n\n/**\n * SSH Manager — remote SSH execution, file transfer, tunnels, health checks, and deployment ops.\n * Server credentials are intentionally NOT embedded here. Configure hosts via mcp-ssh-manager's\n * env/TOML config (for example SSH_SERVER_<NAME>_HOST, USER, KEYPATH/PASSWORD) or ssh-agent.\n */\nexport const sshManagerServer = (): MCPServerConfig => ({\n name: 'ssh',\n description:\n 'Remote SSH management — execute commands, transfer files, tunnels, health checks (mcp-ssh-manager)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', 'mcp-ssh-manager'],\n env: {\n MCP_SSH_COMPACT_JSON: 'true',\n MCP_SSH_DEFAULT_TIMEOUT: '120000',\n },\n permission: 'confirm',\n requestTimeoutMs: 180_000,\n});\n\n/** Everything bundled — full set of built-in servers. Useful for `wstack mcp add --all`. */\nexport const allServers = (): Record<string, MCPServerConfig> => ({\n filesystem: { ...filesystemServer(), enabled: false },\n github: { ...githubServer(), enabled: false },\n context7: { ...context7Server(), enabled: false },\n 'brave-search': { ...braveSearchServer(), enabled: false },\n block: { ...blockServer(), enabled: false },\n everart: { ...everArtServer(), enabled: false },\n slack: { ...slackServer(), enabled: false },\n aws: { ...awsServer(), enabled: false },\n 'google-maps': { ...googleMapsServer(), enabled: false },\n sentinel: { ...sentinelServer(), enabled: false },\n 'zai-vision': { ...zaiVisionServer(), enabled: false },\n 'minimax-vision': { ...miniMaxVisionServer(), enabled: false },\n playwright: { ...playwrightServer(), enabled: false },\n ssh: { ...sshManagerServer(), enabled: false },\n});\n","import { randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nexport interface AtomicWriteOptions {\n mode?: number | undefined;\n encoding?: BufferEncoding | undefined;\n}\n\nexport interface FileLockOptions {\n timeoutMs?: number | undefined;\n staleMs?: number | undefined;\n}\n\nexport async function atomicWrite(\n targetPath: string,\n content: string | Uint8Array,\n opts: AtomicWriteOptions = {},\n): Promise<void> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const tmp = path.join(dir, `.${path.basename(targetPath)}.${randomBytes(6).toString('hex')}.tmp`);\n\n // Write content to tmp first; 'wx' ensures exclusive creation (fails if\n // tmp already exists — extremely unlikely with 6-byte random suffix).\n try {\n if (typeof content === 'string') {\n await fs.writeFile(tmp, content, { flag: 'wx', encoding: opts.encoding ?? 'utf8' });\n } else {\n await fs.writeFile(tmp, content, { flag: 'wx' });\n }\n try {\n const fh = await fs.open(tmp, 'r+');\n try {\n await fh.sync();\n } finally {\n await fh.close();\n }\n } catch {\n // fsync best-effort\n }\n // Now safely read mode from target (if it exists) and apply to tmp before rename.\n // Prefer opts.mode for new files; for existing files preserve their mode.\n let mode: number | undefined;\n try {\n const stat = await fs.stat(targetPath);\n mode = stat.mode & 0o777;\n } catch {\n mode = opts.mode;\n }\n if (mode !== undefined) {\n await fs.chmod(tmp, mode);\n }\n await renameWithRetry(tmp, targetPath);\n // P3 #20 (before-release.md): on Windows, fs.rename (MoveFileExW) does\n // not preserve Unix permission bits — the chmod above applies to the tmp\n // file, but the rename may reset the destination's mode to the Windows\n // default. Re-apply the mode after rename on win32 so an edited file\n // keeps its executable bit (or any non-default permission). On POSIX,\n // rename preserves metadata so this is a no-op (chmod is idempotent and\n // cheap), but we gate it on win32 to avoid the extra stat+chmod on the\n // common path.\n if (mode !== undefined && process.platform === 'win32') {\n try {\n await fs.chmod(targetPath, mode);\n } catch {\n // Best-effort: a transient EPERM (antivirus lock) should not fail\n // the write — the content is already on disk.\n }\n }\n } catch (err) {\n try {\n await fs.unlink(tmp);\n } catch {\n // ignore cleanup error\n }\n throw err;\n }\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\nexport async function withFileLock<T>(\n targetPath: string,\n fn: () => Promise<T>,\n opts: FileLockOptions = {},\n): Promise<T> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const lockPath = path.join(dir, `.${path.basename(targetPath)}.lock`);\n const timeoutMs = opts.timeoutMs ?? 5_000;\n const staleMs = opts.staleMs ?? 30_000;\n const started = Date.now();\n let handle: fs.FileHandle | undefined;\n\n for (;;) {\n try {\n handle = await fs.open(lockPath, 'wx');\n await handle.writeFile(`${process.pid}:${Date.now()}`);\n break;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n // ENOENT means the directory was deleted (e.g. by concurrent cleanup).\n // Recreate it and retry acquiring the lock.\n if (code === 'ENOENT') {\n await fs.mkdir(dir, { recursive: true });\n continue;\n }\n if (code !== 'EEXIST') throw err;\n try {\n const stat = await fs.stat(lockPath);\n if (Date.now() - stat.mtimeMs > staleMs) {\n await fs.unlink(lockPath);\n continue;\n }\n } catch {\n continue;\n }\n if (Date.now() - started >= timeoutMs) {\n throw new Error(`Timed out waiting for file lock: ${targetPath}`);\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n }\n\n try {\n return await fn();\n } finally {\n try {\n await handle?.close();\n } catch {\n // ignore\n }\n try {\n await fs.unlink(lockPath);\n } catch {\n // ignore\n }\n }\n}\n\n// On Windows, fs.rename over an existing file can fail with EPERM/EBUSY/EACCES\n// when antivirus, file indexers, editor file watchers, or a concurrent writer\n// briefly hold a handle on the destination. These are transient — retry with a\n// short backoff before giving up. POSIX renames are atomic and won't hit this.\nconst TRANSIENT_RENAME_CODES = new Set(['EPERM', 'EBUSY', 'EACCES', 'ENOTEMPTY']);\n\nasync function renameWithRetry(from: string, to: string): Promise<void> {\n if (process.platform !== 'win32') {\n await fs.rename(from, to);\n return;\n }\n const delays = [10, 25, 60, 120, 250];\n let lastErr: unknown;\n for (let i = 0; i <= delays.length; i++) {\n try {\n await fs.rename(from, to);\n return;\n } catch (err) {\n lastErr = err;\n const code = (err as NodeJS.ErrnoException)?.code;\n if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {\n throw err;\n }\n await new Promise((resolve) => setTimeout(resolve, delays[i]));\n }\n }\n throw lastErr;\n}\n","import * as fs from 'node:fs/promises';\nimport { atomicWrite } from './atomic-write.js';\n\nexport type JsonObject = Record<string, unknown>;\nexport type JsonPathSegment = string | number;\nexport type JsonPath = readonly JsonPathSegment[];\n\nexport async function readJsonObjectFile(filePath: string): Promise<JsonObject> {\n try {\n const parsed = JSON.parse(await fs.readFile(filePath, 'utf8')) as unknown;\n return isJsonObject(parsed) ? parsed : {};\n } catch {\n return {};\n }\n}\n\nexport async function jsonObjectFileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function writeJsonObjectFile(filePath: string, value: JsonObject): Promise<void> {\n await atomicWrite(filePath, JSON.stringify(value, null, 2), { mode: 0o600 });\n}\n\nexport async function updateJsonObjectFile(\n filePath: string,\n mutator: (config: JsonObject) => void | JsonObject | Promise<void | JsonObject>,\n): Promise<JsonObject> {\n const config = await readJsonObjectFile(filePath);\n const maybeNext = await mutator(config);\n const next = maybeNext && isJsonObject(maybeNext) ? maybeNext : config;\n await writeJsonObjectFile(filePath, next);\n return next;\n}\n\nexport function getJsonPath(root: unknown, path: JsonPath): unknown {\n let current = root;\n for (const segment of path) {\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) return undefined;\n current = current[segment];\n continue;\n }\n if (!isJsonObject(current)) return undefined;\n current = current[segment];\n }\n return current;\n}\n\nexport function setJsonPath(root: JsonObject, path: JsonPath, value: unknown): JsonObject {\n if (path.length === 0) {\n if (!isJsonObject(value)) throw new Error('Root config value must be an object');\n return value;\n }\n const parent = ensureJsonParent(root, path);\n const leaf = lastPathSegment(path);\n if (typeof leaf === 'number') {\n if (!Array.isArray(parent)) throw new Error(`Cannot set numeric segment ${leaf} on non-array parent`);\n parent[leaf] = value;\n } else {\n if (!isJsonObject(parent)) throw new Error(`Cannot set property ${leaf} on non-object parent`);\n parent[leaf] = value;\n }\n return root;\n}\n\nexport function removeJsonPath(root: JsonObject, path: JsonPath): boolean {\n if (path.length === 0) return false;\n const parent = getJsonPath(root, path.slice(0, -1));\n const leaf = lastPathSegment(path);\n if (typeof leaf === 'number') {\n if (!Array.isArray(parent) || leaf < 0 || leaf >= parent.length) return false;\n parent.splice(leaf, 1);\n return true;\n }\n if (!isJsonObject(parent) || !(leaf in parent)) return false;\n delete parent[leaf];\n return true;\n}\n\nexport async function setJsonPathInFile(filePath: string, path: JsonPath, value: unknown): Promise<JsonObject> {\n return updateJsonObjectFile(filePath, (config) => setJsonPath(config, path, value));\n}\n\nexport async function removeJsonPathInFile(filePath: string, path: JsonPath): Promise<JsonObject> {\n return updateJsonObjectFile(filePath, (config) => {\n removeJsonPath(config, path);\n });\n}\n\nexport function isJsonObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction lastPathSegment(path: JsonPath): JsonPathSegment {\n const segment = path[path.length - 1];\n if (segment === undefined) throw new Error('Invalid empty JSON path');\n return segment;\n}\n\nfunction ensureJsonParent(root: JsonObject, path: JsonPath): JsonObject | unknown[] {\n let current: JsonObject | unknown[] = root;\n for (let i = 0; i < path.length - 1; i += 1) {\n const segment = path[i];\n const nextSegment = path[i + 1];\n if (segment === undefined) throw new Error('Invalid empty JSON path segment');\n const nextContainer = typeof nextSegment === 'number' ? [] : {};\n\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) throw new Error(`Cannot traverse numeric segment ${segment} on non-array parent`);\n if (!isJsonObject(current[segment]) && !Array.isArray(current[segment])) current[segment] = nextContainer;\n current = current[segment] as JsonObject | unknown[];\n } else {\n if (!isJsonObject(current)) throw new Error(`Cannot traverse property ${segment} on non-object parent`);\n if (!isJsonObject(current[segment]) && !Array.isArray(current[segment])) current[segment] = nextContainer;\n current = current[segment] as JsonObject | unknown[];\n }\n }\n return current;\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { ToolCapabilities } from '../security/capabilities.js';\n/**\n * `mcp_control` — LLM-driven MCP server lifecycle management.\n *\n * The model calls this tool to:\n * list — see all known servers (running or not) without starting any\n * search — filter the server catalog by name or description keyword\n * enable — start a server and register its tools\n * disable — stop a server and unregister its tools\n * restart — stop then re-start a running server\n *\n * This is the primary mechanism by which the LLM autonomously extends its\n * own capabilities at runtime — e.g. \"I need GitHub access, let me enable it.\"\n */\nimport { allServers } from '../infrastructure/mcp-servers.js';\nimport { readJsonObjectFile, setJsonPath, updateJsonObjectFile } from '../utils/config-json.js';\nimport type { Config, JSONSchema, MCPServerConfig, Tool } from '../index.js';\nexport interface MCPRegistryHandle {\n start(cfg: MCPServerConfig): Promise<void>;\n stop(name: string): Promise<void>;\n restart(name: string): Promise<void>;\n describe(): {\n name: string;\n state: string;\n toolCount: number;\n enabled: boolean;\n tools?: string[];\n }[];\n list(): { name: string; state: string; toolCount: number; tools?: string[] }[];\n /**\n * Register all cached tools for a server without restarting it.\n * No-op if the server is not connected or tools are already active.\n * Used in token-saving mode to temporarily expose MCP tools.\n */\n activateServer?(name: string): void;\n /**\n * Unregister all tools for a server without disconnecting it.\n * Returns the number of tools that were deactivated.\n * Used in token-saving mode to hide MCP tools after use.\n */\n deactivateServer?(name: string): number;\n /**\n * Check whether a server's tools are currently registered.\n */\n isActivated?(name: string): boolean;\n}\n\nexport interface CreateMcpControlToolOptions {\n /**\n * Read the current config object. The tool never mutates this directly —\n * writes go to the global config file via `configPath`.\n */\n getConfig: () => Config;\n /**\n * Path to ~/.wrongstack/config.json (or equivalent) for atomic config writes.\n */\n configPath: string;\n /**\n * Live MCP registry for runtime start/stop/restart. The tool calls these\n * immediately so the LLM sees the result of its action in the same turn.\n */\n registry: MCPRegistryHandle;\n}\n\nexport function createMcpControlTool(opts: CreateMcpControlToolOptions): Tool {\n const { getConfig, configPath, registry } = opts;\n\n const inputSchema: JSONSchema = {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: ['list', 'search', 'enable', 'disable', 'restart', 'activate', 'deactivate'],\n description: 'The management action to perform. activate/deactivate toggle tool registration ephemerally without disconnecting.',\n },\n /** Filter for `search`. Matches server name or description case-insensitively. */\n query: {\n type: 'string',\n description: 'Search term for `search` action. Matches server name or description.',\n },\n /** Target server name for `enable`, `disable`, `restart`, `activate`, `deactivate`. */\n server: {\n type: 'string',\n description: 'Server name (e.g. \"github\", \"filesystem\", \"brave-search\").',\n },\n },\n required: ['action'],\n };\n\n return {\n name: 'mcp_control',\n description:\n 'Manage MCP server lifecycle: list available servers, search by name or capability, enable or disable servers at runtime, restart running servers. Use activate/deactivate to ephemerally toggle tool registration without disconnecting — ideal for token-saving mode where MCP tools are lazy-loaded on demand. NOTE: `enable`/`restart` start a server process, which for the built-in stdio presets runs `npx -y <package>` — i.e. it fetches and executes an npm package from the network. Treat it as code execution.',\n category: 'mcp',\n permission: 'auto',\n mutating: true,\n // `enable`/`restart` spawn a server process that, for the stdio presets,\n // fetches and runs an npm package (`npx -y <pkg>`) — effectively remote\n // code execution. Marking the tool destructive means the YOLO\n // `confirmDestructive` safety net still prompts before it runs (plain\n // non-YOLO already confirms via the CONFIG_MUTATE dangerous-capability\n // net in the executor). Read-only actions (list/search) ride the same\n // tool but are cheap to confirm/trust once.\n riskTier: 'destructive',\n capabilities: [ToolCapabilities.CONFIG_MUTATE],\n inputSchema,\n async execute(raw) {\n const input = raw as { action: string; query?: string | undefined; server?: string | undefined };\n return mcpControlDispatch(input, { getConfig, configPath, registry });\n },\n };\n}\n\n// ── Dispatch ──────────────────────────────────────────────────────────────────\n\nasync function mcpControlDispatch(\n input: { action: string; query?: string | undefined; server?: string | undefined },\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n const { action, query, server } = input;\n\n switch (action) {\n case 'list': return renderList(deps);\n case 'search': return renderSearch(query ?? '', deps);\n case 'enable': return server ? runEnable(server, deps) : '`server` is required for enable.';\n case 'disable': return server ? runDisable(server, deps) : '`server` is required for disable.';\n case 'restart': return server ? runRestart(server, deps) : '`server` is required for restart.';\n case 'activate': return server ? runActivate(server, deps) : '`server` is required for activate.';\n case 'deactivate': return server ? runDeactivate(server, deps) : '`server` is required for deactivate.';\n default:\n return `Unknown action \"${action}\". Use one of: list, search, enable, disable, restart, activate, deactivate.`;\n }\n}\n\n// ── Actions ───────────────────────────────────────────────────────────────────\n\nasync function renderList(deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle }): Promise<string> {\n const configured = await getConfiguredMcpServers(deps);\n const live = deps.registry.describe();\n\n if (Object.keys(configured).length === 0) {\n return [\n 'No MCP servers configured.',\n ' Use `mcp_control({ action: \"search\" })` to see available presets,',\n ' then `mcp_control({ action: \"enable\", server: \"<name>\" })` to add one.',\n ].join('\\n');\n }\n\n const lines: string[] = [];\n const liveMap = new Map(live.map((s) => [s.name, s]));\n\n for (const [name, cfg] of Object.entries(configured)) {\n const liveInfo = liveMap.get(name);\n const toolCount = liveInfo ? ` (${liveInfo.toolCount} tools)` : '';\n const stateStr = liveInfo ? badge(liveInfo.state) : dim('○ not loaded');\n const enabled = cfg.enabled === false\n ? `${dim('disabled')} `\n : `${green('● enabled')} `;\n lines.push(` ${bold(name)} ${enabled}${stateStr}${toolCount}`);\n if (cfg.description) lines.push(` ${dim(cfg.description)}`);\n }\n\n lines.push('');\n lines.push(dim(' Use `mcp_control({ action: \"search\", query: \"<keyword>\" })` to find servers.'));\n lines.push(dim(' Use `mcp_control({ action: \"enable\", server: \"<name>\" })` to start a server.'));\n return lines.join('\\n');\n}\n\nasync function renderSearch(\n query: string,\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n const configured = await getConfiguredMcpServers(deps);\n const all = allServers();\n const q = query.toLowerCase();\n\n const configuredNames = new Set(Object.keys(configured));\n\n // Match against configured servers first, then remaining presets\n const configuredEntries = Object.entries(configured).filter(\n ([name, cfg]) =>\n name.toLowerCase().includes(q) ||\n (cfg.description ?? '').toLowerCase().includes(q),\n );\n\n const unconfiguredEntries = Object.entries(all)\n .filter(([name]) => !configuredNames.has(name))\n .filter(\n ([name, cfg]) =>\n name.toLowerCase().includes(q) ||\n (cfg.description ?? '').toLowerCase().includes(q),\n );\n\n const lines: string[] = [];\n\n if (configuredEntries.length > 0) {\n lines.push(bold('Configured servers matching \"') + query + '\":');\n for (const [name, cfg] of configuredEntries) {\n lines.push(` ${bold(name)} ${cfg.description ?? cfg.transport}`);\n }\n lines.push('');\n }\n\n if (unconfiguredEntries.length > 0) {\n lines.push(bold('Available presets matching \"') + query + '\":');\n for (const [name, cfg] of unconfiguredEntries) {\n const warn = cfg.permission === 'deny' ? red(' ⚠ confirm required') : '';\n lines.push(` ${bold(name)} ${cfg.description ?? cfg.transport}${warn}`);\n }\n lines.push('');\n }\n\n if (configuredEntries.length === 0 && unconfiguredEntries.length === 0) {\n return `No servers match \"${query}\". Try a shorter keyword or \\`mcp_control({ action: \"list\" })\\`.`;\n }\n\n const total = configuredEntries.length + unconfiguredEntries.length;\n lines.push(dim(` ${total} server${total !== 1 ? 's' : ''} shown. Run \\`enable\\` on one to activate it.`));\n return lines.join('\\n');\n}\n\nasync function runEnable(\n name: string | undefined,\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for enable. Example: { action: \"enable\", server: \"github\" }';\n\n const all = allServers();\n const configured = deps.getConfig().mcpServers ?? {};\n\n // Resolve the target config — it may be a preset not yet in config\n const cfg = configured[name] ?? all[name];\n if (!cfg) {\n const known = Object.keys(all).join(', ');\n return `Unknown server \"${name}\". Available presets: ${known}`;\n }\n\n // Write to config (add or update) using the shared JSON path helper.\n await updateJsonObjectFile(deps.configPath, (full) => {\n const current = isMcpServerRecord(full.mcpServers) ? full.mcpServers : {};\n setJsonPath(full, ['mcpServers', name], { ...current[name], ...cfg, enabled: true });\n });\n\n // Start the server in the registry\n try {\n const live = deps.registry.describe().find((s) => s.name === name);\n if (live && live.state === 'connected') {\n return `${green('●')} Server \"${name}\" is already running (${live.toolCount} tools registered).`;\n }\n await deps.registry.start({ ...cfg, enabled: true });\n const updated = deps.registry.describe().find((s) => s.name === name);\n return `${green('✓ Enabled and started')} \"${name}\"${updated ? ` (${updated.toolCount} tools registered).` : '.'}`;\n } catch (err) {\n return `${red('✗ Failed to start')} \"${name}\": ${toErrorMessage(err)}`;\n }\n}\n\nasync function runDisable(\n name: string | undefined,\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for disable. Example: { action: \"disable\", server: \"github\" }';\n\n const configured = deps.getConfig().mcpServers ?? {};\n if (!configured[name]) {\n return `Server \"${name}\" is not in config. Add it with \\`mcp_control({ action: \"enable\", server: \"${name}\" })\\`.`;\n }\n\n // Write to config using the shared JSON path helper.\n await updateJsonObjectFile(deps.configPath, (full) => {\n const current = isMcpServerRecord(full.mcpServers) ? full.mcpServers : {};\n const existing = expectDefined(current[name]);\n setJsonPath(full, ['mcpServers', name], { ...existing, enabled: false });\n });\n\n // Stop the running server\n try {\n await deps.registry.stop(name);\n return `${yellow('○ Disabled')} \"${name}\". It will not be started on next boot.`;\n } catch {\n return `${yellow('○ Disabled')} \"${name}\" (it was not running). Config updated.`;\n }\n}\n\nasync function runRestart(\n name: string | undefined,\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for restart. Example: { action: \"restart\", server: \"github\" }';\n\n const configured = deps.getConfig().mcpServers ?? {};\n if (!configured[name]) {\n return `Server \"${name}\" is not configured. Use \\`mcp_control({ action: \"enable\", server: \"${name}\" })\\` first.`;\n }\n\n try {\n await deps.registry.restart(name);\n const updated = deps.registry.describe().find((s) => s.name === name);\n return `${green('✓ Restarted')} \"${name}\"${updated ? ` (${updated.toolCount} tools registered).` : '.'}`;\n } catch (err) {\n return `${red('✗ Restart failed')} for \"${name}\": ${toErrorMessage(err)}`;\n }\n}\n\n/**\n * Ephemerally activate a server's tools without writing to config or\n * restarting the connection. The server must already be connected (lazy mode).\n * Calls `registry.activateServer()` when available; falls back to a message\n * if the registry doesn't support ephemeral activation.\n */\nasync function runActivate(\n name: string | undefined,\n deps: { registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for activate.';\n if (!deps.registry.activateServer) {\n return `Registry does not support ephemeral activation. Use \\`enable\\` to start \"${name}\" instead.`;\n }\n const live = deps.registry.describe().find((s) => s.name === name);\n if (!live) {\n return `Server \"${name}\" is not registered. Use \\`mcp_control({ action: \"enable\", server: \"${name}\" })\\` first.`;\n }\n if (live.state !== 'connected') {\n return `Server \"${name}\" is not connected (state: ${live.state}). Use \\`enable\\` to start it first.`;\n }\n if (deps.registry.isActivated?.(name)) {\n return `${green('●')} Server \"${name}\" tools are already active. Use \\`deactivate\\` to hide them.`;\n }\n deps.registry.activateServer(name);\n const updated = deps.registry.describe().find((s) => s.name === name);\n return `${green('✓ Activated')} \"${name}\" — ${updated?.toolCount ?? 0} tool(s) now registered. Use \\`mcp_control({ action: \"deactivate\", server: \"${name}\" })\\` to hide them when done.`;\n}\n\n/**\n * Ephemerally deactivate a server's tools without disconnecting.\n * Calls `registry.deactivateServer()` when available.\n */\nasync function runDeactivate(\n name: string | undefined,\n deps: { registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for deactivate.';\n if (!deps.registry.deactivateServer) {\n return `Registry does not support ephemeral deactivation. Use \\`disable\\` to stop \"${name}\" instead.`;\n }\n if (!deps.registry.isActivated?.(name)) {\n return `Server \"${name}\" tools are not currently active.`;\n }\n const count = deps.registry.deactivateServer(name);\n return `${yellow('○ Deactivated')} \"${name}\" — ${count} tool(s) unregistered. Server stays connected.`;\n}\n\n// ── Config helpers ──────────────────────────────────────────────────────────────\n\nasync function getConfiguredMcpServers(deps: { getConfig: () => Config; configPath: string }): Promise<Record<string, MCPServerConfig>> {\n const diskConfig = await readJsonObjectFile(deps.configPath);\n if (isMcpServerRecord(diskConfig.mcpServers)) return diskConfig.mcpServers;\n return deps.getConfig().mcpServers ?? {};\n}\n\nfunction isMcpServerRecord(value: unknown): value is Record<string, MCPServerConfig> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\n// ── Colour helpers (no dep on core color — inline) ───────────────────────────\n\nfunction bold(s: string) { return `\\x1b[1m${s}\\x1b[0m`; }\nfunction dim(s: string) { return `\\x1b[2m${s}\\x1b[0m`; }\nfunction green(s: string) { return `\\x1b[32m${s}\\x1b[0m`; }\nfunction yellow(s: string){ return `\\x1b[33m${s}\\x1b[0m`; }\nfunction red(s: string) { return `\\x1b[31m${s}\\x1b[0m`; }\n\nfunction badge(state: string): string {\n switch (state) {\n case 'connected': return green('● connected');\n case 'connecting': return `\\x1b[36m◐ connecting\\x1b[0m`;\n case 'reconnecting': return `\\x1b[36m◑ reconnecting\\x1b[0m`;\n case 'disconnected': return dim('○ disconnected');\n case 'failed': return red('✗ failed');\n default: return dim(state);\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/expect-defined.ts","../../src/utils/error.ts","../../src/security/capabilities.ts","../../src/infrastructure/mcp-servers.ts","../../src/utils/atomic-write.ts","../../src/utils/config-json.ts","../../src/tools/mcp-control.ts"],"names":["stat","fs2","path"],"mappings":"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","file":"index.js","sourcesContent":["/** Assert a value is neither null nor undefined. Throws if it is.\n * Useful after optional chaining and indexed access when the\n * control flow guarantees the value exists but TypeScript can't\n * prove it (e.g. after a check on a related field). */\nexport function expectDefined<T>(value: T | null | undefined, label?: string): T {\n if (value === null || value === undefined) {\n const err = new Error(label ? `Expected ${label} to be defined` : 'Expected value to be defined');\n err.name = 'ExpectDefinedError';\n throw err;\n }\n return value;\n}\n","/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","/**\n * Well-known tool capabilities used for authorization decisions.\n *\n * These are the preferred values for `Tool.capabilities`.\n * New capabilities should be added here with clear documentation.\n *\n * Philosophy (2026-06+):\n * - Prefer capabilities over exact tool name matching.\n * - Subagent guards and future policies should primarily key off capabilities.\n * - Name-based denylists are legacy and will be phased down.\n */\nexport const ToolCapabilities = {\n /** Can execute arbitrary commands in the user's shell (the `bash` tool). */\n SHELL_ARBITRARY: 'shell.arbitrary',\n\n /** Can execute a restricted set of commands (the `exec` tool). */\n SHELL_RESTRICTED: 'shell.restricted',\n\n /** Can read files inside the project (and possibly outside via symlinks if not guarded). */\n FS_READ: 'fs.read',\n\n /** Can write / modify / delete files inside the project. */\n FS_WRITE: 'fs.write',\n\n /** Can write files outside the current project root (very high risk). */\n FS_WRITE_OUTSIDE_PROJECT: 'fs.write.outside-project',\n\n /** Can perform outbound network requests. */\n NET_OUTBOUND: 'net.outbound',\n\n /** Proxies tools from external MCP servers (unknown capability). */\n MCP_PROXY: 'mcp.proxy',\n\n /** Can spawn or manage subagents / multi-agent tasks. */\n SUBAGENT_SPAWN: 'subagent.spawn',\n\n /** Can inspect fleet/subagent coordination state without mutating it. */\n COORDINATION_FLEET_READ: 'coordination.fleet.read',\n\n /** Can read or write inter-agent mailbox messages. */\n COORDINATION_MAIL: 'coordination.mail',\n\n /** Can schedule, inspect, or cancel in-session cron jobs. */\n COORDINATION_CRON: 'coordination.cron',\n\n /** Can mutate global or session configuration / trust state. */\n CONFIG_MUTATE: 'config.mutate',\n\n /** Can install packages or run package managers with side effects. */\n PACKAGE_INSTALL: 'package.install',\n} as const;\n\nexport type ToolCapability = (typeof ToolCapabilities)[keyof typeof ToolCapabilities];\n\n/**\n * Set of capabilities that are considered dangerous for subagents by default.\n * Subagents should not receive these capabilities unless the leader explicitly\n * allows the specific tool at spawn time.\n */\nexport const DANGEROUS_FOR_SUBAGENTS: readonly ToolCapability[] = [\n ToolCapabilities.SHELL_ARBITRARY,\n ToolCapabilities.SHELL_RESTRICTED,\n ToolCapabilities.FS_WRITE,\n ToolCapabilities.FS_WRITE_OUTSIDE_PROJECT,\n ToolCapabilities.MCP_PROXY,\n ToolCapabilities.SUBAGENT_SPAWN,\n ToolCapabilities.CONFIG_MUTATE,\n ToolCapabilities.PACKAGE_INSTALL,\n];\n\n/**\n * Wide capability allowlist for subagents that the user has authorized to act\n * with full developer power (the CLI fleet host applies this to any subagent\n * that isn't given an explicit, narrower grant). It covers everything needed to\n * do real work end-to-end — read, write/edit inside the project, outbound\n * network, and shell/build/install — so a delegated coding or build agent runs\n * the same toolchain the leader would, without per-tool confirmation it cannot\n * answer.\n *\n * Deliberately EXCLUDED (require an explicit per-spawn `allowedCapabilities`\n * grant, because they escape the task's blast radius rather than perform it):\n * - `fs.write.outside-project` — writing outside the repo (e.g. ~/.ssh).\n * - `mcp.proxy` — third-party MCP tools (also hard-blocked by name).\n * - `subagent.spawn` — recursive delegation (the baseline prompt forbids it).\n * - `config.mutate` — rewriting trust/config is privilege escalation, not work.\n */\nexport const WIDE_SUBAGENT_CAPABILITIES: readonly ToolCapability[] = [\n ToolCapabilities.FS_READ,\n ToolCapabilities.FS_WRITE,\n ToolCapabilities.NET_OUTBOUND,\n ToolCapabilities.SHELL_ARBITRARY,\n ToolCapabilities.SHELL_RESTRICTED,\n ToolCapabilities.PACKAGE_INSTALL,\n];\n\n/**\n * Check if a tool (or its capabilities array) includes any dangerous capability\n * for subagent execution.\n */\nexport function hasDangerousCapabilityForSubagents(\n toolOrCaps: { capabilities?: readonly string[] | undefined } | readonly string[] | undefined,\n): boolean {\n if (!toolOrCaps) return false;\n const input = toolOrCaps as never as { capabilities?: readonly string[] | undefined };\n const caps: readonly string[] = Array.isArray(toolOrCaps) ? toolOrCaps : (input.capabilities ?? []);\n return caps.some((c) => DANGEROUS_FOR_SUBAGENTS.includes(c as ToolCapability));\n}\n\n/**\n * Check if a tool declares a specific capability (or any of the provided ones).\n */\nexport function hasCapability(\n toolOrCaps: { capabilities?: readonly string[] | undefined } | readonly string[] | undefined,\n capability: ToolCapability | ToolCapability[],\n): boolean {\n if (!toolOrCaps) return false;\n const input = toolOrCaps as never as { capabilities?: readonly string[] | undefined };\n const caps: readonly string[] = Array.isArray(toolOrCaps) ? toolOrCaps : (input.capabilities ?? []);\n const toCheck = Array.isArray(capability) ? capability : [capability];\n return toCheck.some((c) => caps.includes(c));\n}\n\n/**\n * Returns the intersection of a tool's capabilities with the dangerous set.\n * Useful for logging and audit trails.\n */\nexport function getDangerousCapabilities(\n toolOrCaps: { capabilities?: readonly string[] | undefined } | readonly string[] | undefined,\n): ToolCapability[] {\n if (!toolOrCaps) return [];\n const input = toolOrCaps as never as { capabilities?: readonly string[] | undefined };\n const caps: readonly string[] = Array.isArray(toolOrCaps) ? toolOrCaps : (input.capabilities ?? []);\n return caps.filter((c): c is ToolCapability =>\n DANGEROUS_FOR_SUBAGENTS.includes(c as ToolCapability),\n );\n}\n","import type { MCPServerConfig } from '../types/config.js';\n\n/**\n * Built-in MCP server presets available to all WrongStack users out of the box.\n * These servers must be explicitly enabled in config (disabled by default).\n *\n * To enable: set `mcpServers: { serverName: { enabled: true } }` in your config.\n *\n * Some servers require environment variables or additional config — see notes below.\n *\n * Transport types:\n * stdio — spawns a local npm package binary via child_process\n * sse — HTTP SSE endpoint (client POSTs requests)\n * streamable-http — session-based HTTP with NDJSON responses\n */\n\n/** Filesystem access: read, write, list, search, tree. Good for exploring projects. */\nexport const filesystemServer = (): MCPServerConfig => ({\n name: 'filesystem',\n description: 'Read, write, and navigate the local filesystem (read-heavy tools)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-filesystem', '.'],\n permission: 'confirm',\n});\n\n/** GitHub API: issues, PRs, repos, search, file operations. Requires GITHUB_PERSONAL_ACCESS_TOKEN. */\nexport const githubServer = (): MCPServerConfig => ({\n name: 'github',\n description:\n 'GitHub API — issues, PRs, repos, search, file ops (requires GITHUB_PERSONAL_ACCESS_TOKEN)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-github'],\n permission: 'confirm',\n});\n\n/**\n * Context7 — codebase-aware documentation and Q&A using context from your code.\n * Live documentation for any library, grounded in your actual versions.\n */\nexport const context7Server = (): MCPServerConfig => ({\n name: 'context7',\n description: 'Codebase-aware documentation and Q&A (context7.ai)',\n transport: 'streamable-http',\n url: 'https://mcp.context7.com/mcp',\n permission: 'confirm',\n});\n\n/**\n * Brave Search — web search via Brave Browser's API.\n * Requires BRAVE_SEARCH_API_KEY. Free tier: 2,000 queries/month.\n * Sign up at https://api.search.brave.com/\n */\nexport const braveSearchServer = (): MCPServerConfig => ({\n name: 'brave-search',\n description: 'Web search (Brave). Requires BRAVE_SEARCH_API_KEY — free tier 2k queries/month',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-brave-search'],\n permission: 'confirm',\n});\n\n/**\n * Block (Block, Inc.) — Postgres database access via SQL.\n * Useful for running queries against a connected database during development.\n */\nexport const blockServer = (): MCPServerConfig => ({\n name: 'block',\n description: 'Postgres database access via SQL (Block MCP server)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-block'],\n permission: 'confirm',\n});\n\n/**\n * EverArt — AI image generation via various providers.\n * Requires EVERART_API_KEY.\n */\nexport const everArtServer = (): MCPServerConfig => ({\n name: 'everart',\n description: 'AI image generation (EverArt). Requires EVERART_API_KEY',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-everart'],\n permission: 'confirm',\n});\n\n/**\n * Slack — messaging, channels, search.\n * Requires SLACK_BOT_TOKEN and either SLACK_TEAM_ID or SLACK_USER_TOKEN.\n */\nexport const slackServer = (): MCPServerConfig => ({\n name: 'slack',\n description: 'Slack — messaging, channels, search. Requires SLACK_BOT_TOKEN + SLACK_TEAM_ID',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-slack'],\n permission: 'confirm',\n});\n\n/**\n * AWS knowledge base — EC2, S3, Lambda, IAM, CloudFormation, cost management.\n * Requires AWS access key + secret in environment.\n */\nexport const awsServer = (): MCPServerConfig => ({\n name: 'aws',\n description: 'AWS — EC2, S3, Lambda, IAM, CloudFormation, costs. Requires AWS credentials',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-aws'],\n permission: 'confirm',\n});\n\n/**\n * Google Maps — directions, distance matrix, geocoding, places.\n * Requires GOOGLE_MAPS_API_KEY.\n */\nexport const googleMapsServer = (): MCPServerConfig => ({\n name: 'google-maps',\n description: 'Google Maps — directions, geocoding, places. Requires GOOGLE_MAPS_API_KEY',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-google-maps'],\n permission: 'confirm',\n});\n\n/** Sentinel — security vulnerability scanning (sentinel-labs). */\nexport const sentinelServer = (): MCPServerConfig => ({\n name: 'sentinel',\n description: 'Security vulnerability scanning (Sentinel)',\n transport: 'streamable-http',\n url: 'https://mcp.sentinel.ai',\n permission: 'deny', // security tool — require explicit confirmation\n});\n\n/**\n * Z.AI Vision MCP — image understanding fallback for text-only models.\n * Requires Z_AI_API_KEY. Tools are read-only and safe to run automatically.\n */\nexport const zaiVisionServer = (): MCPServerConfig => ({\n name: 'zai-vision',\n description: 'Z.AI Vision MCP — image analysis and screenshot understanding',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@z_ai/mcp-server@latest'],\n env: { Z_AI_MODE: 'ZAI' },\n allowedTools: [\n 'image_analysis',\n 'extract_text_from_screenshot',\n 'diagnose_error_screenshot',\n 'understand_technical_diagram',\n 'analyze_data_visualization',\n 'ui_diff_check',\n ],\n permission: 'auto',\n});\n\n/**\n * Playwright — browser automation: navigate, click, type, screenshot, evaluate JS.\n * Spawns a headless Chromium browser via @modelcontextprotocol/server-playwright.\n * Tools can read and interact with live web pages — permission defaults to\n * `confirm` because form submission / DOM mutation is possible.\n */\nexport const playwrightServer = (): MCPServerConfig => ({\n name: 'playwright',\n description:\n 'Browser automation — navigate, screenshot, click, type, evaluate JS (headless Chromium)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-playwright'],\n permission: 'confirm',\n});\n\n/**\n * MiniMax Token Plan MCP — search + understand_image.\n * This preset exposes only the read-only image understanding tool by default.\n * Requires MINIMAX_API_KEY and uvx on PATH.\n */\nexport const miniMaxVisionServer = (): MCPServerConfig => ({\n name: 'minimax-vision',\n description: 'MiniMax MCP — image understanding via understand_image',\n transport: 'stdio',\n command: 'uvx',\n args: ['minimax-coding-plan-mcp', '-y'],\n env: {\n MINIMAX_MCP_BASE_PATH: './.wrongstack/minimax-output',\n MINIMAX_API_HOST: 'https://api.minimax.io',\n MINIMAX_API_RESOURCE_MODE: 'url',\n },\n allowedTools: ['understand_image'],\n permission: 'auto',\n});\n\n/**\n * SSH Manager — remote SSH execution, file transfer, tunnels, health checks, and deployment ops.\n * Server credentials are intentionally NOT embedded here. Configure hosts via mcp-ssh-manager's\n * env/TOML config (for example SSH_SERVER_<NAME>_HOST, USER, KEYPATH/PASSWORD) or ssh-agent.\n */\nexport const sshManagerServer = (): MCPServerConfig => ({\n name: 'ssh',\n description:\n 'Remote SSH management — execute commands, transfer files, tunnels, health checks (mcp-ssh-manager)',\n transport: 'stdio',\n command: 'npx',\n args: ['-y', 'mcp-ssh-manager'],\n env: {\n MCP_SSH_COMPACT_JSON: 'true',\n MCP_SSH_DEFAULT_TIMEOUT: '120000',\n },\n permission: 'confirm',\n requestTimeoutMs: 180_000,\n});\n\n/** Everything bundled — full set of built-in servers. Useful for `wstack mcp add --all`. */\nexport const allServers = (): Record<string, MCPServerConfig> => ({\n filesystem: { ...filesystemServer(), enabled: false },\n github: { ...githubServer(), enabled: false },\n context7: { ...context7Server(), enabled: false },\n 'brave-search': { ...braveSearchServer(), enabled: false },\n block: { ...blockServer(), enabled: false },\n everart: { ...everArtServer(), enabled: false },\n slack: { ...slackServer(), enabled: false },\n aws: { ...awsServer(), enabled: false },\n 'google-maps': { ...googleMapsServer(), enabled: false },\n sentinel: { ...sentinelServer(), enabled: false },\n 'zai-vision': { ...zaiVisionServer(), enabled: false },\n 'minimax-vision': { ...miniMaxVisionServer(), enabled: false },\n playwright: { ...playwrightServer(), enabled: false },\n ssh: { ...sshManagerServer(), enabled: false },\n});\n","import { randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { FsError } from '../types/errors.js';\n\nexport interface AtomicWriteOptions {\n mode?: number | undefined;\n encoding?: BufferEncoding | undefined;\n}\n\nexport interface FileLockOptions {\n timeoutMs?: number | undefined;\n staleMs?: number | undefined;\n}\n\nexport async function atomicWrite(\n targetPath: string,\n content: string | Uint8Array,\n opts: AtomicWriteOptions = {},\n): Promise<void> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const tmp = path.join(dir, `.${path.basename(targetPath)}.${randomBytes(6).toString('hex')}.tmp`);\n\n // Write content to tmp first; 'wx' ensures exclusive creation (fails if\n // tmp already exists — extremely unlikely with 6-byte random suffix).\n try {\n if (typeof content === 'string') {\n await fs.writeFile(tmp, content, { flag: 'wx', encoding: opts.encoding ?? 'utf8' });\n } else {\n await fs.writeFile(tmp, content, { flag: 'wx' });\n }\n try {\n const fh = await fs.open(tmp, 'r+');\n try {\n await fh.sync();\n } finally {\n await fh.close();\n }\n } catch {\n // fsync best-effort\n }\n // Now safely read mode from target (if it exists) and apply to tmp before rename.\n // Prefer opts.mode for new files; for existing files preserve their mode.\n let mode: number | undefined;\n try {\n const stat = await fs.stat(targetPath);\n mode = stat.mode & 0o777;\n } catch {\n mode = opts.mode;\n }\n if (mode !== undefined) {\n await fs.chmod(tmp, mode);\n }\n await renameWithRetry(tmp, targetPath);\n // P3 #20 (before-release.md): on Windows, fs.rename (MoveFileExW) does\n // not preserve Unix permission bits — the chmod above applies to the tmp\n // file, but the rename may reset the destination's mode to the Windows\n // default. Re-apply the mode after rename on win32 so an edited file\n // keeps its executable bit (or any non-default permission). On POSIX,\n // rename preserves metadata so this is a no-op (chmod is idempotent and\n // cheap), but we gate it on win32 to avoid the extra stat+chmod on the\n // common path.\n if (mode !== undefined && process.platform === 'win32') {\n try {\n await fs.chmod(targetPath, mode);\n } catch {\n // Best-effort: a transient EPERM (antivirus lock) should not fail\n // the write — the content is already on disk.\n }\n }\n } catch (err) {\n try {\n await fs.unlink(tmp);\n } catch {\n // ignore cleanup error\n }\n throw err;\n }\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\nexport async function withFileLock<T>(\n targetPath: string,\n fn: () => Promise<T>,\n opts: FileLockOptions = {},\n): Promise<T> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const lockPath = path.join(dir, `.${path.basename(targetPath)}.lock`);\n const timeoutMs = opts.timeoutMs ?? 5_000;\n const staleMs = opts.staleMs ?? 30_000;\n const started = Date.now();\n let handle: fs.FileHandle | undefined;\n\n for (;;) {\n try {\n handle = await fs.open(lockPath, 'wx');\n await handle.writeFile(`${process.pid}:${Date.now()}`);\n break;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n // ENOENT means the directory was deleted (e.g. by concurrent cleanup).\n // Recreate it and retry acquiring the lock.\n if (code === 'ENOENT') {\n await fs.mkdir(dir, { recursive: true });\n continue;\n }\n if (code !== 'EEXIST') throw err;\n try {\n const stat = await fs.stat(lockPath);\n if (Date.now() - stat.mtimeMs > staleMs) {\n await fs.unlink(lockPath);\n continue;\n }\n } catch {\n continue;\n }\n if (Date.now() - started >= timeoutMs) {\n throw new FsError({\n message: `Timed out waiting for file lock: ${targetPath}`,\n code: 'FS_ATOMIC_WRITE_FAILED',\n path: targetPath,\n context: { timeoutMs },\n });\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n }\n\n try {\n return await fn();\n } finally {\n try {\n await handle?.close();\n } catch {\n // ignore\n }\n try {\n await fs.unlink(lockPath);\n } catch {\n // ignore\n }\n }\n}\n\n// On Windows, fs.rename over an existing file can fail with EPERM/EBUSY/EACCES\n// when antivirus, file indexers, editor file watchers, or a concurrent writer\n// briefly hold a handle on the destination. These are transient — retry with a\n// short backoff before giving up. POSIX renames are atomic and won't hit this.\nconst TRANSIENT_RENAME_CODES = new Set(['EPERM', 'EBUSY', 'EACCES', 'ENOTEMPTY']);\n\nasync function renameWithRetry(from: string, to: string): Promise<void> {\n if (process.platform !== 'win32') {\n await fs.rename(from, to);\n return;\n }\n const delays = [10, 25, 60, 120, 250];\n let lastErr: unknown;\n for (let i = 0; i <= delays.length; i++) {\n try {\n await fs.rename(from, to);\n return;\n } catch (err) {\n lastErr = err;\n const code = (err as NodeJS.ErrnoException)?.code;\n if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {\n throw err;\n }\n await new Promise((resolve) => setTimeout(resolve, delays[i]));\n }\n }\n throw lastErr;\n}\n","import * as fs from 'node:fs/promises';\nimport { atomicWrite } from './atomic-write.js';\n\nexport type JsonObject = Record<string, unknown>;\nexport type JsonPathSegment = string | number;\nexport type JsonPath = readonly JsonPathSegment[];\n\nexport async function readJsonObjectFile(filePath: string): Promise<JsonObject> {\n try {\n const parsed = JSON.parse(await fs.readFile(filePath, 'utf8')) as unknown;\n return isJsonObject(parsed) ? parsed : {};\n } catch {\n return {};\n }\n}\n\nexport async function jsonObjectFileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function writeJsonObjectFile(filePath: string, value: JsonObject): Promise<void> {\n await atomicWrite(filePath, JSON.stringify(value, null, 2), { mode: 0o600 });\n}\n\nexport async function updateJsonObjectFile(\n filePath: string,\n mutator: (config: JsonObject) => void | JsonObject | Promise<void | JsonObject>,\n): Promise<JsonObject> {\n const config = await readJsonObjectFile(filePath);\n const maybeNext = await mutator(config);\n const next = maybeNext && isJsonObject(maybeNext) ? maybeNext : config;\n await writeJsonObjectFile(filePath, next);\n return next;\n}\n\nexport function getJsonPath(root: unknown, path: JsonPath): unknown {\n let current = root;\n for (const segment of path) {\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) return undefined;\n current = current[segment];\n continue;\n }\n if (!isJsonObject(current)) return undefined;\n current = current[segment];\n }\n return current;\n}\n\nexport function setJsonPath(root: JsonObject, path: JsonPath, value: unknown): JsonObject {\n if (path.length === 0) {\n if (!isJsonObject(value)) throw new Error('Root config value must be an object');\n return value;\n }\n const parent = ensureJsonParent(root, path);\n const leaf = lastPathSegment(path);\n if (typeof leaf === 'number') {\n if (!Array.isArray(parent)) throw new Error(`Cannot set numeric segment ${leaf} on non-array parent`);\n parent[leaf] = value;\n } else {\n if (!isJsonObject(parent)) throw new Error(`Cannot set property ${leaf} on non-object parent`);\n parent[leaf] = value;\n }\n return root;\n}\n\nexport function removeJsonPath(root: JsonObject, path: JsonPath): boolean {\n if (path.length === 0) return false;\n const parent = getJsonPath(root, path.slice(0, -1));\n const leaf = lastPathSegment(path);\n if (typeof leaf === 'number') {\n if (!Array.isArray(parent) || leaf < 0 || leaf >= parent.length) return false;\n parent.splice(leaf, 1);\n return true;\n }\n if (!isJsonObject(parent) || !(leaf in parent)) return false;\n delete parent[leaf];\n return true;\n}\n\nexport async function setJsonPathInFile(filePath: string, path: JsonPath, value: unknown): Promise<JsonObject> {\n return updateJsonObjectFile(filePath, (config) => setJsonPath(config, path, value));\n}\n\nexport async function removeJsonPathInFile(filePath: string, path: JsonPath): Promise<JsonObject> {\n return updateJsonObjectFile(filePath, (config) => {\n removeJsonPath(config, path);\n });\n}\n\nexport function isJsonObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction lastPathSegment(path: JsonPath): JsonPathSegment {\n const segment = path[path.length - 1];\n if (segment === undefined) throw new Error('Invalid empty JSON path');\n return segment;\n}\n\nfunction ensureJsonParent(root: JsonObject, path: JsonPath): JsonObject | unknown[] {\n let current: JsonObject | unknown[] = root;\n for (let i = 0; i < path.length - 1; i += 1) {\n const segment = path[i];\n const nextSegment = path[i + 1];\n if (segment === undefined) throw new Error('Invalid empty JSON path segment');\n const nextContainer = typeof nextSegment === 'number' ? [] : {};\n\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) throw new Error(`Cannot traverse numeric segment ${segment} on non-array parent`);\n if (!isJsonObject(current[segment]) && !Array.isArray(current[segment])) current[segment] = nextContainer;\n current = current[segment] as JsonObject | unknown[];\n } else {\n if (!isJsonObject(current)) throw new Error(`Cannot traverse property ${segment} on non-object parent`);\n if (!isJsonObject(current[segment]) && !Array.isArray(current[segment])) current[segment] = nextContainer;\n current = current[segment] as JsonObject | unknown[];\n }\n }\n return current;\n}\n","import { expectDefined } from '../utils/expect-defined.js';\nimport { toErrorMessage } from '../utils/error.js';\nimport { ToolCapabilities } from '../security/capabilities.js';\n/**\n * `mcp_control` — LLM-driven MCP server lifecycle management.\n *\n * The model calls this tool to:\n * list — see all known servers (running or not) without starting any\n * search — filter the server catalog by name or description keyword\n * enable — start a server and register its tools\n * disable — stop a server and unregister its tools\n * restart — stop then re-start a running server\n *\n * This is the primary mechanism by which the LLM autonomously extends its\n * own capabilities at runtime — e.g. \"I need GitHub access, let me enable it.\"\n */\nimport { allServers } from '../infrastructure/mcp-servers.js';\nimport { readJsonObjectFile, setJsonPath, updateJsonObjectFile } from '../utils/config-json.js';\nimport type { Config, JSONSchema, MCPServerConfig, Tool } from '../index.js';\nexport interface MCPRegistryHandle {\n start(cfg: MCPServerConfig): Promise<void>;\n stop(name: string): Promise<void>;\n restart(name: string): Promise<void>;\n describe(): {\n name: string;\n state: string;\n toolCount: number;\n enabled: boolean;\n tools?: string[];\n }[];\n list(): { name: string; state: string; toolCount: number; tools?: string[] }[];\n /**\n * Register all cached tools for a server without restarting it.\n * No-op if the server is not connected or tools are already active.\n * Used in token-saving mode to temporarily expose MCP tools.\n */\n activateServer?(name: string): void;\n /**\n * Unregister all tools for a server without disconnecting it.\n * Returns the number of tools that were deactivated.\n * Used in token-saving mode to hide MCP tools after use.\n */\n deactivateServer?(name: string): number;\n /**\n * Check whether a server's tools are currently registered.\n */\n isActivated?(name: string): boolean;\n}\n\nexport interface CreateMcpControlToolOptions {\n /**\n * Read the current config object. The tool never mutates this directly —\n * writes go to the global config file via `configPath`.\n */\n getConfig: () => Config;\n /**\n * Path to ~/.wrongstack/config.json (or equivalent) for atomic config writes.\n */\n configPath: string;\n /**\n * Live MCP registry for runtime start/stop/restart. The tool calls these\n * immediately so the LLM sees the result of its action in the same turn.\n */\n registry: MCPRegistryHandle;\n}\n\nexport function createMcpControlTool(opts: CreateMcpControlToolOptions): Tool {\n const { getConfig, configPath, registry } = opts;\n\n const inputSchema: JSONSchema = {\n type: 'object',\n properties: {\n action: {\n type: 'string',\n enum: ['list', 'search', 'enable', 'disable', 'restart', 'activate', 'deactivate'],\n description: 'The management action to perform. activate/deactivate toggle tool registration ephemerally without disconnecting.',\n },\n /** Filter for `search`. Matches server name or description case-insensitively. */\n query: {\n type: 'string',\n description: 'Search term for `search` action. Matches server name or description.',\n },\n /** Target server name for `enable`, `disable`, `restart`, `activate`, `deactivate`. */\n server: {\n type: 'string',\n description: 'Server name (e.g. \"github\", \"filesystem\", \"brave-search\").',\n },\n },\n required: ['action'],\n };\n\n return {\n name: 'mcp_control',\n description:\n 'Manage MCP server lifecycle: list available servers, search by name or capability, enable or disable servers at runtime, restart running servers. Use activate/deactivate to ephemerally toggle tool registration without disconnecting — ideal for token-saving mode where MCP tools are lazy-loaded on demand. NOTE: `enable`/`restart` start a server process, which for the built-in stdio presets runs `npx -y <package>` — i.e. it fetches and executes an npm package from the network. Treat it as code execution.',\n category: 'mcp',\n permission: 'auto',\n mutating: true,\n // `enable`/`restart` spawn a server process that, for the stdio presets,\n // fetches and runs an npm package (`npx -y <pkg>`) — effectively remote\n // code execution. Marking the tool destructive means the YOLO\n // `confirmDestructive` safety net still prompts before it runs (plain\n // non-YOLO already confirms via the CONFIG_MUTATE dangerous-capability\n // net in the executor). Read-only actions (list/search) ride the same\n // tool but are cheap to confirm/trust once.\n riskTier: 'destructive',\n capabilities: [ToolCapabilities.CONFIG_MUTATE],\n inputSchema,\n async execute(raw) {\n const input = raw as { action: string; query?: string | undefined; server?: string | undefined };\n return mcpControlDispatch(input, { getConfig, configPath, registry });\n },\n };\n}\n\n// ── Dispatch ──────────────────────────────────────────────────────────────────\n\nasync function mcpControlDispatch(\n input: { action: string; query?: string | undefined; server?: string | undefined },\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n const { action, query, server } = input;\n\n switch (action) {\n case 'list': return renderList(deps);\n case 'search': return renderSearch(query ?? '', deps);\n case 'enable': return server ? runEnable(server, deps) : '`server` is required for enable.';\n case 'disable': return server ? runDisable(server, deps) : '`server` is required for disable.';\n case 'restart': return server ? runRestart(server, deps) : '`server` is required for restart.';\n case 'activate': return server ? runActivate(server, deps) : '`server` is required for activate.';\n case 'deactivate': return server ? runDeactivate(server, deps) : '`server` is required for deactivate.';\n default:\n return `Unknown action \"${action}\". Use one of: list, search, enable, disable, restart, activate, deactivate.`;\n }\n}\n\n// ── Actions ───────────────────────────────────────────────────────────────────\n\nasync function renderList(deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle }): Promise<string> {\n const configured = await getConfiguredMcpServers(deps);\n const live = deps.registry.describe();\n\n if (Object.keys(configured).length === 0) {\n return [\n 'No MCP servers configured.',\n ' Use `mcp_control({ action: \"search\" })` to see available presets,',\n ' then `mcp_control({ action: \"enable\", server: \"<name>\" })` to add one.',\n ].join('\\n');\n }\n\n const lines: string[] = [];\n const liveMap = new Map(live.map((s) => [s.name, s]));\n\n for (const [name, cfg] of Object.entries(configured)) {\n const liveInfo = liveMap.get(name);\n const toolCount = liveInfo ? ` (${liveInfo.toolCount} tools)` : '';\n const stateStr = liveInfo ? badge(liveInfo.state) : dim('○ not loaded');\n const enabled = cfg.enabled === false\n ? `${dim('disabled')} `\n : `${green('● enabled')} `;\n lines.push(` ${bold(name)} ${enabled}${stateStr}${toolCount}`);\n if (cfg.description) lines.push(` ${dim(cfg.description)}`);\n }\n\n lines.push('');\n lines.push(dim(' Use `mcp_control({ action: \"search\", query: \"<keyword>\" })` to find servers.'));\n lines.push(dim(' Use `mcp_control({ action: \"enable\", server: \"<name>\" })` to start a server.'));\n return lines.join('\\n');\n}\n\nasync function renderSearch(\n query: string,\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n const configured = await getConfiguredMcpServers(deps);\n const all = allServers();\n const q = query.toLowerCase();\n\n const configuredNames = new Set(Object.keys(configured));\n\n // Match against configured servers first, then remaining presets\n const configuredEntries = Object.entries(configured).filter(\n ([name, cfg]) =>\n name.toLowerCase().includes(q) ||\n (cfg.description ?? '').toLowerCase().includes(q),\n );\n\n const unconfiguredEntries = Object.entries(all)\n .filter(([name]) => !configuredNames.has(name))\n .filter(\n ([name, cfg]) =>\n name.toLowerCase().includes(q) ||\n (cfg.description ?? '').toLowerCase().includes(q),\n );\n\n const lines: string[] = [];\n\n if (configuredEntries.length > 0) {\n lines.push(bold('Configured servers matching \"') + query + '\":');\n for (const [name, cfg] of configuredEntries) {\n lines.push(` ${bold(name)} ${cfg.description ?? cfg.transport}`);\n }\n lines.push('');\n }\n\n if (unconfiguredEntries.length > 0) {\n lines.push(bold('Available presets matching \"') + query + '\":');\n for (const [name, cfg] of unconfiguredEntries) {\n const warn = cfg.permission === 'deny' ? red(' ⚠ confirm required') : '';\n lines.push(` ${bold(name)} ${cfg.description ?? cfg.transport}${warn}`);\n }\n lines.push('');\n }\n\n if (configuredEntries.length === 0 && unconfiguredEntries.length === 0) {\n return `No servers match \"${query}\". Try a shorter keyword or \\`mcp_control({ action: \"list\" })\\`.`;\n }\n\n const total = configuredEntries.length + unconfiguredEntries.length;\n lines.push(dim(` ${total} server${total !== 1 ? 's' : ''} shown. Run \\`enable\\` on one to activate it.`));\n return lines.join('\\n');\n}\n\nasync function runEnable(\n name: string | undefined,\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for enable. Example: { action: \"enable\", server: \"github\" }';\n\n const all = allServers();\n const configured = deps.getConfig().mcpServers ?? {};\n\n // Resolve the target config — it may be a preset not yet in config\n const cfg = configured[name] ?? all[name];\n if (!cfg) {\n const known = Object.keys(all).join(', ');\n return `Unknown server \"${name}\". Available presets: ${known}`;\n }\n\n // Write to config (add or update) using the shared JSON path helper.\n await updateJsonObjectFile(deps.configPath, (full) => {\n const current = isMcpServerRecord(full.mcpServers) ? full.mcpServers : {};\n setJsonPath(full, ['mcpServers', name], { ...current[name], ...cfg, enabled: true });\n });\n\n // Start the server in the registry\n try {\n const live = deps.registry.describe().find((s) => s.name === name);\n if (live && live.state === 'connected') {\n return `${green('●')} Server \"${name}\" is already running (${live.toolCount} tools registered).`;\n }\n await deps.registry.start({ ...cfg, enabled: true });\n const updated = deps.registry.describe().find((s) => s.name === name);\n return `${green('✓ Enabled and started')} \"${name}\"${updated ? ` (${updated.toolCount} tools registered).` : '.'}`;\n } catch (err) {\n return `${red('✗ Failed to start')} \"${name}\": ${toErrorMessage(err)}`;\n }\n}\n\nasync function runDisable(\n name: string | undefined,\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for disable. Example: { action: \"disable\", server: \"github\" }';\n\n const configured = deps.getConfig().mcpServers ?? {};\n if (!configured[name]) {\n return `Server \"${name}\" is not in config. Add it with \\`mcp_control({ action: \"enable\", server: \"${name}\" })\\`.`;\n }\n\n // Write to config using the shared JSON path helper.\n await updateJsonObjectFile(deps.configPath, (full) => {\n const current = isMcpServerRecord(full.mcpServers) ? full.mcpServers : {};\n const existing = expectDefined(current[name]);\n setJsonPath(full, ['mcpServers', name], { ...existing, enabled: false });\n });\n\n // Stop the running server\n try {\n await deps.registry.stop(name);\n return `${yellow('○ Disabled')} \"${name}\". It will not be started on next boot.`;\n } catch {\n return `${yellow('○ Disabled')} \"${name}\" (it was not running). Config updated.`;\n }\n}\n\nasync function runRestart(\n name: string | undefined,\n deps: { getConfig: () => Config; configPath: string; registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for restart. Example: { action: \"restart\", server: \"github\" }';\n\n const configured = deps.getConfig().mcpServers ?? {};\n if (!configured[name]) {\n return `Server \"${name}\" is not configured. Use \\`mcp_control({ action: \"enable\", server: \"${name}\" })\\` first.`;\n }\n\n try {\n await deps.registry.restart(name);\n const updated = deps.registry.describe().find((s) => s.name === name);\n return `${green('✓ Restarted')} \"${name}\"${updated ? ` (${updated.toolCount} tools registered).` : '.'}`;\n } catch (err) {\n return `${red('✗ Restart failed')} for \"${name}\": ${toErrorMessage(err)}`;\n }\n}\n\n/**\n * Ephemerally activate a server's tools without writing to config or\n * restarting the connection. The server must already be connected (lazy mode).\n * Calls `registry.activateServer()` when available; falls back to a message\n * if the registry doesn't support ephemeral activation.\n */\nasync function runActivate(\n name: string | undefined,\n deps: { registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for activate.';\n if (!deps.registry.activateServer) {\n return `Registry does not support ephemeral activation. Use \\`enable\\` to start \"${name}\" instead.`;\n }\n const live = deps.registry.describe().find((s) => s.name === name);\n if (!live) {\n return `Server \"${name}\" is not registered. Use \\`mcp_control({ action: \"enable\", server: \"${name}\" })\\` first.`;\n }\n if (live.state !== 'connected') {\n return `Server \"${name}\" is not connected (state: ${live.state}). Use \\`enable\\` to start it first.`;\n }\n if (deps.registry.isActivated?.(name)) {\n return `${green('●')} Server \"${name}\" tools are already active. Use \\`deactivate\\` to hide them.`;\n }\n deps.registry.activateServer(name);\n const updated = deps.registry.describe().find((s) => s.name === name);\n return `${green('✓ Activated')} \"${name}\" — ${updated?.toolCount ?? 0} tool(s) now registered. Use \\`mcp_control({ action: \"deactivate\", server: \"${name}\" })\\` to hide them when done.`;\n}\n\n/**\n * Ephemerally deactivate a server's tools without disconnecting.\n * Calls `registry.deactivateServer()` when available.\n */\nasync function runDeactivate(\n name: string | undefined,\n deps: { registry: MCPRegistryHandle },\n): Promise<string> {\n if (!name) return '`server` is required for deactivate.';\n if (!deps.registry.deactivateServer) {\n return `Registry does not support ephemeral deactivation. Use \\`disable\\` to stop \"${name}\" instead.`;\n }\n if (!deps.registry.isActivated?.(name)) {\n return `Server \"${name}\" tools are not currently active.`;\n }\n const count = deps.registry.deactivateServer(name);\n return `${yellow('○ Deactivated')} \"${name}\" — ${count} tool(s) unregistered. Server stays connected.`;\n}\n\n// ── Config helpers ──────────────────────────────────────────────────────────────\n\nasync function getConfiguredMcpServers(deps: { getConfig: () => Config; configPath: string }): Promise<Record<string, MCPServerConfig>> {\n const diskConfig = await readJsonObjectFile(deps.configPath);\n if (isMcpServerRecord(diskConfig.mcpServers)) return diskConfig.mcpServers;\n return deps.getConfig().mcpServers ?? {};\n}\n\nfunction isMcpServerRecord(value: unknown): value is Record<string, MCPServerConfig> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\n// ── Colour helpers (no dep on core color — inline) ───────────────────────────\n\nfunction bold(s: string) { return `\\x1b[1m${s}\\x1b[0m`; }\nfunction dim(s: string) { return `\\x1b[2m${s}\\x1b[0m`; }\nfunction green(s: string) { return `\\x1b[32m${s}\\x1b[0m`; }\nfunction yellow(s: string){ return `\\x1b[33m${s}\\x1b[0m`; }\nfunction red(s: string) { return `\\x1b[31m${s}\\x1b[0m`; }\n\nfunction badge(state: string): string {\n switch (state) {\n case 'connected': return green('● connected');\n case 'connecting': return `\\x1b[36m◐ connecting\\x1b[0m`;\n case 'reconnecting': return `\\x1b[36m◑ reconnecting\\x1b[0m`;\n case 'disconnected': return dim('○ disconnected');\n case 'failed': return red('✗ failed');\n default: return dim(state);\n }\n}\n"]}