indusagi-coding-agent 0.2.3 → 0.2.5

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 (260) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +661 -0
  3. package/README.md +95 -1
  4. package/dist/entry.js +3205 -1585
  5. package/dist/guardrails.js +47 -515
  6. package/dist/index.js +3232 -1671
  7. package/package.json +8 -7
  8. package/dist/types/addons/addons.test.d.ts +0 -21
  9. package/dist/types/addons/contract.d.ts +0 -640
  10. package/dist/types/addons/dispatch/event-dispatcher.d.ts +0 -140
  11. package/dist/types/addons/dispatch/index.d.ts +0 -23
  12. package/dist/types/addons/dispatch/tool-interceptor.d.ts +0 -128
  13. package/dist/types/addons/host.d.ts +0 -246
  14. package/dist/types/addons/index.d.ts +0 -51
  15. package/dist/types/addons/manifest.d.ts +0 -56
  16. package/dist/types/addons/sandbox.d.ts +0 -103
  17. package/dist/types/addons/surface.d.ts +0 -42
  18. package/dist/types/boot/auth-vault.d.ts +0 -29
  19. package/dist/types/boot/boot.d.ts +0 -26
  20. package/dist/types/boot/boot.test.d.ts +0 -15
  21. package/dist/types/boot/contract.d.ts +0 -236
  22. package/dist/types/boot/index.d.ts +0 -20
  23. package/dist/types/boot/invocation.d.ts +0 -40
  24. package/dist/types/boot/invocation.test.d.ts +0 -8
  25. package/dist/types/boot/runners/addon-wiring.d.ts +0 -103
  26. package/dist/types/boot/runners/addon-wiring.test.d.ts +0 -19
  27. package/dist/types/boot/runners/checkpoint.d.ts +0 -133
  28. package/dist/types/boot/runners/checkpoint.test.d.ts +0 -12
  29. package/dist/types/boot/runners/delegate-runner.d.ts +0 -89
  30. package/dist/types/boot/runners/delegate-runner.test.d.ts +0 -13
  31. package/dist/types/boot/runners/index.d.ts +0 -13
  32. package/dist/types/boot/runners/link-runner.d.ts +0 -20
  33. package/dist/types/boot/runners/memdir.d.ts +0 -103
  34. package/dist/types/boot/runners/memdir.test.d.ts +0 -12
  35. package/dist/types/boot/runners/oneshot-runner.d.ts +0 -19
  36. package/dist/types/boot/runners/read-state.d.ts +0 -82
  37. package/dist/types/boot/runners/read-state.test.d.ts +0 -10
  38. package/dist/types/boot/runners/registry.d.ts +0 -30
  39. package/dist/types/boot/runners/repl-runner.d.ts +0 -19
  40. package/dist/types/boot/runners/session-persist.test.d.ts +0 -10
  41. package/dist/types/boot/runners/session.d.ts +0 -65
  42. package/dist/types/boot/runners/session.test.d.ts +0 -10
  43. package/dist/types/boot/stages.d.ts +0 -92
  44. package/dist/types/boot/upgrade/apply.d.ts +0 -45
  45. package/dist/types/boot/upgrade/index.d.ts +0 -13
  46. package/dist/types/boot/upgrade/upgrades.d.ts +0 -126
  47. package/dist/types/briefing/briefing.test.d.ts +0 -15
  48. package/dist/types/briefing/compose.d.ts +0 -37
  49. package/dist/types/briefing/context-docs.d.ts +0 -38
  50. package/dist/types/briefing/context-docs.test.d.ts +0 -18
  51. package/dist/types/briefing/contract.d.ts +0 -686
  52. package/dist/types/briefing/index.d.ts +0 -29
  53. package/dist/types/briefing/macros.d.ts +0 -206
  54. package/dist/types/briefing/skills.d.ts +0 -67
  55. package/dist/types/capability-deck/bridge-ledger/index.d.ts +0 -25
  56. package/dist/types/capability-deck/bridge-ledger/key.d.ts +0 -65
  57. package/dist/types/capability-deck/bridge-ledger/ledger.d.ts +0 -129
  58. package/dist/types/capability-deck/bridge-ledger/network.d.ts +0 -115
  59. package/dist/types/capability-deck/builtin-bridge.d.ts +0 -114
  60. package/dist/types/capability-deck/capability-deck.test.d.ts +0 -18
  61. package/dist/types/capability-deck/cards/bg-process-card.d.ts +0 -99
  62. package/dist/types/capability-deck/cards/index.d.ts +0 -37
  63. package/dist/types/capability-deck/cards/memory-card.d.ts +0 -68
  64. package/dist/types/capability-deck/cards/plan-file.d.ts +0 -56
  65. package/dist/types/capability-deck/cards/plan-tools.d.ts +0 -97
  66. package/dist/types/capability-deck/cards/plan-tools.test.d.ts +0 -9
  67. package/dist/types/capability-deck/cards/saas-card.d.ts +0 -78
  68. package/dist/types/capability-deck/cards/task-card.d.ts +0 -106
  69. package/dist/types/capability-deck/cards/todo-card.d.ts +0 -78
  70. package/dist/types/capability-deck/cards/workflow-card.d.ts +0 -55
  71. package/dist/types/capability-deck/cards/workflow-card.test.d.ts +0 -12
  72. package/dist/types/capability-deck/checkpoint.int.test.d.ts +0 -25
  73. package/dist/types/capability-deck/contract.d.ts +0 -317
  74. package/dist/types/capability-deck/index.d.ts +0 -46
  75. package/dist/types/capability-deck/manifest.d.ts +0 -60
  76. package/dist/types/capability-deck/provision.d.ts +0 -76
  77. package/dist/types/capability-deck/read-edit-gate.int.test.d.ts +0 -21
  78. package/dist/types/channels/channels.test.d.ts +0 -15
  79. package/dist/types/channels/contract.d.ts +0 -489
  80. package/dist/types/channels/framer.d.ts +0 -49
  81. package/dist/types/channels/index.d.ts +0 -24
  82. package/dist/types/channels/link/dialog.d.ts +0 -138
  83. package/dist/types/channels/link/driver.d.ts +0 -81
  84. package/dist/types/channels/link/index.d.ts +0 -13
  85. package/dist/types/channels/link/server.d.ts +0 -70
  86. package/dist/types/channels/oneshot.d.ts +0 -37
  87. package/dist/types/channels/ops.d.ts +0 -89
  88. package/dist/types/channels/session-ops.d.ts +0 -80
  89. package/dist/types/conductor/bash-guard.d.ts +0 -106
  90. package/dist/types/conductor/bash-guard.test.d.ts +0 -17
  91. package/dist/types/conductor/catalog/catalog.d.ts +0 -87
  92. package/dist/types/conductor/catalog/index.d.ts +0 -14
  93. package/dist/types/conductor/catalog/matcher.d.ts +0 -47
  94. package/dist/types/conductor/conductor.d.ts +0 -189
  95. package/dist/types/conductor/conductor.test.d.ts +0 -10
  96. package/dist/types/conductor/contract.d.ts +0 -774
  97. package/dist/types/conductor/diagnostics.d.ts +0 -183
  98. package/dist/types/conductor/diagnostics.test.d.ts +0 -10
  99. package/dist/types/conductor/index.d.ts +0 -26
  100. package/dist/types/conductor/permission-gate.integration.test.d.ts +0 -22
  101. package/dist/types/conductor/permission-wiring.test.d.ts +0 -14
  102. package/dist/types/conductor/permissions.d.ts +0 -217
  103. package/dist/types/conductor/permissions.test.d.ts +0 -12
  104. package/dist/types/conductor/plan-mode.integration.test.d.ts +0 -23
  105. package/dist/types/conductor/post-edit-diagnostics.test.d.ts +0 -13
  106. package/dist/types/conductor/signal-hub/hub.d.ts +0 -83
  107. package/dist/types/conductor/signal-hub/index.d.ts +0 -19
  108. package/dist/types/conductor/signal-hub/translate.d.ts +0 -77
  109. package/dist/types/conductor/skill-parse/index.d.ts +0 -10
  110. package/dist/types/conductor/skill-parse/parse.d.ts +0 -67
  111. package/dist/types/conductor/submit.test.d.ts +0 -28
  112. package/dist/types/conductor/transcript-store/index.d.ts +0 -16
  113. package/dist/types/conductor/transcript-store/serialize.d.ts +0 -106
  114. package/dist/types/conductor/transcript-store/serialize.test.d.ts +0 -10
  115. package/dist/types/conductor/transcript-store/store.d.ts +0 -188
  116. package/dist/types/console/components/AgentsView.d.ts +0 -41
  117. package/dist/types/console/components/BackgroundAgents.d.ts +0 -63
  118. package/dist/types/console/components/BackgroundAgents.test.d.ts +0 -8
  119. package/dist/types/console/components/Banner.d.ts +0 -110
  120. package/dist/types/console/components/Composer.d.ts +0 -37
  121. package/dist/types/console/components/StatusBar.d.ts +0 -42
  122. package/dist/types/console/components/TerminalConsole.d.ts +0 -32
  123. package/dist/types/console/components/WorkingIndicator.d.ts +0 -44
  124. package/dist/types/console/components/WorkingIndicator.test.d.ts +0 -9
  125. package/dist/types/console/components/banner-sweep.d.ts +0 -55
  126. package/dist/types/console/components/banner.test.d.ts +0 -9
  127. package/dist/types/console/components/welcome.d.ts +0 -115
  128. package/dist/types/console/components/welcome.test.d.ts +0 -9
  129. package/dist/types/console/console.test.d.ts +0 -19
  130. package/dist/types/console/contract.d.ts +0 -598
  131. package/dist/types/console/index.d.ts +0 -34
  132. package/dist/types/console/input/complete.d.ts +0 -120
  133. package/dist/types/console/input/dir-reader.d.ts +0 -28
  134. package/dist/types/console/input/index.d.ts +0 -24
  135. package/dist/types/console/input/input.test.d.ts +0 -14
  136. package/dist/types/console/input/keymap.d.ts +0 -193
  137. package/dist/types/console/input/paste.d.ts +0 -131
  138. package/dist/types/console/mount.d.ts +0 -53
  139. package/dist/types/console/overlays/approval-queue.d.ts +0 -71
  140. package/dist/types/console/overlays/approval.d.ts +0 -104
  141. package/dist/types/console/overlays/approval.test.d.ts +0 -17
  142. package/dist/types/console/overlays/auth.d.ts +0 -31
  143. package/dist/types/console/overlays/boards.d.ts +0 -55
  144. package/dist/types/console/overlays/host.d.ts +0 -45
  145. package/dist/types/console/overlays/index.d.ts +0 -15
  146. package/dist/types/console/overlays/pickers.d.ts +0 -37
  147. package/dist/types/console/overlays/sessions.d.ts +0 -29
  148. package/dist/types/console/reducer.d.ts +0 -51
  149. package/dist/types/console/slash/builtins.d.ts +0 -33
  150. package/dist/types/console/slash/commands/dynamic.d.ts +0 -57
  151. package/dist/types/console/slash/commands/dynamic.test.d.ts +0 -9
  152. package/dist/types/console/slash/commands/integrations.d.ts +0 -28
  153. package/dist/types/console/slash/commands/integrations.test.d.ts +0 -18
  154. package/dist/types/console/slash/commands/shared.d.ts +0 -72
  155. package/dist/types/console/slash/commands/transcript.d.ts +0 -24
  156. package/dist/types/console/slash/commands/transcript.test.d.ts +0 -10
  157. package/dist/types/console/slash/commands/workbench.d.ts +0 -21
  158. package/dist/types/console/slash/commands/workbench.test.d.ts +0 -10
  159. package/dist/types/console/slash/index.d.ts +0 -34
  160. package/dist/types/console/slash/registry.d.ts +0 -90
  161. package/dist/types/console/slash/resolve.d.ts +0 -109
  162. package/dist/types/console/slash/slash.test.d.ts +0 -18
  163. package/dist/types/console/startup.d.ts +0 -119
  164. package/dist/types/console/theme/adapter.d.ts +0 -79
  165. package/dist/types/console/theme/index.d.ts +0 -18
  166. package/dist/types/console/theme/palette.d.ts +0 -77
  167. package/dist/types/console/theme/resolve.d.ts +0 -45
  168. package/dist/types/console/theme/theme.test.d.ts +0 -16
  169. package/dist/types/console/theme/tokens.d.ts +0 -62
  170. package/dist/types/entry.d.ts +0 -17
  171. package/dist/types/guardrails.d.ts +0 -33
  172. package/dist/types/index.d.ts +0 -24
  173. package/dist/types/insight/channel.d.ts +0 -45
  174. package/dist/types/insight/contract.d.ts +0 -411
  175. package/dist/types/insight/index.d.ts +0 -26
  176. package/dist/types/insight/insight.test.d.ts +0 -17
  177. package/dist/types/insight/recorder.d.ts +0 -63
  178. package/dist/types/insight/redaction.d.ts +0 -44
  179. package/dist/types/insight/replay.d.ts +0 -77
  180. package/dist/types/insight/sampling.d.ts +0 -84
  181. package/dist/types/insight/serialize.d.ts +0 -54
  182. package/dist/types/insight/sinks/console.d.ts +0 -36
  183. package/dist/types/insight/sinks/file.d.ts +0 -37
  184. package/dist/types/insight/sinks/index.d.ts +0 -16
  185. package/dist/types/insight/sinks/stream.d.ts +0 -53
  186. package/dist/types/kit/clipboard-image.d.ts +0 -40
  187. package/dist/types/kit/external-editor.d.ts +0 -35
  188. package/dist/types/kit/image.d.ts +0 -102
  189. package/dist/types/kit/index.d.ts +0 -29
  190. package/dist/types/kit/kit.test.d.ts +0 -13
  191. package/dist/types/kit/shell.d.ts +0 -50
  192. package/dist/types/kit/tool-fetch.d.ts +0 -165
  193. package/dist/types/launch/catalog.d.ts +0 -51
  194. package/dist/types/launch/contract.d.ts +0 -387
  195. package/dist/types/launch/credentials.d.ts +0 -112
  196. package/dist/types/launch/index.d.ts +0 -28
  197. package/dist/types/launch/invocation/attachments.d.ts +0 -72
  198. package/dist/types/launch/invocation/flags.d.ts +0 -59
  199. package/dist/types/launch/invocation/index.d.ts +0 -23
  200. package/dist/types/launch/invocation/read.d.ts +0 -52
  201. package/dist/types/launch/invocation/usage.d.ts +0 -25
  202. package/dist/types/launch/launch.test.d.ts +0 -20
  203. package/dist/types/launch/oauth.d.ts +0 -101
  204. package/dist/types/launch/packages.d.ts +0 -75
  205. package/dist/types/launch/packages.test.d.ts +0 -15
  206. package/dist/types/launch/pickers.d.ts +0 -97
  207. package/dist/types/runtime-bridge/bridges/_drive.d.ts +0 -74
  208. package/dist/types/runtime-bridge/bridges/builtins.d.ts +0 -77
  209. package/dist/types/runtime-bridge/bridges/claude-cli.d.ts +0 -37
  210. package/dist/types/runtime-bridge/bridges/codex-cli.d.ts +0 -27
  211. package/dist/types/runtime-bridge/bridges/index.d.ts +0 -15
  212. package/dist/types/runtime-bridge/bridges/indusagi-cli.d.ts +0 -36
  213. package/dist/types/runtime-bridge/broker.d.ts +0 -182
  214. package/dist/types/runtime-bridge/contract.d.ts +0 -436
  215. package/dist/types/runtime-bridge/index.d.ts +0 -21
  216. package/dist/types/runtime-bridge/runtime-bridge.test.d.ts +0 -17
  217. package/dist/types/runtime-bridge/sink.d.ts +0 -59
  218. package/dist/types/sessions/contract.d.ts +0 -79
  219. package/dist/types/sessions/index.d.ts +0 -11
  220. package/dist/types/sessions/library.d.ts +0 -95
  221. package/dist/types/sessions/sessions.test.d.ts +0 -11
  222. package/dist/types/settings/contract.d.ts +0 -175
  223. package/dist/types/settings/index.d.ts +0 -13
  224. package/dist/types/settings/manager.d.ts +0 -109
  225. package/dist/types/settings/settings.test.d.ts +0 -16
  226. package/dist/types/transcript-export/index.d.ts +0 -20
  227. package/dist/types/transcript-export/publish.d.ts +0 -81
  228. package/dist/types/transcript-export/sgr.d.ts +0 -90
  229. package/dist/types/transcript-export/template.d.ts +0 -64
  230. package/dist/types/transcript-export/theme-bridge.d.ts +0 -99
  231. package/dist/types/transcript-export/transcript-export.test.d.ts +0 -16
  232. package/dist/types/window-budget/budget/estimate.d.ts +0 -47
  233. package/dist/types/window-budget/budget/gate.d.ts +0 -37
  234. package/dist/types/window-budget/budget/index.d.ts +0 -14
  235. package/dist/types/window-budget/budget/slice.d.ts +0 -38
  236. package/dist/types/window-budget/condenser.d.ts +0 -73
  237. package/dist/types/window-budget/contract.d.ts +0 -182
  238. package/dist/types/window-budget/index.d.ts +0 -17
  239. package/dist/types/window-budget/microcompact.d.ts +0 -68
  240. package/dist/types/window-budget/microcompact.test.d.ts +0 -16
  241. package/dist/types/window-budget/rehydrate.d.ts +0 -56
  242. package/dist/types/window-budget/summarize/condense.d.ts +0 -70
  243. package/dist/types/window-budget/summarize/index.d.ts +0 -12
  244. package/dist/types/window-budget/summarize/prompt.d.ts +0 -56
  245. package/dist/types/window-budget/window-budget.test.d.ts +0 -18
  246. package/dist/types/workflow-engine/agent-runner.d.ts +0 -105
  247. package/dist/types/workflow-engine/agent-runner.test.d.ts +0 -8
  248. package/dist/types/workflow-engine/display.d.ts +0 -148
  249. package/dist/types/workflow-engine/display.test.d.ts +0 -1
  250. package/dist/types/workflow-engine/engine.d.ts +0 -183
  251. package/dist/types/workflow-engine/engine.test.d.ts +0 -1
  252. package/dist/types/workflow-engine/index.d.ts +0 -21
  253. package/dist/types/workflow-engine/parse.d.ts +0 -64
  254. package/dist/types/workflow-engine/parse.test.d.ts +0 -1
  255. package/dist/types/workflow-engine/structured-output.d.ts +0 -51
  256. package/dist/types/workflow-engine/structured-output.test.d.ts +0 -1
  257. package/dist/types/workspace/brand.d.ts +0 -26
  258. package/dist/types/workspace/index.d.ts +0 -11
  259. package/dist/types/workspace/locator.d.ts +0 -50
  260. package/dist/types/workspace/runtime-detect.d.ts +0 -56
@@ -1,183 +0,0 @@
1
- /**
2
- * Post-edit live diagnostics — an LSP-free, shell-sourced baseline-diff engine.
3
- *
4
- * The full induscode story runs a long-lived LSP and pulls structured
5
- * diagnostics off the language server. That stack is out of scope for the
6
- * clean-room product, so this is the **pragmatic shell path**: after a turn that
7
- * edited TypeScript/JS files, the conductor asks this engine to run a project
8
- * checker (`tsc --noEmit`, plus `eslint --format json` when an eslint config is
9
- * present), scoped to the workspace, and diff the result against a *per-session
10
- * baseline* captured before the edits. Only the diagnostics that are genuinely
11
- * **new** (not in the baseline, not already delivered in a prior turn) are
12
- * surfaced, and they are injected into the NEXT agent turn as a follow-up note.
13
- *
14
- * Everything here is best-effort and non-fatal:
15
- * - the checker spawns its OWN child process (lazy `node:child_process`), so
16
- * the module stays importable in a non-Node test context;
17
- * - a missing/slow/erroring checker NEVER faults the turn — the run is bounded
18
- * by an {@link AbortController} timeout and every failure resolves to `[]`;
19
- * - results are deduplicated and volume-capped (10/file, 30 total,
20
- * severity-sorted) so a broken project can't dump hundreds of lines into
21
- * context;
22
- * - it is fully opt-out-able (`DiagnosticsConfig.enabled === false`) and
23
- * defaults OFF when the workspace has no `tsconfig.json`.
24
- *
25
- * The line/column convention mirrors the LSP `Diagnostic.range`: 0-based.
26
- * `tsc` reports 1-based positions, so {@link runTscDiagnostics} subtracts 1 and
27
- * {@link formatDiagnosticsSummary} re-adds 1 when rendering for a human/agent.
28
- */
29
- /** Severity rank, ordered most→least urgent for the volume cap's sort. */
30
- export type DiagnosticSeverity = "Error" | "Warning" | "Info" | "Hint";
31
- /** A zero-based line/column position. */
32
- export interface Position {
33
- readonly line: number;
34
- readonly character: number;
35
- }
36
- /** A single diagnostic, shaped after the LSP `Diagnostic` (0-based range). */
37
- export interface Diagnostic {
38
- readonly message: string;
39
- readonly severity: DiagnosticSeverity;
40
- readonly range: {
41
- readonly start: Position;
42
- readonly end: Position;
43
- };
44
- readonly source?: string;
45
- readonly code?: string | number;
46
- }
47
- /** All diagnostics for one file, keyed by an absolute fs path used as the uri. */
48
- export interface DiagnosticFile {
49
- readonly uri: string;
50
- readonly diagnostics: Diagnostic[];
51
- }
52
- /** Max diagnostics surfaced for any single file (mirrors the LSP registry cap). */
53
- export declare const MAX_PER_FILE = 10;
54
- /** Max diagnostics surfaced across all files in one turn. */
55
- export declare const MAX_TOTAL = 30;
56
- /** Char budget for the rendered summary (truncated past this). */
57
- export declare const MAX_SUMMARY_CHARS = 4000;
58
- /**
59
- * A stable identity for one diagnostic: position + code + (trimmed) message.
60
- * Two diagnostics with the same key are "the same problem" for dedup/baseline
61
- * purposes even across separate checker runs.
62
- */
63
- export declare function createDiagnosticKey(d: Diagnostic): string;
64
- /** Structural equality over a diagnostic's salient fields (via the dedup key). */
65
- export declare function areDiagnosticsEqual(a: Diagnostic, b: Diagnostic): boolean;
66
- /** Options for {@link deduplicateAndCap}. */
67
- export interface DedupOptions {
68
- readonly maxPerFile?: number;
69
- readonly maxTotal?: number;
70
- }
71
- /**
72
- * Filter, deduplicate, severity-sort, and volume-cap a batch of diagnostic
73
- * files against a cross-turn `delivered` ledger.
74
- *
75
- * - drops any diagnostic whose key is already in `delivered[uri]` (already
76
- * surfaced in a prior turn — don't nag);
77
- * - dedups within a file (identical keys collapse to one);
78
- * - sorts each file's diagnostics by severity then position;
79
- * - caps to `maxPerFile` per file and `maxTotal` overall (errors win the cap);
80
- * - records every diagnostic it RETURNS into `delivered` (FIFO-capped per uri)
81
- * so the next turn won't re-surface it.
82
- *
83
- * `delivered` is mutated in place. Files that end up empty are dropped.
84
- */
85
- export declare function deduplicateAndCap(files: readonly DiagnosticFile[], delivered: Map<string, Set<string>>, opts?: DedupOptions): DiagnosticFile[];
86
- /** Inline ASCII severity marker (no `figures` dep). */
87
- export declare function getSeveritySymbol(severity: DiagnosticSeverity): string;
88
- /**
89
- * Render a deduped/capped batch into a compact, agent-readable block. Positions
90
- * are re-converted to 1-based for display (the engine carries 0-based). The
91
- * output is truncated to `maxChars` so it can never blow up a context window.
92
- */
93
- export declare function formatDiagnosticsSummary(files: readonly DiagnosticFile[], maxChars?: number): string;
94
- /** A diagnostics source: produces files for the workspace, honoring `signal`. */
95
- export type DiagnosticRunner = (cwd: string, signal?: AbortSignal) => Promise<DiagnosticFile[]>;
96
- /**
97
- * Run a project `tsc --noEmit --pretty false` and parse the flat diagnostic
98
- * lines. Resolves to `[]` on ANY failure (binary missing, abort, non-Node).
99
- * The local `node_modules/.bin/tsc` is preferred over a global/`npx` install to
100
- * avoid a version mismatch with the project's own config.
101
- *
102
- * tsc lines look like: `src/x.ts(12,5): error TS2322: Type 'a' ...`
103
- * Positions are 1-based in tsc; we store them 0-based (subtract 1).
104
- */
105
- export declare function runTscDiagnostics(cwd: string, signal?: AbortSignal): Promise<DiagnosticFile[]>;
106
- /** Parse the combined stdout/stderr of a `tsc --pretty false` run. */
107
- export declare function parseTscOutput(output: string, cwd: string): DiagnosticFile[];
108
- /**
109
- * Run a project `eslint --format json` over `files` and parse the result.
110
- * Resolves to `[]` when eslint is absent, no config is found, or anything else
111
- * goes wrong. severity 2→Error, 1→Warning. Positions are 1-based; stored 0-based.
112
- */
113
- export declare function runEslintDiagnostics(files: readonly string[], cwd: string, signal?: AbortSignal): Promise<DiagnosticFile[]>;
114
- /** Parse `eslint --format json` output. Resolves config-not-found to `[]`. */
115
- export declare function parseEslintOutput(output: string, cwd: string): DiagnosticFile[];
116
- /** Configuration for the {@link DiagnosticsEngine}. */
117
- export interface DiagnosticsConfig {
118
- /** Master switch. When `false` the engine reports nothing (opt-out). */
119
- readonly enabled?: boolean;
120
- /** The diagnostic sources to run. Defaults to `[runTscDiagnostics]`. */
121
- readonly runners?: DiagnosticRunner[];
122
- /** Per-run timeout in ms before the checker is aborted (default 30000). */
123
- readonly timeoutMs?: number;
124
- /** Per-file cap (default {@link MAX_PER_FILE}). */
125
- readonly maxPerFile?: number;
126
- /** Total cap (default {@link MAX_TOTAL}). */
127
- readonly maxTotal?: number;
128
- }
129
- /**
130
- * The post-edit diagnostics engine: runs checkers, diffs against a per-session
131
- * baseline, and dedups across turns. Stateful and per-session — one instance
132
- * lives on the conductor for the life of a session.
133
- */
134
- export declare class DiagnosticsEngine {
135
- #private;
136
- constructor(cwd: string, config?: DiagnosticsConfig);
137
- /** Whether this engine is active. */
138
- get enabled(): boolean;
139
- /** Whether the per-session baseline has already been captured. */
140
- get hasBaseline(): boolean;
141
- /**
142
- * Capture the per-session baseline NOW (before any edits land) by running the
143
- * checkers once over the current project state. Every diagnostic present is
144
- * recorded as pre-existing, so a later {@link newDiagnostics} surfaces only the
145
- * problems the session's own edits introduced. Idempotent: a second call is a
146
- * no-op once a baseline exists. Best-effort — never throws.
147
- *
148
- * Prefer calling this at session start (before the agent can edit anything); if
149
- * it is never called, {@link newDiagnostics} falls back to seeding the baseline
150
- * on its first invocation.
151
- */
152
- seedBaseline(signal?: AbortSignal): Promise<void>;
153
- /**
154
- * Run every checker, restrict the results to `editedPaths`, subtract the
155
- * per-session baseline, dedup against prior turns, and volume-cap. Returns the
156
- * NEW diagnostics for the edited files (empty when nothing new). Best-effort:
157
- * never throws, never blocks beyond the configured timeout.
158
- *
159
- * The first invocation seeds the baseline from the current project state and
160
- * returns `[]` (the pre-existing problems are the baseline, not "new").
161
- */
162
- newDiagnostics(editedPaths: readonly string[], signal?: AbortSignal): Promise<DiagnosticFile[]>;
163
- /**
164
- * Forget the delivered-key history for one uri so a problem at that file can
165
- * re-surface (e.g. the agent edited it again). The baseline is left intact.
166
- */
167
- clearDeliveredForFile(uri: string): void;
168
- /** Drop all cross-turn state and the baseline (re-seeds on the next run). */
169
- reset(): void;
170
- }
171
- /** Whether a path looks like a TypeScript/JS source file (by extension). */
172
- export declare function isTypeScriptOrJs(filePath: string): boolean;
173
- /**
174
- * Whether the workspace has a `tsconfig.json` at its root — the signal used to
175
- * default the engine ON. Best-effort + synchronous: a probe failure (or a
176
- * non-Node context) reports `false` so the engine defaults OFF and stays inert.
177
- */
178
- export declare function hasTsConfig(cwd: string): boolean;
179
- /**
180
- * Whether the workspace has an eslint config at its root — the signal used to
181
- * additionally enable the eslint runner. Best-effort + synchronous.
182
- */
183
- export declare function hasEslintConfig(cwd: string): boolean;
@@ -1,10 +0,0 @@
1
- /**
2
- * Unit tests for the LSP-free post-edit diagnostics engine: the pure keying /
3
- * dedup / cap / render logic, the tsc + eslint output parsers, and the
4
- * baseline-diff behavior of {@link DiagnosticsEngine}.
5
- *
6
- * No network and no real `tsc`/`eslint` spawn — the engine is driven with
7
- * scripted in-memory runners so the baseline/diff/dedup logic is exercised
8
- * deterministically.
9
- */
10
- export {};
@@ -1,26 +0,0 @@
1
- /**
2
- * Conductor subsystem — public barrel.
3
- *
4
- * Re-exports the FROZEN Phase-2 contract: the product-level signal stream
5
- * ({@link SessionSignal}), the typed fault model ({@link ConductorFault} +
6
- * {@link conductorFault}), the on-disk transcript schema ({@link TranscriptEntry},
7
- * {@link SessionHead}, {@link TRANSCRIPT_SCHEMA}), the model catalog/matcher
8
- * reference types ({@link ModelCardRef}, {@link MatchQuery}), the immutable
9
- * state snapshot ({@link ConductorState}), and the {@link SessionConductor}
10
- * interface plus its {@link SessionConductorOptions}.
11
- *
12
- * Behavior modules (signal hub, transcript store, model catalog/matcher,
13
- * conductor factory, the conductor itself) are added to this barrel as they
14
- * land; consumers import the conductor surface from `src/conductor` rather than
15
- * reaching into individual modules.
16
- */
17
- export type { FaultKind, ConductorFault, SessionSignal, SignalKind, SignalOf, SignalHandler, TranscriptSchema, TranscriptRole, TranscriptEntry, SessionHead, ModelCardRef, MatchQuery, ConductorPhase, ConductorState, QueueMode, QueuedInput, SessionStats, ExecuteBashOptions, BashOutcome, SessionConductor, SessionConductorOptions, AgentMessage, AgentTool, CanUseToolFn, ThinkingLevel, Model, Usage, KnownProvider, PermissionMode, } from "./contract";
18
- export { conductorFault, TRANSCRIPT_SCHEMA } from "./contract";
19
- export { createSessionConductor, reduceState, noopCondense, type AgentLike, type ConductorDeps, type CondenseFn, type RetryPolicy, } from "./conductor";
20
- export { SignalHub, translateAgentEvent, type SignalHubOptions } from "./signal-hub";
21
- export { ModelCatalog, ModelMatcher, canonicalId, toCardRef, type CatalogCard, type CatalogSource, type ResolveInput, } from "./catalog";
22
- export { TranscriptStore, memoryBackend, fsBackend, replay, type TranscriptBackend, type TranscriptState, type TranscriptClock, type TranscriptStoreOptions, } from "./transcript-store";
23
- export { parseSkillInvocation, type SkillInvocation } from "./skill-parse";
24
- export { resolveRuleDecision, parseRule, makeRule, toolMatchesRule, createPermissionGate, isReadOnlyToolName, isEditToolName, READ_ONLY_TOOL_NAMES, EDIT_TOOL_NAMES, type PermissionBehavior, type PermissionRule, type PermissionDecision, type CanUseToolFn as PermissionCanUseToolFn, type ApprovalChoice, type ApprovalResolver, type PermissionGateConfig, } from "./permissions";
25
- export { parseBashCommand, catastrophicReason, isCatastrophicCommand, evaluateCatastrophic, bashSubcommandSubjects, type ParsedCommand, } from "./bash-guard";
26
- export { DiagnosticsEngine, createDiagnosticKey, deduplicateAndCap, formatDiagnosticsSummary, getSeveritySymbol, parseTscOutput, parseEslintOutput, runTscDiagnostics, runEslintDiagnostics, hasTsConfig, hasEslintConfig, isTypeScriptOrJs, areDiagnosticsEqual, MAX_PER_FILE, MAX_TOTAL, MAX_SUMMARY_CHARS, type Diagnostic, type DiagnosticFile, type DiagnosticSeverity, type DiagnosticsConfig, type DiagnosticRunner, type DedupOptions, type Position, } from "./diagnostics";
@@ -1,22 +0,0 @@
1
- /**
2
- * Permission gate — integration against the REAL wired framework loop.
3
- *
4
- * The point of this suite (vs the pure {@link "./permissions.test"} unit tests) is
5
- * to prove the gate actually lands where tools execute. It drives a real
6
- * `indusagi/agent` `Agent` — the exact class the conductor's `makeAgent` wires —
7
- * with a scripted `streamFn` that has the model request a tool call, and the
8
- * SAME `createPermissionGate` output the conductor threads in as `canUseTool`.
9
- *
10
- * We assert through the framework's own message list (not a mock of an unwired
11
- * module):
12
- * - a **deny** rule blocks the tool: it never executes, and the turn carries an
13
- * `isError` tool result with the deny message (an unanswered tool_use would
14
- * 400 the next call, so the loop must still emit the result);
15
- * - an **allow** rule (or read-only auto-allow) lets the tool execute;
16
- * - **acceptEdits** auto-allows an edit without a rule;
17
- * - **bypass** allows everything;
18
- * - **plan** denies a mutating tool;
19
- * - an **ask** with no host resolver denies (non-interactive default);
20
- * - a live **mode switch** retargets subsequent calls with no agent rebuild.
21
- */
22
- export {};
@@ -1,14 +0,0 @@
1
- /**
2
- * Conductor permission wiring — proves `createSessionConductor` threads the gate
3
- * factory and exposes live `permissionMode()` / `setPermissionMode()`.
4
- *
5
- * The end-to-end "gate blocks a real tool" proof lives in
6
- * {@link "./permission-gate.integration.test"} (it drives the real framework
7
- * loop). Here we pin the PRODUCT seam: the conductor (a) seeds the mode from
8
- * options, (b) updates it through `setPermissionMode`, and (c) hands the gate
9
- * factory a getter that reads the conductor's LIVE mode — so a mode switch after
10
- * assembly is visible to the gate with no agent rebuild. A scripted fake
11
- * `AgentLike` keeps it network/disk-free, and a separate check confirms the gate
12
- * factory IS resolved with a live-mode getter on the real-agent path.
13
- */
14
- export {};
@@ -1,217 +0,0 @@
1
- /**
2
- * Permission rule engine + the `canUseTool` gate seam.
3
- *
4
- * This module is the product-side brain of the permission stack. It is split in
5
- * two layers:
6
- *
7
- * 1. **A pure rule engine** — {@link resolveRuleDecision} maps a single tool
8
- * call `(toolName, input, mode, rules)` to a {@link PermissionBehavior}
9
- * (`allow` / `ask` / `deny`). It is total, synchronous, and side-effect free
10
- * so the precedence (deny > ask > mode auto-allow > allow) is exhaustively
11
- * unit-testable. Rule strings are induscode-style: a bare tool name
12
- * (`"Bash"`) or a tool name with an argument specifier
13
- * (`"Bash(npm run test:*)"`).
14
- *
15
- * 2. **A gate factory** — {@link createPermissionGate} turns that engine into a
16
- * framework {@link CanUseToolFn}: the hard async hook the framework agent
17
- * awaits immediately before every tool runs. An `ask` decision is routed to
18
- * an OPTIONAL host-supplied approval resolver; when the resolver is absent
19
- * (a non-interactive boot) `ask` denies with a clear message. An
20
- * `allow-always` approval appends a session-scoped allow rule so later
21
- * identical calls auto-allow.
22
- *
23
- * Backwards-compatibility: the framework `canUseTool` hook is itself optional, so
24
- * a session that never builds a gate keeps today's allow-all behavior. A gate
25
- * built from an empty rule set in `default` mode allows read-only tools and asks
26
- * for everything else — and, with no resolver, the `ask` denials are explicit
27
- * rather than silent.
28
- */
29
- import type { PermissionMode } from "../settings";
30
- /** Re-exported so consumers of the engine get the mode vocabulary in one import. */
31
- export type { PermissionMode };
32
- /** The verdict the rule engine renders for a single tool call. */
33
- export type PermissionBehavior = "allow" | "ask" | "deny";
34
- /**
35
- * One parsed permission rule: a behavior plus the tool it targets, with an
36
- * optional argument specifier (`ruleContent`) that further narrows the match.
37
- */
38
- export interface PermissionRule {
39
- /** What happens when this rule matches a tool call. */
40
- readonly ruleBehavior: PermissionBehavior;
41
- /** The tool (and optional argument specifier) this rule selects. */
42
- readonly ruleValue: {
43
- /** The canonical tool name, e.g. `"Bash"` / `"bash"` (matched case-insensitively). */
44
- readonly toolName: string;
45
- /** An optional argument specifier, e.g. `"npm run test:*"`. Absent = bare match. */
46
- readonly ruleContent?: string;
47
- };
48
- }
49
- /**
50
- * The framework's tool-permission verdict. Mirrors `indusagi/agent`'s
51
- * `PermissionDecision`; re-declared here so the product engine never imports the
52
- * framework just for a structural type (the gate is assignable to the
53
- * framework's `CanUseToolFn` because the shapes coincide).
54
- */
55
- export type PermissionDecision = {
56
- behavior: "allow";
57
- updatedInput?: unknown;
58
- } | {
59
- behavior: "deny";
60
- message: string;
61
- };
62
- /**
63
- * The hard permission gate the framework agent awaits before each tool executes.
64
- * Structurally identical to `indusagi/agent`'s `CanUseToolFn`, so a value of this
65
- * type is accepted by `new Agent({ canUseTool })` with no cast.
66
- */
67
- export type CanUseToolFn = (toolName: string, input: unknown, opts: {
68
- signal?: AbortSignal;
69
- }) => Promise<PermissionDecision>;
70
- /**
71
- * The outcome of the host approval prompt raised for an `ask` decision:
72
- * - `allow-once` — run this single call, do not remember.
73
- * - `allow-always` — run it and append a session allow rule for the tool.
74
- * - `deny` — block this call.
75
- */
76
- export type ApprovalChoice = "allow-once" | "allow-always" | "deny";
77
- /**
78
- * The OPTIONAL host approval resolver. When present, an `ask` decision awaits it;
79
- * the host (an interactive overlay) returns the user's choice. It MUST resolve to
80
- * `"deny"` on abort so a cancelled turn never hangs on a pending prompt. When the
81
- * resolver is absent (non-interactive boot / oneshot / link), an `ask` decision
82
- * deterministically denies.
83
- */
84
- export type ApprovalResolver = (toolName: string, input: unknown, opts: {
85
- signal?: AbortSignal;
86
- }) => Promise<ApprovalChoice>;
87
- /**
88
- * Tool names known to only inspect state (never mutate). Mirrors the framework's
89
- * `READ_ONLY_TOOL_NAMES`; matched case-insensitively. A tool the framework marks
90
- * `readOnly: true` is also auto-allowed via {@link createPermissionGate}'s
91
- * `readOnlyToolNames` option, so this set is the static fallback for callers that
92
- * only know names.
93
- */
94
- export declare const READ_ONLY_TOOL_NAMES: ReadonlySet<string>;
95
- /**
96
- * Tool names that mutate the workspace by editing or writing files. Auto-allowed
97
- * under `acceptEdits`, and (together with every other non-read-only tool) denied
98
- * under `plan`.
99
- */
100
- export declare const EDIT_TOOL_NAMES: ReadonlySet<string>;
101
- /** Whether `toolName` is a statically-known read-only tool. */
102
- export declare function isReadOnlyToolName(toolName: string, extra?: ReadonlySet<string>): boolean;
103
- /** Whether `toolName` is an edit/write tool (auto-allowed under `acceptEdits`). */
104
- export declare function isEditToolName(toolName: string): boolean;
105
- /**
106
- * Parse an induscode-style rule string into its tool name and optional argument
107
- * specifier.
108
- *
109
- * - `"Bash"` → `{ toolName: "Bash" }`
110
- * - `"Bash(npm run test:*)"` → `{ toolName: "Bash", ruleContent: "npm run test:*" }`
111
- * - `"mcp__server"` → `{ toolName: "mcp__server" }`
112
- *
113
- * Whitespace around the tool name is trimmed; an empty argument specifier
114
- * (`"Bash()"`) is treated as a bare rule.
115
- */
116
- export declare function parseRule(raw: string): {
117
- toolName: string;
118
- ruleContent?: string;
119
- };
120
- /**
121
- * Build a {@link PermissionRule} from a behavior and an induscode-style rule
122
- * string. The single place a raw settings list entry becomes a typed rule.
123
- */
124
- export declare function makeRule(ruleBehavior: PermissionBehavior, raw: string): PermissionRule;
125
- /**
126
- * Whether a tool call matches a rule (the ANY-match semantics used for deny/ask).
127
- *
128
- * The tool name must match (case-insensitive), with an `mcp__server` rule also
129
- * matching every `mcp__server__tool` under it (the induscode MCP-wildcard
130
- * convention). A bare rule (no specifier) matches any arguments.
131
- *
132
- * When the rule carries an argument specifier:
133
- * - for the **shell** tool the command is split into its constituent
134
- * sub-commands and the specifier is tested against EACH — a match on ANY
135
- * sub-command counts (so `Bash(rm:*)` denies `git status && rm x`);
136
- * - for any other tool the specifier is tested against the single rendered
137
- * subject (the command field, or a JSON encoding).
138
- *
139
- * The any-match semantics are correct for `deny` and `ask` (a single offending
140
- * sub-command should trigger them). The `allow` branch needs ALL sub-commands
141
- * covered instead — see {@link bashAllowCoversAll}.
142
- */
143
- export declare function toolMatchesRule(toolName: string, input: unknown, rule: PermissionRule): boolean;
144
- /**
145
- * Resolve the behavior for a single tool call against the rule set and mode.
146
- *
147
- * Precedence, highest first:
148
- * 1. **deny rules** — any matching `deny` rule blocks, regardless of mode. Deny
149
- * wins across every tier (the caller concatenates the tiers before passing
150
- * the list in, and this scans all deny rules first).
151
- * 2. **plan mode** — denies any mutating (non-read-only) tool outright.
152
- * 3. **ask rules** — a matching `ask` rule forces a prompt (unless a deny
153
- * already fired). Mode auto-allow does NOT override an explicit ask.
154
- * 4. **bypass mode** — allows everything not already denied/asked.
155
- * 5. **read-only auto-allow** — a known read-only tool allows in any mode.
156
- * 6. **acceptEdits mode** — auto-allows edit/write tools.
157
- * 7. **allow rules** — a matching `allow` rule (or, for the shell tool, the
158
- * allow rule SET) allows.
159
- * 8. **fallthrough** — `ask` (the safe default: prompt, then deny when no
160
- * resolver is wired).
161
- *
162
- * The catastrophic-command blocklist sits ABOVE all of this (step 0): a shell
163
- * command on the built-in blocklist (`rm -rf /`, fork bombs, `curl | sh`, …) is
164
- * denied regardless of rules or mode — even `bypass` cannot run it. See
165
- * {@link evaluateCatastrophic}.
166
- *
167
- * Shell handling threads through the per-sub-command matching: a compound
168
- * command (`a && b; c | d`) is split into its constituent commands and each rule
169
- * is evaluated against each — a deny/ask on ANY sub-command fires, while
170
- * auto-allow requires the allow rule set to cover EVERY sub-command.
171
- *
172
- * Pure and total: no I/O, no async, deterministic for a given input.
173
- */
174
- export declare function resolveRuleDecision(toolName: string, input: unknown, rules: readonly PermissionRule[], mode: PermissionMode, readOnlyExtra?: ReadonlySet<string>): PermissionBehavior;
175
- /** Configuration for {@link createPermissionGate}. */
176
- export interface PermissionGateConfig {
177
- /**
178
- * The ordered rule set, already concatenated across the project/global tiers.
179
- * Deny rules are scanned first so a deny anywhere in the list wins.
180
- */
181
- readonly rules: readonly PermissionRule[];
182
- /** A live getter for the current permission mode (so a mode switch is honored). */
183
- readonly mode: () => PermissionMode;
184
- /**
185
- * The OPTIONAL host approval resolver consulted on an `ask` decision. Absent on
186
- * a non-interactive boot — then `ask` deterministically denies.
187
- */
188
- readonly requestApproval?: ApprovalResolver;
189
- /**
190
- * Append a session-scoped allow rule when the host returns `allow-always`. The
191
- * conductor owns the mutable rule list and passes a setter here so the new rule
192
- * is visible to subsequent calls within the session.
193
- */
194
- readonly appendAllowRule?: (rule: PermissionRule) => void;
195
- /**
196
- * Tool names (beyond {@link READ_ONLY_TOOL_NAMES}) to treat as read-only —
197
- * derived from the deck's `readOnly: true` tool flags so MCP/custom read-only
198
- * tools also auto-allow.
199
- */
200
- readonly readOnlyToolNames?: ReadonlySet<string>;
201
- }
202
- /**
203
- * Build a framework {@link CanUseToolFn} from the rule engine + the current mode.
204
- *
205
- * The returned gate:
206
- * - resolves the behavior via {@link resolveRuleDecision},
207
- * - on `allow` proceeds (the framework keeps the validated args),
208
- * - on `deny` short-circuits with a clear message (the framework turns it into
209
- * an `isError` tool result so the model sees why),
210
- * - on `ask` awaits {@link PermissionGateConfig.requestApproval} when present —
211
- * `allow-once` proceeds, `allow-always` proceeds and appends a session allow
212
- * rule, `deny` blocks — and DENIES when no resolver is wired (the safe
213
- * non-interactive default).
214
- *
215
- * The result is assignable to `indusagi/agent`'s `CanUseToolFn`.
216
- */
217
- export declare function createPermissionGate(config: PermissionGateConfig): CanUseToolFn;
@@ -1,12 +0,0 @@
1
- /**
2
- * Permission rule engine + gate — unit tests.
3
- *
4
- * Exhaustively pins the pure decision ({@link resolveRuleDecision}) precedence
5
- * (deny > plan-deny > ask > bypass > read-only > acceptEdits > allow > ask
6
- * fallthrough), the induscode rule parsing/matching ({@link parseRule},
7
- * {@link toolMatchesRule}, including argument specifiers and the `mcp__` wildcard),
8
- * the mode behaviors, and the {@link createPermissionGate} `ask` routing — a host
9
- * resolver returns allow-once / allow-always (which appends a session allow rule)
10
- * / deny, and an ABSENT resolver denies. No framework, no network.
11
- */
12
- export {};
@@ -1,23 +0,0 @@
1
- /**
2
- * Plan-mode round-trip — integration across the gate + the conductor handshake.
3
- *
4
- * Two proofs, against the REAL wired pieces (the rule engine's gate + the live
5
- * conductor), not mocks of an unwired module:
6
- *
7
- * 1. **The gate denies edits in plan mode.** A `createPermissionGate` whose mode
8
- * getter reads the conductor's LIVE `permissionMode()` allows an edit in
9
- * `default` mode, denies it once the conductor enters plan mode
10
- * (`togglePlanMode(true)` / `setPermissionMode('plan')`), and allows it again
11
- * once an approved exit restores the prior mode. This is the exact gate the
12
- * conductor threads into the framework `Agent`, so the deny lands where tools
13
- * execute.
14
- *
15
- * 2. **ExitPlanMode approval restores the mode, persists the plan, and resumes.**
16
- * A scripted fake agent emits a `tool_execution_end` carrying the
17
- * `{ exitPlan: true, plan }` detail the conductor intercepts. With an approval
18
- * resolver installed that approves, a turn run while in plan mode: restores
19
- * the captured pre-plan mode, writes the plan to a file under `plansDir`, and
20
- * enqueues the approved plan as a follow-up so the model proceeds from it. A
21
- * rejecting resolver keeps the session in plan mode and writes nothing.
22
- */
23
- export {};
@@ -1,13 +0,0 @@
1
- /**
2
- * Conductor-integration tests for the post-edit live-diagnostics seam.
3
- *
4
- * Drives a scripted {@link AgentLike} that emits a `tool_execution_start` for an
5
- * `edit`/`write` tool during `prompt`, with an injected {@link DiagnosticsEngine}
6
- * over a scripted in-memory runner (no real tsc spawn). Verifies:
7
- * - a turn that introduces a NEW diagnostic enqueues the summary follow-up;
8
- * - a clean edit (no new diagnostics) enqueues nothing;
9
- * - re-editing a file re-surfaces a previously-cleared diagnostic;
10
- * - a non-TS edit never triggers the checker;
11
- * - the injected follow-up turn (which edits nothing) does not loop.
12
- */
13
- export {};
@@ -1,83 +0,0 @@
1
- /**
2
- * SignalHub — the conductor's product-event fan-out.
3
- *
4
- * A tiny, synchronous publish/subscribe bus over the {@link SessionSignal}
5
- * stream. The conductor owns one hub per session: behavior modules (the turn
6
- * loop, the persistence layer, the auto-condense pass) push signals in via
7
- * {@link SignalHub.emit}, and every registered consumer handler receives them in
8
- * registration order.
9
- *
10
- * Design (deliberately the conductor's own, not the framework's loop emitter):
11
- * - Handlers live in an insertion-ordered `Set`, so registration order is the
12
- * delivery order and duplicate handler identities collapse to one slot.
13
- * - {@link SignalHub.subscribe} returns an unsubscribe thunk; calling it (even
14
- * during a dispatch, even more than once) is safe and idempotent.
15
- * - {@link SignalHub.emit} fans out over a *snapshot* of the handler set, so a
16
- * handler that subscribes or unsubscribes mid-dispatch never corrupts the
17
- * in-progress iteration — the change takes effect on the next emit.
18
- * - A throwing handler is isolated: its error is routed to the optional
19
- * {@link SignalHubOptions.onHandlerError} sink and the remaining handlers
20
- * still run. One bad consumer never silences the others.
21
- *
22
- * The hub is transport-agnostic: it knows nothing about the framework `Agent`,
23
- * persistence, or how signals are produced. The {@link module:translate}
24
- * translator is what turns raw framework events into the {@link SessionSignal}s
25
- * that flow through here.
26
- */
27
- import type { SessionSignal, SignalHandler } from "../contract";
28
- /** Tuning hooks for a {@link SignalHub}. All optional. */
29
- export interface SignalHubOptions {
30
- /**
31
- * Invoked when a subscribed handler throws during {@link SignalHub.emit}.
32
- *
33
- * Lets the owner observe/log faults in consumer code without aborting the
34
- * fan-out. If omitted, handler errors are swallowed so a misbehaving consumer
35
- * cannot break signal delivery to the others. This sink is itself guarded —
36
- * if it throws, the throw is ignored.
37
- *
38
- * @param error the value the handler threw
39
- * @param signal the signal that was being delivered when it threw
40
- */
41
- readonly onHandlerError?: (error: unknown, signal: SessionSignal) => void;
42
- }
43
- /**
44
- * A synchronous fan-out bus for {@link SessionSignal}s.
45
- *
46
- * Construct one per session; subscribe consumers; emit signals. Not a framework
47
- * type and not wired to one — purely the conductor's own event surface.
48
- */
49
- export declare class SignalHub {
50
- /** Insertion-ordered live set of subscribed handlers. */
51
- private readonly handlers;
52
- private readonly onHandlerError?;
53
- constructor(options?: SignalHubOptions);
54
- /**
55
- * Register a handler to receive every subsequently emitted signal.
56
- *
57
- * Registering the same function reference twice is a no-op (the `Set`
58
- * collapses it). The returned thunk removes the handler; it is idempotent and
59
- * safe to call during a dispatch.
60
- *
61
- * @param handler the consumer callback
62
- * @returns an unsubscribe function
63
- */
64
- subscribe(handler: SignalHandler): () => void;
65
- /**
66
- * Fan a signal out to every currently-subscribed handler, in registration
67
- * order.
68
- *
69
- * Iterates a snapshot of the handler set, so subscribe/unsubscribe performed
70
- * by a handler mid-dispatch affects only later emits. A throwing handler is
71
- * isolated via {@link SignalHubOptions.onHandlerError}; the remaining handlers
72
- * still run.
73
- *
74
- * @param signal the signal to deliver
75
- */
76
- emit(signal: SessionSignal): void;
77
- /** Number of currently-subscribed handlers. */
78
- get size(): number;
79
- /** Remove every handler. Subsequent {@link emit} calls deliver to no one. */
80
- clear(): void;
81
- /** Route a handler error to the sink, guarding the sink itself. */
82
- private report;
83
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * signal-hub — the conductor's product-event hub + framework-event translator.
3
- *
4
- * Two cooperating pieces sitting between the framework `Agent` loop and the
5
- * conductor's consumers:
6
- *
7
- * - {@link SignalHub} — a synchronous, insertion-ordered fan-out bus over the
8
- * {@link SessionSignal} stream. Behavior modules emit into it; UI/print/RPC
9
- * consumers subscribe to it.
10
- * - {@link translateAgentEvent} — the pure projection that turns a single
11
- * framework {@link AgentEvent} into the zero-or-more {@link SessionSignal}s
12
- * that flow through the hub. {@link TRANSLATOR_TABLE} is the underlying,
13
- * exhaustiveness-checked dispatch table (exported for inspection/testing).
14
- *
15
- * Typical wiring: subscribe the framework loop, run each raw event through
16
- * `translateAgentEvent`, and `emit` the results on a `SignalHub`.
17
- */
18
- export { SignalHub, type SignalHubOptions } from "./hub";
19
- export { translateAgentEvent, TRANSLATOR_TABLE } from "./translate";