@heddleagent/execution-host-client 6.5.0 → 6.6.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 (98) hide show
  1. package/README.md +17 -10
  2. package/dist/adopter/contracts.d.ts +13 -0
  3. package/dist/adopter/contracts.d.ts.map +1 -0
  4. package/dist/adopter/contracts.js +13 -0
  5. package/dist/adopter/contracts.js.map +1 -0
  6. package/dist/adopter/hosted-conversation-client.d.ts +20 -0
  7. package/dist/adopter/hosted-conversation-client.d.ts.map +1 -0
  8. package/dist/adopter/hosted-conversation-client.js +103 -0
  9. package/dist/adopter/hosted-conversation-client.js.map +1 -0
  10. package/dist/adopter/index.d.ts +5 -0
  11. package/dist/adopter/index.d.ts.map +1 -0
  12. package/dist/adopter/index.js +3 -0
  13. package/dist/adopter/index.js.map +1 -0
  14. package/dist/adopter/types.d.ts +14 -0
  15. package/dist/adopter/types.d.ts.map +1 -0
  16. package/dist/adopter/types.js +2 -0
  17. package/dist/adopter/types.js.map +1 -0
  18. package/dist/agentcore/agentcore-execution-host.d.ts.map +1 -1
  19. package/dist/agentcore/agentcore-execution-host.js +7 -4
  20. package/dist/agentcore/agentcore-execution-host.js.map +1 -1
  21. package/dist/agentcore/index.d.ts +2 -0
  22. package/dist/agentcore/index.d.ts.map +1 -1
  23. package/dist/agentcore/index.js +1 -0
  24. package/dist/agentcore/index.js.map +1 -1
  25. package/dist/agentcore/schemas.d.ts +11 -0
  26. package/dist/agentcore/schemas.d.ts.map +1 -0
  27. package/dist/agentcore/schemas.js +12 -0
  28. package/dist/agentcore/schemas.js.map +1 -0
  29. package/dist/agentcore/types.d.ts +2 -4
  30. package/dist/agentcore/types.d.ts.map +1 -1
  31. package/dist/agentcore/types.js.map +1 -1
  32. package/dist/coordinator/contracts.d.ts +367 -2
  33. package/dist/coordinator/contracts.d.ts.map +1 -1
  34. package/dist/coordinator/contracts.js +72 -2
  35. package/dist/coordinator/contracts.js.map +1 -1
  36. package/dist/coordinator/hosted-heartbeat-coordinator-client.d.ts +6 -2
  37. package/dist/coordinator/hosted-heartbeat-coordinator-client.d.ts.map +1 -1
  38. package/dist/coordinator/hosted-heartbeat-coordinator-client.js +21 -1
  39. package/dist/coordinator/hosted-heartbeat-coordinator-client.js.map +1 -1
  40. package/dist/coordinator/index.d.ts +2 -2
  41. package/dist/coordinator/index.d.ts.map +1 -1
  42. package/dist/coordinator/index.js +1 -1
  43. package/dist/coordinator/index.js.map +1 -1
  44. package/dist/coordinator/types.d.ts +7 -3
  45. package/dist/coordinator/types.d.ts.map +1 -1
  46. package/dist/coordinator/types.js.map +1 -1
  47. package/dist/host/index.d.ts +1 -0
  48. package/dist/host/index.d.ts.map +1 -1
  49. package/dist/host/index.js +1 -0
  50. package/dist/host/index.js.map +1 -1
  51. package/dist/host/runtime-session/errors.d.ts +21 -0
  52. package/dist/host/runtime-session/errors.d.ts.map +1 -0
  53. package/dist/host/runtime-session/errors.js +21 -0
  54. package/dist/host/runtime-session/errors.js.map +1 -0
  55. package/dist/host/runtime-session/index.d.ts +9 -0
  56. package/dist/host/runtime-session/index.d.ts.map +1 -0
  57. package/dist/host/runtime-session/index.js +5 -0
  58. package/dist/host/runtime-session/index.js.map +1 -0
  59. package/dist/host/runtime-session/scope-binding.d.ts +17 -0
  60. package/dist/host/runtime-session/scope-binding.d.ts.map +1 -0
  61. package/dist/host/runtime-session/scope-binding.js +37 -0
  62. package/dist/host/runtime-session/scope-binding.js.map +1 -0
  63. package/dist/host/runtime-session/service.d.ts +38 -0
  64. package/dist/host/runtime-session/service.d.ts.map +1 -0
  65. package/dist/host/runtime-session/service.js +177 -0
  66. package/dist/host/runtime-session/service.js.map +1 -0
  67. package/dist/host/runtime-session/status.d.ts +17 -0
  68. package/dist/host/runtime-session/status.d.ts.map +1 -0
  69. package/dist/host/runtime-session/status.js +33 -0
  70. package/dist/host/runtime-session/status.js.map +1 -0
  71. package/dist/host/runtime-session/types.d.ts +61 -0
  72. package/dist/host/runtime-session/types.d.ts.map +1 -0
  73. package/dist/host/runtime-session/types.js +2 -0
  74. package/dist/host/runtime-session/types.js.map +1 -0
  75. package/dist/http-sse/direct-http-execution-host.d.ts.map +1 -1
  76. package/dist/http-sse/direct-http-execution-host.js +10 -177
  77. package/dist/http-sse/direct-http-execution-host.js.map +1 -1
  78. package/dist/index.d.ts +1 -0
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +1 -0
  81. package/dist/index.js.map +1 -1
  82. package/dist/internal/execution-host-event-stream.d.ts +18 -0
  83. package/dist/internal/execution-host-event-stream.d.ts.map +1 -0
  84. package/dist/internal/execution-host-event-stream.js +141 -0
  85. package/dist/internal/execution-host-event-stream.js.map +1 -0
  86. package/dist/internal/http-response.d.ts +4 -0
  87. package/dist/internal/http-response.d.ts.map +1 -0
  88. package/dist/internal/http-response.js +57 -0
  89. package/dist/internal/http-response.js.map +1 -0
  90. package/dist/node/http-service.d.ts +0 -2
  91. package/dist/node/http-service.d.ts.map +1 -1
  92. package/dist/node/http-service.js +1 -2
  93. package/dist/node/http-service.js.map +1 -1
  94. package/dist/node/index.d.ts +2 -1
  95. package/dist/node/index.d.ts.map +1 -1
  96. package/dist/node/index.js +2 -1
  97. package/dist/node/index.js.map +1 -1
  98. package/package.json +22 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-host-event-stream.js","sourceRoot":"","sources":["../../src/internal/execution-host-event-stream.ts"],"names":[],"mappings":"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","sourcesContent":["import { createParser, type EventSourceMessage } from 'eventsource-parser';\nimport type { z } from 'zod';\nimport {\n ExecutionHostInvocationCancelledError,\n ExecutionHostProtocolError,\n ExecutionHostStreamInterruptedError,\n} from '../http-sse/errors.js';\nimport {\n cancelResponseBody,\n isEventStreamResponse,\n} from './http-response.js';\n\nconst MAX_SSE_BUFFER_CHARACTERS = 1_048_576;\nconst MAX_PENDING_SSE_FRAMES = 1_024;\n\ntype ExecutionHostEvent = {\n kind: string;\n invocationId: string;\n runId: string;\n sequence: number;\n timestamp: string;\n};\n\ntype StreamValidationState = {\n invocationId?: string;\n runId?: string;\n nextSequence: number;\n accepted?: true;\n terminal: boolean;\n};\n\nexport async function* readExecutionHostEventStream<\n Event extends ExecutionHostEvent,\n>(input: {\n response: Response;\n schema: z.ZodType<Event>;\n isTerminal: (event: Event) => boolean;\n invocationId?: string;\n signal?: AbortSignal;\n}): AsyncIterable<Event> {\n if (!isEventStreamResponse(input.response)) {\n await cancelResponseBody(input.response);\n throw new ExecutionHostProtocolError(\n 'Execution Host did not return an SSE stream.',\n );\n }\n if (!input.response.body) {\n throw new ExecutionHostProtocolError(\n 'Execution Host returned an empty SSE response body.',\n );\n }\n\n const state: StreamValidationState = {\n invocationId: input.invocationId,\n nextSequence: 0,\n terminal: false,\n };\n const decoder = new TextDecoder();\n const pending: EventSourceMessage[] = [];\n let terminalEvent: Event | undefined;\n let parserFailed = false;\n const parser = createParser({\n maxBufferSize: MAX_SSE_BUFFER_CHARACTERS,\n onEvent: (event) => {\n if (pending.length >= MAX_PENDING_SSE_FRAMES) {\n parserFailed = true;\n return;\n }\n pending.push(event);\n },\n onError: () => {\n parserFailed = true;\n },\n });\n const reader = input.response.body.getReader();\n\n try {\n while (true) {\n input.signal?.throwIfAborted();\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n parser.feed(decoder.decode(value, { stream: true }));\n assertParserHealthy(parserFailed);\n for (const event of drainEvents(pending, state, input.schema, input.isTerminal)) {\n if (input.isTerminal(event)) {\n terminalEvent = event;\n } else {\n yield event;\n }\n }\n }\n\n parser.feed(decoder.decode());\n parser.reset({ consume: true });\n assertParserHealthy(parserFailed);\n for (const event of drainEvents(pending, state, input.schema, input.isTerminal)) {\n if (input.isTerminal(event)) {\n terminalEvent = event;\n } else {\n yield event;\n }\n }\n } catch (error) {\n await reader.cancel().catch(() => undefined);\n if (error instanceof ExecutionHostProtocolError) {\n throw error;\n }\n throw toExecutionHostTransportError(error, input.signal);\n } finally {\n reader.releaseLock();\n }\n\n if (!state.accepted) {\n throw new ExecutionHostProtocolError(\n 'Execution Host stream omitted the accepted event.',\n );\n }\n if (!state.terminal || !terminalEvent) {\n throw new ExecutionHostStreamInterruptedError();\n }\n // A terminal event is observable only after clean EOF. This keeps success\n // truthful if the transport appends malformed or post-terminal data.\n yield terminalEvent;\n}\n\nexport function toExecutionHostTransportError(\n error: unknown,\n signal?: AbortSignal,\n): Error {\n if (signal?.aborted || isAbortError(error)) {\n return new ExecutionHostInvocationCancelledError();\n }\n return new ExecutionHostStreamInterruptedError();\n}\n\nfunction* drainEvents<Event extends ExecutionHostEvent>(\n pending: EventSourceMessage[],\n state: StreamValidationState,\n schema: z.ZodType<Event>,\n isTerminal: (event: Event) => boolean,\n): Generator<Event> {\n while (pending.length > 0) {\n yield validateEvent(pending.shift()!, state, schema, isTerminal);\n }\n}\n\nfunction validateEvent<Event extends ExecutionHostEvent>(\n frame: EventSourceMessage,\n state: StreamValidationState,\n schema: z.ZodType<Event>,\n isTerminal: (event: Event) => boolean,\n): Event {\n let decoded: unknown;\n try {\n decoded = JSON.parse(frame.data) as unknown;\n } catch {\n throw new ExecutionHostProtocolError();\n }\n const parsed = schema.safeParse(decoded);\n if (!parsed.success) {\n throw new ExecutionHostProtocolError();\n }\n const event = parsed.data;\n const correctFrameMetadata = frame.event === event.kind\n && frame.id === String(event.sequence);\n const correctEnvelope = event.sequence === state.nextSequence\n && (!state.invocationId || event.invocationId === state.invocationId);\n if (!correctFrameMetadata || !correctEnvelope || state.terminal) {\n throw new ExecutionHostProtocolError();\n }\n\n if (!state.accepted) {\n if (event.kind !== 'accepted') {\n throw new ExecutionHostProtocolError();\n }\n state.accepted = true;\n state.invocationId = event.invocationId;\n state.runId = event.runId;\n } else if (event.kind === 'accepted' || event.runId !== state.runId) {\n throw new ExecutionHostProtocolError();\n }\n\n state.nextSequence += 1;\n state.terminal = isTerminal(event);\n return event;\n}\n\nfunction assertParserHealthy(failed: boolean): void {\n if (failed) {\n throw new ExecutionHostProtocolError();\n }\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError';\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export declare function cancelResponseBody(response: Response): Promise<void>;
2
+ export declare function isEventStreamResponse(response: Response): boolean;
3
+ export declare function readBoundedJsonResponse(response: Response, maxBytes: number): Promise<unknown | undefined>;
4
+ //# sourceMappingURL=http-response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-response.d.ts","sourceRoot":"","sources":["../../src/internal/http-response.ts"],"names":[],"mappings":"AAAA,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1E;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAKjE;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAyC9B"}
@@ -0,0 +1,57 @@
1
+ export async function cancelResponseBody(response) {
2
+ try {
3
+ await response.body?.cancel();
4
+ }
5
+ catch {
6
+ // Response cleanup is best effort and must not replace the owning error.
7
+ }
8
+ }
9
+ export function isEventStreamResponse(response) {
10
+ return response.headers.get('content-type')
11
+ ?.split(';', 1)[0]
12
+ ?.trim()
13
+ .toLowerCase() === 'text/event-stream';
14
+ }
15
+ export async function readBoundedJsonResponse(response, maxBytes) {
16
+ const declaredLength = Number(response.headers.get('content-length'));
17
+ if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
18
+ await cancelResponseBody(response);
19
+ return undefined;
20
+ }
21
+ if (!response.body) {
22
+ return undefined;
23
+ }
24
+ const reader = response.body.getReader();
25
+ const chunks = [];
26
+ let totalBytes = 0;
27
+ try {
28
+ while (true) {
29
+ const { done, value } = await reader.read();
30
+ if (done) {
31
+ break;
32
+ }
33
+ totalBytes += value.byteLength;
34
+ if (totalBytes > maxBytes) {
35
+ await reader.cancel();
36
+ return undefined;
37
+ }
38
+ chunks.push(value);
39
+ }
40
+ }
41
+ finally {
42
+ reader.releaseLock();
43
+ }
44
+ const bytes = new Uint8Array(totalBytes);
45
+ let offset = 0;
46
+ for (const chunk of chunks) {
47
+ bytes.set(chunk, offset);
48
+ offset += chunk.byteLength;
49
+ }
50
+ try {
51
+ return JSON.parse(new TextDecoder().decode(bytes));
52
+ }
53
+ catch {
54
+ return undefined;
55
+ }
56
+ }
57
+ //# sourceMappingURL=http-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-response.js","sourceRoot":"","sources":["../../src/internal/http-response.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAkB;IACzD,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;IAC3E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAAkB;IACtD,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACzC,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAClB,EAAE,IAAI,EAAE;SACP,WAAW,EAAE,KAAK,mBAAmB,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,QAAkB,EAClB,QAAgB;IAEhB,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACtE,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,QAAQ,EAAE,CAAC;QACjE,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACzC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI,EAAE,CAAC;gBACT,MAAM;YACR,CAAC;YACD,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC;YAC/B,IAAI,UAAU,GAAG,QAAQ,EAAE,CAAC;gBAC1B,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;gBACtB,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC;IAC7B,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAY,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC","sourcesContent":["export async function cancelResponseBody(response: Response): Promise<void> {\n try {\n await response.body?.cancel();\n } catch {\n // Response cleanup is best effort and must not replace the owning error.\n }\n}\n\nexport function isEventStreamResponse(response: Response): boolean {\n return response.headers.get('content-type')\n ?.split(';', 1)[0]\n ?.trim()\n .toLowerCase() === 'text/event-stream';\n}\n\nexport async function readBoundedJsonResponse(\n response: Response,\n maxBytes: number,\n): Promise<unknown | undefined> {\n const declaredLength = Number(response.headers.get('content-length'));\n if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {\n await cancelResponseBody(response);\n return undefined;\n }\n if (!response.body) {\n return undefined;\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalBytes = 0;\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n return undefined;\n }\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n\n const bytes = new Uint8Array(totalBytes);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n try {\n return JSON.parse(new TextDecoder().decode(bytes)) as unknown;\n } catch {\n return undefined;\n }\n}\n"]}
@@ -1,7 +1,5 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import type { NodeExecutionAdopterHttpHandler, NodeExecutionAdopterHttpServiceConfig } from './types.js';
3
- export declare const DEFAULT_ADOPTER_JWKS_PATH = "/.well-known/jwks.json";
4
- export declare const DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH = "/hosted-execution/conversation-turns";
5
3
  /**
6
4
  * Standard Node HTTP edge for adopter-side JWKS and hosted conversations.
7
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"http-service.d.ts","sourceRoot":"","sources":["../../src/node/http-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACf,MAAM,WAAW,CAAC;AAcnB,OAAO,KAAK,EAEV,+BAA+B,EAE/B,qCAAqC,EAEtC,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,yBAAyB,2BAA2B,CAAC;AAClE,eAAO,MAAM,uCAAuC,yCACZ,CAAC;AAgBzC;;;;;;;GAOG;AACH,qBAAa,+BAA+B,CAAC,SAAS,CACtD,YAAW,+BAA+B;;gBAwB5B,MAAM,EAAE,qCAAqC,CAAC,SAAS,CAAC;IAkBpE,MAAM,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO;IAanE,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;IAwBpE,sBAAsB,CACpB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,GACvB,IAAI;IA0CP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAmJvB"}
1
+ {"version":3,"file":"http-service.d.ts","sourceRoot":"","sources":["../../src/node/http-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACf,MAAM,WAAW,CAAC;AAkBnB,OAAO,KAAK,EAEV,+BAA+B,EAE/B,qCAAqC,EAEtC,MAAM,YAAY,CAAC;AAgBpB;;;;;;;GAOG;AACH,qBAAa,+BAA+B,CAAC,SAAS,CACtD,YAAW,+BAA+B;;gBAwB5B,MAAM,EAAE,qCAAqC,CAAC,SAAS,CAAC;IAkBpE,MAAM,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO;IAanE,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;IAwBpE,sBAAsB,CACpB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,GACvB,IAAI;IA0CP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAmJvB"}
@@ -1,10 +1,9 @@
1
1
  import { once } from 'node:events';
2
2
  import { z } from 'zod';
3
+ import { DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH, DEFAULT_ADOPTER_JWKS_PATH, } from '../adopter/index.js';
3
4
  import { ExecutionHostStreamEventSchema } from '../contracts/index.js';
4
5
  import { ExecutionHostInvocationCancelledError } from '../http-sse/index.js';
5
6
  import { NodeHttpPathSchema, NodeHttpRequestError, errorType, readJsonBody, readPathname, takeAuthorization, writeJson, writeJsonError, } from './http-utils.js';
6
- export const DEFAULT_ADOPTER_JWKS_PATH = '/.well-known/jwks.json';
7
- export const DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH = '/hosted-execution/conversation-turns';
8
7
  const DEFAULT_MAX_BODY_BYTES = 64 * 1_024;
9
8
  const DEFAULT_MAX_PROMPT_CHARACTERS = 20_000;
10
9
  const PublicErrorSchema = z.object({
@@ -1 +1 @@
1
- {"version":3,"file":"http-service.js","sourceRoot":"","sources":["../../src/node/http-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { once } from 'node:events';\nimport type {\n IncomingMessage,\n ServerResponse,\n} from 'node:http';\nimport { z } from 'zod';\nimport { ExecutionHostStreamEventSchema } from '../contracts/index.js';\nimport { ExecutionHostInvocationCancelledError } from '../http-sse/index.js';\nimport {\n NodeHttpPathSchema,\n NodeHttpRequestError,\n errorType,\n readJsonBody,\n readPathname,\n takeAuthorization,\n writeJson,\n writeJsonError,\n} from './http-utils.js';\nimport type {\n NodeExecutionAdopterFailure,\n NodeExecutionAdopterHttpHandler,\n NodeExecutionAdopterHttpPaths,\n NodeExecutionAdopterHttpServiceConfig,\n NodeExecutionAdopterPublicError,\n} from './types.js';\n\nexport const DEFAULT_ADOPTER_JWKS_PATH = '/.well-known/jwks.json';\nexport const DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH =\n '/hosted-execution/conversation-turns';\n\nconst DEFAULT_MAX_BODY_BYTES = 64 * 1_024;\nconst DEFAULT_MAX_PROMPT_CHARACTERS = 20_000;\nconst PublicErrorSchema = z.object({\n statusCode: z.number().int().min(400).max(599),\n message: z.string().min(1).max(1_600),\n}).strict();\n\ntype ActiveConversation = {\n abortController: AbortController;\n request: IncomingMessage;\n response: ServerResponse;\n pending: Promise<void>;\n};\n\n/**\n * Standard Node HTTP edge for adopter-side JWKS and hosted conversations.\n *\n * The service owns bounded parsing, credential-header scrubbing, SSE framing,\n * disconnect cancellation, safe failures, and graceful shutdown. Product\n * authentication, authorization, identity selection, and persistence stay in\n * adopter callbacks.\n */\nexport class NodeExecutionAdopterHttpService<Principal>\nimplements NodeExecutionAdopterHttpHandler {\n readonly #authority: NodeExecutionAdopterHttpServiceConfig<Principal>[\n 'authority'\n ];\n readonly #authenticator: NodeExecutionAdopterHttpServiceConfig<Principal>[\n 'authenticator'\n ];\n readonly #conversations: NodeExecutionAdopterHttpServiceConfig<\n Principal\n >['conversations'];\n readonly #projectError: NodeExecutionAdopterHttpServiceConfig<Principal>[\n 'projectError'\n ];\n readonly #reportFailure: NodeExecutionAdopterHttpServiceConfig<Principal>[\n 'reportFailure'\n ];\n readonly #paths: Readonly<NodeExecutionAdopterHttpPaths>;\n readonly #maxBodyBytes: number;\n readonly #maxPromptCharacters: number;\n readonly #jwksMaxAgeSeconds: number;\n readonly #activeConversations = new Set<ActiveConversation>();\n #closed = false;\n #closePromise: Promise<void> | undefined;\n\n constructor(config: NodeExecutionAdopterHttpServiceConfig<Principal>) {\n this.#authority = config.authority;\n this.#authenticator = config.authenticator;\n this.#conversations = config.conversations;\n this.#projectError = config.projectError;\n this.#reportFailure = config.reportFailure;\n this.#paths = parsePaths(config.paths);\n this.#maxBodyBytes = z.number().int().min(1).max(1_048_576).parse(\n config.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,\n );\n this.#maxPromptCharacters = z.number().int().min(1).max(200_000).parse(\n config.maxPromptCharacters ?? DEFAULT_MAX_PROMPT_CHARACTERS,\n );\n this.#jwksMaxAgeSeconds = z.number().int().min(0).max(86_400).parse(\n config.jwksMaxAgeSeconds ?? 60,\n );\n }\n\n handle(request: IncomingMessage, response: ServerResponse): boolean {\n const pathname = readPathname(request.url);\n if (pathname === this.#paths.jwks) {\n this.handleJwks(request, response);\n return true;\n }\n if (pathname === this.#paths.conversationTurns) {\n this.handleConversationTurn(request, response);\n return true;\n }\n return false;\n }\n\n handleJwks(request: IncomingMessage, response: ServerResponse): void {\n request.resume();\n if (this.#closed) {\n writeJsonError(response, 503, 'Hosted execution is unavailable.');\n return;\n }\n if (request.method !== 'GET') {\n writeJsonError(response, 405, 'Method not allowed.');\n return;\n }\n try {\n writeJson(response, 200, this.#authority.publicJwks(), {\n 'Cache-Control': `public, max-age=${this.#jwksMaxAgeSeconds}`,\n });\n } catch (error) {\n this.#report({\n phase: 'jwks',\n errorType: errorType(error),\n streamAccepted: false,\n });\n writeJsonError(response, 500, 'Verification keys are unavailable.');\n }\n }\n\n handleConversationTurn(\n request: IncomingMessage,\n response: ServerResponse,\n ): void {\n if (this.#closed) {\n request.resume();\n writeJsonError(response, 503, 'Hosted execution is unavailable.');\n return;\n }\n\n const abortController = new AbortController();\n const abort = () => abortController.abort(\n new Error('The owning adopter HTTP request closed.'),\n );\n request.once('aborted', abort);\n response.once('close', abort);\n const active: ActiveConversation = {\n abortController,\n request,\n response,\n pending: Promise.resolve(),\n };\n active.pending = this.#serveConversation(\n request,\n response,\n abortController.signal,\n ).catch((error) => {\n this.#report({\n phase: 'conversation',\n errorType: errorType(error),\n streamAccepted: response.headersSent,\n });\n if (!response.headersSent) {\n writeJsonError(response, 500, 'Hosted execution request failed.');\n } else if (!response.destroyed && !response.writableEnded) {\n response.end();\n }\n }).finally(() => {\n request.removeListener('aborted', abort);\n response.removeListener('close', abort);\n this.#activeConversations.delete(active);\n });\n this.#activeConversations.add(active);\n }\n\n close(): Promise<void> {\n if (!this.#closePromise) {\n this.#closed = true;\n this.#closePromise = this.#closeActiveConversations();\n }\n return this.#closePromise;\n }\n\n async #closeActiveConversations(): Promise<void> {\n const active = [...this.#activeConversations];\n active.forEach(({ abortController, request, response }) => {\n abortController.abort(new Error('The adopter HTTP service is stopping.'));\n request.destroy();\n response.destroy();\n });\n await Promise.allSettled(active.map(({ pending }) => pending));\n }\n\n async #serveConversation(\n request: IncomingMessage,\n response: ServerResponse,\n signal: AbortSignal,\n ): Promise<void> {\n let authorization: string | undefined;\n try {\n authorization = takeAuthorization(request);\n if (request.method !== 'POST') {\n request.resume();\n writeJsonError(response, 405, 'Method not allowed.');\n return;\n }\n } catch (error) {\n request.resume();\n writeJsonError(\n response,\n error instanceof NodeHttpRequestError ? error.statusCode : 400,\n 'Invalid conversation request.',\n );\n return;\n }\n\n let principal: Principal | undefined;\n try {\n principal = await this.#authenticator.authenticate({\n authorization,\n remoteAddress: request.socket.remoteAddress,\n signal,\n });\n } catch (error) {\n this.#report({\n phase: 'authentication',\n errorType: errorType(error),\n streamAccepted: false,\n });\n request.resume();\n writeJsonError(response, 500, 'Authentication could not be completed.');\n return;\n }\n if (!principal) {\n request.resume();\n writeJsonError(response, 401, 'Authentication is required.', {\n 'WWW-Authenticate': 'Bearer',\n });\n return;\n }\n\n let prompt: string;\n try {\n const body = await readJsonBody(request, this.#maxBodyBytes, signal);\n prompt = z.object({\n prompt: z.string().trim().min(1).max(this.#maxPromptCharacters),\n }).strict().parse(body).prompt;\n } catch (error) {\n const statusCode = error instanceof NodeHttpRequestError\n ? error.statusCode\n : 400;\n writeJsonError(response, statusCode, 'Invalid conversation request.');\n return;\n }\n\n let streamed = false;\n try {\n for await (const rawEvent of this.#conversations.streamTurn({\n principal,\n prompt,\n signal,\n })) {\n const event = ExecutionHostStreamEventSchema.parse(rawEvent);\n if (!streamed) {\n writeEventStreamHeaders(response);\n streamed = true;\n }\n await writeSseEvent(response, event, signal);\n }\n if (!streamed) {\n writeJsonError(response, 502, 'Execution Host returned no events.');\n return;\n }\n response.end();\n } catch (error) {\n const publicError = !streamed ? this.#project(error) : undefined;\n if (publicError) {\n writeJsonError(response, publicError.statusCode, publicError.message);\n return;\n }\n if (\n error instanceof ExecutionHostInvocationCancelledError\n || signal.aborted\n ) {\n if (!response.headersSent && !response.destroyed) {\n writeJsonError(response, 499, 'Hosted conversation was cancelled.');\n }\n return;\n }\n this.#report({\n phase: 'conversation',\n errorType: errorType(error),\n streamAccepted: streamed,\n });\n if (!response.headersSent) {\n writeJsonError(response, 502, 'Execution Host conversation failed.');\n } else if (!response.destroyed && !response.writableEnded) {\n // A post-acceptance failure deliberately ends without a terminal event.\n response.end();\n }\n }\n }\n\n #project(error: unknown): NodeExecutionAdopterPublicError | undefined {\n if (!this.#projectError) {\n return undefined;\n }\n try {\n const projected = this.#projectError(error);\n return projected ? PublicErrorSchema.parse(projected) : undefined;\n } catch {\n return undefined;\n }\n }\n\n #report(failure: NodeExecutionAdopterFailure): void {\n try {\n this.#reportFailure?.(Object.freeze({ ...failure }));\n } catch {\n // Observability must not change request settlement.\n }\n }\n}\n\nfunction parsePaths(\n paths: Partial<NodeExecutionAdopterHttpPaths> | undefined,\n): Readonly<NodeExecutionAdopterHttpPaths> {\n const parsed = {\n jwks: NodeHttpPathSchema.parse(paths?.jwks ?? DEFAULT_ADOPTER_JWKS_PATH),\n conversationTurns: NodeHttpPathSchema.parse(\n paths?.conversationTurns ?? DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH,\n ),\n };\n if (parsed.jwks === parsed.conversationTurns) {\n throw new Error('Adopter HTTP paths must be distinct.');\n }\n return Object.freeze(parsed);\n}\n\nfunction writeEventStreamHeaders(response: ServerResponse): void {\n response.writeHead(200, {\n 'Cache-Control': 'no-store',\n 'Content-Type': 'text/event-stream; charset=utf-8',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n 'X-Content-Type-Options': 'nosniff',\n });\n}\n\nasync function writeSseEvent(\n response: ServerResponse,\n event: z.infer<typeof ExecutionHostStreamEventSchema>,\n signal: AbortSignal,\n): Promise<void> {\n const frame = [\n `event: ${event.kind}`,\n `id: ${event.sequence}`,\n `data: ${JSON.stringify(event)}`,\n '',\n '',\n ].join('\\n');\n if (!response.write(frame)) {\n await once(response, 'drain', { signal });\n }\n}\n"]}
1
+ {"version":3,"file":"http-service.js","sourceRoot":"","sources":["../../src/node/http-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { once } from 'node:events';\nimport type {\n IncomingMessage,\n ServerResponse,\n} from 'node:http';\nimport { z } from 'zod';\nimport {\n DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH,\n DEFAULT_ADOPTER_JWKS_PATH,\n} from '../adopter/index.js';\nimport { ExecutionHostStreamEventSchema } from '../contracts/index.js';\nimport { ExecutionHostInvocationCancelledError } from '../http-sse/index.js';\nimport {\n NodeHttpPathSchema,\n NodeHttpRequestError,\n errorType,\n readJsonBody,\n readPathname,\n takeAuthorization,\n writeJson,\n writeJsonError,\n} from './http-utils.js';\nimport type {\n NodeExecutionAdopterFailure,\n NodeExecutionAdopterHttpHandler,\n NodeExecutionAdopterHttpPaths,\n NodeExecutionAdopterHttpServiceConfig,\n NodeExecutionAdopterPublicError,\n} from './types.js';\n\nconst DEFAULT_MAX_BODY_BYTES = 64 * 1_024;\nconst DEFAULT_MAX_PROMPT_CHARACTERS = 20_000;\nconst PublicErrorSchema = z.object({\n statusCode: z.number().int().min(400).max(599),\n message: z.string().min(1).max(1_600),\n}).strict();\n\ntype ActiveConversation = {\n abortController: AbortController;\n request: IncomingMessage;\n response: ServerResponse;\n pending: Promise<void>;\n};\n\n/**\n * Standard Node HTTP edge for adopter-side JWKS and hosted conversations.\n *\n * The service owns bounded parsing, credential-header scrubbing, SSE framing,\n * disconnect cancellation, safe failures, and graceful shutdown. Product\n * authentication, authorization, identity selection, and persistence stay in\n * adopter callbacks.\n */\nexport class NodeExecutionAdopterHttpService<Principal>\nimplements NodeExecutionAdopterHttpHandler {\n readonly #authority: NodeExecutionAdopterHttpServiceConfig<Principal>[\n 'authority'\n ];\n readonly #authenticator: NodeExecutionAdopterHttpServiceConfig<Principal>[\n 'authenticator'\n ];\n readonly #conversations: NodeExecutionAdopterHttpServiceConfig<\n Principal\n >['conversations'];\n readonly #projectError: NodeExecutionAdopterHttpServiceConfig<Principal>[\n 'projectError'\n ];\n readonly #reportFailure: NodeExecutionAdopterHttpServiceConfig<Principal>[\n 'reportFailure'\n ];\n readonly #paths: Readonly<NodeExecutionAdopterHttpPaths>;\n readonly #maxBodyBytes: number;\n readonly #maxPromptCharacters: number;\n readonly #jwksMaxAgeSeconds: number;\n readonly #activeConversations = new Set<ActiveConversation>();\n #closed = false;\n #closePromise: Promise<void> | undefined;\n\n constructor(config: NodeExecutionAdopterHttpServiceConfig<Principal>) {\n this.#authority = config.authority;\n this.#authenticator = config.authenticator;\n this.#conversations = config.conversations;\n this.#projectError = config.projectError;\n this.#reportFailure = config.reportFailure;\n this.#paths = parsePaths(config.paths);\n this.#maxBodyBytes = z.number().int().min(1).max(1_048_576).parse(\n config.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,\n );\n this.#maxPromptCharacters = z.number().int().min(1).max(200_000).parse(\n config.maxPromptCharacters ?? DEFAULT_MAX_PROMPT_CHARACTERS,\n );\n this.#jwksMaxAgeSeconds = z.number().int().min(0).max(86_400).parse(\n config.jwksMaxAgeSeconds ?? 60,\n );\n }\n\n handle(request: IncomingMessage, response: ServerResponse): boolean {\n const pathname = readPathname(request.url);\n if (pathname === this.#paths.jwks) {\n this.handleJwks(request, response);\n return true;\n }\n if (pathname === this.#paths.conversationTurns) {\n this.handleConversationTurn(request, response);\n return true;\n }\n return false;\n }\n\n handleJwks(request: IncomingMessage, response: ServerResponse): void {\n request.resume();\n if (this.#closed) {\n writeJsonError(response, 503, 'Hosted execution is unavailable.');\n return;\n }\n if (request.method !== 'GET') {\n writeJsonError(response, 405, 'Method not allowed.');\n return;\n }\n try {\n writeJson(response, 200, this.#authority.publicJwks(), {\n 'Cache-Control': `public, max-age=${this.#jwksMaxAgeSeconds}`,\n });\n } catch (error) {\n this.#report({\n phase: 'jwks',\n errorType: errorType(error),\n streamAccepted: false,\n });\n writeJsonError(response, 500, 'Verification keys are unavailable.');\n }\n }\n\n handleConversationTurn(\n request: IncomingMessage,\n response: ServerResponse,\n ): void {\n if (this.#closed) {\n request.resume();\n writeJsonError(response, 503, 'Hosted execution is unavailable.');\n return;\n }\n\n const abortController = new AbortController();\n const abort = () => abortController.abort(\n new Error('The owning adopter HTTP request closed.'),\n );\n request.once('aborted', abort);\n response.once('close', abort);\n const active: ActiveConversation = {\n abortController,\n request,\n response,\n pending: Promise.resolve(),\n };\n active.pending = this.#serveConversation(\n request,\n response,\n abortController.signal,\n ).catch((error) => {\n this.#report({\n phase: 'conversation',\n errorType: errorType(error),\n streamAccepted: response.headersSent,\n });\n if (!response.headersSent) {\n writeJsonError(response, 500, 'Hosted execution request failed.');\n } else if (!response.destroyed && !response.writableEnded) {\n response.end();\n }\n }).finally(() => {\n request.removeListener('aborted', abort);\n response.removeListener('close', abort);\n this.#activeConversations.delete(active);\n });\n this.#activeConversations.add(active);\n }\n\n close(): Promise<void> {\n if (!this.#closePromise) {\n this.#closed = true;\n this.#closePromise = this.#closeActiveConversations();\n }\n return this.#closePromise;\n }\n\n async #closeActiveConversations(): Promise<void> {\n const active = [...this.#activeConversations];\n active.forEach(({ abortController, request, response }) => {\n abortController.abort(new Error('The adopter HTTP service is stopping.'));\n request.destroy();\n response.destroy();\n });\n await Promise.allSettled(active.map(({ pending }) => pending));\n }\n\n async #serveConversation(\n request: IncomingMessage,\n response: ServerResponse,\n signal: AbortSignal,\n ): Promise<void> {\n let authorization: string | undefined;\n try {\n authorization = takeAuthorization(request);\n if (request.method !== 'POST') {\n request.resume();\n writeJsonError(response, 405, 'Method not allowed.');\n return;\n }\n } catch (error) {\n request.resume();\n writeJsonError(\n response,\n error instanceof NodeHttpRequestError ? error.statusCode : 400,\n 'Invalid conversation request.',\n );\n return;\n }\n\n let principal: Principal | undefined;\n try {\n principal = await this.#authenticator.authenticate({\n authorization,\n remoteAddress: request.socket.remoteAddress,\n signal,\n });\n } catch (error) {\n this.#report({\n phase: 'authentication',\n errorType: errorType(error),\n streamAccepted: false,\n });\n request.resume();\n writeJsonError(response, 500, 'Authentication could not be completed.');\n return;\n }\n if (!principal) {\n request.resume();\n writeJsonError(response, 401, 'Authentication is required.', {\n 'WWW-Authenticate': 'Bearer',\n });\n return;\n }\n\n let prompt: string;\n try {\n const body = await readJsonBody(request, this.#maxBodyBytes, signal);\n prompt = z.object({\n prompt: z.string().trim().min(1).max(this.#maxPromptCharacters),\n }).strict().parse(body).prompt;\n } catch (error) {\n const statusCode = error instanceof NodeHttpRequestError\n ? error.statusCode\n : 400;\n writeJsonError(response, statusCode, 'Invalid conversation request.');\n return;\n }\n\n let streamed = false;\n try {\n for await (const rawEvent of this.#conversations.streamTurn({\n principal,\n prompt,\n signal,\n })) {\n const event = ExecutionHostStreamEventSchema.parse(rawEvent);\n if (!streamed) {\n writeEventStreamHeaders(response);\n streamed = true;\n }\n await writeSseEvent(response, event, signal);\n }\n if (!streamed) {\n writeJsonError(response, 502, 'Execution Host returned no events.');\n return;\n }\n response.end();\n } catch (error) {\n const publicError = !streamed ? this.#project(error) : undefined;\n if (publicError) {\n writeJsonError(response, publicError.statusCode, publicError.message);\n return;\n }\n if (\n error instanceof ExecutionHostInvocationCancelledError\n || signal.aborted\n ) {\n if (!response.headersSent && !response.destroyed) {\n writeJsonError(response, 499, 'Hosted conversation was cancelled.');\n }\n return;\n }\n this.#report({\n phase: 'conversation',\n errorType: errorType(error),\n streamAccepted: streamed,\n });\n if (!response.headersSent) {\n writeJsonError(response, 502, 'Execution Host conversation failed.');\n } else if (!response.destroyed && !response.writableEnded) {\n // A post-acceptance failure deliberately ends without a terminal event.\n response.end();\n }\n }\n }\n\n #project(error: unknown): NodeExecutionAdopterPublicError | undefined {\n if (!this.#projectError) {\n return undefined;\n }\n try {\n const projected = this.#projectError(error);\n return projected ? PublicErrorSchema.parse(projected) : undefined;\n } catch {\n return undefined;\n }\n }\n\n #report(failure: NodeExecutionAdopterFailure): void {\n try {\n this.#reportFailure?.(Object.freeze({ ...failure }));\n } catch {\n // Observability must not change request settlement.\n }\n }\n}\n\nfunction parsePaths(\n paths: Partial<NodeExecutionAdopterHttpPaths> | undefined,\n): Readonly<NodeExecutionAdopterHttpPaths> {\n const parsed = {\n jwks: NodeHttpPathSchema.parse(paths?.jwks ?? DEFAULT_ADOPTER_JWKS_PATH),\n conversationTurns: NodeHttpPathSchema.parse(\n paths?.conversationTurns ?? DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH,\n ),\n };\n if (parsed.jwks === parsed.conversationTurns) {\n throw new Error('Adopter HTTP paths must be distinct.');\n }\n return Object.freeze(parsed);\n}\n\nfunction writeEventStreamHeaders(response: ServerResponse): void {\n response.writeHead(200, {\n 'Cache-Control': 'no-store',\n 'Content-Type': 'text/event-stream; charset=utf-8',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n 'X-Content-Type-Options': 'nosniff',\n });\n}\n\nasync function writeSseEvent(\n response: ServerResponse,\n event: z.infer<typeof ExecutionHostStreamEventSchema>,\n signal: AbortSignal,\n): Promise<void> {\n const frame = [\n `event: ${event.kind}`,\n `id: ${event.sequence}`,\n `data: ${JSON.stringify(event)}`,\n '',\n '',\n ].join('\\n');\n if (!response.write(frame)) {\n await once(response, 'drain', { signal });\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  export { ExecutionAuthorityKeyFileError, generateEphemeralExecutionAuthorityKeyPair, generateExecutionAuthorityKeyFile, loadExecutionAuthorityKeyPairFromFile, } from './authority-key.js';
2
2
  export { DirectExecutionHostCredentials } from './direct-credentials.js';
3
3
  export type { DirectExecutionHostCredentialEnvironmentNames, } from './direct-credentials.js';
4
- export { DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH, DEFAULT_ADOPTER_JWKS_PATH, NodeExecutionAdopterHttpService, } from './http-service.js';
4
+ export { DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH, DEFAULT_ADOPTER_JWKS_PATH, } from '../adopter/index.js';
5
+ export { NodeExecutionAdopterHttpService, } from './http-service.js';
5
6
  export type { NodeExecutionAdopterAuthenticationInput, NodeExecutionAdopterAuthenticator, NodeExecutionAdopterConversationInput, NodeExecutionAdopterConversationService, NodeExecutionAdopterFailure, NodeExecutionAdopterHttpHandler, NodeExecutionAdopterHttpPaths, NodeExecutionAdopterHttpServiceConfig, NodeExecutionAdopterPublicError, } from './types.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,0CAA0C,EAC1C,iCAAiC,EACjC,qCAAqC,GACtC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AACzE,YAAY,EACV,6CAA6C,GAC9C,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,uCAAuC,EACvC,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,uCAAuC,EACvC,iCAAiC,EACjC,qCAAqC,EACrC,uCAAuC,EACvC,2BAA2B,EAC3B,+BAA+B,EAC/B,6BAA6B,EAC7B,qCAAqC,EACrC,+BAA+B,GAChC,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,0CAA0C,EAC1C,iCAAiC,EACjC,qCAAqC,GACtC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AACzE,YAAY,EACV,6CAA6C,GAC9C,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,uCAAuC,EACvC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,+BAA+B,GAChC,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,uCAAuC,EACvC,iCAAiC,EACjC,qCAAqC,EACrC,uCAAuC,EACvC,2BAA2B,EAC3B,+BAA+B,EAC/B,6BAA6B,EAC7B,qCAAqC,EACrC,+BAA+B,GAChC,MAAM,YAAY,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export { ExecutionAuthorityKeyFileError, generateEphemeralExecutionAuthorityKeyPair, generateExecutionAuthorityKeyFile, loadExecutionAuthorityKeyPairFromFile, } from './authority-key.js';
2
2
  export { DirectExecutionHostCredentials } from './direct-credentials.js';
3
- export { DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH, DEFAULT_ADOPTER_JWKS_PATH, NodeExecutionAdopterHttpService, } from './http-service.js';
3
+ export { DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH, DEFAULT_ADOPTER_JWKS_PATH, } from '../adopter/index.js';
4
+ export { NodeExecutionAdopterHttpService, } from './http-service.js';
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,0CAA0C,EAC1C,iCAAiC,EACjC,qCAAqC,GACtC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AAIzE,OAAO,EACL,uCAAuC,EACvC,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC","sourcesContent":["export {\n ExecutionAuthorityKeyFileError,\n generateEphemeralExecutionAuthorityKeyPair,\n generateExecutionAuthorityKeyFile,\n loadExecutionAuthorityKeyPairFromFile,\n} from './authority-key.js';\nexport { DirectExecutionHostCredentials } from './direct-credentials.js';\nexport type {\n DirectExecutionHostCredentialEnvironmentNames,\n} from './direct-credentials.js';\nexport {\n DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH,\n DEFAULT_ADOPTER_JWKS_PATH,\n NodeExecutionAdopterHttpService,\n} from './http-service.js';\nexport type {\n NodeExecutionAdopterAuthenticationInput,\n NodeExecutionAdopterAuthenticator,\n NodeExecutionAdopterConversationInput,\n NodeExecutionAdopterConversationService,\n NodeExecutionAdopterFailure,\n NodeExecutionAdopterHttpHandler,\n NodeExecutionAdopterHttpPaths,\n NodeExecutionAdopterHttpServiceConfig,\n NodeExecutionAdopterPublicError,\n} from './types.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,0CAA0C,EAC1C,iCAAiC,EACjC,qCAAqC,GACtC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AAIzE,OAAO,EACL,uCAAuC,EACvC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,+BAA+B,GAChC,MAAM,mBAAmB,CAAC","sourcesContent":["export {\n ExecutionAuthorityKeyFileError,\n generateEphemeralExecutionAuthorityKeyPair,\n generateExecutionAuthorityKeyFile,\n loadExecutionAuthorityKeyPairFromFile,\n} from './authority-key.js';\nexport { DirectExecutionHostCredentials } from './direct-credentials.js';\nexport type {\n DirectExecutionHostCredentialEnvironmentNames,\n} from './direct-credentials.js';\nexport {\n DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH,\n DEFAULT_ADOPTER_JWKS_PATH,\n} from '../adopter/index.js';\nexport {\n NodeExecutionAdopterHttpService,\n} from './http-service.js';\nexport type {\n NodeExecutionAdopterAuthenticationInput,\n NodeExecutionAdopterAuthenticator,\n NodeExecutionAdopterConversationInput,\n NodeExecutionAdopterConversationService,\n NodeExecutionAdopterFailure,\n NodeExecutionAdopterHttpHandler,\n NodeExecutionAdopterHttpPaths,\n NodeExecutionAdopterHttpServiceConfig,\n NodeExecutionAdopterPublicError,\n} from './types.js';\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@heddleagent/execution-host-client",
3
- "version": "6.5.0",
4
- "description": "Backend contracts, execution authority, lifecycle services, and clients for compatible Heddle Execution Hosts",
3
+ "version": "6.6.1",
4
+ "description": "Contracts, execution authority, lifecycle services, and adopter clients for compatible Heddle Execution Hosts",
5
5
  "author": "Jay / Fienna Liang <roackb2@gmail.com>",
6
6
  "license": "MIT",
7
7
  "type": "module",
@@ -11,11 +11,6 @@
11
11
  "tag": "latest",
12
12
  "registry": "https://registry.npmjs.org/"
13
13
  },
14
- "repository": {
15
- "type": "git",
16
- "url": "git+https://github.com/roackb2/heddle.git",
17
- "directory": "packages/execution-host-client"
18
- },
19
14
  "homepage": "https://heddleagent.com",
20
15
  "bugs": {
21
16
  "url": "https://github.com/roackb2/heddle/issues"
@@ -38,6 +33,10 @@
38
33
  "types": "./dist/authority/index.d.ts",
39
34
  "import": "./dist/authority/index.js"
40
35
  },
36
+ "./adopter": {
37
+ "types": "./dist/adopter/index.d.ts",
38
+ "import": "./dist/adopter/index.js"
39
+ },
41
40
  "./conversation": {
42
41
  "types": "./dist/conversation/index.d.ts",
43
42
  "import": "./dist/conversation/index.js"
@@ -102,6 +101,16 @@
102
101
  "sdk",
103
102
  "streaming"
104
103
  ],
104
+ "scripts": {
105
+ "build": "yarn clean && yarn contract:verify && tsc -p tsconfig.build.json",
106
+ "clean": "node ../../scripts/clean-dist.mjs execution-host-client",
107
+ "conformance:python-v1": "python3 -m ruff check conformance/reference-adopters/python-v1 && python3 -m ruff format --check conformance/reference-adopters/python-v1 && python3 -m pytest conformance/reference-adopters/python-v1",
108
+ "contract:generate": "tsx scripts/generate-contract-artifacts.ts",
109
+ "contract:verify": "tsx scripts/generate-contract-artifacts.ts --check",
110
+ "example:node-control-plane": "yarn build && tsx examples/node-control-plane.ts",
111
+ "test": "vitest run --config vitest.config.ts",
112
+ "typecheck": "tsc -p tsconfig.test.json --noEmit"
113
+ },
105
114
  "dependencies": {
106
115
  "@aws-sdk/client-bedrock-agentcore": "^3.1107.0",
107
116
  "@modelcontextprotocol/sdk": "^1.29.0",
@@ -110,5 +119,11 @@
110
119
  "eventsource-parser": "^3.1.0",
111
120
  "jose": "^6.2.8",
112
121
  "zod": "^4.3.6"
122
+ },
123
+ "devDependencies": {
124
+ "@types/node": "^22.13.10",
125
+ "tsx": "^4.19.3",
126
+ "typescript": "^5.9.3",
127
+ "vitest": "^4.1.2"
113
128
  }
114
129
  }