@heddleagent/execution-host-client 7.0.0 → 8.0.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 (79) hide show
  1. package/README.md +48 -34
  2. package/dist/cli/hostctl.d.ts +11 -0
  3. package/dist/cli/hostctl.d.ts.map +1 -0
  4. package/dist/cli/hostctl.js +62 -0
  5. package/dist/cli/hostctl.js.map +1 -0
  6. package/dist/contracts/index.d.ts +2 -0
  7. package/dist/contracts/index.d.ts.map +1 -1
  8. package/dist/contracts/index.js +9 -0
  9. package/dist/contracts/index.js.map +1 -1
  10. package/dist/coordinator/contracts.d.ts +148 -5
  11. package/dist/coordinator/contracts.d.ts.map +1 -1
  12. package/dist/coordinator/contracts.js +74 -3
  13. package/dist/coordinator/contracts.js.map +1 -1
  14. package/dist/coordinator/hosted-heartbeat-execution-client.d.ts +30 -0
  15. package/dist/coordinator/hosted-heartbeat-execution-client.d.ts.map +1 -0
  16. package/dist/coordinator/hosted-heartbeat-execution-client.js +240 -0
  17. package/dist/coordinator/hosted-heartbeat-execution-client.js.map +1 -0
  18. package/dist/coordinator/hosted-heartbeat-execution-service.d.ts +14 -0
  19. package/dist/coordinator/hosted-heartbeat-execution-service.d.ts.map +1 -0
  20. package/dist/coordinator/hosted-heartbeat-execution-service.js +100 -0
  21. package/dist/coordinator/hosted-heartbeat-execution-service.js.map +1 -0
  22. package/dist/coordinator/index.d.ts +5 -5
  23. package/dist/coordinator/index.d.ts.map +1 -1
  24. package/dist/coordinator/index.js +3 -3
  25. package/dist/coordinator/index.js.map +1 -1
  26. package/dist/coordinator/node/execution-http-service.d.ts +11 -0
  27. package/dist/coordinator/node/execution-http-service.d.ts.map +1 -0
  28. package/dist/coordinator/node/{delegation-http-service.js → execution-http-service.js} +52 -39
  29. package/dist/coordinator/node/execution-http-service.js.map +1 -0
  30. package/dist/coordinator/node/index.d.ts +2 -2
  31. package/dist/coordinator/node/index.d.ts.map +1 -1
  32. package/dist/coordinator/node/index.js +1 -1
  33. package/dist/coordinator/node/index.js.map +1 -1
  34. package/dist/coordinator/node/types.d.ts +10 -9
  35. package/dist/coordinator/node/types.d.ts.map +1 -1
  36. package/dist/coordinator/node/types.js.map +1 -1
  37. package/dist/coordinator/types.d.ts +51 -13
  38. package/dist/coordinator/types.d.ts.map +1 -1
  39. package/dist/coordinator/types.js.map +1 -1
  40. package/dist/host/schemas.d.ts.map +1 -1
  41. package/dist/host/schemas.js +2 -7
  42. package/dist/host/schemas.js.map +1 -1
  43. package/dist/http-sse/direct-http-execution-host.d.ts.map +1 -1
  44. package/dist/http-sse/direct-http-execution-host.js +6 -5
  45. package/dist/http-sse/direct-http-execution-host.js.map +1 -1
  46. package/dist/http-sse/types.d.ts +2 -0
  47. package/dist/http-sse/types.d.ts.map +1 -1
  48. package/dist/http-sse/types.js.map +1 -1
  49. package/dist/node/authority-key.d.ts.map +1 -1
  50. package/dist/node/authority-key.js +24 -49
  51. package/dist/node/authority-key.js.map +1 -1
  52. package/dist/node/environment-value.d.ts +17 -0
  53. package/dist/node/environment-value.d.ts.map +1 -0
  54. package/dist/node/environment-value.js +78 -0
  55. package/dist/node/environment-value.js.map +1 -0
  56. package/dist/node/index.d.ts +4 -0
  57. package/dist/node/index.d.ts.map +1 -1
  58. package/dist/node/index.js +2 -0
  59. package/dist/node/index.js.map +1 -1
  60. package/dist/node/local-credential-bundle.d.ts +33 -0
  61. package/dist/node/local-credential-bundle.d.ts.map +1 -0
  62. package/dist/node/local-credential-bundle.js +196 -0
  63. package/dist/node/local-credential-bundle.js.map +1 -0
  64. package/dist/node/owner-only-file.d.ts +17 -0
  65. package/dist/node/owner-only-file.d.ts.map +1 -0
  66. package/dist/node/owner-only-file.js +59 -0
  67. package/dist/node/owner-only-file.js.map +1 -0
  68. package/package.json +6 -1
  69. package/dist/coordinator/hosted-heartbeat-delegation-client.d.ts +0 -21
  70. package/dist/coordinator/hosted-heartbeat-delegation-client.d.ts.map +0 -1
  71. package/dist/coordinator/hosted-heartbeat-delegation-client.js +0 -117
  72. package/dist/coordinator/hosted-heartbeat-delegation-client.js.map +0 -1
  73. package/dist/coordinator/hosted-heartbeat-delegation-service.d.ts +0 -15
  74. package/dist/coordinator/hosted-heartbeat-delegation-service.d.ts.map +0 -1
  75. package/dist/coordinator/hosted-heartbeat-delegation-service.js +0 -81
  76. package/dist/coordinator/hosted-heartbeat-delegation-service.js.map +0 -1
  77. package/dist/coordinator/node/delegation-http-service.d.ts +0 -11
  78. package/dist/coordinator/node/delegation-http-service.d.ts.map +0 -1
  79. package/dist/coordinator/node/delegation-http-service.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { AGENTCORE_RUNTIME_SESSION_HEADER, CONVERSATION_TURN_WORKFLOW, EXECUTION_ASSERTION_HEADER, EXECUTION_CONTRACT_VERSION, EXECUTION_HOST_LOCAL_TOKEN_HEADER, ExecutionHostConversationTurnRequestSchema, ExecutionHostHeartbeatStreamEventSchema, ExecutionHostHeartbeatTaskRequestSchema, ExecutionHostModelCredentialSchema, ExecutionHostStreamEventSchema, HEARTBEAT_TASK_WORKFLOW, MCP_CAPABILITY_HEADER, MODEL_CREDENTIAL_HEADER, OpaqueIdSchema, RuntimeSessionIdSchema, TimestampSchema, isExecutionHostHeartbeatTerminalEvent, isExecutionHostTerminalEvent, isSafeWebUrl, } from '../contracts/index.js';
2
+ import { AGENTCORE_RUNTIME_SESSION_HEADER, CONVERSATION_TURN_WORKFLOW, EXECUTION_ASSERTION_HEADER, EXECUTION_CONTRACT_VERSION, EXECUTION_HOST_LOCAL_TOKEN_HEADER, ExecutionHostConversationTurnRequestSchema, ExecutionHostHeartbeatStreamEventSchema, ExecutionHostHeartbeatTaskRequestSchema, ExecutionHostModelCredentialSchema, ExecutionHostStreamEventSchema, HEARTBEAT_TASK_WORKFLOW, MCP_CAPABILITY_HEADER, MODEL_CREDENTIAL_HEADER, OpaqueIdSchema, RuntimeSessionIdSchema, TimestampSchema, isExecutionHostHeartbeatTerminalEvent, isExecutionHostTerminalEvent, isDockerLocalWebUrl, isSafeWebUrl, } from '../contracts/index.js';
3
3
  import { ExecutionHostInvocationCancelledError, ExecutionHostRejectedError, } from './errors.js';
4
4
  import { readExecutionHostEventStream, toExecutionHostTransportError, } from '../internal/execution-host-event-stream.js';
5
5
  import { readBoundedJsonResponse } from '../internal/http-response.js';
@@ -36,7 +36,7 @@ export class DirectHttpExecutionHost {
36
36
  #fetch;
37
37
  #localToken;
38
38
  constructor(config) {
39
- assertSafeBaseUrl(config.baseUrl);
39
+ assertSafeBaseUrl(config.baseUrl, config.allowDockerLocalHost === true);
40
40
  this.#localToken = SecretSchema.parse(config.localToken);
41
41
  this.#endpoint = new URL('invocations', withTrailingSlash(config.baseUrl));
42
42
  this.#fetch = config.fetch ?? globalThis.fetch;
@@ -132,9 +132,10 @@ async function readSafeErrorCode(response) {
132
132
  return 'unknown';
133
133
  }
134
134
  }
135
- function assertSafeBaseUrl(url) {
136
- if (!isSafeWebUrl(url)) {
137
- throw new Error('Direct Execution Host URL must use HTTPS or loopback HTTP and contain no credentials, query, or fragment.');
135
+ function assertSafeBaseUrl(url, allowDockerLocalHost) {
136
+ if (!isSafeWebUrl(url)
137
+ && !(allowDockerLocalHost && isDockerLocalWebUrl(url))) {
138
+ throw new Error('Direct Execution Host URL must use HTTPS or loopback HTTP; Docker local-host HTTP requires an explicit opt-in; URLs must contain no credentials, query, or fragment.');
138
139
  }
139
140
  }
140
141
  function withTrailingSlash(url) {
@@ -1 +1 @@
1
- {"version":3,"file":"direct-http-execution-host.js","sourceRoot":"","sources":["../../src/http-sse/direct-http-execution-host.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport {\n AGENTCORE_RUNTIME_SESSION_HEADER,\n CONVERSATION_TURN_WORKFLOW,\n EXECUTION_ASSERTION_HEADER,\n EXECUTION_CONTRACT_VERSION,\n EXECUTION_HOST_LOCAL_TOKEN_HEADER,\n ExecutionHostConversationTurnRequestSchema,\n ExecutionHostHeartbeatStreamEventSchema,\n ExecutionHostHeartbeatTaskRequestSchema,\n ExecutionHostModelCredentialSchema,\n ExecutionHostStreamEventSchema,\n HEARTBEAT_TASK_WORKFLOW,\n MCP_CAPABILITY_HEADER,\n MODEL_CREDENTIAL_HEADER,\n OpaqueIdSchema,\n RuntimeSessionIdSchema,\n TimestampSchema,\n isExecutionHostHeartbeatTerminalEvent,\n isExecutionHostTerminalEvent,\n isSafeWebUrl,\n type ExecutionHostHeartbeatStreamEvent,\n type ExecutionHostStreamEvent,\n} from '../contracts/index.js';\nimport {\n ExecutionHostInvocationCancelledError,\n ExecutionHostRejectedError,\n} from './errors.js';\nimport type {\n DirectHttpExecutionHostConfig,\n ExecutionHost,\n ExecutionHostConversationTurn,\n ExecutionHostHeartbeatTask,\n HeartbeatExecutionHost,\n} from './types.js';\nimport {\n readExecutionHostEventStream,\n toExecutionHostTransportError,\n} from '../internal/execution-host-event-stream.js';\nimport { readBoundedJsonResponse } from '../internal/http-response.js';\n\nconst MAX_ERROR_BODY_BYTES = 16_384;\nconst SecretSchema = z.string().min(8).max(4_096);\nconst InvocationAuthoritySchema = z.object({\n runtimeSessionId: RuntimeSessionIdSchema,\n executionAssertion: z.string().min(32).max(4_096),\n mcpCapability: z.string().min(32).max(4_096).optional(),\n modelCredential: ExecutionHostModelCredentialSchema,\n signal: z.custom<AbortSignal>(\n (value) => value instanceof AbortSignal,\n 'signal must be an AbortSignal',\n ).optional(),\n}).strict();\nconst ConversationTurnSchema = InvocationAuthoritySchema.extend({\n invocationId: OpaqueIdSchema,\n prompt: z.string().trim().min(1).max(200_000),\n deadlineAt: TimestampSchema.optional(),\n}).strict();\nconst HeartbeatTaskSchema = InvocationAuthoritySchema.extend(\n ExecutionHostHeartbeatTaskRequestSchema.omit({\n schemaVersion: true,\n kind: true,\n }).shape,\n).strict();\nconst ApiErrorSchema = z.object({\n error: z.object({\n code: z.string().min(1).max(128).regex(/^[a-z0-9_]+$/),\n message: z.string(),\n }).strict(),\n}).strict();\n\n/**\n * Strict direct-development HTTP/SSE adapter for the Execution Host v1 wire.\n * It deliberately owns neither AWS SDK nor SigV4 behavior.\n */\nexport class DirectHttpExecutionHost\nimplements ExecutionHost, HeartbeatExecutionHost {\n readonly #endpoint: URL;\n readonly #fetch: typeof fetch;\n readonly #localToken: string;\n\n constructor(config: DirectHttpExecutionHostConfig) {\n assertSafeBaseUrl(config.baseUrl);\n this.#localToken = SecretSchema.parse(config.localToken);\n this.#endpoint = new URL('invocations', withTrailingSlash(config.baseUrl));\n this.#fetch = config.fetch ?? globalThis.fetch;\n }\n\n async *streamConversationTurn(\n rawInput: ExecutionHostConversationTurn,\n ): AsyncIterable<ExecutionHostStreamEvent> {\n const input = ConversationTurnSchema.parse(rawInput);\n if (input.signal?.aborted) {\n throw new ExecutionHostInvocationCancelledError();\n }\n const body = ExecutionHostConversationTurnRequestSchema.parse({\n schemaVersion: EXECUTION_CONTRACT_VERSION,\n kind: CONVERSATION_TURN_WORKFLOW,\n invocationId: input.invocationId,\n prompt: input.prompt,\n ...(input.deadlineAt ? { deadlineAt: input.deadlineAt } : {}),\n });\n yield* this.#streamInvocation(\n input,\n body,\n ExecutionHostStreamEventSchema,\n isExecutionHostTerminalEvent,\n );\n }\n\n async *streamHeartbeatTask(\n rawInput: ExecutionHostHeartbeatTask,\n ): AsyncIterable<ExecutionHostHeartbeatStreamEvent> {\n const input = HeartbeatTaskSchema.parse(rawInput);\n if (input.signal?.aborted) {\n throw new ExecutionHostInvocationCancelledError();\n }\n const body = ExecutionHostHeartbeatTaskRequestSchema.parse({\n schemaVersion: EXECUTION_CONTRACT_VERSION,\n kind: HEARTBEAT_TASK_WORKFLOW,\n invocationId: input.invocationId,\n taskId: input.taskId,\n task: input.task,\n ...(input.checkpoint ? { checkpoint: input.checkpoint } : {}),\n runContext: input.runContext,\n ...(input.model ? { model: input.model } : {}),\n ...(input.reasoningEffort\n ? { reasoningEffort: input.reasoningEffort }\n : {}),\n ...(input.maxSteps !== undefined ? { maxSteps: input.maxSteps } : {}),\n ...(input.searchIgnoreDirs\n ? { searchIgnoreDirs: input.searchIgnoreDirs }\n : {}),\n ...(input.systemContext ? { systemContext: input.systemContext } : {}),\n ...(input.deadlineAt ? { deadlineAt: input.deadlineAt } : {}),\n });\n yield* this.#streamInvocation(\n input,\n body,\n ExecutionHostHeartbeatStreamEventSchema,\n isExecutionHostHeartbeatTerminalEvent,\n );\n }\n\n async *#streamInvocation<TEvent extends ValidatedStreamEvent>(\n input: InvocationInput,\n body: unknown,\n schema: z.ZodType<TEvent>,\n isTerminal: (event: TEvent) => boolean,\n ): AsyncIterable<TEvent> {\n const response = await this.#invoke(input, body);\n if (!response.ok) {\n throw new ExecutionHostRejectedError(\n response.status,\n await readSafeErrorCode(response),\n );\n }\n yield* readExecutionHostEventStream({\n response,\n schema,\n isTerminal,\n invocationId: input.invocationId,\n signal: input.signal,\n });\n }\n\n async #invoke(input: InvocationInput, body: unknown): Promise<Response> {\n try {\n return await this.#fetch(this.#endpoint, {\n method: 'POST',\n redirect: 'error',\n signal: input.signal,\n headers: createSensitiveHeaders(input, this.#localToken),\n body: JSON.stringify(body),\n });\n } catch (error) {\n throw toExecutionHostTransportError(error, input.signal);\n }\n }\n}\n\ntype InvocationInput = {\n invocationId: string;\n runtimeSessionId: string;\n executionAssertion: string;\n mcpCapability?: string;\n modelCredential: z.infer<typeof ExecutionHostModelCredentialSchema>;\n signal?: AbortSignal;\n};\n\ntype ValidatedStreamEvent = {\n kind: string;\n invocationId: string;\n runId: string;\n sequence: number;\n timestamp: string;\n};\n\nfunction createSensitiveHeaders(\n input: InvocationInput,\n localToken: string,\n): Headers {\n const headers = new Headers({\n Accept: 'text/event-stream',\n 'Content-Type': 'application/json',\n [AGENTCORE_RUNTIME_SESSION_HEADER]: input.runtimeSessionId,\n [EXECUTION_HOST_LOCAL_TOKEN_HEADER]: localToken,\n [MODEL_CREDENTIAL_HEADER]: JSON.stringify(input.modelCredential),\n [EXECUTION_ASSERTION_HEADER]: input.executionAssertion,\n });\n if (input.mcpCapability) {\n headers.set(MCP_CAPABILITY_HEADER, input.mcpCapability);\n }\n return headers;\n}\n\nasync function readSafeErrorCode(response: Response): Promise<string> {\n try {\n const parsed = ApiErrorSchema.safeParse(await readBoundedJsonResponse(\n response,\n MAX_ERROR_BODY_BYTES,\n ));\n return parsed.success ? parsed.data.error.code : 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\nfunction assertSafeBaseUrl(url: URL): void {\n if (!isSafeWebUrl(url)) {\n throw new Error(\n 'Direct Execution Host URL must use HTTPS or loopback HTTP and contain no credentials, query, or fragment.',\n );\n }\n}\n\nfunction withTrailingSlash(url: URL): URL {\n const normalized = new URL(url);\n normalized.pathname = normalized.pathname.endsWith('/')\n ? normalized.pathname\n : `${normalized.pathname}/`;\n return normalized;\n}\n"]}
1
+ {"version":3,"file":"direct-http-execution-host.js","sourceRoot":"","sources":["../../src/http-sse/direct-http-execution-host.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport {\n AGENTCORE_RUNTIME_SESSION_HEADER,\n CONVERSATION_TURN_WORKFLOW,\n EXECUTION_ASSERTION_HEADER,\n EXECUTION_CONTRACT_VERSION,\n EXECUTION_HOST_LOCAL_TOKEN_HEADER,\n ExecutionHostConversationTurnRequestSchema,\n ExecutionHostHeartbeatStreamEventSchema,\n ExecutionHostHeartbeatTaskRequestSchema,\n ExecutionHostModelCredentialSchema,\n ExecutionHostStreamEventSchema,\n HEARTBEAT_TASK_WORKFLOW,\n MCP_CAPABILITY_HEADER,\n MODEL_CREDENTIAL_HEADER,\n OpaqueIdSchema,\n RuntimeSessionIdSchema,\n TimestampSchema,\n isExecutionHostHeartbeatTerminalEvent,\n isExecutionHostTerminalEvent,\n isDockerLocalWebUrl,\n isSafeWebUrl,\n type ExecutionHostHeartbeatStreamEvent,\n type ExecutionHostStreamEvent,\n} from '../contracts/index.js';\nimport {\n ExecutionHostInvocationCancelledError,\n ExecutionHostRejectedError,\n} from './errors.js';\nimport type {\n DirectHttpExecutionHostConfig,\n ExecutionHost,\n ExecutionHostConversationTurn,\n ExecutionHostHeartbeatTask,\n HeartbeatExecutionHost,\n} from './types.js';\nimport {\n readExecutionHostEventStream,\n toExecutionHostTransportError,\n} from '../internal/execution-host-event-stream.js';\nimport { readBoundedJsonResponse } from '../internal/http-response.js';\n\nconst MAX_ERROR_BODY_BYTES = 16_384;\nconst SecretSchema = z.string().min(8).max(4_096);\nconst InvocationAuthoritySchema = z.object({\n runtimeSessionId: RuntimeSessionIdSchema,\n executionAssertion: z.string().min(32).max(4_096),\n mcpCapability: z.string().min(32).max(4_096).optional(),\n modelCredential: ExecutionHostModelCredentialSchema,\n signal: z.custom<AbortSignal>(\n (value) => value instanceof AbortSignal,\n 'signal must be an AbortSignal',\n ).optional(),\n}).strict();\nconst ConversationTurnSchema = InvocationAuthoritySchema.extend({\n invocationId: OpaqueIdSchema,\n prompt: z.string().trim().min(1).max(200_000),\n deadlineAt: TimestampSchema.optional(),\n}).strict();\nconst HeartbeatTaskSchema = InvocationAuthoritySchema.extend(\n ExecutionHostHeartbeatTaskRequestSchema.omit({\n schemaVersion: true,\n kind: true,\n }).shape,\n).strict();\nconst ApiErrorSchema = z.object({\n error: z.object({\n code: z.string().min(1).max(128).regex(/^[a-z0-9_]+$/),\n message: z.string(),\n }).strict(),\n}).strict();\n\n/**\n * Strict direct-development HTTP/SSE adapter for the Execution Host v1 wire.\n * It deliberately owns neither AWS SDK nor SigV4 behavior.\n */\nexport class DirectHttpExecutionHost\nimplements ExecutionHost, HeartbeatExecutionHost {\n readonly #endpoint: URL;\n readonly #fetch: typeof fetch;\n readonly #localToken: string;\n\n constructor(config: DirectHttpExecutionHostConfig) {\n assertSafeBaseUrl(config.baseUrl, config.allowDockerLocalHost === true);\n this.#localToken = SecretSchema.parse(config.localToken);\n this.#endpoint = new URL('invocations', withTrailingSlash(config.baseUrl));\n this.#fetch = config.fetch ?? globalThis.fetch;\n }\n\n async *streamConversationTurn(\n rawInput: ExecutionHostConversationTurn,\n ): AsyncIterable<ExecutionHostStreamEvent> {\n const input = ConversationTurnSchema.parse(rawInput);\n if (input.signal?.aborted) {\n throw new ExecutionHostInvocationCancelledError();\n }\n const body = ExecutionHostConversationTurnRequestSchema.parse({\n schemaVersion: EXECUTION_CONTRACT_VERSION,\n kind: CONVERSATION_TURN_WORKFLOW,\n invocationId: input.invocationId,\n prompt: input.prompt,\n ...(input.deadlineAt ? { deadlineAt: input.deadlineAt } : {}),\n });\n yield* this.#streamInvocation(\n input,\n body,\n ExecutionHostStreamEventSchema,\n isExecutionHostTerminalEvent,\n );\n }\n\n async *streamHeartbeatTask(\n rawInput: ExecutionHostHeartbeatTask,\n ): AsyncIterable<ExecutionHostHeartbeatStreamEvent> {\n const input = HeartbeatTaskSchema.parse(rawInput);\n if (input.signal?.aborted) {\n throw new ExecutionHostInvocationCancelledError();\n }\n const body = ExecutionHostHeartbeatTaskRequestSchema.parse({\n schemaVersion: EXECUTION_CONTRACT_VERSION,\n kind: HEARTBEAT_TASK_WORKFLOW,\n invocationId: input.invocationId,\n taskId: input.taskId,\n task: input.task,\n ...(input.checkpoint ? { checkpoint: input.checkpoint } : {}),\n runContext: input.runContext,\n ...(input.model ? { model: input.model } : {}),\n ...(input.reasoningEffort\n ? { reasoningEffort: input.reasoningEffort }\n : {}),\n ...(input.maxSteps !== undefined ? { maxSteps: input.maxSteps } : {}),\n ...(input.searchIgnoreDirs\n ? { searchIgnoreDirs: input.searchIgnoreDirs }\n : {}),\n ...(input.systemContext ? { systemContext: input.systemContext } : {}),\n ...(input.deadlineAt ? { deadlineAt: input.deadlineAt } : {}),\n });\n yield* this.#streamInvocation(\n input,\n body,\n ExecutionHostHeartbeatStreamEventSchema,\n isExecutionHostHeartbeatTerminalEvent,\n );\n }\n\n async *#streamInvocation<TEvent extends ValidatedStreamEvent>(\n input: InvocationInput,\n body: unknown,\n schema: z.ZodType<TEvent>,\n isTerminal: (event: TEvent) => boolean,\n ): AsyncIterable<TEvent> {\n const response = await this.#invoke(input, body);\n if (!response.ok) {\n throw new ExecutionHostRejectedError(\n response.status,\n await readSafeErrorCode(response),\n );\n }\n yield* readExecutionHostEventStream({\n response,\n schema,\n isTerminal,\n invocationId: input.invocationId,\n signal: input.signal,\n });\n }\n\n async #invoke(input: InvocationInput, body: unknown): Promise<Response> {\n try {\n return await this.#fetch(this.#endpoint, {\n method: 'POST',\n redirect: 'error',\n signal: input.signal,\n headers: createSensitiveHeaders(input, this.#localToken),\n body: JSON.stringify(body),\n });\n } catch (error) {\n throw toExecutionHostTransportError(error, input.signal);\n }\n }\n}\n\ntype InvocationInput = {\n invocationId: string;\n runtimeSessionId: string;\n executionAssertion: string;\n mcpCapability?: string;\n modelCredential: z.infer<typeof ExecutionHostModelCredentialSchema>;\n signal?: AbortSignal;\n};\n\ntype ValidatedStreamEvent = {\n kind: string;\n invocationId: string;\n runId: string;\n sequence: number;\n timestamp: string;\n};\n\nfunction createSensitiveHeaders(\n input: InvocationInput,\n localToken: string,\n): Headers {\n const headers = new Headers({\n Accept: 'text/event-stream',\n 'Content-Type': 'application/json',\n [AGENTCORE_RUNTIME_SESSION_HEADER]: input.runtimeSessionId,\n [EXECUTION_HOST_LOCAL_TOKEN_HEADER]: localToken,\n [MODEL_CREDENTIAL_HEADER]: JSON.stringify(input.modelCredential),\n [EXECUTION_ASSERTION_HEADER]: input.executionAssertion,\n });\n if (input.mcpCapability) {\n headers.set(MCP_CAPABILITY_HEADER, input.mcpCapability);\n }\n return headers;\n}\n\nasync function readSafeErrorCode(response: Response): Promise<string> {\n try {\n const parsed = ApiErrorSchema.safeParse(await readBoundedJsonResponse(\n response,\n MAX_ERROR_BODY_BYTES,\n ));\n return parsed.success ? parsed.data.error.code : 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\nfunction assertSafeBaseUrl(url: URL, allowDockerLocalHost: boolean): void {\n if (\n !isSafeWebUrl(url)\n && !(allowDockerLocalHost && isDockerLocalWebUrl(url))\n ) {\n throw new Error(\n 'Direct Execution Host URL must use HTTPS or loopback HTTP; Docker local-host HTTP requires an explicit opt-in; URLs must contain no credentials, query, or fragment.',\n );\n }\n}\n\nfunction withTrailingSlash(url: URL): URL {\n const normalized = new URL(url);\n normalized.pathname = normalized.pathname.endsWith('/')\n ? normalized.pathname\n : `${normalized.pathname}/`;\n return normalized;\n}\n"]}
@@ -25,6 +25,8 @@ export interface HeartbeatExecutionHost {
25
25
  export type DirectHttpExecutionHostConfig = {
26
26
  baseUrl: URL;
27
27
  localToken: string;
28
+ /** Allows only Docker's explicit local-host alias over HTTP. */
29
+ allowDockerLocalHost?: boolean;
28
30
  fetch?: typeof fetch;
29
31
  };
30
32
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/http-sse/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAC5B,iCAAiC,EACjC,iCAAiC,EACjC,wBAAwB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,4BAA4B,CAAC;IAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,sBAAsB,CACpB,KAAK,EAAE,6BAA6B,GACnC,aAAa,CAAC,wBAAwB,CAAC,CAAC;CAC5C;AAED,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,iCAAiC,EACjC,eAAe,GAAG,MAAM,CACzB,GAAG;IACF,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,4BAA4B,CAAC;IAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,mBAAmB,CACjB,KAAK,EAAE,0BAA0B,GAChC,aAAa,CAAC,iCAAiC,CAAC,CAAC;CACrD;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,OAAO,EAAE,GAAG,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/http-sse/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAC5B,iCAAiC,EACjC,iCAAiC,EACjC,wBAAwB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,4BAA4B,CAAC;IAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,sBAAsB,CACpB,KAAK,EAAE,6BAA6B,GACnC,aAAa,CAAC,wBAAwB,CAAC,CAAC;CAC5C;AAED,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,iCAAiC,EACjC,eAAe,GAAG,MAAM,CACzB,GAAG;IACF,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,4BAA4B,CAAC;IAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,mBAAmB,CACjB,KAAK,EAAE,0BAA0B,GAChC,aAAa,CAAC,iCAAiC,CAAC,CAAC;CACrD;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,OAAO,EAAE,GAAG,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/http-sse/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ExecutionHostModelCredential,\n ExecutionHostHeartbeatStreamEvent,\n ExecutionHostHeartbeatTaskRequest,\n ExecutionHostStreamEvent,\n} from '../contracts/index.js';\n\nexport type ExecutionHostConversationTurn = {\n invocationId: string;\n runtimeSessionId: string;\n prompt: string;\n deadlineAt?: string;\n executionAssertion: string;\n mcpCapability?: string;\n modelCredential: ExecutionHostModelCredential;\n signal?: AbortSignal;\n};\n\nexport interface ExecutionHost {\n streamConversationTurn(\n input: ExecutionHostConversationTurn,\n ): AsyncIterable<ExecutionHostStreamEvent>;\n}\n\nexport type ExecutionHostHeartbeatTask = Omit<\n ExecutionHostHeartbeatTaskRequest,\n 'schemaVersion' | 'kind'\n> & {\n runtimeSessionId: string;\n executionAssertion: string;\n mcpCapability?: string;\n modelCredential: ExecutionHostModelCredential;\n signal?: AbortSignal;\n};\n\nexport interface HeartbeatExecutionHost {\n streamHeartbeatTask(\n input: ExecutionHostHeartbeatTask,\n ): AsyncIterable<ExecutionHostHeartbeatStreamEvent>;\n}\n\nexport type DirectHttpExecutionHostConfig = {\n baseUrl: URL;\n localToken: string;\n fetch?: typeof fetch;\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/http-sse/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ExecutionHostModelCredential,\n ExecutionHostHeartbeatStreamEvent,\n ExecutionHostHeartbeatTaskRequest,\n ExecutionHostStreamEvent,\n} from '../contracts/index.js';\n\nexport type ExecutionHostConversationTurn = {\n invocationId: string;\n runtimeSessionId: string;\n prompt: string;\n deadlineAt?: string;\n executionAssertion: string;\n mcpCapability?: string;\n modelCredential: ExecutionHostModelCredential;\n signal?: AbortSignal;\n};\n\nexport interface ExecutionHost {\n streamConversationTurn(\n input: ExecutionHostConversationTurn,\n ): AsyncIterable<ExecutionHostStreamEvent>;\n}\n\nexport type ExecutionHostHeartbeatTask = Omit<\n ExecutionHostHeartbeatTaskRequest,\n 'schemaVersion' | 'kind'\n> & {\n runtimeSessionId: string;\n executionAssertion: string;\n mcpCapability?: string;\n modelCredential: ExecutionHostModelCredential;\n signal?: AbortSignal;\n};\n\nexport interface HeartbeatExecutionHost {\n streamHeartbeatTask(\n input: ExecutionHostHeartbeatTask,\n ): AsyncIterable<ExecutionHostHeartbeatStreamEvent>;\n}\n\nexport type DirectHttpExecutionHostConfig = {\n baseUrl: URL;\n localToken: string;\n /** Allows only Docker's explicit local-host alias over HTTP. */\n allowDockerLocalHost?: boolean;\n fetch?: typeof fetch;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"authority-key.d.ts","sourceRoot":"","sources":["../../src/node/authority-key.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAavE,iFAAiF;AACjF,wBAAsB,0CAA0C,IAAI,OAAO,CACzE,yBAAyB,CAC1B,CAMA;AAED;;;GAGG;AACH,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAsCf;AAED,gFAAgF;AAChF,wBAAsB,qCAAqC,CACzD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,yBAAyB,CAAC,CAoDpC;AAED,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,IAAI,oCAAoC;CAClD"}
1
+ {"version":3,"file":"authority-key.d.ts","sourceRoot":"","sources":["../../src/node/authority-key.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAkBvE,iFAAiF;AACjF,wBAAsB,0CAA0C,IAAI,OAAO,CACzE,yBAAyB,CAC1B,CAEA;AAED;;;GAGG;AACH,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,gFAAgF;AAChF,wBAAsB,qCAAqC,CACzD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,yBAAyB,CAAC,CA8BpC;AAED,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,IAAI,oCAAoC;CAClD"}
@@ -1,9 +1,8 @@
1
- import { constants } from 'node:fs';
2
- import { open, unlink, } from 'node:fs/promises';
3
- import { webcrypto } from 'node:crypto';
1
+ import { exportJWK, generateKeyPair, importJWK, } from 'jose';
4
2
  import { z } from 'zod';
3
+ import { createOwnerOnlyFile, OwnerOnlyFileError, readOwnerOnlyFile, } from './owner-only-file.js';
5
4
  const MAX_PRIVATE_JWK_BYTES = 16 * 1_024;
6
- const ECDSA_P256 = { name: 'ECDSA', namedCurve: 'P-256' };
5
+ const SIGNING_ALGORITHM = 'ES256';
7
6
  const Base64UrlSchema = z.string().min(1).regex(/^[A-Za-z0-9_-]+$/);
8
7
  const PrivateP256JwkSchema = z.object({
9
8
  kty: z.literal('EC'),
@@ -14,74 +13,50 @@ const PrivateP256JwkSchema = z.object({
14
13
  }).passthrough();
15
14
  /** Generates a non-persisted ES256 pair for tests and disposable local demos. */
16
15
  export async function generateEphemeralExecutionAuthorityKeyPair() {
17
- return webcrypto.subtle.generateKey(ECDSA_P256, false, ['sign', 'verify']);
16
+ return generateKeyPair(SIGNING_ALGORITHM);
18
17
  }
19
18
  /**
20
19
  * Creates a new owner-only ES256 private-JWK file for local development.
21
20
  * Existing paths are never overwritten.
22
21
  */
23
22
  export async function generateExecutionAuthorityKeyFile(filePath) {
24
- const keyPair = await webcrypto.subtle.generateKey(ECDSA_P256, true, ['sign', 'verify']);
25
- const jwk = PrivateP256JwkSchema.parse(await webcrypto.subtle.exportKey('jwk', keyPair.privateKey));
26
- const body = `${JSON.stringify({
27
- kty: jwk.kty,
28
- crv: jwk.crv,
29
- x: jwk.x,
30
- y: jwk.y,
31
- d: jwk.d,
32
- })}\n`;
33
- let file;
34
- let created = false;
35
23
  try {
36
- file = await open(filePath, 'wx', 0o600);
37
- created = true;
38
- await file.writeFile(body, 'utf8');
39
- await file.sync();
40
- await file.close();
41
- file = undefined;
24
+ const { privateKey } = await generateKeyPair(SIGNING_ALGORITHM, {
25
+ extractable: true,
26
+ });
27
+ const jwk = PrivateP256JwkSchema.parse(await exportJWK(privateKey));
28
+ await createOwnerOnlyFile(filePath, `${JSON.stringify({
29
+ kty: jwk.kty,
30
+ crv: jwk.crv,
31
+ x: jwk.x,
32
+ y: jwk.y,
33
+ d: jwk.d,
34
+ })}\n`);
42
35
  }
43
36
  catch {
44
- if (created) {
45
- await file?.close().catch(() => undefined);
46
- file = undefined;
47
- await unlink(filePath).catch(() => undefined);
48
- }
49
37
  throw new ExecutionAuthorityKeyFileError('Execution authority signing JWK could not be generated at the requested path.');
50
38
  }
51
- finally {
52
- await file?.close().catch(() => undefined);
53
- }
54
39
  }
55
40
  /** Loads a non-exportable ES256 signing pair from an owner-only private JWK. */
56
41
  export async function loadExecutionAuthorityKeyPairFromFile(filePath) {
57
- let file;
58
42
  try {
59
- file = await open(filePath, constants.O_RDONLY | constants.O_NOFOLLOW);
60
- const metadata = await file.stat();
61
- if (!metadata.isFile()
62
- || metadata.size <= 0
63
- || metadata.size > MAX_PRIVATE_JWK_BYTES) {
64
- throw new ExecutionAuthorityKeyFileError('Execution authority signing JWK must be a small regular file.');
65
- }
66
- if (process.platform !== 'win32' && (metadata.mode & 0o077) !== 0) {
67
- throw new ExecutionAuthorityKeyFileError('Execution authority signing JWK must not be group- or world-accessible.');
68
- }
69
- const jwk = PrivateP256JwkSchema.parse(JSON.parse(await file.readFile('utf8')));
70
- const privateKey = await webcrypto.subtle.importKey('jwk', { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y, d: jwk.d }, ECDSA_P256, false, ['sign']);
71
- const publicKey = await webcrypto.subtle.importKey('jwk', { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y }, ECDSA_P256, true, ['verify']);
72
- await file.close();
73
- file = undefined;
43
+ const jwk = PrivateP256JwkSchema.parse(JSON.parse(await readOwnerOnlyFile(filePath, {
44
+ description: 'Execution authority signing JWK',
45
+ maxBytes: MAX_PRIVATE_JWK_BYTES,
46
+ })));
47
+ const privateKey = await importJWK({ kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y, d: jwk.d }, SIGNING_ALGORITHM, { extractable: false });
48
+ const publicKey = await importJWK({ kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y }, SIGNING_ALGORITHM, { extractable: true });
74
49
  return { privateKey, publicKey };
75
50
  }
76
51
  catch (error) {
77
52
  if (error instanceof ExecutionAuthorityKeyFileError) {
78
53
  throw error;
79
54
  }
55
+ if (error instanceof OwnerOnlyFileError) {
56
+ throw new ExecutionAuthorityKeyFileError(error.message);
57
+ }
80
58
  throw new ExecutionAuthorityKeyFileError('Execution authority signing JWK could not be loaded.');
81
59
  }
82
- finally {
83
- await file?.close().catch(() => undefined);
84
- }
85
60
  }
86
61
  export class ExecutionAuthorityKeyFileError extends Error {
87
62
  name = 'ExecutionAuthorityKeyFileError';
@@ -1 +1 @@
1
- {"version":3,"file":"authority-key.js","sourceRoot":"","sources":["../../src/node/authority-key.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from 'node:fs';\nimport {\n open,\n unlink,\n type FileHandle,\n} from 'node:fs/promises';\nimport { webcrypto } from 'node:crypto';\nimport { z } from 'zod';\nimport type { ExecutionAuthorityKeyPair } from '../authority/index.js';\n\nconst MAX_PRIVATE_JWK_BYTES = 16 * 1_024;\nconst ECDSA_P256 = { name: 'ECDSA', namedCurve: 'P-256' } as const;\nconst Base64UrlSchema = z.string().min(1).regex(/^[A-Za-z0-9_-]+$/);\nconst PrivateP256JwkSchema = z.object({\n kty: z.literal('EC'),\n crv: z.literal('P-256'),\n x: Base64UrlSchema,\n y: Base64UrlSchema,\n d: Base64UrlSchema,\n}).passthrough();\n\n/** Generates a non-persisted ES256 pair for tests and disposable local demos. */\nexport async function generateEphemeralExecutionAuthorityKeyPair(): Promise<\n ExecutionAuthorityKeyPair\n> {\n return webcrypto.subtle.generateKey(\n ECDSA_P256,\n false,\n ['sign', 'verify'],\n );\n}\n\n/**\n * Creates a new owner-only ES256 private-JWK file for local development.\n * Existing paths are never overwritten.\n */\nexport async function generateExecutionAuthorityKeyFile(\n filePath: string,\n): Promise<void> {\n const keyPair = await webcrypto.subtle.generateKey(\n ECDSA_P256,\n true,\n ['sign', 'verify'],\n );\n const jwk = PrivateP256JwkSchema.parse(\n await webcrypto.subtle.exportKey('jwk', keyPair.privateKey),\n );\n const body = `${JSON.stringify({\n kty: jwk.kty,\n crv: jwk.crv,\n x: jwk.x,\n y: jwk.y,\n d: jwk.d,\n })}\\n`;\n\n let file: FileHandle | undefined;\n let created = false;\n try {\n file = await open(filePath, 'wx', 0o600);\n created = true;\n await file.writeFile(body, 'utf8');\n await file.sync();\n await file.close();\n file = undefined;\n } catch {\n if (created) {\n await file?.close().catch(() => undefined);\n file = undefined;\n await unlink(filePath).catch(() => undefined);\n }\n throw new ExecutionAuthorityKeyFileError(\n 'Execution authority signing JWK could not be generated at the requested path.',\n );\n } finally {\n await file?.close().catch(() => undefined);\n }\n}\n\n/** Loads a non-exportable ES256 signing pair from an owner-only private JWK. */\nexport async function loadExecutionAuthorityKeyPairFromFile(\n filePath: string,\n): Promise<ExecutionAuthorityKeyPair> {\n let file: FileHandle | undefined;\n try {\n file = await open(\n filePath,\n constants.O_RDONLY | constants.O_NOFOLLOW,\n );\n const metadata = await file.stat();\n if (\n !metadata.isFile()\n || metadata.size <= 0\n || metadata.size > MAX_PRIVATE_JWK_BYTES\n ) {\n throw new ExecutionAuthorityKeyFileError(\n 'Execution authority signing JWK must be a small regular file.',\n );\n }\n if (process.platform !== 'win32' && (metadata.mode & 0o077) !== 0) {\n throw new ExecutionAuthorityKeyFileError(\n 'Execution authority signing JWK must not be group- or world-accessible.',\n );\n }\n const jwk = PrivateP256JwkSchema.parse(\n JSON.parse(await file.readFile('utf8')) as unknown,\n );\n const privateKey = await webcrypto.subtle.importKey(\n 'jwk',\n { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y, d: jwk.d },\n ECDSA_P256,\n false,\n ['sign'],\n );\n const publicKey = await webcrypto.subtle.importKey(\n 'jwk',\n { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y },\n ECDSA_P256,\n true,\n ['verify'],\n );\n await file.close();\n file = undefined;\n return { privateKey, publicKey };\n } catch (error) {\n if (error instanceof ExecutionAuthorityKeyFileError) {\n throw error;\n }\n throw new ExecutionAuthorityKeyFileError(\n 'Execution authority signing JWK could not be loaded.',\n );\n } finally {\n await file?.close().catch(() => undefined);\n }\n}\n\nexport class ExecutionAuthorityKeyFileError extends Error {\n readonly name = 'ExecutionAuthorityKeyFileError';\n}\n"]}
1
+ {"version":3,"file":"authority-key.js","sourceRoot":"","sources":["../../src/node/authority-key.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n exportJWK,\n generateKeyPair,\n importJWK,\n} from 'jose';\nimport { z } from 'zod';\nimport type { ExecutionAuthorityKeyPair } from '../authority/index.js';\nimport {\n createOwnerOnlyFile,\n OwnerOnlyFileError,\n readOwnerOnlyFile,\n} from './owner-only-file.js';\n\nconst MAX_PRIVATE_JWK_BYTES = 16 * 1_024;\nconst SIGNING_ALGORITHM = 'ES256';\nconst Base64UrlSchema = z.string().min(1).regex(/^[A-Za-z0-9_-]+$/);\nconst PrivateP256JwkSchema = z.object({\n kty: z.literal('EC'),\n crv: z.literal('P-256'),\n x: Base64UrlSchema,\n y: Base64UrlSchema,\n d: Base64UrlSchema,\n}).passthrough();\n\n/** Generates a non-persisted ES256 pair for tests and disposable local demos. */\nexport async function generateEphemeralExecutionAuthorityKeyPair(): Promise<\n ExecutionAuthorityKeyPair\n> {\n return generateKeyPair(SIGNING_ALGORITHM);\n}\n\n/**\n * Creates a new owner-only ES256 private-JWK file for local development.\n * Existing paths are never overwritten.\n */\nexport async function generateExecutionAuthorityKeyFile(\n filePath: string,\n): Promise<void> {\n try {\n const { privateKey } = await generateKeyPair(SIGNING_ALGORITHM, {\n extractable: true,\n });\n const jwk = PrivateP256JwkSchema.parse(await exportJWK(privateKey));\n await createOwnerOnlyFile(filePath, `${JSON.stringify({\n kty: jwk.kty,\n crv: jwk.crv,\n x: jwk.x,\n y: jwk.y,\n d: jwk.d,\n })}\\n`);\n } catch {\n throw new ExecutionAuthorityKeyFileError(\n 'Execution authority signing JWK could not be generated at the requested path.',\n );\n }\n}\n\n/** Loads a non-exportable ES256 signing pair from an owner-only private JWK. */\nexport async function loadExecutionAuthorityKeyPairFromFile(\n filePath: string,\n): Promise<ExecutionAuthorityKeyPair> {\n try {\n const jwk = PrivateP256JwkSchema.parse(\n JSON.parse(await readOwnerOnlyFile(filePath, {\n description: 'Execution authority signing JWK',\n maxBytes: MAX_PRIVATE_JWK_BYTES,\n })) as unknown,\n );\n const privateKey = await importJWK(\n { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y, d: jwk.d },\n SIGNING_ALGORITHM,\n { extractable: false },\n );\n const publicKey = await importJWK(\n { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y },\n SIGNING_ALGORITHM,\n { extractable: true },\n );\n return { privateKey, publicKey };\n } catch (error) {\n if (error instanceof ExecutionAuthorityKeyFileError) {\n throw error;\n }\n if (error instanceof OwnerOnlyFileError) {\n throw new ExecutionAuthorityKeyFileError(error.message);\n }\n throw new ExecutionAuthorityKeyFileError(\n 'Execution authority signing JWK could not be loaded.',\n );\n }\n}\n\nexport class ExecutionAuthorityKeyFileError extends Error {\n readonly name = 'ExecutionAuthorityKeyFileError';\n}\n"]}
@@ -0,0 +1,17 @@
1
+ export type EnvironmentFileValueOptions = {
2
+ maxFileBytes?: number;
3
+ };
4
+ /**
5
+ * Takes one deployment value from either `NAME` or the conventional
6
+ * `NAME_FILE` indirection. Both source variables are removed before parsing.
7
+ */
8
+ export declare function takeEnvironmentValueOrFile(environment: NodeJS.ProcessEnv, name: string, options?: EnvironmentFileValueOptions): string | undefined;
9
+ /**
10
+ * Atomically takes a set of deployment values from `NAME` / `NAME_FILE`
11
+ * sources. Every source is removed even when one value is invalid.
12
+ */
13
+ export declare function takeEnvironmentValuesOrFiles(environment: NodeJS.ProcessEnv, rawNames: readonly string[], options?: EnvironmentFileValueOptions): Readonly<Record<string, string | undefined>>;
14
+ export declare class EnvironmentFileValueError extends Error {
15
+ readonly name = "EnvironmentFileValueError";
16
+ }
17
+ //# sourceMappingURL=environment-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment-value.d.ts","sourceRoot":"","sources":["../../src/node/environment-value.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,2BAA2B,GAAG;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAQF;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,CAAC,UAAU,EAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,2BAAgC,GACxC,MAAM,GAAG,SAAS,CAEpB;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,CAAC,UAAU,EAC9B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,OAAO,GAAE,2BAAgC,GACxC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAoB9C;AAqDD,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,+BAA+B;CAC7C"}
@@ -0,0 +1,78 @@
1
+ import { closeSync, fstatSync, openSync, readFileSync, } from 'node:fs';
2
+ import { z } from 'zod';
3
+ import { removeOneTrailingLineEnding } from './owner-only-file.js';
4
+ const DEFAULT_MAX_FILE_BYTES = 16 * 1_024;
5
+ const EnvironmentNameSchema = z.string().min(1).max(128).regex(/^[A-Za-z_][A-Za-z0-9_]*$/, 'must be an environment variable name');
6
+ const EnvironmentNamesSchema = z.array(EnvironmentNameSchema).min(1)
7
+ .refine((names) => new Set(names).size === names.length, 'must contain unique environment variable names');
8
+ /**
9
+ * Takes one deployment value from either `NAME` or the conventional
10
+ * `NAME_FILE` indirection. Both source variables are removed before parsing.
11
+ */
12
+ export function takeEnvironmentValueOrFile(environment, name, options = {}) {
13
+ return takeEnvironmentValuesOrFiles(environment, [name], options)[name];
14
+ }
15
+ /**
16
+ * Atomically takes a set of deployment values from `NAME` / `NAME_FILE`
17
+ * sources. Every source is removed even when one value is invalid.
18
+ */
19
+ export function takeEnvironmentValuesOrFiles(environment, rawNames, options = {}) {
20
+ const names = EnvironmentNamesSchema.parse(rawNames);
21
+ const maxFileBytes = z.number().int().min(1).max(1024 * 1_024)
22
+ .default(DEFAULT_MAX_FILE_BYTES)
23
+ .parse(options.maxFileBytes);
24
+ const sources = names.map((name) => ({
25
+ name,
26
+ directValue: environment[name],
27
+ filePath: environment[`${name}_FILE`],
28
+ }));
29
+ sources.forEach(({ name }) => {
30
+ delete environment[name];
31
+ delete environment[`${name}_FILE`];
32
+ });
33
+ return Object.freeze(Object.fromEntries(sources.map((source) => [
34
+ source.name,
35
+ readEnvironmentValueSource(source, maxFileBytes),
36
+ ])));
37
+ }
38
+ function readEnvironmentValueSource(source, maxFileBytes) {
39
+ if (source.directValue !== undefined && source.filePath !== undefined) {
40
+ throw new EnvironmentFileValueError(`${source.name} and ${source.name}_FILE are mutually exclusive.`);
41
+ }
42
+ if (source.directValue !== undefined) {
43
+ return source.directValue;
44
+ }
45
+ if (source.filePath === undefined) {
46
+ return undefined;
47
+ }
48
+ const filePath = source.filePath.trim();
49
+ if (!filePath) {
50
+ throw new EnvironmentFileValueError(`${source.name}_FILE must name a readable regular file.`);
51
+ }
52
+ let descriptor;
53
+ try {
54
+ descriptor = openSync(filePath, 'r');
55
+ const metadata = fstatSync(descriptor);
56
+ if (!metadata.isFile()
57
+ || metadata.size <= 0
58
+ || metadata.size > maxFileBytes) {
59
+ throw new EnvironmentFileValueError(`${source.name}_FILE must name a non-empty regular file no larger than ${maxFileBytes} bytes.`);
60
+ }
61
+ return removeOneTrailingLineEnding(readFileSync(descriptor, 'utf8'));
62
+ }
63
+ catch (error) {
64
+ if (error instanceof EnvironmentFileValueError) {
65
+ throw error;
66
+ }
67
+ throw new EnvironmentFileValueError(`${source.name}_FILE could not be read.`);
68
+ }
69
+ finally {
70
+ if (descriptor !== undefined) {
71
+ closeSync(descriptor);
72
+ }
73
+ }
74
+ }
75
+ export class EnvironmentFileValueError extends Error {
76
+ name = 'EnvironmentFileValueError';
77
+ }
78
+ //# sourceMappingURL=environment-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment-value.js","sourceRoot":"","sources":["../../src/node/environment-value.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n closeSync,\n fstatSync,\n openSync,\n readFileSync,\n} from 'node:fs';\nimport { z } from 'zod';\nimport { removeOneTrailingLineEnding } from './owner-only-file.js';\n\nconst DEFAULT_MAX_FILE_BYTES = 16 * 1_024;\nconst EnvironmentNameSchema = z.string().min(1).max(128).regex(\n /^[A-Za-z_][A-Za-z0-9_]*$/,\n 'must be an environment variable name',\n);\nconst EnvironmentNamesSchema = z.array(EnvironmentNameSchema).min(1)\n .refine(\n (names) => new Set(names).size === names.length,\n 'must contain unique environment variable names',\n );\n\nexport type EnvironmentFileValueOptions = {\n maxFileBytes?: number;\n};\n\ntype EnvironmentValueSource = {\n name: string;\n directValue: string | undefined;\n filePath: string | undefined;\n};\n\n/**\n * Takes one deployment value from either `NAME` or the conventional\n * `NAME_FILE` indirection. Both source variables are removed before parsing.\n */\nexport function takeEnvironmentValueOrFile(\n environment: NodeJS.ProcessEnv,\n name: string,\n options: EnvironmentFileValueOptions = {},\n): string | undefined {\n return takeEnvironmentValuesOrFiles(environment, [name], options)[name];\n}\n\n/**\n * Atomically takes a set of deployment values from `NAME` / `NAME_FILE`\n * sources. Every source is removed even when one value is invalid.\n */\nexport function takeEnvironmentValuesOrFiles(\n environment: NodeJS.ProcessEnv,\n rawNames: readonly string[],\n options: EnvironmentFileValueOptions = {},\n): Readonly<Record<string, string | undefined>> {\n const names = EnvironmentNamesSchema.parse(rawNames);\n const maxFileBytes = z.number().int().min(1).max(1024 * 1_024)\n .default(DEFAULT_MAX_FILE_BYTES)\n .parse(options.maxFileBytes);\n const sources = names.map((name): EnvironmentValueSource => ({\n name,\n directValue: environment[name],\n filePath: environment[`${name}_FILE`],\n }));\n\n sources.forEach(({ name }) => {\n delete environment[name];\n delete environment[`${name}_FILE`];\n });\n\n return Object.freeze(Object.fromEntries(sources.map((source) => [\n source.name,\n readEnvironmentValueSource(source, maxFileBytes),\n ])));\n}\n\nfunction readEnvironmentValueSource(\n source: EnvironmentValueSource,\n maxFileBytes: number,\n): string | undefined {\n if (source.directValue !== undefined && source.filePath !== undefined) {\n throw new EnvironmentFileValueError(\n `${source.name} and ${source.name}_FILE are mutually exclusive.`,\n );\n }\n if (source.directValue !== undefined) {\n return source.directValue;\n }\n if (source.filePath === undefined) {\n return undefined;\n }\n\n const filePath = source.filePath.trim();\n if (!filePath) {\n throw new EnvironmentFileValueError(\n `${source.name}_FILE must name a readable regular file.`,\n );\n }\n\n let descriptor: number | undefined;\n try {\n descriptor = openSync(filePath, 'r');\n const metadata = fstatSync(descriptor);\n if (\n !metadata.isFile()\n || metadata.size <= 0\n || metadata.size > maxFileBytes\n ) {\n throw new EnvironmentFileValueError(\n `${source.name}_FILE must name a non-empty regular file no larger than ${maxFileBytes} bytes.`,\n );\n }\n return removeOneTrailingLineEnding(readFileSync(descriptor, 'utf8'));\n } catch (error) {\n if (error instanceof EnvironmentFileValueError) {\n throw error;\n }\n throw new EnvironmentFileValueError(\n `${source.name}_FILE could not be read.`,\n );\n } finally {\n if (descriptor !== undefined) {\n closeSync(descriptor);\n }\n }\n}\n\nexport class EnvironmentFileValueError extends Error {\n readonly name = 'EnvironmentFileValueError';\n}\n"]}
@@ -1,4 +1,8 @@
1
1
  export { ExecutionAuthorityKeyFileError, generateEphemeralExecutionAuthorityKeyPair, generateExecutionAuthorityKeyFile, loadExecutionAuthorityKeyPairFromFile, } from './authority-key.js';
2
+ export { EnvironmentFileValueError, takeEnvironmentValueOrFile, takeEnvironmentValuesOrFiles, } from './environment-value.js';
3
+ export type { EnvironmentFileValueOptions } from './environment-value.js';
4
+ export { initializeLocalCredentialBundle, LOCAL_CREDENTIAL_BUNDLE_FILES, LocalCredentialBundleError, validateLocalCredentialBundle, } from './local-credential-bundle.js';
5
+ export type { LocalCredentialBundleInitialization, LocalCredentialBundlePaths, } from './local-credential-bundle.js';
2
6
  export { DirectExecutionHostCredentials } from './direct-credentials.js';
3
7
  export type { DirectExecutionHostCredentialEnvironmentNames, } from './direct-credentials.js';
4
8
  export { DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH, DEFAULT_ADOPTER_JWKS_PATH, } from '../adopter/index.js';
@@ -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,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
+ {"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,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,mCAAmC,EACnC,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC;AACtC,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,6 @@
1
1
  export { ExecutionAuthorityKeyFileError, generateEphemeralExecutionAuthorityKeyPair, generateExecutionAuthorityKeyFile, loadExecutionAuthorityKeyPairFromFile, } from './authority-key.js';
2
+ export { EnvironmentFileValueError, takeEnvironmentValueOrFile, takeEnvironmentValuesOrFiles, } from './environment-value.js';
3
+ export { initializeLocalCredentialBundle, LOCAL_CREDENTIAL_BUNDLE_FILES, LocalCredentialBundleError, validateLocalCredentialBundle, } from './local-credential-bundle.js';
2
4
  export { DirectExecutionHostCredentials } from './direct-credentials.js';
3
5
  export { DEFAULT_ADOPTER_CONVERSATION_TURNS_PATH, DEFAULT_ADOPTER_JWKS_PATH, } from '../adopter/index.js';
4
6
  export { NodeExecutionAdopterHttpService, } from './http-service.js';
@@ -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,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"]}
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,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,8BAA8B,CAAC;AAKtC,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 {\n EnvironmentFileValueError,\n takeEnvironmentValueOrFile,\n takeEnvironmentValuesOrFiles,\n} from './environment-value.js';\nexport type { EnvironmentFileValueOptions } from './environment-value.js';\nexport {\n initializeLocalCredentialBundle,\n LOCAL_CREDENTIAL_BUNDLE_FILES,\n LocalCredentialBundleError,\n validateLocalCredentialBundle,\n} from './local-credential-bundle.js';\nexport type {\n LocalCredentialBundleInitialization,\n LocalCredentialBundlePaths,\n} from './local-credential-bundle.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"]}
@@ -0,0 +1,33 @@
1
+ export declare const LOCAL_CREDENTIAL_BUNDLE_FILES: Readonly<{
2
+ readonly executionHostLocalToken: "execution-host-local-token";
3
+ readonly executionHostLocalTokenSha256: "execution-host-local-token.sha256";
4
+ readonly coordinatorApiToken: "coordinator-api-token";
5
+ readonly coordinatorProductExecutionToken: "coordinator-product-execution-token";
6
+ readonly executionAuthorityPrivateJwk: "execution-authority-private.jwk";
7
+ readonly manifest: "manifest.json";
8
+ }>;
9
+ export type LocalCredentialBundlePaths = {
10
+ directory: string;
11
+ manifest: string;
12
+ executionHostLocalToken: string;
13
+ executionHostLocalTokenSha256: string;
14
+ coordinatorApiToken: string;
15
+ coordinatorProductExecutionToken: string;
16
+ executionAuthorityPrivateJwk: string;
17
+ };
18
+ export type LocalCredentialBundleInitialization = {
19
+ created: boolean;
20
+ paths: LocalCredentialBundlePaths;
21
+ };
22
+ /**
23
+ * Creates one versioned, owner-only credential bundle for local hosted-service
24
+ * composition. A valid existing bundle is returned unchanged; partial or
25
+ * unmanaged directories fail closed.
26
+ */
27
+ export declare function initializeLocalCredentialBundle(rawOutputDirectory: string): Promise<LocalCredentialBundleInitialization>;
28
+ /** Validates one generated bundle without returning any credential value. */
29
+ export declare function validateLocalCredentialBundle(rawDirectory: string): Promise<LocalCredentialBundlePaths>;
30
+ export declare class LocalCredentialBundleError extends Error {
31
+ readonly name = "LocalCredentialBundleError";
32
+ }
33
+ //# sourceMappingURL=local-credential-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-credential-bundle.d.ts","sourceRoot":"","sources":["../../src/node/local-credential-bundle.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,6BAA6B;;;;;;;EAO/B,CAAC;AA0BZ,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB,EAAE,MAAM,CAAC;IAChC,6BAA6B,EAAE,MAAM,CAAC;IACtC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gCAAgC,EAAE,MAAM,CAAC;IACzC,4BAA4B,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,0BAA0B,CAAC;CACnC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,+BAA+B,CACnD,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,mCAAmC,CAAC,CA2C9C;AAED,6EAA6E;AAC7E,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,0BAA0B,CAAC,CA4CrC;AAiID,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,gCAAgC;CAC9C"}