@bradygaster/squad-sdk 0.8.0 → 0.8.2-1.4

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 (240) hide show
  1. package/README.md +296 -296
  2. package/dist/adapter/client.d.ts +25 -4
  3. package/dist/adapter/client.d.ts.map +1 -1
  4. package/dist/adapter/client.js +377 -75
  5. package/dist/adapter/client.js.map +1 -1
  6. package/dist/adapter/errors.js.map +1 -1
  7. package/dist/adapter/types.d.ts +38 -0
  8. package/dist/adapter/types.d.ts.map +1 -1
  9. package/dist/agents/charter-compiler.d.ts +4 -0
  10. package/dist/agents/charter-compiler.d.ts.map +1 -1
  11. package/dist/agents/charter-compiler.js +8 -0
  12. package/dist/agents/charter-compiler.js.map +1 -1
  13. package/dist/agents/history-shadow.js +30 -30
  14. package/dist/agents/history-shadow.js.map +1 -1
  15. package/dist/agents/index.d.ts +6 -3
  16. package/dist/agents/index.d.ts.map +1 -1
  17. package/dist/agents/index.js +132 -23
  18. package/dist/agents/index.js.map +1 -1
  19. package/dist/agents/lifecycle.d.ts.map +1 -1
  20. package/dist/agents/lifecycle.js +28 -2
  21. package/dist/agents/lifecycle.js.map +1 -1
  22. package/dist/agents/model-selector.d.ts.map +1 -1
  23. package/dist/agents/model-selector.js +10 -37
  24. package/dist/agents/model-selector.js.map +1 -1
  25. package/dist/agents/onboarding.js +12 -12
  26. package/dist/agents/onboarding.js.map +1 -1
  27. package/dist/build/ci-pipeline.js.map +1 -1
  28. package/dist/build/github-dist.d.ts +2 -2
  29. package/dist/build/github-dist.js +45 -45
  30. package/dist/build/github-dist.js.map +1 -1
  31. package/dist/build/install-migration.js +2 -2
  32. package/dist/build/install-migration.js.map +1 -1
  33. package/dist/build/release.js.map +1 -1
  34. package/dist/build/versioning.js.map +1 -1
  35. package/dist/builders/index.d.ts +156 -0
  36. package/dist/builders/index.d.ts.map +1 -0
  37. package/dist/builders/index.js +404 -0
  38. package/dist/builders/index.js.map +1 -0
  39. package/dist/builders/types.d.ts +187 -0
  40. package/dist/builders/types.d.ts.map +1 -0
  41. package/dist/builders/types.js +12 -0
  42. package/dist/builders/types.js.map +1 -0
  43. package/dist/casting/index.d.ts.map +1 -1
  44. package/dist/casting/index.js +10 -2
  45. package/dist/casting/index.js.map +1 -1
  46. package/dist/client/event-bus.d.ts.map +1 -1
  47. package/dist/client/event-bus.js +0 -1
  48. package/dist/client/event-bus.js.map +1 -1
  49. package/dist/client/index.d.ts +7 -4
  50. package/dist/client/index.d.ts.map +1 -1
  51. package/dist/client/index.js +22 -10
  52. package/dist/client/index.js.map +1 -1
  53. package/dist/config/agent-doc.js.map +1 -1
  54. package/dist/config/agent-source.js.map +1 -1
  55. package/dist/config/doc-sync.js.map +1 -1
  56. package/dist/config/init.d.ts +38 -13
  57. package/dist/config/init.d.ts.map +1 -1
  58. package/dist/config/init.js +615 -177
  59. package/dist/config/init.js.map +1 -1
  60. package/dist/config/legacy-fallback.js.map +1 -1
  61. package/dist/config/markdown-migration.js.map +1 -1
  62. package/dist/config/migration.js.map +1 -1
  63. package/dist/config/routing.js.map +1 -1
  64. package/dist/coordinator/coordinator.d.ts.map +1 -1
  65. package/dist/coordinator/coordinator.js +73 -55
  66. package/dist/coordinator/coordinator.js.map +1 -1
  67. package/dist/coordinator/fan-out.js.map +1 -1
  68. package/dist/coordinator/index.d.ts +19 -4
  69. package/dist/coordinator/index.d.ts.map +1 -1
  70. package/dist/coordinator/index.js +144 -21
  71. package/dist/coordinator/index.js.map +1 -1
  72. package/dist/index.d.ts +15 -2
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +16 -2
  75. package/dist/index.js.map +1 -1
  76. package/dist/multi-squad.d.ts +89 -0
  77. package/dist/multi-squad.d.ts.map +1 -0
  78. package/dist/multi-squad.js +233 -0
  79. package/dist/multi-squad.js.map +1 -0
  80. package/dist/ralph/index.d.ts +3 -1
  81. package/dist/ralph/index.d.ts.map +1 -1
  82. package/dist/ralph/index.js +83 -16
  83. package/dist/ralph/index.js.map +1 -1
  84. package/dist/ralph/triage.d.ts +48 -0
  85. package/dist/ralph/triage.d.ts.map +1 -0
  86. package/dist/ralph/triage.js +310 -0
  87. package/dist/ralph/triage.js.map +1 -0
  88. package/dist/remote/bridge.d.ts +79 -0
  89. package/dist/remote/bridge.d.ts.map +1 -0
  90. package/dist/remote/bridge.js +583 -0
  91. package/dist/remote/bridge.js.map +1 -0
  92. package/dist/remote/index.d.ts +7 -0
  93. package/dist/remote/index.d.ts.map +1 -0
  94. package/dist/remote/index.js +6 -0
  95. package/dist/remote/index.js.map +1 -0
  96. package/dist/remote/protocol.d.ts +130 -0
  97. package/dist/remote/protocol.d.ts.map +1 -0
  98. package/dist/remote/protocol.js +25 -0
  99. package/dist/remote/protocol.js.map +1 -0
  100. package/dist/remote/types.d.ts +34 -0
  101. package/dist/remote/types.d.ts.map +1 -0
  102. package/dist/remote/types.js +5 -0
  103. package/dist/remote/types.js.map +1 -0
  104. package/dist/resolution.d.ts +72 -0
  105. package/dist/resolution.d.ts.map +1 -1
  106. package/dist/resolution.js +153 -0
  107. package/dist/resolution.js.map +1 -1
  108. package/dist/runtime/benchmarks.js.map +1 -1
  109. package/dist/runtime/config.d.ts +3 -2
  110. package/dist/runtime/config.d.ts.map +1 -1
  111. package/dist/runtime/config.js +7 -6
  112. package/dist/runtime/config.js.map +1 -1
  113. package/dist/runtime/constants.d.ts +37 -0
  114. package/dist/runtime/constants.d.ts.map +1 -0
  115. package/dist/runtime/constants.js +60 -0
  116. package/dist/runtime/constants.js.map +1 -0
  117. package/dist/runtime/event-bus-ws-bridge.d.ts +35 -0
  118. package/dist/runtime/event-bus-ws-bridge.d.ts.map +1 -0
  119. package/dist/runtime/event-bus-ws-bridge.js +55 -0
  120. package/dist/runtime/event-bus-ws-bridge.js.map +1 -0
  121. package/dist/runtime/event-payloads.d.ts +108 -0
  122. package/dist/runtime/event-payloads.d.ts.map +1 -0
  123. package/dist/runtime/event-payloads.js +28 -0
  124. package/dist/runtime/event-payloads.js.map +1 -0
  125. package/dist/runtime/health.d.ts.map +1 -1
  126. package/dist/runtime/health.js +2 -1
  127. package/dist/runtime/health.js.map +1 -1
  128. package/dist/runtime/otel-api.d.ts +38 -0
  129. package/dist/runtime/otel-api.d.ts.map +1 -0
  130. package/dist/runtime/otel-api.js +94 -0
  131. package/dist/runtime/otel-api.js.map +1 -0
  132. package/dist/runtime/otel-bridge.d.ts +52 -0
  133. package/dist/runtime/otel-bridge.d.ts.map +1 -0
  134. package/dist/runtime/otel-bridge.js +132 -0
  135. package/dist/runtime/otel-bridge.js.map +1 -0
  136. package/dist/runtime/otel-init.d.ts +84 -0
  137. package/dist/runtime/otel-init.d.ts.map +1 -0
  138. package/dist/runtime/otel-init.js +86 -0
  139. package/dist/runtime/otel-init.js.map +1 -0
  140. package/dist/runtime/otel-metrics.d.ts +42 -0
  141. package/dist/runtime/otel-metrics.d.ts.map +1 -0
  142. package/dist/runtime/otel-metrics.js +196 -0
  143. package/dist/runtime/otel-metrics.js.map +1 -0
  144. package/dist/runtime/otel.d.ts +55 -0
  145. package/dist/runtime/otel.d.ts.map +1 -0
  146. package/dist/runtime/otel.js +165 -0
  147. package/dist/runtime/otel.js.map +1 -0
  148. package/dist/runtime/squad-observer.d.ts +75 -0
  149. package/dist/runtime/squad-observer.d.ts.map +1 -0
  150. package/dist/runtime/squad-observer.js +190 -0
  151. package/dist/runtime/squad-observer.js.map +1 -0
  152. package/dist/runtime/streaming.d.ts +9 -0
  153. package/dist/runtime/streaming.d.ts.map +1 -1
  154. package/dist/runtime/streaming.js +37 -1
  155. package/dist/runtime/streaming.js.map +1 -1
  156. package/dist/sharing/conflicts.js +7 -5
  157. package/dist/sharing/conflicts.js.map +1 -1
  158. package/dist/sharing/consult.d.ts +226 -0
  159. package/dist/sharing/consult.d.ts.map +1 -0
  160. package/dist/sharing/consult.js +818 -0
  161. package/dist/sharing/consult.js.map +1 -0
  162. package/dist/sharing/export.js.map +1 -1
  163. package/dist/sharing/import.js.map +1 -1
  164. package/dist/sharing/index.d.ts +2 -1
  165. package/dist/sharing/index.d.ts.map +1 -1
  166. package/dist/sharing/index.js +2 -1
  167. package/dist/sharing/index.js.map +1 -1
  168. package/dist/skills/skill-loader.js.map +1 -1
  169. package/dist/streams/filter.d.ts +33 -0
  170. package/dist/streams/filter.d.ts.map +1 -0
  171. package/dist/streams/filter.js +29 -0
  172. package/dist/streams/filter.js.map +1 -0
  173. package/dist/streams/index.d.ts +9 -0
  174. package/dist/streams/index.d.ts.map +1 -0
  175. package/dist/streams/index.js +9 -0
  176. package/dist/streams/index.js.map +1 -0
  177. package/dist/streams/resolver.d.ts +40 -0
  178. package/dist/streams/resolver.d.ts.map +1 -0
  179. package/dist/streams/resolver.js +162 -0
  180. package/dist/streams/resolver.js.map +1 -0
  181. package/dist/streams/types.d.ts +44 -0
  182. package/dist/streams/types.d.ts.map +1 -0
  183. package/dist/streams/types.js +10 -0
  184. package/dist/streams/types.js.map +1 -0
  185. package/dist/tools/index.d.ts +8 -0
  186. package/dist/tools/index.d.ts.map +1 -1
  187. package/dist/tools/index.js +57 -1
  188. package/dist/tools/index.js.map +1 -1
  189. package/dist/types.d.ts +23 -0
  190. package/dist/types.d.ts.map +1 -1
  191. package/dist/upstream/index.d.ts +8 -0
  192. package/dist/upstream/index.d.ts.map +1 -0
  193. package/dist/upstream/index.js +7 -0
  194. package/dist/upstream/index.js.map +1 -0
  195. package/dist/upstream/resolver.d.ts +37 -0
  196. package/dist/upstream/resolver.d.ts.map +1 -0
  197. package/dist/upstream/resolver.js +234 -0
  198. package/dist/upstream/resolver.js.map +1 -0
  199. package/dist/upstream/types.d.ts +55 -0
  200. package/dist/upstream/types.d.ts.map +1 -0
  201. package/dist/upstream/types.js +11 -0
  202. package/dist/upstream/types.js.map +1 -0
  203. package/dist/utils/safe-timestamp.d.ts +6 -0
  204. package/dist/utils/safe-timestamp.d.ts.map +1 -0
  205. package/dist/utils/safe-timestamp.js +8 -0
  206. package/dist/utils/safe-timestamp.js.map +1 -0
  207. package/package.json +208 -115
  208. package/templates/casting-history.json +4 -0
  209. package/templates/casting-policy.json +35 -0
  210. package/templates/casting-registry.json +3 -0
  211. package/templates/ceremonies.md +41 -0
  212. package/templates/charter.md +53 -0
  213. package/templates/constraint-tracking.md +38 -0
  214. package/templates/copilot-instructions.md +46 -0
  215. package/templates/history.md +10 -0
  216. package/templates/identity/now.md +9 -0
  217. package/templates/identity/wisdom.md +15 -0
  218. package/templates/mcp-config.md +98 -0
  219. package/templates/multi-agent-format.md +28 -0
  220. package/templates/orchestration-log.md +27 -0
  221. package/templates/plugin-marketplace.md +49 -0
  222. package/templates/raw-agent-output.md +37 -0
  223. package/templates/roster.md +60 -0
  224. package/templates/routing.md +54 -0
  225. package/templates/run-output.md +50 -0
  226. package/templates/scribe-charter.md +119 -0
  227. package/templates/skill.md +24 -0
  228. package/templates/skills/project-conventions/SKILL.md +56 -0
  229. package/templates/squad.agent.md +1146 -0
  230. package/templates/workflows/squad-ci.yml +24 -0
  231. package/templates/workflows/squad-docs.yml +50 -0
  232. package/templates/workflows/squad-heartbeat.yml +316 -0
  233. package/templates/workflows/squad-insider-release.yml +61 -0
  234. package/templates/workflows/squad-issue-assign.yml +161 -0
  235. package/templates/workflows/squad-label-enforce.yml +181 -0
  236. package/templates/workflows/squad-preview.yml +55 -0
  237. package/templates/workflows/squad-promote.yml +120 -0
  238. package/templates/workflows/squad-release.yml +77 -0
  239. package/templates/workflows/squad-triage.yml +260 -0
  240. package/templates/workflows/sync-squad-labels.yml +169 -0
@@ -10,7 +10,7 @@
10
10
  * 2. Watchdog: Periodic health checks on session pool
11
11
  * 3. Cloud heartbeat: External health signal (future)
12
12
  */
13
- import type { EventBus } from '../client/event-bus.js';
13
+ import type { EventBus } from '../runtime/event-bus.js';
14
14
  export interface MonitorConfig {
15
15
  /** Team root directory */
16
16
  teamRoot: string;
@@ -41,6 +41,8 @@ export declare class RalphMonitor {
41
41
  private config;
42
42
  private state;
43
43
  private eventBus;
44
+ private unsubscribers;
45
+ private healthCheckTimer;
44
46
  constructor(config: MonitorConfig);
45
47
  /** Start monitoring — subscribe to EventBus and begin health checks */
46
48
  start(eventBus: EventBus): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ralph/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,wBAAwB,CAAC;AAInE,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IAEjB,iDAAiD;IACjD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,oDAAoD;IACpD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAC/C,YAAY,EAAE,IAAI,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,qCAAqC;IACrC,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;IAC7B,4BAA4B;IAC5B,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACrC,6CAA6C;IAC7C,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAID,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,MAAM,EAAE,aAAa;IAWjC,uEAAuE;IACjE,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C,iDAAiD;IACjD,OAAO,CAAC,WAAW;IAMnB,2DAA2D;IACrD,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAQ/C,6CAA6C;IAC7C,SAAS,IAAI,eAAe,EAAE;IAI9B,8CAA8C;IACxC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAK5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ralph/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,yBAAyB,CAAC;AAIpE,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IAEjB,iDAAiD;IACjD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,oDAAoD;IACpD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAC/C,YAAY,EAAE,IAAI,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,qCAAqC;IACrC,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;IAC7B,4BAA4B;IAC5B,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACrC,6CAA6C;IAC7C,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAID,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,gBAAgB,CAA+C;gBAE3D,MAAM,EAAE,aAAa;IASjC,uEAAuE;IACjE,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB9C,iDAAiD;IACjD,OAAO,CAAC,WAAW;IA6CnB,2DAA2D;IACrD,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAc/C,6CAA6C;IAC7C,SAAS,IAAI,eAAe,EAAE;IAI9B,8CAA8C;IACxC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAyB5B"}
@@ -10,11 +10,14 @@
10
10
  * 2. Watchdog: Periodic health checks on session pool
11
11
  * 3. Cloud heartbeat: External health signal (future)
12
12
  */
13
+ import { writeFile } from 'node:fs/promises';
13
14
  // --- Ralph Monitor ---
14
15
  export class RalphMonitor {
15
16
  config;
16
17
  state;
17
18
  eventBus = null;
19
+ unsubscribers = [];
20
+ healthCheckTimer = null;
18
21
  constructor(config) {
19
22
  this.config = config;
20
23
  this.state = {
@@ -22,29 +25,76 @@ export class RalphMonitor {
22
25
  agents: new Map(),
23
26
  observations: [],
24
27
  };
25
- // TODO: PRD 8 — Load persisted state from statePath if exists
26
- // TODO: PRD 8 — Initialize as persistent SDK session via resumeSession('squad-ralph')
27
28
  }
28
29
  /** Start monitoring — subscribe to EventBus and begin health checks */
29
30
  async start(eventBus) {
30
31
  this.eventBus = eventBus;
31
- // TODO: PRD 8 — Subscribe to session lifecycle events
32
- // TODO: PRD 8 — Subscribe to agent.milestone events
33
- // TODO: PRD 8 — Start periodic health check timer
34
- // TODO: PRD 8 — Register onSessionStart hook to track new agents
32
+ // Subscribe to session lifecycle events
33
+ this.unsubscribers.push(eventBus.subscribe('session:created', (event) => this.handleEvent(event)));
34
+ this.unsubscribers.push(eventBus.subscribe('session:destroyed', (event) => this.handleEvent(event)));
35
+ this.unsubscribers.push(eventBus.subscribe('session:error', (event) => this.handleEvent(event)));
36
+ this.unsubscribers.push(eventBus.subscribe('agent:milestone', (event) => this.handleEvent(event)));
37
+ // DISABLED: Heartbeat timer commented out pre-migration — re-enable when ready
38
+ // const interval = this.config.healthCheckInterval ?? 30_000;
39
+ // this.healthCheckTimer = setInterval(() => {
40
+ // void this.healthCheck();
41
+ // }, interval);
35
42
  }
36
43
  /** Handle an incoming event from the EventBus */
37
44
  handleEvent(event) {
38
- // TODO: PRD 8 Update agent work status based on event type
39
- // TODO: PRD 8 Extract [MILESTONE] markers from agent output
40
- // TODO: PRD 8 — Detect stale sessions and flag for coordinator
45
+ const agentName = event.agentName ?? 'unknown';
46
+ const sessionId = event.sessionId ?? 'unknown';
47
+ switch (event.type) {
48
+ case 'session:created': {
49
+ this.state.agents.set(agentName, {
50
+ agentName,
51
+ sessionId,
52
+ status: 'working',
53
+ lastActivity: event.timestamp,
54
+ milestones: [],
55
+ });
56
+ break;
57
+ }
58
+ case 'session:destroyed': {
59
+ this.state.agents.delete(agentName);
60
+ break;
61
+ }
62
+ case 'session:error': {
63
+ const existing = this.state.agents.get(agentName);
64
+ if (existing) {
65
+ existing.status = 'error';
66
+ existing.lastActivity = event.timestamp;
67
+ }
68
+ break;
69
+ }
70
+ case 'agent:milestone': {
71
+ const agent = this.state.agents.get(agentName);
72
+ if (agent) {
73
+ const payload = event.payload;
74
+ if (payload?.milestone) {
75
+ agent.milestones.push(payload.milestone);
76
+ }
77
+ if (payload?.task) {
78
+ agent.currentTask = payload.task;
79
+ }
80
+ agent.lastActivity = event.timestamp;
81
+ agent.status = 'working';
82
+ }
83
+ break;
84
+ }
85
+ }
41
86
  }
42
87
  /** Run a health check across all tracked agent sessions */
43
88
  async healthCheck() {
44
- // TODO: PRD 8 — Check each session's last activity timestamp
45
- // TODO: PRD 8 Mark stale sessions (no activity > threshold)
46
- // TODO: PRD 8 — Persist state to statePath for crash recovery
47
- this.state.lastHealthCheck = new Date();
89
+ const now = new Date();
90
+ const staleThreshold = this.config.staleSessionThreshold ?? 300_000;
91
+ for (const agent of this.state.agents.values()) {
92
+ if (agent.status === 'error')
93
+ continue;
94
+ const elapsed = now.getTime() - agent.lastActivity.getTime();
95
+ agent.status = elapsed > staleThreshold ? 'stale' : agent.status === 'stale' ? 'idle' : agent.status;
96
+ }
97
+ this.state.lastHealthCheck = now;
48
98
  return Array.from(this.state.agents.values());
49
99
  }
50
100
  /** Get current work status for all agents */
@@ -53,9 +103,26 @@ export class RalphMonitor {
53
103
  }
54
104
  /** Stop monitoring and persist final state */
55
105
  async stop() {
56
- // TODO: PRD 8 — Unsubscribe from EventBus
57
- // TODO: PRD 8 Stop health check timer
58
- // TODO: PRD 8 — Persist final state to statePath
106
+ // Unsubscribe from EventBus
107
+ for (const unsub of this.unsubscribers) {
108
+ unsub();
109
+ }
110
+ this.unsubscribers = [];
111
+ // Stop health check timer
112
+ if (this.healthCheckTimer !== null) {
113
+ clearInterval(this.healthCheckTimer);
114
+ this.healthCheckTimer = null;
115
+ }
116
+ // Persist state if statePath is configured
117
+ if (this.config.statePath) {
118
+ const serializable = {
119
+ lastHealthCheck: this.state.lastHealthCheck?.toISOString() ?? null,
120
+ agents: Array.from(this.state.agents.entries()),
121
+ observations: this.state.observations,
122
+ };
123
+ await writeFile(this.config.statePath, JSON.stringify(serializable, null, 2), 'utf-8');
124
+ }
125
+ this.eventBus = null;
59
126
  }
60
127
  }
61
128
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ralph/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAsCH,wBAAwB;AAExB,MAAM,OAAO,YAAY;IACf,MAAM,CAAgB;IACtB,KAAK,CAAe;IACpB,QAAQ,GAAoB,IAAI,CAAC;IAEzC,YAAY,MAAqB;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG;YACX,eAAe,EAAE,IAAI;YACrB,MAAM,EAAE,IAAI,GAAG,EAAE;YACjB,YAAY,EAAE,EAAE;SACjB,CAAC;QACF,8DAA8D;QAC9D,sFAAsF;IACxF,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,KAAK,CAAC,QAAkB;QAC5B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,sDAAsD;QACtD,oDAAoD;QACpD,kDAAkD;QAClD,iEAAiE;IACnE,CAAC;IAED,iDAAiD;IACzC,WAAW,CAAC,KAAiB;QACnC,6DAA6D;QAC7D,8DAA8D;QAC9D,+DAA+D;IACjE,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,WAAW;QACf,6DAA6D;QAC7D,8DAA8D;QAC9D,8DAA8D;QAC9D,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,IAAI,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,6CAA6C;IAC7C,SAAS;QACP,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,IAAI;QACR,0CAA0C;QAC1C,wCAAwC;QACxC,iDAAiD;IACnD,CAAC;CACF"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ralph/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /** Parsed routing rule from routing.md */
2
+ export interface RoutingRule {
3
+ workType: string;
4
+ agentName: string;
5
+ keywords: string[];
6
+ }
7
+ /** Parsed module ownership rule from routing.md */
8
+ export interface ModuleOwnership {
9
+ modulePath: string;
10
+ primary: string;
11
+ secondary: string | null;
12
+ }
13
+ /** Team member from team.md roster */
14
+ export interface TeamMember {
15
+ name: string;
16
+ role: string;
17
+ label: string;
18
+ }
19
+ /** Triage decision result */
20
+ export interface TriageDecision {
21
+ agent: TeamMember;
22
+ reason: string;
23
+ source: 'module-ownership' | 'routing-rule' | 'role-keyword' | 'lead-fallback';
24
+ confidence: 'high' | 'medium' | 'low';
25
+ }
26
+ /** Issue data for triage */
27
+ export interface TriageIssue {
28
+ number: number;
29
+ title: string;
30
+ body?: string;
31
+ labels: string[];
32
+ }
33
+ /** Parse routing rules from routing.md content */
34
+ export declare function parseRoutingRules(routingMd: string): RoutingRule[];
35
+ /** Parse module ownership from routing.md content */
36
+ export declare function parseModuleOwnership(routingMd: string): ModuleOwnership[];
37
+ /** Parse team roster from team.md content */
38
+ export declare function parseRoster(teamMd: string): TeamMember[];
39
+ /**
40
+ * Triage an issue using routing rules, module ownership, and roster.
41
+ * Priority order:
42
+ * 1. Module path match — issue mentions a file path matching module ownership
43
+ * 2. Work type keyword — issue content matches routing rule keywords
44
+ * 3. Role keyword — fallback to generic role-based matching (frontend/backend/test)
45
+ * 4. Lead fallback — assign to Lead/Architect if no match
46
+ */
47
+ export declare function triageIssue(issue: TriageIssue, rules: RoutingRule[], modules: ModuleOwnership[], roster: TeamMember[]): TriageDecision | null;
48
+ //# sourceMappingURL=triage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triage.d.ts","sourceRoot":"","sources":["../../src/ralph/triage.ts"],"names":[],"mappings":"AAEA,0CAA0C;AAC1C,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,sCAAsC;AACtC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,kBAAkB,GAAG,cAAc,GAAG,cAAc,GAAG,eAAe,CAAC;IAC/E,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAED,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAOD,kDAAkD;AAClD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,CAwBlE;AAED,qDAAqD;AACrD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAsBzE;AAED,6CAA6C;AAC7C,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CA4BxD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,WAAW,EAAE,EACpB,OAAO,EAAE,eAAe,EAAE,EAC1B,MAAM,EAAE,UAAU,EAAE,GACnB,cAAc,GAAG,IAAI,CA6DvB"}
@@ -0,0 +1,310 @@
1
+ import { normalizeEol } from '../utils/normalize-eol.js';
2
+ /** Parse routing rules from routing.md content */
3
+ export function parseRoutingRules(routingMd) {
4
+ const table = parseTableSection(routingMd, /^##\s*work\s*type\s*(?:→|->)\s*agent\b/i);
5
+ if (!table)
6
+ return [];
7
+ const workTypeIndex = findColumnIndex(table.headers, ['work type', 'type']);
8
+ const agentIndex = findColumnIndex(table.headers, ['agent', 'route to', 'route']);
9
+ const examplesIndex = findColumnIndex(table.headers, ['examples', 'example']);
10
+ if (workTypeIndex < 0 || agentIndex < 0)
11
+ return [];
12
+ const rules = [];
13
+ for (const row of table.rows) {
14
+ const workType = cleanCell(row[workTypeIndex] ?? '');
15
+ const agentName = cleanCell(row[agentIndex] ?? '');
16
+ const keywords = splitKeywords(examplesIndex >= 0 ? row[examplesIndex] : '');
17
+ if (!workType || !agentName)
18
+ continue;
19
+ rules.push({ workType, agentName, keywords });
20
+ }
21
+ return rules;
22
+ }
23
+ /** Parse module ownership from routing.md content */
24
+ export function parseModuleOwnership(routingMd) {
25
+ const table = parseTableSection(routingMd, /^##\s*module\s*ownership\b/i);
26
+ if (!table)
27
+ return [];
28
+ const moduleIndex = findColumnIndex(table.headers, ['module', 'path']);
29
+ const primaryIndex = findColumnIndex(table.headers, ['primary']);
30
+ const secondaryIndex = findColumnIndex(table.headers, ['secondary']);
31
+ if (moduleIndex < 0 || primaryIndex < 0)
32
+ return [];
33
+ const modules = [];
34
+ for (const row of table.rows) {
35
+ const modulePath = normalizeModulePath(row[moduleIndex] ?? '');
36
+ const primary = cleanCell(row[primaryIndex] ?? '');
37
+ const secondaryRaw = cleanCell(secondaryIndex >= 0 ? row[secondaryIndex] ?? '' : '');
38
+ const secondary = normalizeOptionalOwner(secondaryRaw);
39
+ if (!modulePath || !primary)
40
+ continue;
41
+ modules.push({ modulePath, primary, secondary });
42
+ }
43
+ return modules;
44
+ }
45
+ /** Parse team roster from team.md content */
46
+ export function parseRoster(teamMd) {
47
+ const table = parseTableSection(teamMd, /^##\s*members\b/i) ??
48
+ parseTableSection(teamMd, /^##\s*team\s*roster\b/i);
49
+ if (!table)
50
+ return [];
51
+ const nameIndex = findColumnIndex(table.headers, ['name']);
52
+ const roleIndex = findColumnIndex(table.headers, ['role']);
53
+ if (nameIndex < 0 || roleIndex < 0)
54
+ return [];
55
+ const excluded = new Set(['scribe', 'ralph']);
56
+ const members = [];
57
+ for (const row of table.rows) {
58
+ const name = cleanCell(row[nameIndex] ?? '');
59
+ const role = cleanCell(row[roleIndex] ?? '');
60
+ if (!name || !role)
61
+ continue;
62
+ if (excluded.has(name.toLowerCase()))
63
+ continue;
64
+ members.push({
65
+ name,
66
+ role,
67
+ label: `squad:${name.toLowerCase()}`,
68
+ });
69
+ }
70
+ return members;
71
+ }
72
+ /**
73
+ * Triage an issue using routing rules, module ownership, and roster.
74
+ * Priority order:
75
+ * 1. Module path match — issue mentions a file path matching module ownership
76
+ * 2. Work type keyword — issue content matches routing rule keywords
77
+ * 3. Role keyword — fallback to generic role-based matching (frontend/backend/test)
78
+ * 4. Lead fallback — assign to Lead/Architect if no match
79
+ */
80
+ export function triageIssue(issue, rules, modules, roster) {
81
+ const issueText = `${issue.title}\n${issue.body ?? ''}`.toLowerCase();
82
+ const normalizedIssueText = normalizeTextForPathMatch(issueText);
83
+ const bestModule = findBestModuleMatch(normalizedIssueText, modules);
84
+ if (bestModule) {
85
+ const primaryMember = findMember(bestModule.primary, roster);
86
+ if (primaryMember) {
87
+ return {
88
+ agent: primaryMember,
89
+ reason: `Matched module path "${bestModule.modulePath}" to primary owner "${bestModule.primary}"`,
90
+ source: 'module-ownership',
91
+ confidence: 'high',
92
+ };
93
+ }
94
+ if (bestModule.secondary) {
95
+ const secondaryMember = findMember(bestModule.secondary, roster);
96
+ if (secondaryMember) {
97
+ return {
98
+ agent: secondaryMember,
99
+ reason: `Matched module path "${bestModule.modulePath}" to secondary owner "${bestModule.secondary}"`,
100
+ source: 'module-ownership',
101
+ confidence: 'medium',
102
+ };
103
+ }
104
+ }
105
+ }
106
+ const bestRule = findBestRuleMatch(issueText, rules);
107
+ if (bestRule) {
108
+ const agent = findMember(bestRule.rule.agentName, roster);
109
+ if (agent) {
110
+ return {
111
+ agent,
112
+ reason: `Matched routing keyword(s): ${bestRule.matchedKeywords.join(', ')}`,
113
+ source: 'routing-rule',
114
+ confidence: bestRule.matchedKeywords.length >= 2 ? 'high' : 'medium',
115
+ };
116
+ }
117
+ }
118
+ const roleMatch = findRoleKeywordMatch(issueText, roster);
119
+ if (roleMatch) {
120
+ return {
121
+ agent: roleMatch.agent,
122
+ reason: roleMatch.reason,
123
+ source: 'role-keyword',
124
+ confidence: 'medium',
125
+ };
126
+ }
127
+ const lead = findLeadFallback(roster);
128
+ if (!lead)
129
+ return null;
130
+ return {
131
+ agent: lead,
132
+ reason: 'No module, routing, or role keyword match — routed to Lead/Architect',
133
+ source: 'lead-fallback',
134
+ confidence: 'low',
135
+ };
136
+ }
137
+ function parseTableSection(markdown, sectionHeader) {
138
+ const lines = normalizeEol(markdown).split('\n');
139
+ let inSection = false;
140
+ const tableLines = [];
141
+ for (const line of lines) {
142
+ const trimmed = line.trim();
143
+ if (!inSection && sectionHeader.test(trimmed)) {
144
+ inSection = true;
145
+ continue;
146
+ }
147
+ if (inSection && /^##\s+/.test(trimmed)) {
148
+ break;
149
+ }
150
+ if (inSection && trimmed.startsWith('|')) {
151
+ tableLines.push(trimmed);
152
+ }
153
+ }
154
+ if (tableLines.length === 0)
155
+ return null;
156
+ let headers = null;
157
+ const rows = [];
158
+ for (const line of tableLines) {
159
+ const cells = parseTableLine(line);
160
+ if (cells.length === 0)
161
+ continue;
162
+ if (cells.every((cell) => /^:?-{2,}:?$/.test(cell)))
163
+ continue;
164
+ if (!headers) {
165
+ headers = cells;
166
+ continue;
167
+ }
168
+ rows.push(cells);
169
+ }
170
+ if (!headers)
171
+ return null;
172
+ return { headers, rows };
173
+ }
174
+ function parseTableLine(line) {
175
+ return line
176
+ .replace(/^\|/, '')
177
+ .replace(/\|$/, '')
178
+ .split('|')
179
+ .map((cell) => cell.trim());
180
+ }
181
+ function findColumnIndex(headers, candidates) {
182
+ const normalizedHeaders = headers.map((header) => cleanCell(header).toLowerCase());
183
+ for (const candidate of candidates) {
184
+ const index = normalizedHeaders.findIndex((header) => header.includes(candidate));
185
+ if (index >= 0)
186
+ return index;
187
+ }
188
+ return -1;
189
+ }
190
+ function cleanCell(value) {
191
+ return value
192
+ .replace(/`/g, '')
193
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
194
+ .trim();
195
+ }
196
+ function splitKeywords(examplesCell) {
197
+ if (!examplesCell)
198
+ return [];
199
+ return examplesCell
200
+ .split(',')
201
+ .map((keyword) => cleanCell(keyword))
202
+ .filter((keyword) => keyword.length > 0);
203
+ }
204
+ function normalizeOptionalOwner(owner) {
205
+ if (!owner)
206
+ return null;
207
+ if (/^[-—–]+$/.test(owner))
208
+ return null;
209
+ return owner;
210
+ }
211
+ function normalizeModulePath(modulePath) {
212
+ return cleanCell(modulePath).replace(/\\/g, '/').toLowerCase();
213
+ }
214
+ function normalizeTextForPathMatch(text) {
215
+ return text.replace(/\\/g, '/').replace(/`/g, '');
216
+ }
217
+ function normalizeName(value) {
218
+ return cleanCell(value)
219
+ .toLowerCase()
220
+ .replace(/[^\w@\s-]/g, '')
221
+ .replace(/\s+/g, ' ')
222
+ .trim();
223
+ }
224
+ function findMember(target, roster) {
225
+ const normalizedTarget = normalizeName(target);
226
+ if (!normalizedTarget)
227
+ return null;
228
+ for (const member of roster) {
229
+ if (normalizeName(member.name) === normalizedTarget)
230
+ return member;
231
+ }
232
+ for (const member of roster) {
233
+ if (normalizeName(member.role) === normalizedTarget)
234
+ return member;
235
+ }
236
+ for (const member of roster) {
237
+ const memberName = normalizeName(member.name);
238
+ if (normalizedTarget.includes(memberName) || memberName.includes(normalizedTarget)) {
239
+ return member;
240
+ }
241
+ }
242
+ for (const member of roster) {
243
+ const memberRole = normalizeName(member.role);
244
+ if (normalizedTarget.includes(memberRole) || memberRole.includes(normalizedTarget)) {
245
+ return member;
246
+ }
247
+ }
248
+ return null;
249
+ }
250
+ function findBestModuleMatch(issueText, modules) {
251
+ let best = null;
252
+ let bestLength = -1;
253
+ for (const module of modules) {
254
+ const modulePath = normalizeModulePath(module.modulePath);
255
+ if (!modulePath)
256
+ continue;
257
+ if (!issueText.includes(modulePath))
258
+ continue;
259
+ if (modulePath.length > bestLength) {
260
+ best = module;
261
+ bestLength = modulePath.length;
262
+ }
263
+ }
264
+ return best;
265
+ }
266
+ function findBestRuleMatch(issueText, rules) {
267
+ let best = null;
268
+ let bestScore = 0;
269
+ for (const rule of rules) {
270
+ const matchedKeywords = rule.keywords
271
+ .map((keyword) => keyword.toLowerCase())
272
+ .filter((keyword) => keyword.length > 0 && issueText.includes(keyword));
273
+ if (matchedKeywords.length === 0)
274
+ continue;
275
+ const score = matchedKeywords.length * 100 + matchedKeywords.reduce((sum, keyword) => sum + keyword.length, 0);
276
+ if (score > bestScore) {
277
+ best = {
278
+ rule,
279
+ matchedKeywords,
280
+ };
281
+ bestScore = score;
282
+ }
283
+ }
284
+ return best;
285
+ }
286
+ function findRoleKeywordMatch(issueText, roster) {
287
+ for (const member of roster) {
288
+ const role = member.role.toLowerCase();
289
+ if ((role.includes('frontend') || role.includes('ui')) &&
290
+ (issueText.includes('ui') || issueText.includes('frontend') || issueText.includes('css'))) {
291
+ return { agent: member, reason: 'Matched frontend/UI role keywords' };
292
+ }
293
+ if ((role.includes('backend') || role.includes('api') || role.includes('server')) &&
294
+ (issueText.includes('api') || issueText.includes('backend') || issueText.includes('database'))) {
295
+ return { agent: member, reason: 'Matched backend/API role keywords' };
296
+ }
297
+ if ((role.includes('test') || role.includes('qa')) &&
298
+ (issueText.includes('test') || issueText.includes('bug') || issueText.includes('fix'))) {
299
+ return { agent: member, reason: 'Matched testing/QA role keywords' };
300
+ }
301
+ }
302
+ return null;
303
+ }
304
+ function findLeadFallback(roster) {
305
+ return (roster.find((member) => {
306
+ const role = member.role.toLowerCase();
307
+ return role.includes('lead') || role.includes('architect');
308
+ }) ?? null);
309
+ }
310
+ //# sourceMappingURL=triage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triage.js","sourceRoot":"","sources":["../../src/ralph/triage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Squad Remote Control — RemoteBridge
3
+ *
4
+ * WebSocket server that bridges Squad's EventBus to remote PWA clients.
5
+ * Maintains message history, broadcasts events, handles incoming commands.
6
+ */
7
+ import http from 'node:http';
8
+ import { type RCMessage, type RCAgent } from './protocol.js';
9
+ import type { RemoteBridgeConfig, RemoteConnection, ConnectionState } from './types.js';
10
+ export declare class RemoteBridge {
11
+ private config;
12
+ private server;
13
+ private wss;
14
+ private connections;
15
+ private messages;
16
+ private agents;
17
+ private state;
18
+ private messageIdCounter;
19
+ private staticHandler?;
20
+ private acpEventLog;
21
+ private wsRateLimit;
22
+ private ipConnections;
23
+ private httpRateLimits;
24
+ private sessionToken;
25
+ private tickets;
26
+ private readonly SESSION_TTL;
27
+ private readonly sessionCreatedAt;
28
+ private auditLogDir;
29
+ private auditLogPath;
30
+ private auditLog;
31
+ constructor(config: RemoteBridgeConfig);
32
+ /** Set a handler to serve static PWA files */
33
+ setStaticHandler(handler: (req: http.IncomingMessage, res: http.ServerResponse) => void): void;
34
+ /** Get the session token for WebSocket authentication */
35
+ getSessionToken(): string;
36
+ /** Get the audit log file path */
37
+ getAuditLogPath(): string;
38
+ /** Get the session expiry timestamp */
39
+ getSessionExpiry(): number;
40
+ /** Start the HTTP + WebSocket server */
41
+ start(): Promise<number>;
42
+ /** Stop the server and clean up */
43
+ stop(): Promise<void>;
44
+ /** Get the actual port the server is listening on */
45
+ getPort(): number;
46
+ getState(): ConnectionState;
47
+ getConnectionCount(): number;
48
+ getConnections(): RemoteConnection[];
49
+ /** Add a message to history and broadcast to clients */
50
+ addMessage(role: 'user' | 'agent' | 'system', content: string, agentName?: string): RCMessage;
51
+ getMessageHistory(): RCMessage[];
52
+ /** Send a streaming delta to all clients */
53
+ sendDelta(sessionId: string, agentName: string, content: string): void;
54
+ /** Update the agent roster and broadcast */
55
+ updateAgents(agents: RCAgent[]): void;
56
+ /** Update a single agent's status */
57
+ updateAgentStatus(name: string, status: RCAgent['status']): void;
58
+ sendToolCall(agentName: string, tool: string, args: Record<string, unknown>, status: 'running' | 'completed' | 'error'): void;
59
+ sendPermissionRequest(id: string, agentName: string, tool: string, args: Record<string, unknown>, description: string): void;
60
+ sendUsage(model: string, inputTokens: number, outputTokens: number, cost: number): void;
61
+ sendError(message: string, agentName?: string): void;
62
+ private handleSessionsAPI;
63
+ private handleDeleteSession;
64
+ /** Strip ANSI escape codes and Unicode invisible characters */
65
+ private stripInvisible;
66
+ /** Redact secrets from text before replay */
67
+ private redactSecrets;
68
+ private passthroughWrite;
69
+ /** Set a passthrough pipe — raw WebSocket messages go to this writer,
70
+ * and call passthroughFromAgent() to send agent responses back */
71
+ setPassthrough(writer: (msg: string) => void): void;
72
+ /** Forward a raw message from the agent (copilot stdout) to all clients + record */
73
+ passthroughFromAgent(line: string): void;
74
+ private handleConnection;
75
+ private handleClientCommand;
76
+ private broadcast;
77
+ private send;
78
+ }
79
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/remote/bridge.ts"],"names":[],"mappings":"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"}