indusagi-coding-agent 0.2.8 → 0.2.10

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 (222) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/entry.js +4 -4
  3. package/dist/index.js +4 -4
  4. package/package.json +3 -2
  5. package/src/_decls/entry.ts +18 -0
  6. package/src/_decls/guardrails.ts +35 -0
  7. package/src/_decls/index.ts +26 -0
  8. package/src/addons/contract.ts +236 -0
  9. package/src/addons/dispatch/event-dispatcher.ts +164 -0
  10. package/src/addons/dispatch/index.ts +25 -0
  11. package/src/addons/dispatch/tool-interceptor.ts +208 -0
  12. package/src/addons/host.ts +225 -0
  13. package/src/addons/index.ts +112 -0
  14. package/src/addons/manifest.ts +158 -0
  15. package/src/addons/sandbox.ts +170 -0
  16. package/src/addons/surface.ts +78 -0
  17. package/src/boot/auth-vault.ts +195 -0
  18. package/src/boot/boot.ts +138 -0
  19. package/src/boot/contract.ts +238 -0
  20. package/src/boot/heap.ts +59 -0
  21. package/src/boot/index.ts +28 -0
  22. package/src/boot/invocation.ts +93 -0
  23. package/src/boot/runners/addon-wiring.ts +153 -0
  24. package/src/boot/runners/checkpoint.ts +169 -0
  25. package/src/boot/runners/delegate-runner.ts +294 -0
  26. package/src/boot/runners/index.ts +13 -0
  27. package/src/boot/runners/link-runner.ts +45 -0
  28. package/src/boot/runners/memdir.ts +168 -0
  29. package/src/boot/runners/oneshot-runner.ts +58 -0
  30. package/src/boot/runners/read-state.ts +90 -0
  31. package/src/boot/runners/registry.ts +42 -0
  32. package/src/boot/runners/repl-runner.ts +143 -0
  33. package/src/boot/runners/server-mode.ts +121 -0
  34. package/src/boot/runners/session.ts +641 -0
  35. package/src/boot/server-token.ts +148 -0
  36. package/src/boot/stages.ts +167 -0
  37. package/src/boot/upgrade/apply.ts +94 -0
  38. package/src/boot/upgrade/index.ts +13 -0
  39. package/src/boot/upgrade/upgrades.ts +289 -0
  40. package/src/briefing/compose.ts +150 -0
  41. package/src/briefing/context-docs.ts +19 -0
  42. package/src/briefing/contract.ts +717 -0
  43. package/src/briefing/index.ts +31 -0
  44. package/src/briefing/macros.ts +97 -0
  45. package/src/briefing/skills.ts +47 -0
  46. package/src/capability-deck/bridge-ledger/index.ts +27 -0
  47. package/src/capability-deck/bridge-ledger/key.ts +67 -0
  48. package/src/capability-deck/bridge-ledger/ledger.ts +131 -0
  49. package/src/capability-deck/bridge-ledger/network.ts +117 -0
  50. package/src/capability-deck/builtin-bridge.ts +312 -0
  51. package/src/capability-deck/cards/bg-process-card.ts +335 -0
  52. package/src/capability-deck/cards/index.ts +115 -0
  53. package/src/capability-deck/cards/memory-card.ts +146 -0
  54. package/src/capability-deck/cards/plan-file.ts +97 -0
  55. package/src/capability-deck/cards/plan-tools.ts +185 -0
  56. package/src/capability-deck/cards/saas-card.ts +183 -0
  57. package/src/capability-deck/cards/task-card.ts +207 -0
  58. package/src/capability-deck/cards/todo-card.ts +168 -0
  59. package/src/capability-deck/cards/workflow-card.ts +247 -0
  60. package/src/capability-deck/contract.ts +388 -0
  61. package/src/capability-deck/index.ts +48 -0
  62. package/src/capability-deck/manifest.ts +109 -0
  63. package/src/capability-deck/provision.ts +169 -0
  64. package/src/channels/contract.ts +191 -0
  65. package/src/channels/framer.ts +50 -0
  66. package/src/channels/index.ts +101 -0
  67. package/src/channels/link/dialog.ts +129 -0
  68. package/src/channels/link/driver.ts +190 -0
  69. package/src/channels/link/index.ts +34 -0
  70. package/src/channels/link/server.ts +134 -0
  71. package/src/channels/oneshot.ts +90 -0
  72. package/src/channels/ops.ts +65 -0
  73. package/src/channels/session-ops.ts +81 -0
  74. package/src/conductor/bash-guard.ts +599 -0
  75. package/src/conductor/catalog/catalog.ts +116 -0
  76. package/src/conductor/catalog/index.ts +8 -0
  77. package/src/conductor/catalog/matcher.ts +134 -0
  78. package/src/conductor/conductor.ts +234 -0
  79. package/src/conductor/contract.ts +842 -0
  80. package/src/conductor/diagnostics.ts +227 -0
  81. package/src/conductor/index.ts +33 -0
  82. package/src/conductor/permissions.ts +588 -0
  83. package/src/conductor/quota-error.ts +49 -0
  84. package/src/conductor/signal-hub/hub.ts +46 -0
  85. package/src/conductor/signal-hub/index.ts +2 -0
  86. package/src/conductor/signal-hub/translate.test.ts +81 -0
  87. package/src/conductor/signal-hub/translate.ts +74 -0
  88. package/src/conductor/skill-parse/index.ts +2 -0
  89. package/src/conductor/skill-parse/parse.ts +108 -0
  90. package/src/conductor/transcript-store/index.ts +22 -0
  91. package/src/conductor/transcript-store/serialize.ts +116 -0
  92. package/src/conductor/transcript-store/store.ts +205 -0
  93. package/src/console/auth-status.ts +56 -0
  94. package/src/console/components/AgentsView.ts +165 -0
  95. package/src/console/components/BackgroundAgents.ts +155 -0
  96. package/src/console/components/Banner.ts +334 -0
  97. package/src/console/components/Composer.ts +94 -0
  98. package/src/console/components/StatusBar.ts +49 -0
  99. package/src/console/components/TerminalConsole.ts +1090 -0
  100. package/src/console/components/WorkingIndicator.ts +98 -0
  101. package/src/console/components/banner-sweep.ts +24 -0
  102. package/src/console/components/welcome.ts +74 -0
  103. package/src/console/contract.ts +630 -0
  104. package/src/console/index.ts +34 -0
  105. package/src/console/input/complete.ts +127 -0
  106. package/src/console/input/dir-reader.ts +34 -0
  107. package/src/console/input/index.ts +23 -0
  108. package/src/console/input/keymap.ts +159 -0
  109. package/src/console/input/paste.ts +104 -0
  110. package/src/console/mount.ts +56 -0
  111. package/src/console/overlays/approval-queue.ts +57 -0
  112. package/src/console/overlays/approval.ts +130 -0
  113. package/src/console/overlays/auth.ts +342 -0
  114. package/src/console/overlays/boards.ts +308 -0
  115. package/src/console/overlays/host.ts +36 -0
  116. package/src/console/overlays/index.ts +26 -0
  117. package/src/console/overlays/pickers.ts +258 -0
  118. package/src/console/overlays/sessions.ts +190 -0
  119. package/src/console/reducer.ts +182 -0
  120. package/src/console/slash/builtins.ts +81 -0
  121. package/src/console/slash/commands/dynamic.ts +83 -0
  122. package/src/console/slash/commands/integrations.ts +695 -0
  123. package/src/console/slash/commands/shared.ts +75 -0
  124. package/src/console/slash/commands/transcript.ts +263 -0
  125. package/src/console/slash/commands/workbench.ts +246 -0
  126. package/src/console/slash/index.ts +15 -0
  127. package/src/console/slash/registry.ts +70 -0
  128. package/src/console/slash/resolve.ts +63 -0
  129. package/src/console/startup.ts +209 -0
  130. package/src/console/theme/adapter.ts +45 -0
  131. package/src/console/theme/index.ts +7 -0
  132. package/src/console/theme/palette.ts +68 -0
  133. package/src/console/theme/resolve.ts +39 -0
  134. package/src/console/theme/tokens.ts +71 -0
  135. package/src/entry.ts +55 -0
  136. package/src/guardrails.ts +37 -0
  137. package/src/index.ts +18 -0
  138. package/src/insight/channel.ts +88 -0
  139. package/src/insight/contract.ts +185 -0
  140. package/src/insight/index.ts +110 -0
  141. package/src/insight/recorder.ts +213 -0
  142. package/src/insight/redaction.ts +157 -0
  143. package/src/insight/replay.ts +158 -0
  144. package/src/insight/sampling.ts +70 -0
  145. package/src/insight/serialize.ts +50 -0
  146. package/src/insight/sinks/console.ts +64 -0
  147. package/src/insight/sinks/file.ts +40 -0
  148. package/src/insight/sinks/index.ts +24 -0
  149. package/src/insight/sinks/stream.ts +54 -0
  150. package/src/integrations/sarvam/attach.ts +239 -0
  151. package/src/integrations/sarvam/config.ts +156 -0
  152. package/src/integrations/sarvam/index.ts +25 -0
  153. package/src/integrations/sarvam/sarvam.test.ts +60 -0
  154. package/src/integrations/sarvam/types.ts +27 -0
  155. package/src/integrations/zoho/attach.ts +342 -0
  156. package/src/integrations/zoho/config.ts +125 -0
  157. package/src/integrations/zoho/index.ts +27 -0
  158. package/src/integrations/zoho/types.ts +21 -0
  159. package/src/integrations/zoho/zoho.test.ts +50 -0
  160. package/src/kit/clipboard-image.ts +107 -0
  161. package/src/kit/external-editor.ts +48 -0
  162. package/src/kit/image.ts +59 -0
  163. package/src/kit/index.ts +51 -0
  164. package/src/kit/shell.ts +19 -0
  165. package/src/kit/tool-fetch.ts +85 -0
  166. package/src/launch/catalog.ts +148 -0
  167. package/src/launch/contract.ts +187 -0
  168. package/src/launch/credentials.ts +625 -0
  169. package/src/launch/index.ts +98 -0
  170. package/src/launch/invocation/attachments.ts +179 -0
  171. package/src/launch/invocation/flags.ts +196 -0
  172. package/src/launch/invocation/index.ts +25 -0
  173. package/src/launch/invocation/read.ts +260 -0
  174. package/src/launch/invocation/usage.ts +67 -0
  175. package/src/launch/login.ts +324 -0
  176. package/src/launch/oauth.test.ts +18 -0
  177. package/src/launch/oauth.ts +203 -0
  178. package/src/launch/packages.ts +194 -0
  179. package/src/launch/pickers.ts +189 -0
  180. package/src/runtime-bridge/bridges/_drive.ts +96 -0
  181. package/src/runtime-bridge/bridges/builtins.ts +68 -0
  182. package/src/runtime-bridge/bridges/claude-cli.ts +123 -0
  183. package/src/runtime-bridge/bridges/codex-cli.ts +142 -0
  184. package/src/runtime-bridge/bridges/index.ts +33 -0
  185. package/src/runtime-bridge/bridges/indusagi-cli.ts +155 -0
  186. package/src/runtime-bridge/broker.ts +227 -0
  187. package/src/runtime-bridge/contract.ts +122 -0
  188. package/src/runtime-bridge/index.ts +79 -0
  189. package/src/runtime-bridge/sink.ts +180 -0
  190. package/src/sessions/contract.ts +81 -0
  191. package/src/sessions/index.ts +13 -0
  192. package/src/sessions/library.ts +229 -0
  193. package/src/settings/contract.ts +114 -0
  194. package/src/settings/index.ts +32 -0
  195. package/src/settings/manager.ts +117 -0
  196. package/src/transcript-export/index.ts +45 -0
  197. package/src/transcript-export/publish.ts +260 -0
  198. package/src/transcript-export/sgr.ts +315 -0
  199. package/src/transcript-export/template.ts +272 -0
  200. package/src/transcript-export/theme-bridge.ts +150 -0
  201. package/src/window-budget/budget/estimate.ts +135 -0
  202. package/src/window-budget/budget/gate.ts +33 -0
  203. package/src/window-budget/budget/index.ts +16 -0
  204. package/src/window-budget/budget/slice.ts +56 -0
  205. package/src/window-budget/condenser.ts +58 -0
  206. package/src/window-budget/contract.ts +184 -0
  207. package/src/window-budget/index.ts +19 -0
  208. package/src/window-budget/microcompact.ts +95 -0
  209. package/src/window-budget/rehydrate.ts +136 -0
  210. package/src/window-budget/summarize/condense.ts +103 -0
  211. package/src/window-budget/summarize/index.ts +14 -0
  212. package/src/window-budget/summarize/prompt.ts +149 -0
  213. package/src/workflow-engine/agent-runner.ts +181 -0
  214. package/src/workflow-engine/display.ts +224 -0
  215. package/src/workflow-engine/engine.ts +294 -0
  216. package/src/workflow-engine/index.ts +23 -0
  217. package/src/workflow-engine/parse.ts +172 -0
  218. package/src/workflow-engine/structured-output.ts +35 -0
  219. package/src/workspace/brand.ts +29 -0
  220. package/src/workspace/index.ts +18 -0
  221. package/src/workspace/locator.ts +103 -0
  222. package/src/workspace/runtime-detect.ts +64 -0
@@ -0,0 +1,31 @@
1
+ // @ts-nocheck
2
+ // Type declarations recovered from dist/types (no runtime body)
3
+ /**
4
+ * Briefing subsystem — public barrel.
5
+ *
6
+ * Re-exports the FROZEN prompt-and-presentation contract: the declarative
7
+ * system-prompt pipeline ({@link BriefingSection} over a {@link BriefingContext},
8
+ * composed by `composeBriefing`), the single-pass `$arg` macro model
9
+ * ({@link Macro}, {@link MacroScope}, {@link MacroToken}), the Agent-Skills
10
+ * capability cards ({@link SkillCard} parsed from a `SKILL.md`), the table-driven
11
+ * SGR machine ({@link SgrState}, {@link SgrToken}, {@link SgrMutation}), and the
12
+ * HTML-transcript color layer ({@link ExportTheme} behind a {@link ThemeBridge}
13
+ * with a {@link LuminanceLut}) plus the publish surface.
14
+ *
15
+ * Behavior modules land in this barrel as they are written. Currently exported:
16
+ * the declarative section composer (`composeBriefing` over `BRIEFING_SECTIONS`),
17
+ * the single-pass `$arg` macro scanner + loader (`loadMacros`, `applyMacros`,
18
+ * and friends), and the Agent-Skills capability-card loader (`loadSkillCards`,
19
+ * `gatherSkillCards`). The SGR painter, theme bridge, and transcript publisher
20
+ * are added here as they land. Consumers import the briefing surface from
21
+ * `src/briefing` rather than reaching into individual modules.
22
+ */
23
+ export type { BriefingContext, BriefingSection, Briefing, BriefingInputs, SubagentBrief, ContextDoc, MacroOrigin, Macro, MacroScope, MacroTokenKind, MacroToken, SkillFrontmatter, SkillCard, SkillOutcomeKind, SkillDiagnostic, SkillLoad, SgrState, SgrToken, SgrMutation, ExportTheme, Rgb, LuminanceLut, ThemeMode, ThemeBridge, TranscriptPart, WidgetRender, PublishOptions, ShellSlot, BriefingFaultKind, BriefingFault, AgentState, AgentTool, TextContent, ImageContent, } from "./contract.js";
24
+ export { SKILL_NAME_LIMIT, SKILL_DESCRIPTION_LIMIT, SGR_INITIAL_STATE, FALLBACK_EXPORT_THEME, SHELL_SLOTS, briefingFault, } from "./contract.js";
25
+ export { BRIEFING_SECTIONS, composeBriefing, joinBlocks, bullets, escapeXml, TOOL_SUMMARIES } from "./compose.js";
26
+ export { scanMacroBody, resolveTokens, applyMacros, buildMacroScope, expandInvocation, loadMacros, readMacroFile, splitFrontmatter, } from "./macros.js";
27
+ export type { LoadMacrosOptions, FrontmatterSplit } from "./macros.js";
28
+ export { loadSkillCards, gatherSkillCards, modelInvocableCards, } from "./skills.js";
29
+ export type { SkillRoot } from "./skills.js";
30
+ export { gatherContextDocs } from "./context-docs.js";
31
+ export type { GatherContextDocsOptions } from "./context-docs.js";
@@ -0,0 +1,97 @@
1
+ import { readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { basename, join } from "node:path";
3
+ import { briefingFault } from "./contract.js";
4
+ import type { Macro, MacroOrigin, MacroScope, MacroToken } from "./contract.js";
5
+
6
+ export interface LoadMacrosOptions { readonly origin?: MacroOrigin; readonly label?: string; }
7
+ export interface FrontmatterSplit { readonly frontmatter: Record<string, unknown>; readonly body: string; }
8
+
9
+ const decimal = (ch: string): boolean => ch.charCodeAt(0) >= 48 && ch.charCodeAt(0) <= 57;
10
+ const bareword = (ch: string): boolean => { const c = ch.charCodeAt(0); return (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c === 95; };
11
+ export const LEGACY_ALL_BAREWORD = ["A", "R", "G", "U", "M", "E", "N", "T", "S"].join("");
12
+ export const DERIVED_DESCRIPTION_BUDGET = 72;
13
+ let legacyReporter: ((kind: string, source: string) => void) | undefined;
14
+
15
+ export function setLegacyMacroReporter(fn: ((kind: string, source: string) => void) | undefined): void { legacyReporter = fn; }
16
+ export function reportLegacyUsage(kind: string, source: string): void { legacyReporter?.(kind, source); }
17
+ export function readNumber(text: string, i: number): { value: number; next: number } { let j = i; while (j < text.length && decimal(text[j])) j++; return { value: Number.parseInt(text.slice(i, j), 10), next: j }; }
18
+ export function readBareword(text: string, i: number): number { let j = i; while (j < text.length && bareword(text[j])) j++; return j; }
19
+ export function skipInlineSpace(text: string, i: number): number { let j = i; while (j < text.length && (text[j] === " " || text[j] === "\t")) j++; return j; }
20
+
21
+ type Scan = { token: MacroToken; next: number };
22
+ type LegacyScan = { token: MacroToken | null; literal?: string; next: number };
23
+
24
+ export function scanMacroBody(body: string): MacroToken[] {
25
+ const tokens: MacroToken[] = []; let literal = ""; let i = 0;
26
+ const flush = (): void => { if (literal) { tokens.push({ kind: "literal", text: literal }); literal = ""; } };
27
+ while (i < body.length) {
28
+ const ch = body[i];
29
+ if (ch === "{" && body[i + 1] === "{") {
30
+ if (body[i + 2] === "{" && body[i + 3] === "{") { literal += "{{"; i += 4; continue; }
31
+ const parsed = scanIndusForm(body, i);
32
+ if (parsed) { flush(); tokens.push(parsed.token); i = parsed.next; continue; }
33
+ } else if (ch === "$") {
34
+ const parsed = scanLegacyForm(body, i);
35
+ if (parsed) { flush(); if (parsed.token) tokens.push(parsed.token); else literal += parsed.literal ?? ""; i = parsed.next; continue; }
36
+ }
37
+ literal += ch; i++;
38
+ }
39
+ flush(); return tokens;
40
+ }
41
+
42
+ export function scanIndusForm(text: string, start: number): Scan | null {
43
+ let i = skipInlineSpace(text, start + 2); if (text.slice(i, i + 4) !== "arg.") return null; i += 4;
44
+ const end = readBareword(text, i); const accessor = text.slice(i, end); i = end;
45
+ if (!accessor && decimal(text[i] ?? "")) { const num = readNumber(text, i); i = skipInlineSpace(text, num.next); return text[i] === "}" && text[i + 1] === "}" && num.value >= 1 ? { token: { kind: "positional", index: num.value }, next: i + 2 } : null; }
46
+ if (accessor === "all") { i = skipInlineSpace(text, i); return text[i] === "}" && text[i + 1] === "}" ? { token: { kind: "all" }, next: i + 2 } : null; }
47
+ if (accessor === "slice") {
48
+ i = skipInlineSpace(text, i); if (!decimal(text[i] ?? "")) return null; const startNum = readNumber(text, i); i = skipInlineSpace(text, startNum.next); let length: number | undefined;
49
+ if (decimal(text[i] ?? "")) { const len = readNumber(text, i); length = len.value; i = skipInlineSpace(text, len.next); }
50
+ if (text[i] !== "}" || text[i + 1] !== "}") return null;
51
+ return { token: length === undefined ? { kind: "slice", start: startNum.value } : { kind: "slice", start: startNum.value, length }, next: i + 2 };
52
+ }
53
+ if (accessor === "rest") { i = skipInlineSpace(text, i); let value = 2; if (decimal(text[i] ?? "")) { const num = readNumber(text, i); value = num.value; i = skipInlineSpace(text, num.next); } return text[i] === "}" && text[i + 1] === "}" ? { token: { kind: "slice", start: value }, next: i + 2 } : null; }
54
+ return null;
55
+ }
56
+
57
+ export function scanLegacyForm(text: string, start: number): LegacyScan | null {
58
+ const next = text[start + 1];
59
+ if (next === "$") return { token: null, literal: "$", next: start + 2 };
60
+ if (next && decimal(next)) { const num = readNumber(text, start + 1); if (num.value < 1) return null; reportLegacyUsage("positional", text.slice(start, num.next)); return { token: { kind: "positional", index: num.value }, next: num.next }; }
61
+ if (next === "@") { reportLegacyUsage("all", text.slice(start, start + 2)); return { token: { kind: "all" }, next: start + 2 }; }
62
+ if (next === "{") return scanLegacyBraceForm(text, start);
63
+ if (next && bareword(next)) { const end = readBareword(text, start + 1); if (text.slice(start + 1, end) === LEGACY_ALL_BAREWORD) { reportLegacyUsage("all", text.slice(start, end)); return { token: { kind: "all" }, next: end }; } }
64
+ return null;
65
+ }
66
+
67
+ export function scanLegacyBraceForm(text: string, start: number): LegacyScan | null {
68
+ let i = start + 2; if (text[i++] !== "@") return null;
69
+ if (text[i] === "}") { reportLegacyUsage("all", text.slice(start, i + 1)); return { token: { kind: "all" }, next: i + 1 }; }
70
+ if (text[i++] !== ":" || !decimal(text[i] ?? "")) return null; const startNum = readNumber(text, i); i = startNum.next; let length: number | undefined;
71
+ if (text[i] === ":") { i++; if (!decimal(text[i] ?? "")) return null; const len = readNumber(text, i); length = len.value; i = len.next; }
72
+ if (text[i] !== "}") return null; reportLegacyUsage("slice", text.slice(start, i + 1));
73
+ return { token: length === undefined ? { kind: "slice", start: startNum.value } : { kind: "slice", start: startNum.value, length }, next: i + 1 };
74
+ }
75
+
76
+ export function splitArguments(raw: string): string[] {
77
+ const out: string[] = []; let current = ""; let inWord = false; let quote: string | null = null;
78
+ for (const ch of raw) { if (quote) { if (ch === quote) quote = null; else current += ch; inWord = true; } else if (ch === '"' || ch === "'") { quote = ch; inWord = true; } else if (/\s/.test(ch)) { if (inWord) { out.push(current); current = ""; inWord = false; } } else { current += ch; inWord = true; } }
79
+ if (inWord) out.push(current); return out;
80
+ }
81
+ export function buildMacroScope(raw: string): MacroScope { const args = splitArguments(raw); return { args, all: args.join(" "), raw }; }
82
+ export function resolveTokens(tokens: readonly MacroToken[], scope: MacroScope): string { return tokens.map((token) => { if (token.kind === "literal") return token.text; if (token.kind === "positional") return scope.args[token.index - 1] ?? ""; if (token.kind === "all") return scope.all; const from = Math.max(0, token.start - 1); return (token.length === undefined ? scope.args.slice(from) : scope.args.slice(from, from + Math.max(0, token.length))).join(" "); }).join(""); }
83
+ export function applyMacros(body: string, raw: string): string { return resolveTokens(scanMacroBody(body), buildMacroScope(raw)); }
84
+ export function firstSpaceIndex(value: string): number { for (let i = 0; i < value.length; i++) if (/\s/.test(value[i])) return i; return -1; }
85
+ export function expandInvocation(line: string, macros: readonly Macro[]): string { if (!line.startsWith("/")) return line; const sliced = line.slice(1); const space = firstSpaceIndex(sliced); const name = space < 0 ? sliced : sliced.slice(0, space); const macro = macros.find((item) => item.name === name); return macro ? applyMacros(macro.body, space < 0 ? "" : sliced.slice(space + 1)) : line; }
86
+
87
+ export function loadMacros(dir: string, opts: LoadMacrosOptions = {}): Macro[] {
88
+ const origin = opts.origin ?? "path"; const label = opts.label ?? origin; let entries: string[];
89
+ try { entries = readdirSync(dir); } catch { return []; }
90
+ const seen = new Set<string>(); const macros: Macro[] = [];
91
+ for (const entry of entries.sort()) { if (entry.startsWith(".") || !entry.toLowerCase().endsWith(".md")) continue; const path = join(dir, entry); try { if (!statSync(path).isFile()) continue; } catch { continue; } const macro = readMacroFile(path, origin, label); if (!seen.has(macro.name)) { seen.add(macro.name); macros.push(macro); } }
92
+ return macros;
93
+ }
94
+ export function readMacroFile(path: string, origin: MacroOrigin, label: string): Macro { let text: string; try { text = readFileSync(path, "utf8"); } catch (cause) { throw briefingFault("macro_invalid", `could not read macro file at ${path}`, cause); } const { frontmatter, body } = splitFrontmatter(text); const name = basename(path).replace(/\.md$/i, ""); const declared = typeof frontmatter.description === "string" ? frontmatter.description.trim() : ""; return { name, description: declared ? `${declared} (${label})` : deriveDescription(body, label), body, origin, source: path }; }
95
+ export function deriveDescription(body: string, label: string): string { const first = body.split("\n").find((line) => line.trim())?.trim() ?? ""; const trimmed = first.length > DERIVED_DESCRIPTION_BUDGET ? `${first.slice(0, DERIVED_DESCRIPTION_BUDGET).trimEnd()}…` : first; return `${trimmed || "custom macro"} (${label})`; }
96
+ export function splitFrontmatter(text: string): FrontmatterSplit { const lines = text.split("\n"); if (lines[0]?.trim() !== "---") return { frontmatter: {}, body: text }; const close = lines.findIndex((line, i) => i > 0 && line.trim() === "---"); if (close < 0) return { frontmatter: {}, body: text }; const frontmatter: Record<string, unknown> = {}; for (const line of lines.slice(1, close)) { if (!line.trim() || line.trimStart().startsWith("#")) continue; const colon = line.indexOf(":"); if (colon > 0) frontmatter[line.slice(0, colon).trim()] = unquoteScalar(line.slice(colon + 1).trim()); } return { frontmatter, body: lines.slice(close + 1).join("\n").replace(/^\n+/, "") }; }
97
+ export function unquoteScalar(value: string): string { if (value.length >= 2 && ((value[0] === '"' && value.at(-1) === '"') || (value[0] === "'" && value.at(-1) === "'"))) return value.slice(1, -1); return value; }
@@ -0,0 +1,47 @@
1
+ import { readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
2
+ import { basename, dirname, join } from "node:path";
3
+ import { SKILL_DESCRIPTION_LIMIT, SKILL_NAME_LIMIT } from "./contract.js";
4
+ import type { MacroOrigin, SkillCard, SkillDiagnostic, SkillFrontmatter, SkillLoad } from "./contract.js";
5
+ import { splitFrontmatter } from "./macros.js";
6
+
7
+ export interface SkillRoot { readonly dir: string; readonly origin: MacroOrigin; }
8
+ interface Candidate { path: string; dirName: string; }
9
+
10
+ export const SKILL_MANIFEST = "SKILL.md";
11
+ export const PRUNED_DIRS = new Set(["node_modules", ".git"]);
12
+ export const KNOWN_FRONTMATTER_KEYS = new Set(["name", "description", "license", "compatibility", "metadata", "allowed-tools", "disable-model-invocation"]);
13
+
14
+ function* walkCandidates(root: string, seen: Set<string>): Generator<Candidate> { yield* walkLevel(root, true, seen); }
15
+ function* walkLevel(dir: string, atRoot: boolean, seen: Set<string>): Generator<Candidate> {
16
+ let entries: string[]; try { entries = readdirSync(dir).sort(); } catch { return; }
17
+ for (const entry of entries) {
18
+ if (entry.startsWith(".")) continue; const full = join(dir, entry); let stats: import("node:fs").Stats;
19
+ try { stats = statSync(full); } catch { continue; }
20
+ if (stats.isDirectory()) { if (PRUNED_DIRS.has(entry)) continue; let real: string; try { real = realpathSync(full); } catch { continue; } if (!seen.has(real)) { seen.add(real); yield* walkLevel(full, false, seen); } }
21
+ else if (stats.isFile() && ((atRoot && entry.toLowerCase().endsWith(".md")) || (!atRoot && entry === SKILL_MANIFEST))) yield { path: full, dirName: basename(dirname(full)) };
22
+ }
23
+ }
24
+
25
+ export function checkName(name: string, dirName: string, fromDir: boolean): string | null { if (!name) return "a skill must declare a non-empty name"; if (name.length > SKILL_NAME_LIMIT) return `the name exceeds the ${SKILL_NAME_LIMIT}-character limit`; if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) return "the name must be lowercase words joined by single hyphens"; if (!fromDir && name !== dirName) return `the declared name "${name}" does not match its directory "${dirName}"`; return null; }
26
+ export function checkDescription(description: string): string | null { if (!description) return "a skill must declare a description so the model can gate it"; return description.length > SKILL_DESCRIPTION_LIMIT ? `the description exceeds the ${SKILL_DESCRIPTION_LIMIT}-character limit` : null; }
27
+ export function checkFrontmatterKeys(frontmatter: Record<string, unknown>): string | null { for (const key of Object.keys(frontmatter)) if (!KNOWN_FRONTMATTER_KEYS.has(key)) return `unrecognised frontmatter key "${key}"`; return null; }
28
+ export function projectFrontmatter(raw: Record<string, unknown>): SkillFrontmatter {
29
+ const out: { name?: string; description?: string; license?: string; compatibility?: string; metadata?: Readonly<Record<string, unknown>>; allowedTools?: readonly string[]; disableModelInvocation?: boolean } = {};
30
+ for (const key of ["name", "description", "license", "compatibility"] as const) if (typeof raw[key] === "string") out[key] = raw[key].trim();
31
+ if (typeof raw.metadata === "object" && raw.metadata !== null) out.metadata = raw.metadata as Record<string, unknown>;
32
+ const tools = raw["allowed-tools"]; if (typeof tools === "string") { const list = tools.split(/[\s,]+/).filter(Boolean); if (list.length) out.allowedTools = list; } else if (Array.isArray(tools)) out.allowedTools = tools.map(String);
33
+ if (raw["disable-model-invocation"] === true || raw["disable-model-invocation"] === "true") out.disableModelInvocation = true;
34
+ return out;
35
+ }
36
+ export function diag(kind: SkillDiagnostic["kind"], location: string, detail: string): SkillDiagnostic { return { kind, location, detail }; }
37
+ export function describeCause(cause: unknown): string { return cause instanceof Error ? cause.message : String(cause); }
38
+ export function parseCandidate(candidate: Candidate, origin: MacroOrigin): { card: SkillCard | null; diagnostic: SkillDiagnostic } {
39
+ let text: string; try { text = readFileSync(candidate.path, "utf8"); } catch (cause) { return { card: null, diagnostic: diag("invalid", candidate.path, `could not read the skill file (${describeCause(cause)})`) }; }
40
+ const { frontmatter, body } = splitFrontmatter(text); const keyProblem = checkFrontmatterKeys(frontmatter); if (keyProblem) return { card: null, diagnostic: diag("invalid", candidate.path, keyProblem) };
41
+ const fm = projectFrontmatter(frontmatter); const fromDir = !(fm.name ?? ""); const name = fromDir ? candidate.dirName : fm.name!; const nameProblem = checkName(name, candidate.dirName, fromDir); if (nameProblem) return { card: null, diagnostic: diag("invalid", candidate.path, nameProblem) };
42
+ const description = fm.description ?? ""; const descriptionProblem = checkDescription(description); if (descriptionProblem) return { card: null, diagnostic: diag("invalid", candidate.path, descriptionProblem) };
43
+ return { card: { name, description, body, location: candidate.path, origin, frontmatter: fm }, diagnostic: diag("loaded", candidate.path, `loaded skill "${name}"`) };
44
+ }
45
+ export function loadSkillCards(dir: string, origin: MacroOrigin = "path"): SkillLoad { const cards: SkillCard[] = []; const diagnostics: SkillDiagnostic[] = []; for (const candidate of walkCandidates(dir, new Set())) { const parsed = parseCandidate(candidate, origin); diagnostics.push(parsed.diagnostic); if (parsed.card) cards.push(parsed.card); } return { cards, diagnostics }; }
46
+ export function gatherSkillCards(roots: readonly SkillRoot[]): SkillLoad { const cards: SkillCard[] = []; const diagnostics: SkillDiagnostic[] = []; const claimed = new Map<string, string>(); for (const root of roots) { const loaded = loadSkillCards(root.dir, root.origin); diagnostics.push(...loaded.diagnostics.filter((item: SkillDiagnostic) => item.kind !== "loaded")); for (const card of loaded.cards) { const winner = claimed.get(card.name); if (winner) diagnostics.push(diag("collision", card.location, `the name "${card.name}" was already claimed by ${winner}; this card is dropped`)); else { claimed.set(card.name, card.location); cards.push(card); diagnostics.push(diag("loaded", card.location, `loaded skill "${card.name}"`)); } } } return { cards, diagnostics }; }
47
+ export function modelInvocableCards(cards: readonly SkillCard[]): SkillCard[] { return cards.filter((card) => card.frontmatter.disableModelInvocation !== true); }
@@ -0,0 +1,27 @@
1
+ // @ts-nocheck
2
+ // Type declarations recovered from dist/types (no runtime body)
3
+ /**
4
+ * Bridge-ledger — public barrel for event-sourced MCP tool enrollment.
5
+ *
6
+ * Three concerns, one import site:
7
+ *
8
+ * - **Keys** (`./key`) — content-addressed and ULID {@link BridgeKey} minting,
9
+ * so re-enrolling the same external tool is an idempotent upsert.
10
+ * - **Ledger** (`./ledger`) — the immutable {@link BridgeLedger} value and its
11
+ * pure transitions: {@link enrollBridgeCard} (upsert), {@link retire} /
12
+ * {@link withdrawServer} (splice), each returning a new ledger folded by the
13
+ * contract's {@link reduceLedger}.
14
+ * - **Network** (`./network`) — {@link attachBridgeCapabilities}, which mounts
15
+ * external MCP servers through the framework's `mountProtocolBridge`, adapts
16
+ * the returned `ToolBox` into {@link Capability} objects + {@link
17
+ * CapabilityCard}s, and enrolls them into a ledger.
18
+ *
19
+ * The frozen shapes ({@link BridgeKey}, {@link BridgeEntry}, {@link
20
+ * LedgerSnapshot}, {@link reduceLedger}) continue to live in the deck contract;
21
+ * this module re-exports the behavior that operates on them.
22
+ */
23
+ export { qualifyBridgeName, bridgeContentKey, bridgeUlidKey, } from "./key.js";
24
+ export type { BridgeLedger, EnrollRequest } from "./ledger.js";
25
+ export { emptyBridgeLedger, bridgeLedgerFromLog, enrollBridgeCard, retire, withdrawServer, liveCapabilities, liveCapabilitiesForServer, } from "./ledger.js";
26
+ export type { AttachResult } from "./network.js";
27
+ export { attachBridgeCapabilities, detachBridge, bridgeBoxToCapabilities, bridgeCapabilityCard, bridgeConfig, } from "./network.js";
@@ -0,0 +1,67 @@
1
+ // @ts-nocheck
2
+ // Type declarations recovered from dist/types (no runtime body)
3
+ /**
4
+ * Bridge-key minting — stable identifiers for enrolled MCP capabilities.
5
+ *
6
+ * An enrolled bridge capability needs a key that is *the same* across sessions
7
+ * for the same external tool, so re-enrolling is an idempotent upsert rather
8
+ * than an accumulating duplicate. The catalog already settled this policy in the
9
+ * contract: a {@link BridgeKey} is "a content hash of the qualified
10
+ * `<server>__<tool>` name (and its schema) or a fresh ULID" — keyed by the
11
+ * capability's *identity*, never by a working-directory digest.
12
+ *
13
+ * This module implements both halves of that policy and nothing else:
14
+ *
15
+ * - {@link bridgeContentKey} — the default. A deterministic digest of the
16
+ * qualified name plus the canonicalized parameter schema. Two enrollments of
17
+ * the same remote tool (same name, same schema) collapse to one key, so the
18
+ * ledger upsert is naturally idempotent and the live set never duplicates a
19
+ * tool just because a server reconnected.
20
+ * - {@link bridgeUlidKey} — an opt-in, monotonic, time-sortable ULID for the
21
+ * rare case a caller wants every enrollment to be a distinct event (e.g. an
22
+ * ephemeral, per-invocation graft) rather than a deduplicated identity.
23
+ *
24
+ * Both return a branded {@link BridgeKey}; neither touches the filesystem, the
25
+ * clock-as-state, or any shared mutable value.
26
+ */
27
+ import type { TSchema } from "@sinclair/typebox";
28
+ import { type BridgeKey } from "../contract.js";
29
+ /**
30
+ * The qualified, collision-free name the model sees for a remote tool —
31
+ * `"<server>__<tool>"`, using the framework's bridge {@link QUALIFIER}.
32
+ *
33
+ * The protocol bridge already stamps this exact form onto each grafted tool's
34
+ * descriptor; we recompute it here only so a key can be minted *before* a
35
+ * descriptor is in hand (e.g. from a {@link RemoteToolRef}-shaped pair).
36
+ *
37
+ * @param server the owning MCP server's id
38
+ * @param tool the remote tool's own (unqualified) name
39
+ */
40
+ export declare function qualifyBridgeName(server: string, tool: string): string;
41
+ /**
42
+ * Mint a content-addressed {@link BridgeKey} from a remote tool's identity.
43
+ *
44
+ * The digest is taken over the qualified `<server>__<tool>` name and the
45
+ * canonicalized parameter schema, so the key is a pure function of *what the
46
+ * tool is*. Enrolling the same tool twice yields the same key — the ledger
47
+ * upsert deduplicates it — while a tool whose schema changed yields a new key,
48
+ * correctly surfacing it as a distinct capability.
49
+ *
50
+ * @param server the owning MCP server's id
51
+ * @param tool the remote tool's own (unqualified) name
52
+ * @param parameters the tool's parameter schema (TypeBox or raw JSON Schema)
53
+ */
54
+ export declare function bridgeContentKey(server: string, tool: string, parameters?: TSchema | Record<string, unknown>): BridgeKey;
55
+ /**
56
+ * Mint a fresh, time-sortable {@link BridgeKey} as a ULID.
57
+ *
58
+ * Use when each enrollment must be a *distinct* event rather than a deduplicated
59
+ * identity — for instance an ephemeral, per-invocation graft, or when two
60
+ * differently-configured connections to the same server should each get their
61
+ * own live entry. The ULID is monotonic within a process so ordering is stable.
62
+ *
63
+ * @param monotonic when true (default) use the process-monotonic generator so
64
+ * keys minted in the same millisecond remain strictly increasing; pass false
65
+ * for a plain, independent ULID.
66
+ */
67
+ export declare function bridgeUlidKey(monotonic?: boolean): BridgeKey;
@@ -0,0 +1,131 @@
1
+ // @ts-nocheck
2
+ // Type declarations recovered from dist/types (no runtime body)
3
+ /**
4
+ * The immutable bridge ledger — event-sourced enrollment of MCP capabilities.
5
+ *
6
+ * MCP tools are grafted in and pulled out over a session's life: a server
7
+ * connects and contributes a handful of tools, another disconnects, the same
8
+ * server reconnects after a hot-reload. Rather than mutate a shared module-level
9
+ * array of live tools (which makes "who's enrolled right now" a function of call
10
+ * order and hides every past change), enrollment here is an **append-only event
11
+ * log** folded into a **derived snapshot**.
12
+ *
13
+ * - {@link BridgeLedger} is a plain immutable value: the ordered
14
+ * {@link BridgeEntry} log, its already-folded {@link LedgerSnapshot}, and the
15
+ * next sequence number to stamp.
16
+ * - Every mutation ({@link enrollBridgeCard}, {@link retire},
17
+ * {@link withdrawServer}) returns a *new* ledger; the input is never touched.
18
+ * `enroll` is an upsert (re-enrolling a key replaces its entry), `retire` is
19
+ * a splice (the keyed entry is removed from the live view).
20
+ * - The live view is produced solely by the contract's pure
21
+ * {@link reduceLedger} fold, so the snapshot can never drift from the log.
22
+ *
23
+ * The log is the source of truth; the snapshot is a cache of its fold. Because
24
+ * both live on the value, callers read `ledger.snapshot.live` directly and never
25
+ * re-reduce by hand.
26
+ */
27
+ import { type AnyCapability, type BridgeEntry, type BridgeKey, type LedgerSnapshot } from "../contract.js";
28
+ /**
29
+ * An immutable, event-sourced view of MCP tool enrollment.
30
+ *
31
+ * Holds the append-only {@link BridgeEntry} log, the {@link LedgerSnapshot} that
32
+ * is its current fold, and the sequence number the next appended entry will
33
+ * carry. Treat every instance as frozen: the enroll/retire/withdraw helpers
34
+ * derive a new ledger rather than editing this one in place.
35
+ */
36
+ export interface BridgeLedger {
37
+ /** The append-only enrollment event log, in append order. */
38
+ readonly log: readonly BridgeEntry[];
39
+ /** The current fold of {@link log} — the live capabilities and per-server counts. */
40
+ readonly snapshot: LedgerSnapshot;
41
+ /** The sequence number the next appended {@link BridgeEntry} will carry. */
42
+ readonly nextSeq: number;
43
+ }
44
+ /**
45
+ * The fields an enrollment supplies; the ledger stamps `op`, `seq`, and `at`.
46
+ *
47
+ * A caller names the capability, the owning server, and optionally a pre-minted
48
+ * {@link BridgeKey}; when the key is omitted it is content-addressed from the
49
+ * capability's identity so re-enrolling the same tool is idempotent.
50
+ */
51
+ export interface EnrollRequest {
52
+ /** The grafted capability to enroll (its `name` is the qualified tool name). */
53
+ readonly capability: AnyCapability;
54
+ /** Id of the external MCP server that owns the capability. */
55
+ readonly server: string;
56
+ /**
57
+ * Optional explicit key. When omitted, a content key is derived from the
58
+ * capability's qualified name and parameter schema so the enrollment upserts
59
+ * any prior entry for the same tool instead of duplicating it.
60
+ */
61
+ readonly key?: BridgeKey;
62
+ }
63
+ /** An empty ledger: no events, an empty live view, sequence numbering at 1. */
64
+ export declare function emptyBridgeLedger(): BridgeLedger;
65
+ /**
66
+ * Rebuild a ledger value from a persisted event log.
67
+ *
68
+ * The log is authoritative, so a ledger is fully reconstructable from it: fold
69
+ * it for the snapshot and resume sequence numbering one past its high-water
70
+ * mark. Use when rehydrating enrollment state across a restart.
71
+ *
72
+ * @param log the persisted append-only entries, in any order (sorted on fold)
73
+ */
74
+ export declare function bridgeLedgerFromLog(log: readonly BridgeEntry[]): BridgeLedger;
75
+ /**
76
+ * Append an `enroll` event and return the resulting ledger.
77
+ *
78
+ * The graft is an **upsert**: the appended entry carries a {@link BridgeKey}, and
79
+ * because {@link reduceLedger} lets a later sequence win on a repeated key, a
80
+ * re-enrollment of the same tool transparently replaces its prior live entry
81
+ * rather than duplicating it. The input ledger is not mutated.
82
+ *
83
+ * @param ledger the current ledger (left untouched)
84
+ * @param req the capability + server to enroll, with an optional explicit key
85
+ * @param at enrollment timestamp; defaults to now (ISO-8601)
86
+ */
87
+ export declare function enrollBridgeCard(ledger: BridgeLedger, req: EnrollRequest, at?: string): BridgeLedger;
88
+ /**
89
+ * Append a `retire` event for one capability and return the resulting ledger.
90
+ *
91
+ * The withdrawal is a **splice**: the appended `retire` entry names the key, and
92
+ * the fold drops that key from the live view. Retiring an unknown or
93
+ * already-retired key is a harmless no-op in the live set (the event is still
94
+ * recorded for the audit trail). The input ledger is not mutated.
95
+ *
96
+ * @param ledger the current ledger (left untouched)
97
+ * @param key the stable key of the capability to withdraw
98
+ * @param server the owning server id, recorded on the event
99
+ * @param at retirement timestamp; defaults to now (ISO-8601)
100
+ */
101
+ export declare function retire(ledger: BridgeLedger, key: BridgeKey, server: string, at?: string): BridgeLedger;
102
+ /**
103
+ * Retire every capability a given server currently has live, in one batch.
104
+ *
105
+ * Appends one `retire` event per live key owned by the server — the disconnect
106
+ * counterpart to grafting a whole server's tool set. Servers with nothing live
107
+ * yield the ledger unchanged. The input ledger is not mutated.
108
+ *
109
+ * @param ledger the current ledger (left untouched)
110
+ * @param server the server whose live capabilities should all be withdrawn
111
+ * @param at retirement timestamp applied to every event; defaults to now
112
+ */
113
+ export declare function withdrawServer(ledger: BridgeLedger, server: string, at?: string): BridgeLedger;
114
+ /**
115
+ * Read the live capabilities a single server currently contributes.
116
+ *
117
+ * Pure projection over the snapshot; the per-key→server association is recovered
118
+ * from the log (each live key's last-touching server). Handy for status panels
119
+ * and for {@link withdrawServer}'s batch retirement.
120
+ *
121
+ * @param ledger the ledger to read
122
+ * @param server the server id to filter by
123
+ */
124
+ export declare function liveCapabilitiesForServer(ledger: BridgeLedger, server: string): AnyCapability[];
125
+ /**
126
+ * The flat list of every live capability, in stable iteration order.
127
+ *
128
+ * What a deck assembler grafts onto the static catalog before handing the
129
+ * conductor its `options.tools`.
130
+ */
131
+ export declare function liveCapabilities(ledger: BridgeLedger): AnyCapability[];
@@ -0,0 +1,117 @@
1
+ // @ts-nocheck
2
+ // Type declarations recovered from dist/types (no runtime body)
3
+ /**
4
+ * The bridge network — mounting external MCP servers into the ledger.
5
+ *
6
+ * This is the side-effecting half of bridge enrollment. The framework's
7
+ * {@link mountProtocolBridge} does the protocol work: it connects every
8
+ * configured server, lists each ready endpoint's tools, and hands back a single
9
+ * {@link ToolBox} whose `descriptors()` advertise every grafted remote tool
10
+ * under its qualified `"<server>__<tool>"` name and whose `runner` routes a call
11
+ * back across the owning endpoint.
12
+ *
13
+ * What this module adds on top:
14
+ *
15
+ * - **Adaptation.** A {@link ToolBox} speaks the runtime's descriptor/runner
16
+ * contract; the conductor and catalog speak {@link Capability} (the
17
+ * framework `AgentTool`). {@link bridgeBoxToCapabilities} bridges the two,
18
+ * wrapping each descriptor + the shared runner into an `AgentTool` whose
19
+ * `execute` invokes the runner and projects its opaque outcome onto an
20
+ * {@link AgentToolResult}.
21
+ * - **Enrollment.** {@link attachBridgeCapabilities} folds those adapted
22
+ * capabilities into a {@link BridgeLedger} as `enroll` events, returning the
23
+ * new ledger, the live fleet (for teardown), and the typed status — never
24
+ * mutating a shared array.
25
+ * - **Cataloging.** {@link bridgeCapabilityCard} re-presents a grafted
26
+ * capability as a {@link CapabilityCard}, so dynamic MCP tools surface in
27
+ * help/introspection beside the static catalog rows.
28
+ *
29
+ * Failure isolation comes for free from the fleet: a server that faulted on
30
+ * connect contributes no descriptors and is simply absent from the enrollment.
31
+ */
32
+ import { type AnyCapability, type CapabilityCard, type DeckFault } from "../contract.js";
33
+ import { type BridgeConfig, type ServerConfig, type ServerFleet, type FleetStatus } from "indusagi/interop";
34
+ import type { ToolBox } from "indusagi/runtime";
35
+ import { type BridgeLedger } from "./ledger.js";
36
+ /**
37
+ * Adapt every tool a mounted {@link ToolBox} advertises into a list of
38
+ * {@link Capability} objects the conductor and ledger consume.
39
+ *
40
+ * Each box descriptor becomes one `AgentTool`: its qualified name, description,
41
+ * and parameter schema are carried verbatim, and its `execute` defers to the
42
+ * box's shared `runner` — passing the abort signal through and projecting the
43
+ * outcome with {@link projectOutcome}. The runner already knows how to route a
44
+ * call by name back to the owning endpoint, so the wrapper stays a thin shim.
45
+ *
46
+ * @param box the tool box returned by {@link mountProtocolBridge}
47
+ */
48
+ export declare function bridgeBoxToCapabilities(box: ToolBox): AnyCapability[];
49
+ /**
50
+ * Re-present a grafted bridge capability as a {@link CapabilityCard}.
51
+ *
52
+ * Lets dynamic MCP tools appear in the same catalog/help surface as the static
53
+ * cards: the card's `build` simply returns the already-live capability (the
54
+ * graft happened at mount time, so there is nothing further to construct). The
55
+ * owning server id is recovered from the qualified name for the title.
56
+ *
57
+ * @param capability a capability produced by {@link bridgeBoxToCapabilities}
58
+ */
59
+ export declare function bridgeCapabilityCard(capability: AnyCapability): CapabilityCard;
60
+ /**
61
+ * The outcome of attaching one or more MCP servers to a ledger.
62
+ *
63
+ * Bundles the new {@link BridgeLedger} (with every reachable tool enrolled), the
64
+ * live {@link ServerFleet} the caller owns and must eventually tear down, the
65
+ * aggregate {@link FleetStatus} for rendering, the count of tools grafted, and a
66
+ * non-fatal {@link DeckFault} when the mount itself failed wholesale.
67
+ */
68
+ export interface AttachResult {
69
+ /** The ledger after enrolling every grafted capability. */
70
+ readonly ledger: BridgeLedger;
71
+ /** The running fleet of endpoints; caller closes it via {@link detachBridge}. */
72
+ readonly fleet?: ServerFleet;
73
+ /** Aggregate per-server health, when a fleet came up. */
74
+ readonly status?: FleetStatus;
75
+ /** How many remote tools were enrolled. */
76
+ readonly enrolled: number;
77
+ /** A wholesale-mount fault, when connecting the bridge threw. */
78
+ readonly fault?: DeckFault;
79
+ }
80
+ /**
81
+ * Mount external MCP servers and enroll their tools into the bridge ledger.
82
+ *
83
+ * Connects every server in `config` through {@link mountProtocolBridge}, adapts
84
+ * the resulting box into capabilities, and folds each one into `ledger` as an
85
+ * `enroll` event — yielding a *new* ledger (the input is untouched). The live
86
+ * fleet is returned so the caller can read status and later tear it down; a
87
+ * faulted server simply contributes no tools and is reflected in the status.
88
+ *
89
+ * A wholesale failure (the mount call itself rejecting) is caught and reported
90
+ * as a `bridge` {@link DeckFault} on the result rather than thrown, so a bad MCP
91
+ * configuration degrades the deck instead of sinking session bootstrap.
92
+ *
93
+ * @param ledger the ledger to enroll into (left untouched)
94
+ * @param config the set of MCP servers to connect and graft
95
+ */
96
+ export declare function attachBridgeCapabilities(ledger: BridgeLedger, config: BridgeConfig): Promise<AttachResult>;
97
+ /**
98
+ * Detach one or more servers: retire their ledger entries and close the fleet.
99
+ *
100
+ * Withdraws every named server's live capabilities from `ledger` (or, when no
101
+ * names are given, every server present in the fleet status) and gracefully
102
+ * tears the fleet down. Returns the new ledger; the fleet is no longer usable
103
+ * after this resolves. The teardown is best-effort — a close that throws is
104
+ * swallowed so ledger withdrawal still completes.
105
+ *
106
+ * @param ledger the current ledger (left untouched)
107
+ * @param fleet the live fleet to close
108
+ * @param servers optional subset of server ids to detach; defaults to all
109
+ */
110
+ export declare function detachBridge(ledger: BridgeLedger, fleet: ServerFleet, servers?: readonly string[]): Promise<BridgeLedger>;
111
+ /**
112
+ * Convenience: turn a flat list of MCP server descriptions into the
113
+ * {@link BridgeConfig} {@link attachBridgeCapabilities} expects.
114
+ *
115
+ * @param servers the per-server transport configurations, in declaration order
116
+ */
117
+ export declare function bridgeConfig(servers: readonly ServerConfig[]): BridgeConfig;