agenthooksprotocol 0.0.0-stage → 0.1.1

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 (151) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +69 -2
  3. package/dist/src/client/auth.d.ts +147 -0
  4. package/dist/src/client/auth.d.ts.map +1 -0
  5. package/dist/src/client/auth.js +629 -0
  6. package/dist/src/client/auth.js.map +1 -0
  7. package/dist/src/client/composition.d.ts +44 -0
  8. package/dist/src/client/composition.d.ts.map +1 -0
  9. package/dist/src/client/composition.js +531 -0
  10. package/dist/src/client/composition.js.map +1 -0
  11. package/dist/src/client/content.d.ts +75 -0
  12. package/dist/src/client/content.d.ts.map +1 -0
  13. package/dist/src/client/content.js +415 -0
  14. package/dist/src/client/content.js.map +1 -0
  15. package/dist/src/client/hooks.d.ts +66 -0
  16. package/dist/src/client/hooks.d.ts.map +1 -0
  17. package/dist/src/client/hooks.js +1084 -0
  18. package/dist/src/client/hooks.js.map +1 -0
  19. package/dist/src/client/index.d.ts +12 -0
  20. package/dist/src/client/index.d.ts.map +1 -0
  21. package/dist/src/client/index.js +10 -0
  22. package/dist/src/client/index.js.map +1 -0
  23. package/dist/src/client/transport.d.ts +12 -0
  24. package/dist/src/client/transport.d.ts.map +1 -0
  25. package/dist/src/client/transport.js +347 -0
  26. package/dist/src/client/transport.js.map +1 -0
  27. package/dist/src/client/types.d.ts +117 -0
  28. package/dist/src/client/types.d.ts.map +1 -0
  29. package/dist/src/client/types.js +10 -0
  30. package/dist/src/client/types.js.map +1 -0
  31. package/dist/src/client/validation.d.ts +3 -0
  32. package/dist/src/client/validation.d.ts.map +1 -0
  33. package/dist/src/client/validation.js +25 -0
  34. package/dist/src/client/validation.js.map +1 -0
  35. package/dist/src/compaction.d.ts +27 -0
  36. package/dist/src/compaction.d.ts.map +1 -0
  37. package/dist/src/compaction.js +155 -0
  38. package/dist/src/compaction.js.map +1 -0
  39. package/dist/src/content-upload.d.ts +59 -0
  40. package/dist/src/content-upload.d.ts.map +1 -0
  41. package/dist/src/content-upload.js +133 -0
  42. package/dist/src/content-upload.js.map +1 -0
  43. package/dist/src/draft/generated.d.ts +3111 -0
  44. package/dist/src/draft/generated.d.ts.map +1 -0
  45. package/dist/src/draft/generated.js +15623 -0
  46. package/dist/src/draft/generated.js.map +1 -0
  47. package/dist/src/draft/index.d.ts +34 -0
  48. package/dist/src/draft/index.d.ts.map +1 -0
  49. package/dist/src/draft/index.js +131 -0
  50. package/dist/src/draft/index.js.map +1 -0
  51. package/dist/src/draft/schemas.d.ts +8920 -0
  52. package/dist/src/draft/schemas.d.ts.map +1 -0
  53. package/dist/src/draft/schemas.js +9257 -0
  54. package/dist/src/draft/schemas.js.map +1 -0
  55. package/dist/src/draft-atomic.d.ts +18 -0
  56. package/dist/src/draft-atomic.d.ts.map +1 -0
  57. package/dist/src/draft-atomic.js +102 -0
  58. package/dist/src/draft-atomic.js.map +1 -0
  59. package/dist/src/draft-runtime.d.ts +89 -0
  60. package/dist/src/draft-runtime.d.ts.map +1 -0
  61. package/dist/src/draft-runtime.js +240 -0
  62. package/dist/src/draft-runtime.js.map +1 -0
  63. package/dist/src/elicitation.d.ts +18 -0
  64. package/dist/src/elicitation.d.ts.map +1 -0
  65. package/dist/src/elicitation.js +191 -0
  66. package/dist/src/elicitation.js.map +1 -0
  67. package/dist/src/errors.d.ts +7 -0
  68. package/dist/src/errors.d.ts.map +1 -0
  69. package/dist/src/errors.js +15 -0
  70. package/dist/src/errors.js.map +1 -0
  71. package/dist/src/framing.d.ts +7 -0
  72. package/dist/src/framing.d.ts.map +1 -0
  73. package/dist/src/framing.js +39 -0
  74. package/dist/src/framing.js.map +1 -0
  75. package/dist/src/generated.d.ts +304 -0
  76. package/dist/src/generated.d.ts.map +1 -0
  77. package/dist/src/generated.js +1885 -0
  78. package/dist/src/generated.js.map +1 -0
  79. package/dist/src/hook-runner.d.ts +11 -0
  80. package/dist/src/hook-runner.d.ts.map +1 -0
  81. package/dist/src/hook-runner.js +223 -0
  82. package/dist/src/hook-runner.js.map +1 -0
  83. package/dist/src/index.d.ts +8 -0
  84. package/dist/src/index.d.ts.map +1 -0
  85. package/dist/src/index.js +8 -0
  86. package/dist/src/index.js.map +1 -0
  87. package/dist/src/observation.d.ts +26 -0
  88. package/dist/src/observation.d.ts.map +1 -0
  89. package/dist/src/observation.js +28 -0
  90. package/dist/src/observation.js.map +1 -0
  91. package/dist/src/server/attachments.d.ts +29 -0
  92. package/dist/src/server/attachments.d.ts.map +1 -0
  93. package/dist/src/server/attachments.js +112 -0
  94. package/dist/src/server/attachments.js.map +1 -0
  95. package/dist/src/server/hooks.d.ts +20 -0
  96. package/dist/src/server/hooks.d.ts.map +1 -0
  97. package/dist/src/server/hooks.js +131 -0
  98. package/dist/src/server/hooks.js.map +1 -0
  99. package/dist/src/server/index.d.ts +9 -0
  100. package/dist/src/server/index.d.ts.map +1 -0
  101. package/dist/src/server/index.js +5 -0
  102. package/dist/src/server/index.js.map +1 -0
  103. package/dist/src/server/stdio.d.ts +15 -0
  104. package/dist/src/server/stdio.d.ts.map +1 -0
  105. package/dist/src/server/stdio.js +69 -0
  106. package/dist/src/server/stdio.js.map +1 -0
  107. package/dist/src/transport.d.ts +7 -0
  108. package/dist/src/transport.d.ts.map +1 -0
  109. package/dist/src/transport.js +195 -0
  110. package/dist/src/transport.js.map +1 -0
  111. package/dist/src/types.d.ts +116 -0
  112. package/dist/src/types.d.ts.map +1 -0
  113. package/dist/src/types.js +14 -0
  114. package/dist/src/types.js.map +1 -0
  115. package/dist/src/validation.d.ts +7 -0
  116. package/dist/src/validation.d.ts.map +1 -0
  117. package/dist/src/validation.js +209 -0
  118. package/dist/src/validation.js.map +1 -0
  119. package/package.json +62 -4
  120. package/src/client/auth.ts +1076 -0
  121. package/src/client/composition.ts +717 -0
  122. package/src/client/content.ts +522 -0
  123. package/src/client/hooks.ts +1477 -0
  124. package/src/client/index.ts +30 -0
  125. package/src/client/transport.ts +408 -0
  126. package/src/client/types.ts +173 -0
  127. package/src/client/validation.ts +24 -0
  128. package/src/compaction.ts +196 -0
  129. package/src/content-upload.ts +206 -0
  130. package/src/draft/README.md +16 -0
  131. package/src/draft/ahp-codegen.lock.json +131 -0
  132. package/src/draft/generated.ts +19449 -0
  133. package/src/draft/index.ts +251 -0
  134. package/src/draft/schemas.ts +9453 -0
  135. package/src/draft-atomic.ts +119 -0
  136. package/src/draft-runtime.ts +363 -0
  137. package/src/elicitation.ts +254 -0
  138. package/src/errors.ts +30 -0
  139. package/src/framing.ts +56 -0
  140. package/src/generated.ts +2408 -0
  141. package/src/hook-runner.ts +310 -0
  142. package/src/index.ts +8 -0
  143. package/src/observation.ts +65 -0
  144. package/src/server/attachments.ts +128 -0
  145. package/src/server/hooks.ts +206 -0
  146. package/src/server/index.ts +23 -0
  147. package/src/server/node-crypto.d.ts +7 -0
  148. package/src/server/stdio.ts +81 -0
  149. package/src/transport.ts +273 -0
  150. package/src/types.ts +124 -0
  151. package/src/validation.ts +372 -0
@@ -0,0 +1,240 @@
1
+ import { validateEffect } from "./draft/index.js";
2
+ import { validateUploadReceipt } from "./content-upload.js";
3
+ /** Synthetic semantic harness. Wire acceptance remains the canonical validator's job. */
4
+ import { stageResponse, object } from "./draft-atomic.js";
5
+ export function stageBoundary(before, effects, caps, supplier, validateInput = () => true) {
6
+ // Stage all state, including scheduling and user-facing messages, before the single commit.
7
+ let staged = structuredClone(before);
8
+ if (staged.continuationRemaining === undefined &&
9
+ caps.flow?.remainingContinuations !== undefined)
10
+ staged.continuationRemaining = caps.flow.remainingContinuations;
11
+ const ordinary = [];
12
+ for (const effect of effects) {
13
+ if (!validateEffect(effect).ok)
14
+ throw Error("Invalid effect");
15
+ if (!caps.effects.includes(effect.type))
16
+ throw Error("Unsupported effect");
17
+ if (effect.type === "flow") {
18
+ const operation = effect.operation;
19
+ if (typeof operation !== "string" ||
20
+ !caps.flow?.operations.includes(operation))
21
+ throw Error("Unsupported flow operation");
22
+ if (operation === "continue") {
23
+ if ((!(Number(staged.continuationRemaining) > 0) &&
24
+ before.flow !== "continue") ||
25
+ (caps.flow.maxContinuations !== undefined &&
26
+ (caps.flow.continuationCount ?? 0) >= caps.flow.maxContinuations))
27
+ throw Error("Continuation unavailable");
28
+ if (staged.flow !== "stop")
29
+ staged.flow = "continue";
30
+ if (typeof effect.instruction === "string")
31
+ staged.instructions = [
32
+ ...(staged.instructions ?? []),
33
+ effect.instruction,
34
+ ];
35
+ }
36
+ else if (operation === "stop" && typeof effect.reason === "string")
37
+ staged.flow = "stop";
38
+ else
39
+ throw Error("Invalid flow");
40
+ }
41
+ else if (effect.type === "inject") {
42
+ if (typeof effect.deliverAt !== "string" ||
43
+ !caps.inject?.context.deliverAt.includes(effect.deliverAt) ||
44
+ caps.inject.context.append !== true ||
45
+ effect.target !== "context" ||
46
+ effect.operation !== "append" ||
47
+ !Object.hasOwn(effect, "value"))
48
+ throw Error("Unsupported injection");
49
+ staged.injections = [
50
+ ...(staged.injections ?? []),
51
+ structuredClone(effect),
52
+ ];
53
+ }
54
+ else if (effect.type === "modify") {
55
+ const target = effect.target, operation = effect.operation;
56
+ if (typeof target !== "string" ||
57
+ (operation !== "replace" && operation !== "merge"))
58
+ throw Error("Unsupported modification");
59
+ const targetCaps = caps.modify?.[target];
60
+ if (!(targetCaps?.[operation] === true ||
61
+ targetCaps?.operations?.includes(operation)))
62
+ throw Error("Unsupported target or operation");
63
+ if (target === "input")
64
+ ordinary.push(effect);
65
+ else {
66
+ if (!staged.values || !Object.hasOwn(staged.values, target))
67
+ throw Error("Target unavailable");
68
+ const previous = staged.values[target];
69
+ if (operation === "merge" &&
70
+ (!object(previous) || !object(effect.value)))
71
+ throw Error("Merge requires objects");
72
+ staged.values[target] =
73
+ operation === "merge"
74
+ ? {
75
+ ...previous,
76
+ ...structuredClone(effect.value),
77
+ }
78
+ : structuredClone(effect.value);
79
+ }
80
+ }
81
+ else
82
+ ordinary.push(effect);
83
+ }
84
+ if (!sameValue(before.values, staged.values)) {
85
+ staged.candidate = null;
86
+ if (staged.permission === "allow")
87
+ staged.permission = "native";
88
+ if (staged.approval === "approved")
89
+ staged.approval = "pending";
90
+ }
91
+ const inputCaps = caps.modify?.input;
92
+ const normalized = {
93
+ effects: caps.effects,
94
+ modify: {
95
+ input: {
96
+ replace: inputCaps?.replace === true ||
97
+ inputCaps?.operations?.includes("replace") === true,
98
+ merge: inputCaps?.merge === true ||
99
+ inputCaps?.operations?.includes("merge") === true,
100
+ },
101
+ },
102
+ };
103
+ staged = stageResponse(staged, ordinary, normalized, supplier, validateInput);
104
+ if (staged.continuationRemaining !== undefined) {
105
+ if (staged.flow === "continue" && before.flow !== "continue")
106
+ staged.continuationRemaining--;
107
+ else if (staged.flow === "stop" && before.flow === "continue")
108
+ staged.continuationRemaining++;
109
+ }
110
+ return staged;
111
+ }
112
+ export async function dispatchBoundary(eventId, initial, deliveries) {
113
+ let state = structuredClone(initial);
114
+ for (const [index, delivery] of deliveries.entries())
115
+ if (delivery.mode === "intercept") {
116
+ const effects = await delivery.receive({
117
+ ...structuredClone(state),
118
+ eventId,
119
+ });
120
+ state = stageBoundary(state, effects, delivery.capabilities, String(index));
121
+ }
122
+ // Observation is a settled snapshot, not a second effect channel or execution gate.
123
+ void Promise.all(deliveries
124
+ .filter((d) => d.mode === "observe")
125
+ .map(async (delivery) => {
126
+ try {
127
+ await delivery.receive({ ...structuredClone(state), eventId });
128
+ }
129
+ catch {
130
+ /* best effort */
131
+ }
132
+ }));
133
+ return state;
134
+ }
135
+ /** Receiver storage scoped by the host's authenticated principal, not wire claims. */
136
+ export class ContentReceiver {
137
+ stored = new Map();
138
+ async upload(scope, bytes) {
139
+ if (!scope || !(bytes instanceof Uint8Array))
140
+ throw Error("Authenticated scope and binary bytes required");
141
+ const snapshot = bytes.slice();
142
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", snapshot));
143
+ const sha256 = Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join("");
144
+ const ref = "urn:ahp:content:" + crypto.randomUUID();
145
+ this.stored.set(JSON.stringify([scope, ref]), snapshot);
146
+ return { ref, size: snapshot.length, sha256 };
147
+ }
148
+ read(scope, ref) {
149
+ return this.stored.get(JSON.stringify([scope, ref]))?.slice();
150
+ }
151
+ }
152
+ export async function prepareContent(items, options) {
153
+ const result = [];
154
+ for (const item of items) {
155
+ const view = { id: item.id, kind: item.kind };
156
+ if (!options.requested.includes(item.kind))
157
+ view.gap = "not_requested";
158
+ else if (!options.authorized.includes(item.kind))
159
+ view.gap = "permission_withheld";
160
+ else if (item.bytes === undefined)
161
+ view.gap = "source_unavailable";
162
+ else if (item.bytes.length > options.maxBytes)
163
+ view.gap = "limit_exceeded";
164
+ else
165
+ try {
166
+ const bytes = new Uint8Array(item.bytes);
167
+ const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
168
+ let timer;
169
+ let confirmed;
170
+ try {
171
+ confirmed = await Promise.race([
172
+ options.upload(bytes.slice()),
173
+ new Promise((_, reject) => {
174
+ timer = setTimeout(() => reject(Error("Upload timeout")), options.timeoutMs ?? 1000);
175
+ }),
176
+ ]);
177
+ }
178
+ finally {
179
+ if (timer !== undefined)
180
+ clearTimeout(timer);
181
+ }
182
+ const sha256 = Array.from(hash, (byte) => byte.toString(16).padStart(2, "0")).join("");
183
+ const body = validateUploadReceipt(confirmed, bytes.length, sha256);
184
+ view.ref = body.ref;
185
+ }
186
+ catch {
187
+ view.gap = "transfer_failed";
188
+ }
189
+ if (view.gap &&
190
+ view.gap !== "not_requested" &&
191
+ options.mode === "intercept" &&
192
+ options.failClosed)
193
+ throw Error("Content delivery failure");
194
+ result.push(view);
195
+ }
196
+ return result;
197
+ }
198
+ export class Lineage {
199
+ parents = new Map();
200
+ add(id, parent) {
201
+ if (this.parents.has(id))
202
+ throw Error("Duplicate event");
203
+ const seen = new Set([id]);
204
+ for (let cursor = parent; cursor !== undefined; cursor = this.parents.get(cursor)) {
205
+ if (seen.has(cursor))
206
+ throw Error("Cyclic lineage");
207
+ seen.add(cursor);
208
+ }
209
+ this.parents.set(id, parent);
210
+ }
211
+ }
212
+ function sameValue(a, b) {
213
+ if (a === b)
214
+ return true;
215
+ if (a === null ||
216
+ b === null ||
217
+ typeof a !== "object" ||
218
+ typeof b !== "object" ||
219
+ Array.isArray(a) !== Array.isArray(b))
220
+ return false;
221
+ const left = a, right = b;
222
+ return (Object.keys(left).length === Object.keys(right).length &&
223
+ Object.keys(left).every((key) => Object.hasOwn(right, key) && sameValue(left[key], right[key])));
224
+ }
225
+ export function actualTaskChange(before, after, id, parentEventId) {
226
+ // Arguments are committed snapshots, not proposed values. Denial with no write
227
+ // has equal snapshots; actual partial changes remain observable after refusal.
228
+ if (sameValue(before, after))
229
+ return null;
230
+ return {
231
+ id,
232
+ type: "task.change.after",
233
+ ...(parentEventId === undefined ? {} : { parentEventId }),
234
+ before: structuredClone(before),
235
+ after: structuredClone(after),
236
+ };
237
+ }
238
+ export { uploadContent, prepareWireContent, contentReference } from "./content-upload.js";
239
+ export { dispatchObservations } from "./observation.js";
240
+ //# sourceMappingURL=draft-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft-runtime.js","sourceRoot":"","sources":["../../src/draft-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** MCP 2025-11-25 body binding. Host-owned resolver must verify upload ownership,
2
+ * length and digest before returning bytes. Identity comes from authentication,
3
+ * never event.source or elicitation.server. */
4
+ export declare function validateElicitationExchange(request: any, result: any, resolve: (reference: any) => Uint8Array, validate: (schema: string, value: unknown) => void, principal: string, effect?: {
5
+ type: string;
6
+ target?: string;
7
+ operation?: string;
8
+ }): Record<string, unknown>;
9
+ export declare function validateElicitationAnswer(request: any, answer: any, validate: (name: string, value: any) => void): void;
10
+ export declare function validateElicitationMode(mode: string, capabilities?: Record<string, unknown>, origin?: string): Record<string, unknown>;
11
+ /** Stage the complete effect list on a snapshot; publish only after validation.
12
+ * The caller uploads the resulting complete JSON before emitting a result event. */
13
+ export declare function applyElicitationEffects(request: any, result: any | null, resolve: (reference: any) => Uint8Array, validate: (schema: string, value: any) => void, principal: string, effects: any[]): Record<string, any>;
14
+ /** Metadata and omit never resolve or parse content. Selected gaps fail closed. */
15
+ export declare function readSelectedElicitation(meta: any, stage: "request" | "result", resolve: (reference: any) => Uint8Array, validate: (schema: string, value: any) => void): any | null;
16
+ /** Require source-scoped parent identity and identical session scope before IO. */
17
+ export declare function validateElicitationCorrelation(request: any, result: any): void;
18
+ //# sourceMappingURL=elicitation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elicitation.d.ts","sourceRoot":"","sources":["../../src/elicitation.ts"],"names":[],"mappings":"AAAA;;+CAE+C;AAC/C,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,UAAU,EACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,EAClD,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwEzB;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,GAC3C,IAAI,CAUN;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,MAAM,SAAQ,GACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuBzB;AAED;oFACoF;AACpF,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,GAAG,GAAG,IAAI,EAClB,OAAO,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,UAAU,EACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,EAC9C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,GAAG,EAAE,GACb,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAoErB;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,SAAS,GAAG,QAAQ,EAC3B,OAAO,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,UAAU,EACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,GAC7C,GAAG,GAAG,IAAI,CAuBZ;AAED,mFAAmF;AACnF,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,GAAG,GACV,IAAI,CAUN"}
@@ -0,0 +1,191 @@
1
+ /** MCP 2025-11-25 body binding. Host-owned resolver must verify upload ownership,
2
+ * length and digest before returning bytes. Identity comes from authentication,
3
+ * never event.source or elicitation.server. */
4
+ export function validateElicitationExchange(request, result, resolve, validate, principal, effect) {
5
+ if (!principal)
6
+ throw Error("Authenticated principal required");
7
+ for (const envelope of [request, result]) {
8
+ validate("intercept-request", envelope);
9
+ if (envelope.id !== envelope.params.event.id)
10
+ throw Error("Request/event ID mismatch");
11
+ }
12
+ if (request.params.event.type !== "user.elicitation.request" ||
13
+ result.params.event.type !== "user.elicitation.result")
14
+ throw Error("Wrong elicitation boundary");
15
+ validateElicitationCorrelation(request, result);
16
+ const req = request.params.event.elicitation, res = result.params.event.elicitation;
17
+ const payload = readSelectedElicitation(req, "request", resolve, validate);
18
+ const answer = readSelectedElicitation(res, "result", resolve, validate);
19
+ if (req.mode !== res.mode || req.server !== res.server)
20
+ throw Error("Normalized metadata mismatch");
21
+ if (payload === null || answer === null) {
22
+ if (effect !== undefined)
23
+ throw Error("Effects require selected bodies");
24
+ return {
25
+ selection: {
26
+ request: req.request?.selection ?? "omit",
27
+ result: res.result?.selection ?? "omit",
28
+ },
29
+ bodyValidation: "not-selected",
30
+ provenance: { kind: "mcp", authenticatedSource: principal },
31
+ externalCompletion: false,
32
+ };
33
+ }
34
+ validateElicitationAnswer(payload, answer, validate);
35
+ const mode = payload.mode ?? "form";
36
+ if (req.mode !== mode ||
37
+ res.mode !== mode ||
38
+ req.server !== res.server ||
39
+ res.action !== answer.action)
40
+ throw Error("Normalized metadata mismatch");
41
+ if ((mode === "url" || answer.action !== "accept") && "content" in answer)
42
+ throw Error("Content is only permitted for accepted forms");
43
+ let provenance = {
44
+ kind: "mcp",
45
+ authenticatedSource: principal,
46
+ };
47
+ if (effect !== undefined) {
48
+ validate("effect", effect);
49
+ const kind = effect.type, boundary = kind === "modify" ? result : request;
50
+ if (!["return", "deny", "modify"].includes(kind) ||
51
+ !boundary.params.capabilities.effects.includes(kind))
52
+ throw Error("Effect not granted at this boundary");
53
+ if (kind === "modify" &&
54
+ (effect.target !== "content" ||
55
+ !["replace", "merge"].includes(effect.operation ?? "") ||
56
+ boundary.params.capabilities.modify?.content?.[effect.operation ?? ""] !== true))
57
+ throw Error("Modify target/operation not granted");
58
+ provenance = { kind: "hook", authenticatedSource: principal, effect: kind };
59
+ }
60
+ return structuredClone({
61
+ request: payload,
62
+ result: answer,
63
+ provenance,
64
+ externalCompletion: false,
65
+ });
66
+ }
67
+ export function validateElicitationAnswer(request, answer, validate) {
68
+ validate("mcp-elicitation#result", answer);
69
+ const mode = request.mode ?? "form";
70
+ if ((mode === "url" || answer.action !== "accept") && "content" in answer)
71
+ throw Error("Content is only permitted for accepted forms");
72
+ if (mode === "form" && answer.action === "accept")
73
+ validate("form-answer", {
74
+ schema: request.requestedSchema,
75
+ value: answer.content ?? {},
76
+ });
77
+ }
78
+ export function validateElicitationMode(mode, capabilities, origin = "ahp") {
79
+ if (!["ahp", "mcp"].includes(origin) || !["form", "url"].includes(mode))
80
+ throw Error("Unknown origin or mode");
81
+ let caps = structuredClone(capabilities ?? {});
82
+ if (typeof caps !== "object" ||
83
+ caps === null ||
84
+ Array.isArray(caps) ||
85
+ Object.entries(caps).some(([k, v]) => ["form", "url"].includes(k) &&
86
+ (typeof v !== "object" || v === null || Array.isArray(v))))
87
+ throw Error("Invalid elicitation capabilities");
88
+ if (origin === "mcp" &&
89
+ capabilities !== undefined &&
90
+ Object.keys(capabilities).length === 0)
91
+ caps = { form: {} };
92
+ if (!(mode in caps))
93
+ throw Error("Elicitation mode not registered");
94
+ return caps;
95
+ }
96
+ /** Stage the complete effect list on a snapshot; publish only after validation.
97
+ * The caller uploads the resulting complete JSON before emitting a result event. */
98
+ export function applyElicitationEffects(request, result, resolve, validate, principal, effects) {
99
+ if (!principal || !Array.isArray(effects) || !effects.length)
100
+ throw Error("Authenticated effects required");
101
+ validate("intercept-request", request);
102
+ if (request.id !== request.params.event.id ||
103
+ request.params.event.type !== "user.elicitation.request")
104
+ throw Error("Invalid request boundary");
105
+ if (result !== null)
106
+ validateElicitationCorrelation(request, result);
107
+ const meta = request.params.event.elicitation;
108
+ const payload = readSelectedElicitation(meta, "request", resolve, validate);
109
+ if (payload === null)
110
+ throw Error("Effects require selected request body");
111
+ if (meta.mode !== (payload.mode ?? "form"))
112
+ throw Error("Mode mismatch");
113
+ const boundary = result ?? request, caps = boundary.params.capabilities, kinds = [];
114
+ let staged = result === null
115
+ ? null
116
+ : validateElicitationExchange(request, result, resolve, validate, principal).result;
117
+ if (result !== null && staged === undefined)
118
+ throw Error("Effects require selected bodies");
119
+ for (const effect of effects) {
120
+ validate("effect", effect);
121
+ const kind = effect.type;
122
+ if (!caps.effects.includes(kind) ||
123
+ !(result === null ? ["return", "deny"] : ["modify"]).includes(kind))
124
+ throw Error("Effect not granted at this boundary");
125
+ if (kind === "return" || kind === "deny") {
126
+ if (kinds.length)
127
+ throw Error("Conflicting terminal effects");
128
+ staged =
129
+ kind === "return"
130
+ ? structuredClone(effect.value)
131
+ : { action: "decline" };
132
+ }
133
+ else {
134
+ if (effect.target !== "content" ||
135
+ !["replace", "merge"].includes(effect.operation) ||
136
+ caps.modify?.content?.[effect.operation] !== true)
137
+ throw Error("Modify target/operation not granted");
138
+ staged.content =
139
+ effect.operation === "replace"
140
+ ? structuredClone(effect.value)
141
+ : { ...staged.content, ...structuredClone(effect.value) };
142
+ }
143
+ kinds.push(kind);
144
+ }
145
+ validateElicitationAnswer(payload, staged, validate);
146
+ return {
147
+ request: payload,
148
+ result: staged,
149
+ provenance: {
150
+ kind: "hook",
151
+ authenticatedSource: principal,
152
+ effects: kinds,
153
+ },
154
+ externalCompletion: false,
155
+ };
156
+ }
157
+ /** Metadata and omit never resolve or parse content. Selected gaps fail closed. */
158
+ export function readSelectedElicitation(meta, stage, resolve, validate) {
159
+ const item = meta[stage];
160
+ if (item === undefined)
161
+ return null;
162
+ validate("content-item", item);
163
+ if (item.mediaType !== "application/json")
164
+ throw Error("MCP body must be application/json");
165
+ if (item.selection !== "body")
166
+ return null;
167
+ if (!item.body)
168
+ throw Error("Selected body unavailable (fail closed)");
169
+ const payload = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(resolve(item.body)));
170
+ validate("mcp-elicitation#" + stage, payload);
171
+ if (stage === "request" && meta.mode !== (payload.mode ?? "form"))
172
+ throw Error("Mode mismatch");
173
+ if (stage === "result") {
174
+ if (meta.action !== payload.action)
175
+ throw Error("Action mismatch");
176
+ if ((meta.mode === "url" || payload.action !== "accept") &&
177
+ "content" in payload)
178
+ throw Error("Forbidden content");
179
+ }
180
+ return payload;
181
+ }
182
+ /** Require source-scoped parent identity and identical session scope before IO. */
183
+ export function validateElicitationCorrelation(request, result) {
184
+ const req = request.params.event, res = result.params.event;
185
+ if (typeof res.parentEventId !== "string" ||
186
+ res.parentEventId !== req.id ||
187
+ res.source !== req.source ||
188
+ res.session?.id !== req.session?.id)
189
+ throw Error("Elicitation parent/source/session mismatch");
190
+ }
191
+ //# sourceMappingURL=elicitation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elicitation.js","sourceRoot":"","sources":["../../src/elicitation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export type HookErrorCode = "INVALID_CONFIG" | "SPAWN_ERROR" | "IO_ERROR" | "TIMEOUT" | "MALFORMED_UTF8" | "MALFORMED_JSON" | "MALFORMED_JSON_RPC" | "ID_MISMATCH" | "JSON_RPC_ERROR" | "INCOMPATIBLE_VERSION" | "UNSUPPORTED_EVENT" | "UNSUPPORTED_EFFECT" | "MULTIPLE_EFFECTS";
2
+ export declare class HookOperationalError extends Error {
3
+ readonly code: HookErrorCode;
4
+ constructor(code: HookErrorCode, message: string, options?: ErrorOptions);
5
+ }
6
+ export declare function asOperationalError(error: unknown): HookOperationalError;
7
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,aAAa,GACb,UAAU,GACV,SAAS,GACT,gBAAgB,GAChB,gBAAgB,GAChB,oBAAoB,GACpB,aAAa,GACb,gBAAgB,GAChB,sBAAsB,GACtB,mBAAmB,GACnB,oBAAoB,GACpB,kBAAkB,CAAC;AAEvB,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;gBAEjB,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAKzE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAIvE"}
@@ -0,0 +1,15 @@
1
+ export class HookOperationalError extends Error {
2
+ code;
3
+ constructor(code, message, options) {
4
+ super(message, options);
5
+ this.name = "HookOperationalError";
6
+ this.code = code;
7
+ }
8
+ }
9
+ export function asOperationalError(error) {
10
+ if (error instanceof HookOperationalError)
11
+ return error;
12
+ const message = error instanceof Error ? error.message : String(error);
13
+ return new HookOperationalError("IO_ERROR", message, { cause: error });
14
+ }
15
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,CAAgB;IAE7B,YAAY,IAAmB,EAAE,OAAe,EAAE,OAAsB;QACtE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,KAAK,YAAY,oBAAoB;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,IAAI,oBAAoB,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AACzE,CAAC"}
@@ -0,0 +1,7 @@
1
+ /** Incremental, strict UTF-8 NDJSON decoder. Empty lines are not frames. */
2
+ export declare class NdjsonDecoder {
3
+ #private;
4
+ push(chunk: Uint8Array): string[];
5
+ end(): void;
6
+ }
7
+ //# sourceMappingURL=framing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framing.d.ts","sourceRoot":"","sources":["../../src/framing.ts"],"names":[],"mappings":"AAIA,4EAA4E;AAC5E,qBAAa,aAAa;;IAIxB,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE;IAsCjC,GAAG,IAAI,IAAI;CAQZ"}
@@ -0,0 +1,39 @@
1
+ import { HookOperationalError } from "./errors.js";
2
+ const MAX_LINE_BYTES = 1024 * 1024;
3
+ /** Incremental, strict UTF-8 NDJSON decoder. Empty lines are not frames. */
4
+ export class NdjsonDecoder {
5
+ #buffer = Buffer.alloc(0);
6
+ #decoder = new TextDecoder("utf-8", { fatal: true });
7
+ push(chunk) {
8
+ this.#buffer = Buffer.concat([this.#buffer, chunk]);
9
+ if (this.#buffer.length > MAX_LINE_BYTES && !this.#buffer.includes(0x0a)) {
10
+ throw new HookOperationalError("MALFORMED_JSON_RPC", "NDJSON frame exceeds 1 MiB");
11
+ }
12
+ const lines = [];
13
+ let newline;
14
+ while ((newline = this.#buffer.indexOf(0x0a)) !== -1) {
15
+ let frame = this.#buffer.subarray(0, newline);
16
+ this.#buffer = this.#buffer.subarray(newline + 1);
17
+ if (frame.length > MAX_LINE_BYTES)
18
+ throw new HookOperationalError("MALFORMED_JSON_RPC", "NDJSON frame exceeds 1 MiB");
19
+ if (frame.at(-1) === 0x0d)
20
+ frame = frame.subarray(0, -1);
21
+ if (frame.length === 0) {
22
+ throw new HookOperationalError("MALFORMED_JSON_RPC", "Empty NDJSON frame");
23
+ }
24
+ try {
25
+ lines.push(this.#decoder.decode(frame));
26
+ }
27
+ catch (error) {
28
+ throw new HookOperationalError("MALFORMED_UTF8", "NDJSON frame is not valid UTF-8", { cause: error });
29
+ }
30
+ }
31
+ return lines;
32
+ }
33
+ end() {
34
+ if (this.#buffer.length !== 0) {
35
+ throw new HookOperationalError("MALFORMED_JSON_RPC", "Output ended with an incomplete NDJSON frame");
36
+ }
37
+ }
38
+ }
39
+ //# sourceMappingURL=framing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framing.js","sourceRoot":"","sources":["../../src/framing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnC,4EAA4E;AAC5E,MAAM,OAAO,aAAa;IACxB,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjB,QAAQ,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9D,IAAI,CAAC,KAAiB;QACpB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QACpD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,cAAc,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,EACpB,4BAA4B,CAC7B,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,OAAe,CAAC;QACpB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACrD,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC9C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YAClD,IAAI,KAAK,CAAC,MAAM,GAAG,cAAc;gBAC/B,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,EACpB,4BAA4B,CAC7B,CAAC;YACJ,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI;gBAAE,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACzD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,EACpB,oBAAoB,CACrB,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACH,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,oBAAoB,CAC5B,gBAAgB,EAChB,iCAAiC,EACjC,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,EACpB,8CAA8C,CAC/C,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}