@sentropic/h2a 0.97.2 → 0.97.3

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 (73) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/dist/bin.js +13 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +14 -3
  7. package/dist/cli.js.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/mcp.d.ts +1 -1
  10. package/dist/mcp.d.ts.map +1 -1
  11. package/dist/mcp.js +1 -0
  12. package/dist/mcp.js.map +1 -1
  13. package/dist/runtime/identity/bindings.d.ts.map +1 -1
  14. package/dist/runtime/identity/bindings.js +16 -1
  15. package/dist/runtime/identity/bindings.js.map +1 -1
  16. package/dist/runtime/identity/live.d.ts.map +1 -1
  17. package/dist/runtime/identity/live.js +15 -9
  18. package/dist/runtime/identity/live.js.map +1 -1
  19. package/dist/runtime/local-files/locks.d.ts +20 -0
  20. package/dist/runtime/local-files/locks.d.ts.map +1 -1
  21. package/dist/runtime/local-files/locks.js +42 -2
  22. package/dist/runtime/local-files/locks.js.map +1 -1
  23. package/dist/runtime/local-files/store.d.ts.map +1 -1
  24. package/dist/runtime/local-files/store.js +42 -4
  25. package/dist/runtime/local-files/store.js.map +1 -1
  26. package/dist/runtime/mcp/discovery-pagination.d.ts +73 -0
  27. package/dist/runtime/mcp/discovery-pagination.d.ts.map +1 -0
  28. package/dist/runtime/mcp/discovery-pagination.js +446 -0
  29. package/dist/runtime/mcp/discovery-pagination.js.map +1 -0
  30. package/dist/runtime/mcp/frame-budget.d.ts +149 -0
  31. package/dist/runtime/mcp/frame-budget.d.ts.map +1 -0
  32. package/dist/runtime/mcp/frame-budget.js +275 -0
  33. package/dist/runtime/mcp/frame-budget.js.map +1 -0
  34. package/dist/runtime/mcp/handlers.d.ts +14 -3
  35. package/dist/runtime/mcp/handlers.d.ts.map +1 -1
  36. package/dist/runtime/mcp/handlers.js +22 -1
  37. package/dist/runtime/mcp/handlers.js.map +1 -1
  38. package/dist/runtime/mcp/index.d.ts +1 -0
  39. package/dist/runtime/mcp/index.d.ts.map +1 -1
  40. package/dist/runtime/mcp/index.js +1 -0
  41. package/dist/runtime/mcp/index.js.map +1 -1
  42. package/dist/runtime/mcp/notifications.d.ts +13 -1
  43. package/dist/runtime/mcp/notifications.d.ts.map +1 -1
  44. package/dist/runtime/mcp/notifications.js +36 -20
  45. package/dist/runtime/mcp/notifications.js.map +1 -1
  46. package/dist/runtime/mcp/payload-store.d.ts +67 -0
  47. package/dist/runtime/mcp/payload-store.d.ts.map +1 -0
  48. package/dist/runtime/mcp/payload-store.js +242 -0
  49. package/dist/runtime/mcp/payload-store.js.map +1 -0
  50. package/dist/runtime/mcp/phase-trace.d.ts +98 -0
  51. package/dist/runtime/mcp/phase-trace.d.ts.map +1 -0
  52. package/dist/runtime/mcp/phase-trace.js +179 -0
  53. package/dist/runtime/mcp/phase-trace.js.map +1 -0
  54. package/dist/runtime/mcp/server.d.ts +13 -1
  55. package/dist/runtime/mcp/server.d.ts.map +1 -1
  56. package/dist/runtime/mcp/server.js +57 -3
  57. package/dist/runtime/mcp/server.js.map +1 -1
  58. package/dist/runtime/mcp/stdio.d.ts.map +1 -1
  59. package/dist/runtime/mcp/stdio.js +176 -15
  60. package/dist/runtime/mcp/stdio.js.map +1 -1
  61. package/dist/runtime/mcp/tools.d.ts.map +1 -1
  62. package/dist/runtime/mcp/tools.js +31 -4
  63. package/dist/runtime/mcp/tools.js.map +1 -1
  64. package/dist/runtime/mcp-central.d.ts.map +1 -1
  65. package/dist/runtime/mcp-central.js +17 -7
  66. package/dist/runtime/mcp-central.js.map +1 -1
  67. package/dist/runtime/mcp-http/hosted-mcp-server.d.ts.map +1 -1
  68. package/dist/runtime/mcp-http/hosted-mcp-server.js +16 -6
  69. package/dist/runtime/mcp-http/hosted-mcp-server.js.map +1 -1
  70. package/dist/runtime/mcp-http/readonly-allowlist.d.ts.map +1 -1
  71. package/dist/runtime/mcp-http/readonly-allowlist.js +3 -0
  72. package/dist/runtime/mcp-http/readonly-allowlist.js.map +1 -1
  73. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EACX,KAAK,kBAAkB,EACxB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EACX,KAAK,kBAAkB,EACxB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC"}
@@ -5,4 +5,5 @@ export { H2A_MCP_READY_FILE_ENV, H2A_MCP_READY_KIND, H2A_MCP_READY_NONCE_ENV, ru
5
5
  export { buildH2aRunInvocation, executeH2aRun, executeH2aRunWithSpawn, handleH2aRun, recordMcpRunDelegation, H2A_RUN_API_VERSION, validateH2aRunRequest } from "./agent-launch.js";
6
6
  export { SessionRegistry } from "./sessions.js";
7
7
  export { NotificationDispatcher } from "./notifications.js";
8
+ export { createMcpTrace, getActiveMcpTrace, setActiveMcpTrace, TRACE_LINE_PREFIX, TRACE_DETAIL_ENV } from "./phase-trace.js";
8
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,4BAA4B,EAG7B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGN,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EAEZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EAItB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,eAAe,EAGhB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EAGvB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,4BAA4B,EAG7B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGN,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EAEZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EAItB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,eAAe,EAGhB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EAGvB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAOjB,MAAM,kBAAkB,CAAC"}
@@ -11,7 +11,18 @@ export interface McpPushNotification {
11
11
  data: Record<string, unknown>;
12
12
  };
13
13
  }
14
- export type NotificationSink = (notification: McpPushNotification) => void;
14
+ /**
15
+ * L1: a sink may return a receipt so the dispatcher advances a session's
16
+ * snapshot ONLY after the notification left bounded (or its intact bytes were
17
+ * persisted). `void`/`undefined` is treated as accepted, keeping existing mock
18
+ * sinks working. When a push is not accepted (persistence impossible), the
19
+ * session's snapshot is NOT advanced, so the diff is retried next tick — no ACK
20
+ * of a purely-ephemeral event is fabricated.
21
+ */
22
+ export type NotificationReceipt = {
23
+ readonly accepted: boolean;
24
+ } | void;
25
+ export type NotificationSink = (notification: McpPushNotification) => NotificationReceipt;
15
26
  /**
16
27
  * Owns the per-session diff snapshots and the periodic scan that turns
17
28
  * filesystem changes into pushed JSON-RPC notifications. One dispatcher per
@@ -42,6 +53,7 @@ export declare class NotificationDispatcher {
42
53
  * tests can drive the dispatch deterministically without a timer.
43
54
  */
44
55
  tick(): void;
56
+ /** Emit one notification; returns whether the sink accepted it (see NotificationReceipt). */
45
57
  private push;
46
58
  }
47
59
  //# sourceMappingURL=notifications.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/runtime/mcp/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,2BAA2B,EACjC,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,kEAAkE;AAClE,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE;QACN,KAAK,EAAE,2BAA2B,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,CAAC;CACH;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,YAAY,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAsD3E;;;;;GAKG;AACH,qBAAa,sBAAsB;IAK/B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ,CAAC,UAAU;IAR7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,KAAK,CAAC,CAAiC;gBAG5B,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,EACrB,IAAI,EAAE,gBAAgB,GAAG,SAAS,EACzB,UAAU,EAAE,MAAM;IAGrC,OAAO,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI;IAIjD;;;;OAIG;IACH,OAAO,CAAC,cAAc,CAAC,CAA6B;IACpD,iBAAiB,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI;IAIrE,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAMZ;;;OAGG;IACH,IAAI,IAAI,IAAI;IA6HZ,OAAO,CAAC,IAAI;CAab"}
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/runtime/mcp/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,2BAA2B,EACjC,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,kEAAkE;AAClE,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE;QACN,KAAK,EAAE,2BAA2B,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,CAAC;CACH;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAAC;AAExE,MAAM,MAAM,gBAAgB,GAAG,CAAC,YAAY,EAAE,mBAAmB,KAAK,mBAAmB,CAAC;AAsD1F;;;;;GAKG;AACH,qBAAa,sBAAsB;IAK/B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ,CAAC,UAAU;IAR7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,KAAK,CAAC,CAAiC;gBAG5B,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,EACrB,IAAI,EAAE,gBAAgB,GAAG,SAAS,EACzB,UAAU,EAAE,MAAM;IAGrC,OAAO,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI;IAIjD;;;;OAIG;IACH,OAAO,CAAC,cAAc,CAAC,CAA6B;IACpD,iBAAiB,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI;IAIrE,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAMZ;;;OAGG;IACH,IAAI,IAAI,IAAI;IAqIZ,6FAA6F;IAC7F,OAAO,CAAC,IAAI;CAsBb"}
@@ -92,6 +92,11 @@ export class NotificationDispatcher {
92
92
  const activeBlockages = listBlockages(this.root).filter(isActiveBlockage);
93
93
  for (const session of ownSessions) {
94
94
  const prev = this.snapshots.get(session.sessionId) ?? emptyDiffState();
95
+ // L1: a session's snapshot advances only if EVERY emitted diff was accepted
96
+ // (bounded/persisted). One unaccepted push holds the whole session snapshot
97
+ // so the diffs are retried next tick — an at-least-once guarantee that never
98
+ // fabricates an ACK for a dropped ephemeral notification.
99
+ let accepted = true;
95
100
  // 1. Presence join/leave (excluding self)
96
101
  const others = new Set([...peerIds].filter((sid) => sid !== session.sessionId));
97
102
  if (isInterestedIn(session, "presence.peer_joined")) {
@@ -99,14 +104,14 @@ export class NotificationDispatcher {
99
104
  if (!prev.peers.has(sid)) {
100
105
  const peer = freshPeers.find((p) => p.sessionId === sid);
101
106
  if (peer) {
102
- this.push(session.sessionId, "presence.peer_joined", {
107
+ accepted = this.push(session.sessionId, "presence.peer_joined", {
103
108
  peer: {
104
109
  sessionId: peer.sessionId,
105
110
  instance: peer.instance,
106
111
  host: peer.host,
107
112
  interests: peer.interests
108
113
  }
109
- });
114
+ }) && accepted;
110
115
  }
111
116
  }
112
117
  }
@@ -114,9 +119,9 @@ export class NotificationDispatcher {
114
119
  if (isInterestedIn(session, "presence.peer_left")) {
115
120
  for (const sid of prev.peers) {
116
121
  if (!others.has(sid)) {
117
- this.push(session.sessionId, "presence.peer_left", {
122
+ accepted = this.push(session.sessionId, "presence.peer_left", {
118
123
  peer: { sessionId: sid }
119
- });
124
+ }) && accepted;
120
125
  }
121
126
  }
122
127
  }
@@ -127,10 +132,10 @@ export class NotificationDispatcher {
127
132
  if (isInterestedIn(session, "inbox.envelope_arrived")) {
128
133
  for (const envelopeId of inboxIds) {
129
134
  if (!prev.inbox.envelopeIds.has(envelopeId)) {
130
- this.push(session.sessionId, "inbox.envelope_arrived", {
135
+ accepted = this.push(session.sessionId, "inbox.envelope_arrived", {
131
136
  instance: session.instance,
132
137
  envelopeId
133
- });
138
+ }) && accepted;
134
139
  }
135
140
  }
136
141
  // EVO-1 wake (bug #3): nudge the host every tick while the inbox is
@@ -148,11 +153,11 @@ export class NotificationDispatcher {
148
153
  const count = readJournalLength(this.store, negotiationId);
149
154
  const prevCount = prev.negotiations.get(negotiationId)?.count ?? 0;
150
155
  if (count > prevCount) {
151
- this.push(session.sessionId, "negotiation.event_appended", {
156
+ accepted = this.push(session.sessionId, "negotiation.event_appended", {
152
157
  negotiationId,
153
158
  newEntries: count - prevCount,
154
159
  totalEntries: count
155
- });
160
+ }) && accepted;
156
161
  }
157
162
  negotiationSnap.set(negotiationId, { count });
158
163
  }
@@ -165,40 +170,51 @@ export class NotificationDispatcher {
165
170
  if (isInterestedIn(session, "peer.blocked")) {
166
171
  for (const b of inScope) {
167
172
  if (!prev.blocked.has(b.instance)) {
168
- this.push(session.sessionId, "peer.blocked", {
173
+ accepted = this.push(session.sessionId, "peer.blocked", {
169
174
  instance: b.instance,
170
175
  scope: b.scope,
171
176
  reason: b.reason,
172
177
  ...(b.needs ? { needs: b.needs } : {})
173
- });
178
+ }) && accepted;
174
179
  }
175
180
  }
176
181
  }
177
182
  if (isInterestedIn(session, "peer.unblocked")) {
178
183
  for (const instance of prev.blocked) {
179
184
  if (!blockedNow.has(instance)) {
180
- this.push(session.sessionId, "peer.unblocked", { instance });
185
+ accepted = this.push(session.sessionId, "peer.unblocked", { instance }) && accepted;
181
186
  }
182
187
  }
183
188
  }
184
- this.snapshots.set(session.sessionId, {
185
- peers: others,
186
- inbox: { envelopeIds: new Set(inboxIds) },
187
- negotiations: negotiationSnap,
188
- blocked: blockedNow
189
- });
189
+ if (accepted) {
190
+ this.snapshots.set(session.sessionId, {
191
+ peers: others,
192
+ inbox: { envelopeIds: new Set(inboxIds) },
193
+ negotiations: negotiationSnap,
194
+ blocked: blockedNow
195
+ });
196
+ }
197
+ // else: keep the previous snapshot so the unaccepted diffs are retried.
190
198
  }
191
199
  }
200
+ /** Emit one notification; returns whether the sink accepted it (see NotificationReceipt). */
192
201
  push(sessionId, topic, data) {
193
202
  if (!this.sink)
194
- return;
203
+ return true;
195
204
  if (!H2A_SESSION_NOTIFICATION_TOPICS.includes(topic))
196
- return;
197
- this.sink({
205
+ return true;
206
+ const receipt = this.sink({
198
207
  jsonrpc: "2.0",
199
208
  method: "notifications/h2a",
200
209
  params: { topic, sessionId, data }
201
210
  });
211
+ // Accepted unless the sink explicitly returns `{ accepted: false }`. A sink
212
+ // that returns void, or any other value (e.g. a legacy `array.push` count),
213
+ // is treated as accepted so existing sinks keep advancing the snapshot.
214
+ return !(receipt !== null &&
215
+ typeof receipt === "object" &&
216
+ "accepted" in receipt &&
217
+ receipt.accepted === false);
202
218
  }
203
219
  }
204
220
  //# sourceMappingURL=notifications.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/runtime/mcp/notifications.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/runtime/mcp/notifications.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Durable recovery store for oversize MCP outputs (lot L1).
3
+ *
4
+ * When a legitimate response or notification exceeds the frame budget
5
+ * (`frame-budget.ts`), the INTACT original bytes are persisted here BEFORE the
6
+ * bounded error/notice is emitted, and the client recovers them in budget-sized
7
+ * chunks through the `h2a_read_payload` tool. The store never holds tool
8
+ * arguments or a private key — only output already destined for THIS client —
9
+ * and it never re-executes an effectful tool: it hands back stored bytes.
10
+ *
11
+ * Security properties (DEC-116 lineage):
12
+ * - Root/tenant confinement: one store per store-root; a ref is a 256-bit
13
+ * random capability whose file name IS the ref, so there is no free path, no
14
+ * `../`, and no cross-tenant lookup. Symlinks are refused on read.
15
+ * - Atomic publication: content is staged to a temp file (0600) and renamed.
16
+ * - Integrity: every payload carries a SHA-256 the reader verifies after
17
+ * reassembly.
18
+ * - Durability across restart: refs survive; nothing is purged at boot. Only a
19
+ * dedicated maintenance sweep removes EXPIRED refs, never live data.
20
+ */
21
+ /** Announced recovery window: a ref is readable for 24h after it is written. */
22
+ export declare const PAYLOAD_TTL_MS: number;
23
+ /** Proposed per-root ceiling (measured against the store dir before a write). */
24
+ export declare const PAYLOAD_ROOT_QUOTA_BYTES: number;
25
+ /** Hard maximum a single read may return (also bounded again by the frame budget). */
26
+ export declare const PAYLOAD_MAX_READ_BYTES = 65536;
27
+ export interface PayloadRecoveryRef {
28
+ /** Opaque 256-bit capability. */
29
+ readonly ref: string;
30
+ readonly sha256: string;
31
+ readonly totalBytes: number;
32
+ readonly expiresAt: string;
33
+ }
34
+ export type PayloadReadError = "payload_not_found" | "payload_expired" | "invalid_offset" | "payload_corrupt";
35
+ export interface PayloadReadChunk {
36
+ readonly ref: string;
37
+ readonly encoding: "base64";
38
+ readonly data: string;
39
+ readonly offset: number;
40
+ readonly nextOffset: number | null;
41
+ readonly totalBytes: number;
42
+ readonly sha256: string;
43
+ readonly expiresAt: string;
44
+ }
45
+ export declare class PayloadStoreError extends Error {
46
+ readonly reason: "recovery_unavailable";
47
+ readonly cause: string;
48
+ constructor(reason: "recovery_unavailable", cause: string, message: string);
49
+ }
50
+ export interface PayloadStore {
51
+ /** The scope (store-root) every ref of this store is bound to. */
52
+ readonly scope: string;
53
+ /** Persist output bytes and return the recovery ref, or throw PayloadStoreError. */
54
+ persistOutput(bytes: Buffer): PayloadRecoveryRef;
55
+ /** Read a budget-sized chunk of a ref, or a typed read error. */
56
+ readPayload(ref: string, offset: number, maxBytes: number): PayloadReadChunk | {
57
+ error: PayloadReadError;
58
+ };
59
+ /** Remove ONLY expired refs (dedicated maintenance; never touches live data). */
60
+ sweepExpired(now?: number): number;
61
+ }
62
+ /**
63
+ * A payload store confined to `<root>/mcp-payloads/`. `scope` defaults to the
64
+ * root, so two roots (two tenants) never share a namespace.
65
+ */
66
+ export declare function createPayloadStore(root: string, scope?: string): PayloadStore;
67
+ //# sourceMappingURL=payload-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-store.d.ts","sourceRoot":"","sources":["../../../src/runtime/mcp/payload-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAoBH,gFAAgF;AAChF,eAAO,MAAM,cAAc,QAAsB,CAAC;AAElD,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,QAAoB,CAAC;AAE1D,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,QAAQ,CAAC;AAI5C,MAAM,WAAW,kBAAkB;IACjC,iCAAiC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAWD,MAAM,MAAM,gBAAgB,GACxB,mBAAmB,GACnB,iBAAiB,GACjB,gBAAgB,GAChB,iBAAiB,CAAC;AAEtB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAExC,QAAQ,CAAC,MAAM,EAAE,sBAAsB;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM;gBADb,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM;CAKlB;AAED,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oFAAoF;IACpF,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAAC;IACjD,iEAAiE;IACjE,WAAW,CACT,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,gBAAgB,GAAG;QAAE,KAAK,EAAE,gBAAgB,CAAA;KAAE,CAAC;IAClD,iFAAiF;IACjF,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACpC;AAqBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,GAAG,YAAY,CAwLnF"}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Durable recovery store for oversize MCP outputs (lot L1).
3
+ *
4
+ * When a legitimate response or notification exceeds the frame budget
5
+ * (`frame-budget.ts`), the INTACT original bytes are persisted here BEFORE the
6
+ * bounded error/notice is emitted, and the client recovers them in budget-sized
7
+ * chunks through the `h2a_read_payload` tool. The store never holds tool
8
+ * arguments or a private key — only output already destined for THIS client —
9
+ * and it never re-executes an effectful tool: it hands back stored bytes.
10
+ *
11
+ * Security properties (DEC-116 lineage):
12
+ * - Root/tenant confinement: one store per store-root; a ref is a 256-bit
13
+ * random capability whose file name IS the ref, so there is no free path, no
14
+ * `../`, and no cross-tenant lookup. Symlinks are refused on read.
15
+ * - Atomic publication: content is staged to a temp file (0600) and renamed.
16
+ * - Integrity: every payload carries a SHA-256 the reader verifies after
17
+ * reassembly.
18
+ * - Durability across restart: refs survive; nothing is purged at boot. Only a
19
+ * dedicated maintenance sweep removes EXPIRED refs, never live data.
20
+ */
21
+ import { createHash, randomBytes } from "node:crypto";
22
+ import { chmodSync, closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
23
+ import { join } from "node:path";
24
+ /** Announced recovery window: a ref is readable for 24h after it is written. */
25
+ export const PAYLOAD_TTL_MS = 24 * 60 * 60 * 1000;
26
+ /** Proposed per-root ceiling (measured against the store dir before a write). */
27
+ export const PAYLOAD_ROOT_QUOTA_BYTES = 128 * 1024 * 1024;
28
+ /** Hard maximum a single read may return (also bounded again by the frame budget). */
29
+ export const PAYLOAD_MAX_READ_BYTES = 65536;
30
+ const REF_RE = /^[0-9a-f]{64}$/;
31
+ export class PayloadStoreError extends Error {
32
+ reason;
33
+ cause;
34
+ constructor(reason, cause, message) {
35
+ super(message);
36
+ this.reason = reason;
37
+ this.cause = cause;
38
+ this.name = "PayloadStoreError";
39
+ }
40
+ }
41
+ function binPath(dir, ref) {
42
+ return join(dir, `${ref}.bin`);
43
+ }
44
+ function metaPath(dir, ref) {
45
+ return join(dir, `${ref}.json`);
46
+ }
47
+ function dirBytes(dir) {
48
+ let total = 0;
49
+ for (const entry of readdirSync(dir)) {
50
+ try {
51
+ total += statSync(join(dir, entry)).size;
52
+ }
53
+ catch {
54
+ /* a racing unlink is not a measurement failure */
55
+ }
56
+ }
57
+ return total;
58
+ }
59
+ /**
60
+ * A payload store confined to `<root>/mcp-payloads/`. `scope` defaults to the
61
+ * root, so two roots (two tenants) never share a namespace.
62
+ */
63
+ export function createPayloadStore(root, scope = root) {
64
+ const dir = join(root, "mcp-payloads");
65
+ function ensureDir() {
66
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
67
+ try {
68
+ chmodSync(dir, 0o700);
69
+ }
70
+ catch {
71
+ /* best effort; a pre-existing dir may be owned differently in tests */
72
+ }
73
+ }
74
+ function sweepExpired(now = Date.now()) {
75
+ if (!existsSync(dir))
76
+ return 0;
77
+ let removed = 0;
78
+ for (const entry of readdirSync(dir)) {
79
+ if (!entry.endsWith(".json"))
80
+ continue;
81
+ const ref = entry.slice(0, -".json".length);
82
+ if (!REF_RE.test(ref))
83
+ continue;
84
+ try {
85
+ const meta = JSON.parse(readFileSync(join(dir, entry), "utf8"));
86
+ if (Date.parse(meta.expiresAt) <= now) {
87
+ try {
88
+ unlinkSync(metaPath(dir, ref));
89
+ }
90
+ catch {
91
+ /* already gone */
92
+ }
93
+ try {
94
+ unlinkSync(binPath(dir, ref));
95
+ }
96
+ catch {
97
+ /* already gone */
98
+ }
99
+ removed += 1;
100
+ }
101
+ }
102
+ catch {
103
+ /* a corrupt meta is left for a human sweep, never live source data */
104
+ }
105
+ }
106
+ return removed;
107
+ }
108
+ function persistOutput(bytes) {
109
+ try {
110
+ ensureDir();
111
+ }
112
+ catch (err) {
113
+ throw new PayloadStoreError("recovery_unavailable", err.code ?? "mkdir_failed", `cannot create payload store directory: ${err.message}`);
114
+ }
115
+ // Reclaim expired space before enforcing the quota; never evict live data.
116
+ let used = 0;
117
+ try {
118
+ sweepExpired();
119
+ used = dirBytes(dir);
120
+ }
121
+ catch {
122
+ used = 0;
123
+ }
124
+ if (used + bytes.length > PAYLOAD_ROOT_QUOTA_BYTES) {
125
+ throw new PayloadStoreError("recovery_unavailable", "quota_exceeded", `payload store quota exceeded for ${dir}`);
126
+ }
127
+ const ref = randomBytes(32).toString("hex");
128
+ const sha256 = `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
129
+ const now = Date.now();
130
+ const meta = {
131
+ sha256,
132
+ totalBytes: bytes.length,
133
+ createdAt: new Date(now).toISOString(),
134
+ expiresAt: new Date(now + PAYLOAD_TTL_MS).toISOString(),
135
+ scope
136
+ };
137
+ const tmpBin = binPath(dir, `.${ref}.tmp`);
138
+ const tmpMeta = metaPath(dir, `.${ref}.tmp`);
139
+ try {
140
+ writeFileSync(tmpBin, bytes, { mode: 0o600, flag: "wx" });
141
+ writeFileSync(tmpMeta, `${JSON.stringify(meta)}\n`, { mode: 0o600, flag: "wx" });
142
+ renameSync(tmpBin, binPath(dir, ref));
143
+ renameSync(tmpMeta, metaPath(dir, ref));
144
+ }
145
+ catch (err) {
146
+ for (const p of [tmpBin, tmpMeta, binPath(dir, ref), metaPath(dir, ref)]) {
147
+ try {
148
+ unlinkSync(p);
149
+ }
150
+ catch {
151
+ /* best effort cleanup of a half-written record */
152
+ }
153
+ }
154
+ throw new PayloadStoreError("recovery_unavailable", err.code ?? "write_failed", `cannot persist payload: ${err.message}`);
155
+ }
156
+ return { ref, sha256, totalBytes: bytes.length, expiresAt: meta.expiresAt };
157
+ }
158
+ function readMeta(ref) {
159
+ const mp = metaPath(dir, ref);
160
+ let st;
161
+ try {
162
+ st = lstatSync(mp);
163
+ }
164
+ catch {
165
+ return undefined;
166
+ }
167
+ if (!st.isFile())
168
+ return undefined; // refuse a symlink/dir masquerading as a ref
169
+ try {
170
+ return JSON.parse(readFileSync(mp, "utf8"));
171
+ }
172
+ catch {
173
+ return undefined;
174
+ }
175
+ }
176
+ function readPayload(ref, offset, maxBytes) {
177
+ if (typeof ref !== "string" || !REF_RE.test(ref)) {
178
+ return { error: "payload_not_found" };
179
+ }
180
+ const meta = readMeta(ref);
181
+ if (!meta || meta.scope !== scope)
182
+ return { error: "payload_not_found" };
183
+ if (Date.parse(meta.expiresAt) <= Date.now())
184
+ return { error: "payload_expired" };
185
+ if (!Number.isInteger(offset) || offset < 0 || offset > meta.totalBytes) {
186
+ return { error: "invalid_offset" };
187
+ }
188
+ const bp = binPath(dir, ref);
189
+ let bst;
190
+ try {
191
+ bst = lstatSync(bp);
192
+ }
193
+ catch {
194
+ return { error: "payload_not_found" };
195
+ }
196
+ if (!bst.isFile() || bst.size !== meta.totalBytes)
197
+ return { error: "payload_corrupt" };
198
+ const cap = Math.max(1, Math.min(Number.isInteger(maxBytes) && maxBytes > 0 ? maxBytes : PAYLOAD_MAX_READ_BYTES, PAYLOAD_MAX_READ_BYTES));
199
+ const remaining = meta.totalBytes - offset;
200
+ const chunkLen = Math.min(cap, remaining);
201
+ const buf = Buffer.allocUnsafe(chunkLen);
202
+ let fd;
203
+ try {
204
+ fd = openSync(bp, "r");
205
+ let read = 0;
206
+ while (read < chunkLen) {
207
+ const n = readSync(fd, buf, read, chunkLen - read, offset + read);
208
+ if (n === 0)
209
+ break;
210
+ read += n;
211
+ }
212
+ if (read !== chunkLen)
213
+ return { error: "payload_corrupt" };
214
+ }
215
+ catch {
216
+ return { error: "payload_corrupt" };
217
+ }
218
+ finally {
219
+ if (fd !== undefined) {
220
+ try {
221
+ closeSync(fd);
222
+ }
223
+ catch {
224
+ /* fd closed on error already */
225
+ }
226
+ }
227
+ }
228
+ const nextOffset = offset + chunkLen;
229
+ return {
230
+ ref,
231
+ encoding: "base64",
232
+ data: buf.toString("base64"),
233
+ offset,
234
+ nextOffset: nextOffset >= meta.totalBytes ? null : nextOffset,
235
+ totalBytes: meta.totalBytes,
236
+ sha256: meta.sha256,
237
+ expiresAt: meta.expiresAt
238
+ };
239
+ }
240
+ return { scope, persistOutput, readPayload, sweepExpired };
241
+ }
242
+ //# sourceMappingURL=payload-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-store.js","sourceRoot":"","sources":["../../../src/runtime/mcp/payload-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Per-phase MCP boot/serve tracing (lot L0 — measurement & diagnosis only).
3
+ *
4
+ * Emits correlated, closed-field JSONL spans to an injected stderr writer so a
5
+ * host or an out-of-process measurement probe can reconstruct the whole
6
+ * `mcp-serve` lifecycle — process start, identity resolution, lock waits,
7
+ * registry reads, transport `initialize` / `tools/list` / first tool — WITHOUT
8
+ * pulling in the CLI or the heavy runtime. It has three properties the rest of
9
+ * the fix relies on:
10
+ *
11
+ * 1. **Passive.** A measurement callback can never fail the MCP protocol:
12
+ * every emit is wrapped, a writer throw is swallowed, and the trace has no
13
+ * side effect on the JSON-RPC stream (it only ever writes to stderr).
14
+ * 2. **Confidential.** Fields are a fixed whitelist and every string is
15
+ * sanitized + length-capped, so no PEM, token, lock payload or binding
16
+ * content can ever reach an event — even if a caller passes it by mistake.
17
+ * 3. **Monotonic + correlated.** Every event carries `attemptId` (a locally
18
+ * minted UUID — a child process cannot inherit an identity from the MCP
19
+ * client), `pid`, a per-trace `seq`, and a monotonic `monotonicMs`. Two
20
+ * processes are correlated by matching events, never by subtracting their
21
+ * independent monotonic clocks.
22
+ *
23
+ * `H2A_MCP_TRACE=1` turns on the detailed spans (`begin`/`end` of internal
24
+ * phases). Lifecycle milestones and failure diagnostics stay visible without
25
+ * the flag.
26
+ */
27
+ /** Log line prefix; every trace event is `${TRACE_LINE_PREFIX}${json}\n` on stderr. */
28
+ export declare const TRACE_LINE_PREFIX = "h2a.mcp.phase ";
29
+ /** Env flag that turns on detailed (`begin`/`end`) spans. */
30
+ export declare const TRACE_DETAIL_ENV = "H2A_MCP_TRACE";
31
+ export type McpTraceRole = "server" | "identity-child";
32
+ export type McpTraceEventKind = "begin" | "end" | "error" | "sample";
33
+ /** The wire event. `v:1` is the schema version; keep additions backward-safe. */
34
+ export interface McpTraceEvent {
35
+ readonly v: 1;
36
+ readonly attemptId: string;
37
+ readonly pid: number;
38
+ readonly role: McpTraceRole;
39
+ readonly seq: number;
40
+ readonly monotonicMs: number;
41
+ readonly phase: string;
42
+ readonly event: McpTraceEventKind;
43
+ readonly durationMs?: number;
44
+ readonly requestId?: string | number;
45
+ readonly method?: string;
46
+ readonly tool?: string;
47
+ readonly bytes?: number;
48
+ readonly waitMs?: number;
49
+ readonly holdMs?: number;
50
+ readonly code?: string | number;
51
+ }
52
+ /** The only fields a caller may attach. Everything else is dropped. */
53
+ export interface McpTraceFields {
54
+ readonly requestId?: string | number;
55
+ readonly method?: string;
56
+ readonly tool?: string;
57
+ readonly bytes?: number;
58
+ readonly waitMs?: number;
59
+ readonly holdMs?: number;
60
+ readonly code?: string | number;
61
+ readonly durationMs?: number;
62
+ }
63
+ export interface McpTraceOptions {
64
+ readonly role?: McpTraceRole;
65
+ /** Locally minted UUID; never taken from the MCP client. */
66
+ readonly attemptId?: string;
67
+ readonly pid?: number;
68
+ /** Injected sink; defaults to a swallow-on-throw `process.stderr` writer. */
69
+ readonly writer?: (line: string) => void;
70
+ /** Monotonic clock; defaults to `performance.now`. */
71
+ readonly now?: () => number;
72
+ /** Force detailed spans on/off; defaults to `env[H2A_MCP_TRACE] === "1"`. */
73
+ readonly detailed?: boolean;
74
+ readonly env?: Record<string, string | undefined>;
75
+ }
76
+ export interface McpTrace {
77
+ readonly attemptId: string;
78
+ readonly role: McpTraceRole;
79
+ readonly pid: number;
80
+ readonly detailed: boolean;
81
+ /** A lifecycle milestone (`sample`). Always emitted — this is a diagnostic. */
82
+ phase(name: string, fields?: McpTraceFields): void;
83
+ /** Start of a detailed span. Emitted only when `detailed`. */
84
+ begin(name: string, fields?: McpTraceFields): void;
85
+ /** End of a detailed span. Emitted only when `detailed`. */
86
+ end(name: string, fields?: McpTraceFields): void;
87
+ /** A failure. Always emitted, flag or not. */
88
+ error(name: string, fields?: McpTraceFields): void;
89
+ /** Wrap `fn`: `begin`/`end` when detailed, an `error` event on throw always. */
90
+ span<T>(name: string, fn: () => T, fields?: McpTraceFields): T;
91
+ /** A correlated sub-trace (same `attemptId`) for a child role. */
92
+ child(role: McpTraceRole, options?: Pick<McpTraceOptions, "pid" | "writer">): McpTrace;
93
+ }
94
+ /** Create a fresh trace. `attemptId` defaults to a locally minted UUID. */
95
+ export declare function createMcpTrace(options?: McpTraceOptions): McpTrace;
96
+ export declare function setActiveMcpTrace(trace: McpTrace | undefined): void;
97
+ export declare function getActiveMcpTrace(): McpTrace | undefined;
98
+ //# sourceMappingURL=phase-trace.d.ts.map