@heddleagent/execution-host-client 6.5.0 → 6.6.0
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.
- package/README.md +7 -6
- package/dist/adopter/contracts.d.ts +13 -0
- package/dist/adopter/contracts.d.ts.map +1 -0
- package/dist/adopter/contracts.js +13 -0
- package/dist/adopter/contracts.js.map +1 -0
- package/dist/adopter/hosted-conversation-client.d.ts +20 -0
- package/dist/adopter/hosted-conversation-client.d.ts.map +1 -0
- package/dist/adopter/hosted-conversation-client.js +103 -0
- package/dist/adopter/hosted-conversation-client.js.map +1 -0
- package/dist/adopter/index.d.ts +5 -0
- package/dist/adopter/index.d.ts.map +1 -0
- package/dist/adopter/index.js +3 -0
- package/dist/adopter/index.js.map +1 -0
- package/dist/adopter/types.d.ts +14 -0
- package/dist/adopter/types.d.ts.map +1 -0
- package/dist/adopter/types.js +2 -0
- package/dist/adopter/types.js.map +1 -0
- package/dist/agentcore/agentcore-execution-host.d.ts.map +1 -1
- package/dist/agentcore/agentcore-execution-host.js +7 -4
- package/dist/agentcore/agentcore-execution-host.js.map +1 -1
- package/dist/agentcore/index.d.ts +2 -0
- package/dist/agentcore/index.d.ts.map +1 -1
- package/dist/agentcore/index.js +1 -0
- package/dist/agentcore/index.js.map +1 -1
- package/dist/agentcore/schemas.d.ts +11 -0
- package/dist/agentcore/schemas.d.ts.map +1 -0
- package/dist/agentcore/schemas.js +12 -0
- package/dist/agentcore/schemas.js.map +1 -0
- package/dist/agentcore/types.d.ts +2 -4
- package/dist/agentcore/types.d.ts.map +1 -1
- package/dist/agentcore/types.js.map +1 -1
- package/dist/coordinator/contracts.d.ts +367 -2
- package/dist/coordinator/contracts.d.ts.map +1 -1
- package/dist/coordinator/contracts.js +72 -2
- package/dist/coordinator/contracts.js.map +1 -1
- package/dist/coordinator/hosted-heartbeat-coordinator-client.d.ts +6 -2
- package/dist/coordinator/hosted-heartbeat-coordinator-client.d.ts.map +1 -1
- package/dist/coordinator/hosted-heartbeat-coordinator-client.js +21 -1
- package/dist/coordinator/hosted-heartbeat-coordinator-client.js.map +1 -1
- package/dist/coordinator/index.d.ts +2 -2
- package/dist/coordinator/index.d.ts.map +1 -1
- package/dist/coordinator/index.js +1 -1
- package/dist/coordinator/index.js.map +1 -1
- package/dist/coordinator/types.d.ts +7 -3
- package/dist/coordinator/types.d.ts.map +1 -1
- package/dist/coordinator/types.js.map +1 -1
- package/dist/host/index.d.ts +1 -0
- package/dist/host/index.d.ts.map +1 -1
- package/dist/host/index.js +1 -0
- package/dist/host/index.js.map +1 -1
- package/dist/host/runtime-session/errors.d.ts +21 -0
- package/dist/host/runtime-session/errors.d.ts.map +1 -0
- package/dist/host/runtime-session/errors.js +21 -0
- package/dist/host/runtime-session/errors.js.map +1 -0
- package/dist/host/runtime-session/index.d.ts +9 -0
- package/dist/host/runtime-session/index.d.ts.map +1 -0
- package/dist/host/runtime-session/index.js +5 -0
- package/dist/host/runtime-session/index.js.map +1 -0
- package/dist/host/runtime-session/scope-binding.d.ts +17 -0
- package/dist/host/runtime-session/scope-binding.d.ts.map +1 -0
- package/dist/host/runtime-session/scope-binding.js +37 -0
- package/dist/host/runtime-session/scope-binding.js.map +1 -0
- package/dist/host/runtime-session/service.d.ts +38 -0
- package/dist/host/runtime-session/service.d.ts.map +1 -0
- package/dist/host/runtime-session/service.js +177 -0
- package/dist/host/runtime-session/service.js.map +1 -0
- package/dist/host/runtime-session/status.d.ts +17 -0
- package/dist/host/runtime-session/status.d.ts.map +1 -0
- package/dist/host/runtime-session/status.js +33 -0
- package/dist/host/runtime-session/status.js.map +1 -0
- package/dist/host/runtime-session/types.d.ts +61 -0
- package/dist/host/runtime-session/types.d.ts.map +1 -0
- package/dist/host/runtime-session/types.js +2 -0
- package/dist/host/runtime-session/types.js.map +1 -0
- package/dist/http-sse/direct-http-execution-host.d.ts.map +1 -1
- package/dist/http-sse/direct-http-execution-host.js +10 -177
- package/dist/http-sse/direct-http-execution-host.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/execution-host-event-stream.d.ts +18 -0
- package/dist/internal/execution-host-event-stream.d.ts.map +1 -0
- package/dist/internal/execution-host-event-stream.js +141 -0
- package/dist/internal/execution-host-event-stream.js.map +1 -0
- package/dist/internal/http-response.d.ts +4 -0
- package/dist/internal/http-response.d.ts.map +1 -0
- package/dist/internal/http-response.js +57 -0
- package/dist/internal/http-response.js.map +1 -0
- package/dist/node/http-service.d.ts +0 -2
- package/dist/node/http-service.d.ts.map +1 -1
- package/dist/node/http-service.js +1 -2
- package/dist/node/http-service.js.map +1 -1
- package/dist/node/index.d.ts +2 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +2 -1
- package/dist/node/index.js.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/host/runtime-session/status.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,4BAA4B,GAAG;IACzC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,kFAAkF;AAClF,qBAAa,2BAA2B;IAI1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHhC,OAAO,CAAC,KAAK,CAAiD;IAC9D,OAAO,CAAC,oBAAoB,CAAS;gBAER,GAAG,GAAE,MAAM,IAAuB;IAI/D,aAAa,IAAI,IAAI;IAIrB,QAAQ,IAAI,IAAI;IAIhB,IAAI,IAAI,4BAA4B;IAOpC,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,kBAAkB;CAG3B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Tracks process-local execution status without provider-specific vocabulary. */
|
|
2
|
+
export class RuntimeSessionStatusService {
|
|
3
|
+
now;
|
|
4
|
+
state = 'idle';
|
|
5
|
+
changedAtUnixSeconds;
|
|
6
|
+
constructor(now = () => new Date()) {
|
|
7
|
+
this.now = now;
|
|
8
|
+
this.changedAtUnixSeconds = this.currentUnixSeconds();
|
|
9
|
+
}
|
|
10
|
+
markExecuting() {
|
|
11
|
+
this.transition('executing');
|
|
12
|
+
}
|
|
13
|
+
markIdle() {
|
|
14
|
+
this.transition('idle');
|
|
15
|
+
}
|
|
16
|
+
read() {
|
|
17
|
+
return {
|
|
18
|
+
state: this.state,
|
|
19
|
+
changedAtUnixSeconds: this.changedAtUnixSeconds,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
transition(next) {
|
|
23
|
+
if (this.state === next) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.state = next;
|
|
27
|
+
this.changedAtUnixSeconds = this.currentUnixSeconds();
|
|
28
|
+
}
|
|
29
|
+
currentUnixSeconds() {
|
|
30
|
+
return Math.floor(this.now().getTime() / 1_000);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/host/runtime-session/status.ts"],"names":[],"mappings":"AAKA,kFAAkF;AAClF,MAAM,OAAO,2BAA2B;IAIT;IAHrB,KAAK,GAA0C,MAAM,CAAC;IACtD,oBAAoB,CAAS;IAErC,YAA6B,MAAkB,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE;QAAlC,QAAG,GAAH,GAAG,CAA+B;QAC7D,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACxD,CAAC;IAED,aAAa;QACX,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI;QACF,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;SAChD,CAAC;IACJ,CAAC;IAEO,UAAU,CAAC,IAA2C;QAC5D,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACxD,CAAC;IAEO,kBAAkB;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;IAClD,CAAC;CACF","sourcesContent":["export type RuntimeSessionStatusSnapshot = {\n state: 'idle' | 'executing';\n changedAtUnixSeconds: number;\n};\n\n/** Tracks process-local execution status without provider-specific vocabulary. */\nexport class RuntimeSessionStatusService {\n private state: RuntimeSessionStatusSnapshot['state'] = 'idle';\n private changedAtUnixSeconds: number;\n\n constructor(private readonly now: () => Date = () => new Date()) {\n this.changedAtUnixSeconds = this.currentUnixSeconds();\n }\n\n markExecuting(): void {\n this.transition('executing');\n }\n\n markIdle(): void {\n this.transition('idle');\n }\n\n read(): RuntimeSessionStatusSnapshot {\n return {\n state: this.state,\n changedAtUnixSeconds: this.changedAtUnixSeconds,\n };\n }\n\n private transition(next: RuntimeSessionStatusSnapshot['state']): void {\n if (this.state === next) {\n return;\n }\n this.state = next;\n this.changedAtUnixSeconds = this.currentUnixSeconds();\n }\n\n private currentUnixSeconds(): number {\n return Math.floor(this.now().getTime() / 1_000);\n }\n}\n"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ExecutionHostConversationTurnRequest, ExecutionHostHeartbeatTaskRequest, RuntimePublicResult } from '../../contracts/index.js';
|
|
2
|
+
import type { VerifiedExecutionHostMcpCapability } from '../types.js';
|
|
3
|
+
type RuntimeExecutionStreamEnvelope = {
|
|
4
|
+
runId: string;
|
|
5
|
+
sequence: number;
|
|
6
|
+
timestamp: string;
|
|
7
|
+
};
|
|
8
|
+
/** Ordered execution events exposed by any workflow executor. */
|
|
9
|
+
export type RuntimeExecutionStreamItem<Result = unknown> = (RuntimeExecutionStreamEnvelope & {
|
|
10
|
+
kind: 'activity';
|
|
11
|
+
activity: unknown;
|
|
12
|
+
}) | (RuntimeExecutionStreamEnvelope & {
|
|
13
|
+
kind: 'result';
|
|
14
|
+
result: Result;
|
|
15
|
+
}) | (RuntimeExecutionStreamEnvelope & {
|
|
16
|
+
kind: 'cancelled';
|
|
17
|
+
reason: string;
|
|
18
|
+
}) | (RuntimeExecutionStreamEnvelope & {
|
|
19
|
+
kind: 'error';
|
|
20
|
+
error: {
|
|
21
|
+
code: string;
|
|
22
|
+
message: string;
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
export type RuntimeInvocationRequest = ExecutionHostConversationTurnRequest | ExecutionHostHeartbeatTaskRequest;
|
|
26
|
+
export type RuntimeExecutionInput<Request extends RuntimeInvocationRequest = RuntimeInvocationRequest> = {
|
|
27
|
+
scopeKey: string;
|
|
28
|
+
executionSessionId: string;
|
|
29
|
+
request: Request;
|
|
30
|
+
modelApiKey: string;
|
|
31
|
+
mcpCapability?: VerifiedExecutionHostMcpCapability;
|
|
32
|
+
abortSignal: AbortSignal;
|
|
33
|
+
};
|
|
34
|
+
export type RuntimeExecutionHandle<Result = unknown> = {
|
|
35
|
+
runId: string;
|
|
36
|
+
result: Promise<Result>;
|
|
37
|
+
events(options?: {
|
|
38
|
+
signal?: AbortSignal;
|
|
39
|
+
}): AsyncIterable<RuntimeExecutionStreamItem<Result>>;
|
|
40
|
+
cancel(): boolean;
|
|
41
|
+
};
|
|
42
|
+
/** Outbound execution port for one provider-neutral workflow. */
|
|
43
|
+
export type RuntimeWorkflowExecutor<Request extends RuntimeInvocationRequest, Result> = {
|
|
44
|
+
start(input: RuntimeExecutionInput<Request>): Promise<RuntimeExecutionHandle<Result>>;
|
|
45
|
+
};
|
|
46
|
+
export type RuntimeWorkflowExecutors<HeartbeatResult = unknown> = {
|
|
47
|
+
conversationTurn: RuntimeWorkflowExecutor<ExecutionHostConversationTurnRequest, RuntimePublicResult>;
|
|
48
|
+
heartbeatTask: RuntimeWorkflowExecutor<ExecutionHostHeartbeatTaskRequest, HeartbeatResult>;
|
|
49
|
+
};
|
|
50
|
+
export type RuntimeInvocationHandle<Result = unknown> = {
|
|
51
|
+
runId: string;
|
|
52
|
+
acceptedAt: string;
|
|
53
|
+
events(): AsyncIterable<RuntimeExecutionStreamItem<Result>>;
|
|
54
|
+
cancel(): boolean;
|
|
55
|
+
result: Promise<Result>;
|
|
56
|
+
};
|
|
57
|
+
export type RuntimeSessionConfig = {
|
|
58
|
+
maxInvocationMs: number;
|
|
59
|
+
};
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/host/runtime-session/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oCAAoC,EACpC,iCAAiC,EACjC,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,aAAa,CAAC;AAEtE,KAAK,8BAA8B,GAAG;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,iEAAiE;AACjE,MAAM,MAAM,0BAA0B,CAAC,MAAM,GAAG,OAAO,IACnD,CAAC,8BAA8B,GAAG;IAClC,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC,GACA,CAAC,8BAA8B,GAAG;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,GACA,CAAC,8BAA8B,GAAG;IAClC,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,GACA,CAAC,8BAA8B,GAAG;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C,CAAC,CAAC;AAEL,MAAM,MAAM,wBAAwB,GAChC,oCAAoC,GACpC,iCAAiC,CAAC;AAEtC,MAAM,MAAM,qBAAqB,CAC/B,OAAO,SAAS,wBAAwB,GAAG,wBAAwB,IACjE;IACF,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,kCAAkC,CAAC;IACnD,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,MAAM,GAAG,OAAO,IAAI;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,MAAM,CAAC,OAAO,CAAC,EAAE;QACf,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,aAAa,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,MAAM,IAAI,OAAO,CAAC;CACnB,CAAC;AAEF,iEAAiE;AACjE,MAAM,MAAM,uBAAuB,CACjC,OAAO,SAAS,wBAAwB,EACxC,MAAM,IACJ;IACF,KAAK,CACH,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC,GACpC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,wBAAwB,CAAC,eAAe,GAAG,OAAO,IAAI;IAChE,gBAAgB,EAAE,uBAAuB,CACvC,oCAAoC,EACpC,mBAAmB,CACpB,CAAC;IACF,aAAa,EAAE,uBAAuB,CACpC,iCAAiC,EACjC,eAAe,CAChB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,MAAM,GAAG,OAAO,IAAI;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,IAAI,aAAa,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,MAAM,IAAI,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/host/runtime-session/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ExecutionHostConversationTurnRequest,\n ExecutionHostHeartbeatTaskRequest,\n RuntimePublicResult,\n} from '../../contracts/index.js';\nimport type { VerifiedExecutionHostMcpCapability } from '../types.js';\n\ntype RuntimeExecutionStreamEnvelope = {\n runId: string;\n sequence: number;\n timestamp: string;\n};\n\n/** Ordered execution events exposed by any workflow executor. */\nexport type RuntimeExecutionStreamItem<Result = unknown> =\n | (RuntimeExecutionStreamEnvelope & {\n kind: 'activity';\n activity: unknown;\n })\n | (RuntimeExecutionStreamEnvelope & {\n kind: 'result';\n result: Result;\n })\n | (RuntimeExecutionStreamEnvelope & {\n kind: 'cancelled';\n reason: string;\n })\n | (RuntimeExecutionStreamEnvelope & {\n kind: 'error';\n error: { code: string; message: string };\n });\n\nexport type RuntimeInvocationRequest =\n | ExecutionHostConversationTurnRequest\n | ExecutionHostHeartbeatTaskRequest;\n\nexport type RuntimeExecutionInput<\n Request extends RuntimeInvocationRequest = RuntimeInvocationRequest,\n> = {\n scopeKey: string;\n executionSessionId: string;\n request: Request;\n modelApiKey: string;\n mcpCapability?: VerifiedExecutionHostMcpCapability;\n abortSignal: AbortSignal;\n};\n\nexport type RuntimeExecutionHandle<Result = unknown> = {\n runId: string;\n result: Promise<Result>;\n events(options?: {\n signal?: AbortSignal;\n }): AsyncIterable<RuntimeExecutionStreamItem<Result>>;\n cancel(): boolean;\n};\n\n/** Outbound execution port for one provider-neutral workflow. */\nexport type RuntimeWorkflowExecutor<\n Request extends RuntimeInvocationRequest,\n Result,\n> = {\n start(\n input: RuntimeExecutionInput<Request>,\n ): Promise<RuntimeExecutionHandle<Result>>;\n};\n\nexport type RuntimeWorkflowExecutors<HeartbeatResult = unknown> = {\n conversationTurn: RuntimeWorkflowExecutor<\n ExecutionHostConversationTurnRequest,\n RuntimePublicResult\n >;\n heartbeatTask: RuntimeWorkflowExecutor<\n ExecutionHostHeartbeatTaskRequest,\n HeartbeatResult\n >;\n};\n\nexport type RuntimeInvocationHandle<Result = unknown> = {\n runId: string;\n acceptedAt: string;\n events(): AsyncIterable<RuntimeExecutionStreamItem<Result>>;\n cancel(): boolean;\n result: Promise<Result>;\n};\n\nexport type RuntimeSessionConfig = {\n maxInvocationMs: number;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"direct-http-execution-host.d.ts","sourceRoot":"","sources":["../../src/http-sse/direct-http-execution-host.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"direct-http-execution-host.d.ts","sourceRoot":"","sources":["../../src/http-sse/direct-http-execution-host.ts"],"names":[],"mappings":"AACA,OAAO,EAmBL,KAAK,iCAAiC,EACtC,KAAK,wBAAwB,EAC9B,MAAM,uBAAuB,CAAC;AAK/B,OAAO,KAAK,EACV,6BAA6B,EAC7B,aAAa,EACb,6BAA6B,EAC7B,0BAA0B,EAC1B,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAqCpB;;;GAGG;AACH,qBAAa,uBACb,YAAW,aAAa,EAAE,sBAAsB;;gBAKlC,MAAM,EAAE,6BAA6B;IAO1C,sBAAsB,CAC3B,QAAQ,EAAE,6BAA6B,GACtC,aAAa,CAAC,wBAAwB,CAAC;IAoBnC,mBAAmB,CACxB,QAAQ,EAAE,0BAA0B,GACnC,aAAa,CAAC,iCAAiC,CAAC;CAmEpD"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { createParser } from 'eventsource-parser';
|
|
2
1
|
import { z } from 'zod';
|
|
3
2
|
import { AGENTCORE_RUNTIME_SESSION_HEADER, CONVERSATION_TURN_WORKFLOW, EXECUTION_ASSERTION_HEADER, EXECUTION_CONTRACT_VERSION, EXECUTION_HOST_LOCAL_TOKEN_HEADER, ExecutionHostConversationTurnRequestSchema, ExecutionHostHeartbeatStreamEventSchema, ExecutionHostHeartbeatTaskRequestSchema, ExecutionHostStreamEventSchema, HEARTBEAT_TASK_WORKFLOW, MCP_CAPABILITY_HEADER, MODEL_API_KEY_HEADER, OpaqueIdSchema, RuntimeSessionIdSchema, TimestampSchema, isExecutionHostHeartbeatTerminalEvent, isExecutionHostTerminalEvent, isSafeWebUrl, } from '../contracts/index.js';
|
|
4
|
-
import { ExecutionHostInvocationCancelledError,
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { ExecutionHostInvocationCancelledError, ExecutionHostRejectedError, } from './errors.js';
|
|
4
|
+
import { readExecutionHostEventStream, toExecutionHostTransportError, } from '../internal/execution-host-event-stream.js';
|
|
5
|
+
import { readBoundedJsonResponse } from '../internal/http-response.js';
|
|
7
6
|
const MAX_ERROR_BODY_BYTES = 16_384;
|
|
8
7
|
const SecretSchema = z.string().min(8).max(4_096);
|
|
9
8
|
const InvocationAuthoritySchema = z.object({
|
|
@@ -87,82 +86,13 @@ export class DirectHttpExecutionHost {
|
|
|
87
86
|
if (!response.ok) {
|
|
88
87
|
throw new ExecutionHostRejectedError(response.status, await readSafeErrorCode(response));
|
|
89
88
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (!response.body) {
|
|
95
|
-
throw new ExecutionHostProtocolError('Execution Host returned an empty SSE response body.');
|
|
96
|
-
}
|
|
97
|
-
const state = {
|
|
89
|
+
yield* readExecutionHostEventStream({
|
|
90
|
+
response,
|
|
91
|
+
schema,
|
|
92
|
+
isTerminal,
|
|
98
93
|
invocationId: input.invocationId,
|
|
99
|
-
|
|
100
|
-
terminal: false,
|
|
101
|
-
};
|
|
102
|
-
const decoder = new TextDecoder();
|
|
103
|
-
const pending = [];
|
|
104
|
-
let terminalEvent;
|
|
105
|
-
let parserError = false;
|
|
106
|
-
const parser = createParser({
|
|
107
|
-
maxBufferSize: MAX_SSE_BUFFER_CHARACTERS,
|
|
108
|
-
onEvent: (event) => {
|
|
109
|
-
if (pending.length >= MAX_PENDING_SSE_FRAMES) {
|
|
110
|
-
parserError = true;
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
pending.push(event);
|
|
114
|
-
},
|
|
115
|
-
onError: () => {
|
|
116
|
-
parserError = true;
|
|
117
|
-
},
|
|
94
|
+
signal: input.signal,
|
|
118
95
|
});
|
|
119
|
-
try {
|
|
120
|
-
for await (const chunk of response.body) {
|
|
121
|
-
input.signal?.throwIfAborted();
|
|
122
|
-
parser.feed(decoder.decode(chunk, { stream: true }));
|
|
123
|
-
if (parserError) {
|
|
124
|
-
throw new ExecutionHostProtocolError();
|
|
125
|
-
}
|
|
126
|
-
while (pending.length > 0) {
|
|
127
|
-
const event = validateEvent(pending.shift(), state, schema, isTerminal);
|
|
128
|
-
if (isTerminal(event)) {
|
|
129
|
-
terminalEvent = event;
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
yield event;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
parser.feed(decoder.decode());
|
|
137
|
-
parser.reset({ consume: true });
|
|
138
|
-
if (parserError) {
|
|
139
|
-
throw new ExecutionHostProtocolError();
|
|
140
|
-
}
|
|
141
|
-
while (pending.length > 0) {
|
|
142
|
-
const event = validateEvent(pending.shift(), state, schema, isTerminal);
|
|
143
|
-
if (isTerminal(event)) {
|
|
144
|
-
terminalEvent = event;
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
yield event;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
if (error instanceof ExecutionHostProtocolError) {
|
|
153
|
-
throw error;
|
|
154
|
-
}
|
|
155
|
-
throw toTransportError(error, input.signal);
|
|
156
|
-
}
|
|
157
|
-
if (!state.accepted) {
|
|
158
|
-
throw new ExecutionHostProtocolError('Execution Host stream omitted the accepted event.');
|
|
159
|
-
}
|
|
160
|
-
if (!state.terminal || !terminalEvent) {
|
|
161
|
-
throw new ExecutionHostStreamInterruptedError();
|
|
162
|
-
}
|
|
163
|
-
// Terminal is released only after clean EOF, so a trailing malformed or
|
|
164
|
-
// post-terminal frame cannot be projected as success.
|
|
165
|
-
yield terminalEvent;
|
|
166
96
|
}
|
|
167
97
|
async #invoke(input, body) {
|
|
168
98
|
try {
|
|
@@ -175,43 +105,9 @@ export class DirectHttpExecutionHost {
|
|
|
175
105
|
});
|
|
176
106
|
}
|
|
177
107
|
catch (error) {
|
|
178
|
-
throw
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
function validateEvent(frame, state, schema, isTerminal) {
|
|
183
|
-
let decoded;
|
|
184
|
-
try {
|
|
185
|
-
decoded = JSON.parse(frame.data);
|
|
186
|
-
}
|
|
187
|
-
catch {
|
|
188
|
-
throw new ExecutionHostProtocolError();
|
|
189
|
-
}
|
|
190
|
-
const parsed = schema.safeParse(decoded);
|
|
191
|
-
if (!parsed.success) {
|
|
192
|
-
throw new ExecutionHostProtocolError();
|
|
193
|
-
}
|
|
194
|
-
const event = parsed.data;
|
|
195
|
-
const correctFrameMetadata = frame.event === event.kind
|
|
196
|
-
&& frame.id === String(event.sequence);
|
|
197
|
-
const correctEnvelope = event.invocationId === state.invocationId
|
|
198
|
-
&& event.sequence === state.nextSequence;
|
|
199
|
-
if (!correctFrameMetadata || !correctEnvelope || state.terminal) {
|
|
200
|
-
throw new ExecutionHostProtocolError();
|
|
201
|
-
}
|
|
202
|
-
if (!state.accepted) {
|
|
203
|
-
if (event.kind !== 'accepted') {
|
|
204
|
-
throw new ExecutionHostProtocolError();
|
|
108
|
+
throw toExecutionHostTransportError(error, input.signal);
|
|
205
109
|
}
|
|
206
|
-
state.accepted = true;
|
|
207
|
-
state.runId = event.runId;
|
|
208
|
-
}
|
|
209
|
-
else if (event.kind === 'accepted' || event.runId !== state.runId) {
|
|
210
|
-
throw new ExecutionHostProtocolError();
|
|
211
110
|
}
|
|
212
|
-
state.nextSequence += 1;
|
|
213
|
-
state.terminal = isTerminal(event);
|
|
214
|
-
return event;
|
|
215
111
|
}
|
|
216
112
|
function createSensitiveHeaders(input, localToken) {
|
|
217
113
|
const headers = new Headers({
|
|
@@ -227,78 +123,15 @@ function createSensitiveHeaders(input, localToken) {
|
|
|
227
123
|
}
|
|
228
124
|
return headers;
|
|
229
125
|
}
|
|
230
|
-
function isEventStream(contentType) {
|
|
231
|
-
return contentType?.split(';', 1)[0]?.trim().toLowerCase()
|
|
232
|
-
=== 'text/event-stream';
|
|
233
|
-
}
|
|
234
126
|
async function readSafeErrorCode(response) {
|
|
235
127
|
try {
|
|
236
|
-
const
|
|
237
|
-
if (Number.isFinite(declaredLength)
|
|
238
|
-
&& declaredLength > MAX_ERROR_BODY_BYTES) {
|
|
239
|
-
await cancelBody(response);
|
|
240
|
-
return 'unknown';
|
|
241
|
-
}
|
|
242
|
-
const bytes = await readBoundedBody(response, MAX_ERROR_BODY_BYTES);
|
|
243
|
-
if (!bytes) {
|
|
244
|
-
return 'unknown';
|
|
245
|
-
}
|
|
246
|
-
const parsed = ApiErrorSchema.safeParse(JSON.parse(new TextDecoder().decode(bytes)));
|
|
128
|
+
const parsed = ApiErrorSchema.safeParse(await readBoundedJsonResponse(response, MAX_ERROR_BODY_BYTES));
|
|
247
129
|
return parsed.success ? parsed.data.error.code : 'unknown';
|
|
248
130
|
}
|
|
249
131
|
catch {
|
|
250
132
|
return 'unknown';
|
|
251
133
|
}
|
|
252
134
|
}
|
|
253
|
-
async function readBoundedBody(response, maxBytes) {
|
|
254
|
-
if (!response.body) {
|
|
255
|
-
return new Uint8Array();
|
|
256
|
-
}
|
|
257
|
-
const reader = response.body.getReader();
|
|
258
|
-
const chunks = [];
|
|
259
|
-
let totalBytes = 0;
|
|
260
|
-
try {
|
|
261
|
-
while (true) {
|
|
262
|
-
const { done, value } = await reader.read();
|
|
263
|
-
if (done) {
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
totalBytes += value.byteLength;
|
|
267
|
-
if (totalBytes > maxBytes) {
|
|
268
|
-
await reader.cancel();
|
|
269
|
-
return undefined;
|
|
270
|
-
}
|
|
271
|
-
chunks.push(value);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
finally {
|
|
275
|
-
reader.releaseLock();
|
|
276
|
-
}
|
|
277
|
-
const bytes = new Uint8Array(totalBytes);
|
|
278
|
-
let offset = 0;
|
|
279
|
-
for (const chunk of chunks) {
|
|
280
|
-
bytes.set(chunk, offset);
|
|
281
|
-
offset += chunk.byteLength;
|
|
282
|
-
}
|
|
283
|
-
return bytes;
|
|
284
|
-
}
|
|
285
|
-
async function cancelBody(response) {
|
|
286
|
-
try {
|
|
287
|
-
await response.body?.cancel();
|
|
288
|
-
}
|
|
289
|
-
catch {
|
|
290
|
-
// Response cleanup is best effort and must not replace the protocol error.
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
function toTransportError(error, signal) {
|
|
294
|
-
if (signal?.aborted || isAbortError(error)) {
|
|
295
|
-
return new ExecutionHostInvocationCancelledError();
|
|
296
|
-
}
|
|
297
|
-
return new ExecutionHostStreamInterruptedError();
|
|
298
|
-
}
|
|
299
|
-
function isAbortError(error) {
|
|
300
|
-
return error instanceof Error && error.name === 'AbortError';
|
|
301
|
-
}
|
|
302
135
|
function assertSafeBaseUrl(url) {
|
|
303
136
|
if (!isSafeWebUrl(url)) {
|
|
304
137
|
throw new Error('Direct Execution Host URL must use HTTPS or loopback HTTP and contain no credentials, query, or fragment.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"direct-http-execution-host.js","sourceRoot":"","sources":["../../src/http-sse/direct-http-execution-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA2B,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,gCAAgC,EAChC,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC1B,iCAAiC,EACjC,0CAA0C,EAC1C,uCAAuC,EACvC,uCAAuC,EACvC,8BAA8B,EAC9B,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,qCAAqC,EACrC,4BAA4B,EAC5B,YAAY,GAGb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,qCAAqC,EACrC,0BAA0B,EAC1B,0BAA0B,EAC1B,mCAAmC,GACpC,MAAM,aAAa,CAAC;AASrB,MAAM,yBAAyB,GAAG,SAAS,CAAC;AAC5C,MAAM,sBAAsB,GAAG,KAAK,CAAC;AACrC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAClD,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,gBAAgB,EAAE,sBAAsB;IACxC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;IACjD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;IACvD,WAAW,EAAE,YAAY;IACzB,MAAM,EAAE,CAAC,CAAC,MAAM,CACd,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,YAAY,WAAW,EACvC,+BAA+B,CAChC,CAAC,QAAQ,EAAE;CACb,CAAC,CAAC,MAAM,EAAE,CAAC;AACZ,MAAM,sBAAsB,GAAG,yBAAyB,CAAC,MAAM,CAAC;IAC9D,YAAY,EAAE,cAAc;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;IAC7C,UAAU,EAAE,eAAe,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC,MAAM,EAAE,CAAC;AACZ,MAAM,mBAAmB,GAAG,yBAAyB,CAAC,MAAM,CAC1D,uCAAuC,CAAC,IAAI,CAAC;IAC3C,aAAa,EAAE,IAAI;IACnB,IAAI,EAAE,IAAI;CACX,CAAC,CAAC,KAAK,CACT,CAAC,MAAM,EAAE,CAAC;AACX,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;QACtD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;KACpB,CAAC,CAAC,MAAM,EAAE;CACZ,CAAC,CAAC,MAAM,EAAE,CAAC;AAEZ;;;GAGG;AACH,MAAM,OAAO,uBAAuB;IAEzB,SAAS,CAAM;IACf,MAAM,CAAe;IACrB,WAAW,CAAS;IAE7B,YAAY,MAAqC;QAC/C,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,CAAC,aAAa,EAAE,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,CAAC,sBAAsB,CAC3B,QAAuC;QAEvC,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrD,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC1B,MAAM,IAAI,qCAAqC,EAAE,CAAC;QACpD,CAAC;QACD,MAAM,IAAI,GAAG,0CAA0C,CAAC,KAAK,CAAC;YAC5D,aAAa,EAAE,0BAA0B;YACzC,IAAI,EAAE,0BAA0B;YAChC,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,KAAK,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAC3B,KAAK,EACL,IAAI,EACJ,8BAA8B,EAC9B,4BAA4B,CAC7B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,CAAC,mBAAmB,CACxB,QAAoC;QAEpC,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC1B,MAAM,IAAI,qCAAqC,EAAE,CAAC;QACpD,CAAC;QACD,MAAM,IAAI,GAAG,uCAAuC,CAAC,KAAK,CAAC;YACzD,aAAa,EAAE,0BAA0B;YACzC,IAAI,EAAE,uBAAuB;YAC7B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,GAAG,CAAC,KAAK,CAAC,eAAe;gBACvB,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE;gBAC5C,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,GAAG,CAAC,KAAK,CAAC,gBAAgB;gBACxB,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE;gBAC9C,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,KAAK,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAC3B,KAAK,EACL,IAAI,EACJ,uCAAuC,EACvC,qCAAqC,CACtC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,CAAC,iBAAiB,CACtB,KAAsB,EACtB,IAAa,EACb,MAAyB,EACzB,UAAsC;QAEtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,0BAA0B,CAClC,QAAQ,CAAC,MAAM,EACf,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAClC,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;YACzD,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC3B,MAAM,IAAI,0BAA0B,CAClC,8CAA8C,CAC/C,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,0BAA0B,CAClC,qDAAqD,CACtD,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAA0B;YACnC,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,OAAO,GAAyB,EAAE,CAAC;QACzC,IAAI,aAAiC,CAAC;QACtC,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,MAAM,MAAM,GAAG,YAAY,CAAC;YAC1B,aAAa,EAAE,yBAAyB;YACxC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,IAAI,OAAO,CAAC,MAAM,IAAI,sBAAsB,EAAE,CAAC;oBAC7C,WAAW,GAAG,IAAI,CAAC;oBACnB,OAAO;gBACT,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,GAAG,EAAE;gBACZ,WAAW,GAAG,IAAI,CAAC;YACrB,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBACrD,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,IAAI,0BAA0B,EAAE,CAAC;gBACzC,CAAC;gBACD,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,MAAM,KAAK,GAAG,aAAa,CACzB,OAAO,CAAC,KAAK,EAAG,EAChB,KAAK,EACL,MAAM,EACN,UAAU,CACX,CAAC;oBACF,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;wBACtB,aAAa,GAAG,KAAK,CAAC;oBACxB,CAAC;yBAAM,CAAC;wBACN,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAChC,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,IAAI,0BAA0B,EAAE,CAAC;YACzC,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAG,aAAa,CACzB,OAAO,CAAC,KAAK,EAAG,EAChB,KAAK,EACL,MAAM,EACN,UAAU,CACX,CAAC;gBACF,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtB,aAAa,GAAG,KAAK,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,0BAA0B,EAAE,CAAC;gBAChD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,IAAI,0BAA0B,CAClC,mDAAmD,CACpD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,aAAa,EAAE,CAAC;YACtC,MAAM,IAAI,mCAAmC,EAAE,CAAC;QAClD,CAAC;QACD,wEAAwE;QACxE,sDAAsD;QACtD,MAAM,aAAa,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAsB,EAAE,IAAa;QACjD,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE;gBACvC,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC;gBACxD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;CACF;AA2BD,SAAS,aAAa,CACpB,KAAyB,EACzB,KAA4B,EAC5B,MAAyB,EACzB,UAAsC;IAEtC,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,0BAA0B,EAAE,CAAC;IACzC,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,0BAA0B,EAAE,CAAC;IACzC,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;IAC1B,MAAM,oBAAoB,GAAG,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI;WAClD,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,eAAe,GAAG,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,YAAY;WAC5D,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,YAAY,CAAC;IAC3C,IAAI,CAAC,oBAAoB,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,0BAA0B,EAAE,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC9B,MAAM,IAAI,0BAA0B,EAAE,CAAC;QACzC,CAAC;QACD,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QACtB,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC5B,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;QACpE,MAAM,IAAI,0BAA0B,EAAE,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;IACxB,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,sBAAsB,CAC7B,KAAsB,EACtB,UAAkB;IAElB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;QAC1B,MAAM,EAAE,mBAAmB;QAC3B,cAAc,EAAE,kBAAkB;QAClC,CAAC,gCAAgC,CAAC,EAAE,KAAK,CAAC,gBAAgB;QAC1D,CAAC,iCAAiC,CAAC,EAAE,UAAU;QAC/C,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC,WAAW;QACzC,CAAC,0BAA0B,CAAC,EAAE,KAAK,CAAC,kBAAkB;KACvD,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,WAA0B;IAC/C,OAAO,WAAW,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE;YACpD,mBAAmB,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,QAAkB;IACjD,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACtE,IACE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC;eAC5B,cAAc,GAAG,oBAAoB,EACxC,CAAC;YACD,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC3B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;QACpE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CACrC,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAC5C,CAAC;QACF,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,QAAkB,EAClB,QAAgB;IAEhB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,UAAU,EAAE,CAAC;IAC1B,CAAC;IACD,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;IACD,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,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,QAAkB;IAC1C,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;IAC7E,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc,EAAE,MAAoB;IAC5D,IAAI,MAAM,EAAE,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,qCAAqC,EAAE,CAAC;IACrD,CAAC;IACD,OAAO,IAAI,mCAAmC,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC;AAC/D,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAQ;IACjC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAQ;IACjC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,UAAU,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QACrD,CAAC,CAAC,UAAU,CAAC,QAAQ;QACrB,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,GAAG,CAAC;IAC9B,OAAO,UAAU,CAAC;AACpB,CAAC","sourcesContent":["import { createParser, type EventSourceMessage } from 'eventsource-parser';\nimport { 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 ExecutionHostStreamEventSchema,\n HEARTBEAT_TASK_WORKFLOW,\n MCP_CAPABILITY_HEADER,\n MODEL_API_KEY_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 ExecutionHostProtocolError,\n ExecutionHostRejectedError,\n ExecutionHostStreamInterruptedError,\n} from './errors.js';\nimport type {\n DirectHttpExecutionHostConfig,\n ExecutionHost,\n ExecutionHostConversationTurn,\n ExecutionHostHeartbeatTask,\n HeartbeatExecutionHost,\n} from './types.js';\n\nconst MAX_SSE_BUFFER_CHARACTERS = 1_048_576;\nconst MAX_PENDING_SSE_FRAMES = 1_024;\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 modelApiKey: SecretSchema,\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 if (!isEventStream(response.headers.get('content-type'))) {\n await cancelBody(response);\n throw new ExecutionHostProtocolError(\n 'Execution Host did not return an SSE stream.',\n );\n }\n if (!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: TEvent | undefined;\n let parserError = false;\n const parser = createParser({\n maxBufferSize: MAX_SSE_BUFFER_CHARACTERS,\n onEvent: (event) => {\n if (pending.length >= MAX_PENDING_SSE_FRAMES) {\n parserError = true;\n return;\n }\n pending.push(event);\n },\n onError: () => {\n parserError = true;\n },\n });\n\n try {\n for await (const chunk of response.body) {\n input.signal?.throwIfAborted();\n parser.feed(decoder.decode(chunk, { stream: true }));\n if (parserError) {\n throw new ExecutionHostProtocolError();\n }\n while (pending.length > 0) {\n const event = validateEvent(\n pending.shift()!,\n state,\n schema,\n isTerminal,\n );\n if (isTerminal(event)) {\n terminalEvent = event;\n } else {\n yield event;\n }\n }\n }\n parser.feed(decoder.decode());\n parser.reset({ consume: true });\n if (parserError) {\n throw new ExecutionHostProtocolError();\n }\n while (pending.length > 0) {\n const event = validateEvent(\n pending.shift()!,\n state,\n schema,\n isTerminal,\n );\n if (isTerminal(event)) {\n terminalEvent = event;\n } else {\n yield event;\n }\n }\n } catch (error) {\n if (error instanceof ExecutionHostProtocolError) {\n throw error;\n }\n throw toTransportError(error, input.signal);\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 // Terminal is released only after clean EOF, so a trailing malformed or\n // post-terminal frame cannot be projected as success.\n yield terminalEvent;\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 toTransportError(error, input.signal);\n }\n }\n}\n\ntype StreamValidationState = {\n invocationId: string;\n runId?: string;\n nextSequence: number;\n accepted?: true;\n terminal: boolean;\n};\n\ntype InvocationInput = {\n invocationId: string;\n runtimeSessionId: string;\n executionAssertion: string;\n mcpCapability?: string;\n modelApiKey: string;\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 validateEvent<TEvent extends ValidatedStreamEvent>(\n frame: EventSourceMessage,\n state: StreamValidationState,\n schema: z.ZodType<TEvent>,\n isTerminal: (event: TEvent) => boolean,\n): TEvent {\n let decoded: unknown;\n try {\n decoded = JSON.parse(frame.data);\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.invocationId === state.invocationId\n && event.sequence === state.nextSequence;\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.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 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_API_KEY_HEADER]: input.modelApiKey,\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\nfunction isEventStream(contentType: string | null): boolean {\n return contentType?.split(';', 1)[0]?.trim().toLowerCase()\n === 'text/event-stream';\n}\n\nasync function readSafeErrorCode(response: Response): Promise<string> {\n try {\n const declaredLength = Number(response.headers.get('content-length'));\n if (\n Number.isFinite(declaredLength)\n && declaredLength > MAX_ERROR_BODY_BYTES\n ) {\n await cancelBody(response);\n return 'unknown';\n }\n const bytes = await readBoundedBody(response, MAX_ERROR_BODY_BYTES);\n if (!bytes) {\n return 'unknown';\n }\n const parsed = ApiErrorSchema.safeParse(\n JSON.parse(new TextDecoder().decode(bytes)),\n );\n return parsed.success ? parsed.data.error.code : 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\nasync function readBoundedBody(\n response: Response,\n maxBytes: number,\n): Promise<Uint8Array | undefined> {\n if (!response.body) {\n return new Uint8Array();\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 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 return bytes;\n}\n\nasync function cancelBody(response: Response): Promise<void> {\n try {\n await response.body?.cancel();\n } catch {\n // Response cleanup is best effort and must not replace the protocol error.\n }\n}\n\nfunction toTransportError(error: unknown, signal?: AbortSignal): Error {\n if (signal?.aborted || isAbortError(error)) {\n return new ExecutionHostInvocationCancelledError();\n }\n return new ExecutionHostStreamInterruptedError();\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError';\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 ExecutionHostStreamEventSchema,\n HEARTBEAT_TASK_WORKFLOW,\n MCP_CAPABILITY_HEADER,\n MODEL_API_KEY_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 modelApiKey: SecretSchema,\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 modelApiKey: string;\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_API_KEY_HEADER]: input.modelApiKey,\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"]}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC","sourcesContent":["export * from './contracts/index.js';\nexport * from './authority/index.js';\nexport * from './conversation/index.js';\nexport * from './heartbeat/index.js';\nexport * from './coordinator/index.js';\nexport * from './mcp/index.js';\nexport * from './http-sse/index.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC","sourcesContent":["export * from './contracts/index.js';\nexport * from './adopter/index.js';\nexport * from './authority/index.js';\nexport * from './conversation/index.js';\nexport * from './heartbeat/index.js';\nexport * from './coordinator/index.js';\nexport * from './mcp/index.js';\nexport * from './http-sse/index.js';\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
type ExecutionHostEvent = {
|
|
3
|
+
kind: string;
|
|
4
|
+
invocationId: string;
|
|
5
|
+
runId: string;
|
|
6
|
+
sequence: number;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function readExecutionHostEventStream<Event extends ExecutionHostEvent>(input: {
|
|
10
|
+
response: Response;
|
|
11
|
+
schema: z.ZodType<Event>;
|
|
12
|
+
isTerminal: (event: Event) => boolean;
|
|
13
|
+
invocationId?: string;
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
}): AsyncIterable<Event>;
|
|
16
|
+
export declare function toExecutionHostTransportError(error: unknown, signal?: AbortSignal): Error;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=execution-host-event-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-host-event-stream.d.ts","sourceRoot":"","sources":["../../src/internal/execution-host-event-stream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAc7B,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAUF,wBAAuB,4BAA4B,CACjD,KAAK,SAAS,kBAAkB,EAChC,KAAK,EAAE;IACP,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACzB,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,aAAa,CAAC,KAAK,CAAC,CAsFvB;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,EACd,MAAM,CAAC,EAAE,WAAW,GACnB,KAAK,CAKP"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { createParser } from 'eventsource-parser';
|
|
2
|
+
import { ExecutionHostInvocationCancelledError, ExecutionHostProtocolError, ExecutionHostStreamInterruptedError, } from '../http-sse/errors.js';
|
|
3
|
+
import { cancelResponseBody, isEventStreamResponse, } from './http-response.js';
|
|
4
|
+
const MAX_SSE_BUFFER_CHARACTERS = 1_048_576;
|
|
5
|
+
const MAX_PENDING_SSE_FRAMES = 1_024;
|
|
6
|
+
export async function* readExecutionHostEventStream(input) {
|
|
7
|
+
if (!isEventStreamResponse(input.response)) {
|
|
8
|
+
await cancelResponseBody(input.response);
|
|
9
|
+
throw new ExecutionHostProtocolError('Execution Host did not return an SSE stream.');
|
|
10
|
+
}
|
|
11
|
+
if (!input.response.body) {
|
|
12
|
+
throw new ExecutionHostProtocolError('Execution Host returned an empty SSE response body.');
|
|
13
|
+
}
|
|
14
|
+
const state = {
|
|
15
|
+
invocationId: input.invocationId,
|
|
16
|
+
nextSequence: 0,
|
|
17
|
+
terminal: false,
|
|
18
|
+
};
|
|
19
|
+
const decoder = new TextDecoder();
|
|
20
|
+
const pending = [];
|
|
21
|
+
let terminalEvent;
|
|
22
|
+
let parserFailed = false;
|
|
23
|
+
const parser = createParser({
|
|
24
|
+
maxBufferSize: MAX_SSE_BUFFER_CHARACTERS,
|
|
25
|
+
onEvent: (event) => {
|
|
26
|
+
if (pending.length >= MAX_PENDING_SSE_FRAMES) {
|
|
27
|
+
parserFailed = true;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
pending.push(event);
|
|
31
|
+
},
|
|
32
|
+
onError: () => {
|
|
33
|
+
parserFailed = true;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
const reader = input.response.body.getReader();
|
|
37
|
+
try {
|
|
38
|
+
while (true) {
|
|
39
|
+
input.signal?.throwIfAborted();
|
|
40
|
+
const { done, value } = await reader.read();
|
|
41
|
+
if (done) {
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
parser.feed(decoder.decode(value, { stream: true }));
|
|
45
|
+
assertParserHealthy(parserFailed);
|
|
46
|
+
for (const event of drainEvents(pending, state, input.schema, input.isTerminal)) {
|
|
47
|
+
if (input.isTerminal(event)) {
|
|
48
|
+
terminalEvent = event;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
yield event;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
parser.feed(decoder.decode());
|
|
56
|
+
parser.reset({ consume: true });
|
|
57
|
+
assertParserHealthy(parserFailed);
|
|
58
|
+
for (const event of drainEvents(pending, state, input.schema, input.isTerminal)) {
|
|
59
|
+
if (input.isTerminal(event)) {
|
|
60
|
+
terminalEvent = event;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
yield event;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
await reader.cancel().catch(() => undefined);
|
|
69
|
+
if (error instanceof ExecutionHostProtocolError) {
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
throw toExecutionHostTransportError(error, input.signal);
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
reader.releaseLock();
|
|
76
|
+
}
|
|
77
|
+
if (!state.accepted) {
|
|
78
|
+
throw new ExecutionHostProtocolError('Execution Host stream omitted the accepted event.');
|
|
79
|
+
}
|
|
80
|
+
if (!state.terminal || !terminalEvent) {
|
|
81
|
+
throw new ExecutionHostStreamInterruptedError();
|
|
82
|
+
}
|
|
83
|
+
// A terminal event is observable only after clean EOF. This keeps success
|
|
84
|
+
// truthful if the transport appends malformed or post-terminal data.
|
|
85
|
+
yield terminalEvent;
|
|
86
|
+
}
|
|
87
|
+
export function toExecutionHostTransportError(error, signal) {
|
|
88
|
+
if (signal?.aborted || isAbortError(error)) {
|
|
89
|
+
return new ExecutionHostInvocationCancelledError();
|
|
90
|
+
}
|
|
91
|
+
return new ExecutionHostStreamInterruptedError();
|
|
92
|
+
}
|
|
93
|
+
function* drainEvents(pending, state, schema, isTerminal) {
|
|
94
|
+
while (pending.length > 0) {
|
|
95
|
+
yield validateEvent(pending.shift(), state, schema, isTerminal);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function validateEvent(frame, state, schema, isTerminal) {
|
|
99
|
+
let decoded;
|
|
100
|
+
try {
|
|
101
|
+
decoded = JSON.parse(frame.data);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
throw new ExecutionHostProtocolError();
|
|
105
|
+
}
|
|
106
|
+
const parsed = schema.safeParse(decoded);
|
|
107
|
+
if (!parsed.success) {
|
|
108
|
+
throw new ExecutionHostProtocolError();
|
|
109
|
+
}
|
|
110
|
+
const event = parsed.data;
|
|
111
|
+
const correctFrameMetadata = frame.event === event.kind
|
|
112
|
+
&& frame.id === String(event.sequence);
|
|
113
|
+
const correctEnvelope = event.sequence === state.nextSequence
|
|
114
|
+
&& (!state.invocationId || event.invocationId === state.invocationId);
|
|
115
|
+
if (!correctFrameMetadata || !correctEnvelope || state.terminal) {
|
|
116
|
+
throw new ExecutionHostProtocolError();
|
|
117
|
+
}
|
|
118
|
+
if (!state.accepted) {
|
|
119
|
+
if (event.kind !== 'accepted') {
|
|
120
|
+
throw new ExecutionHostProtocolError();
|
|
121
|
+
}
|
|
122
|
+
state.accepted = true;
|
|
123
|
+
state.invocationId = event.invocationId;
|
|
124
|
+
state.runId = event.runId;
|
|
125
|
+
}
|
|
126
|
+
else if (event.kind === 'accepted' || event.runId !== state.runId) {
|
|
127
|
+
throw new ExecutionHostProtocolError();
|
|
128
|
+
}
|
|
129
|
+
state.nextSequence += 1;
|
|
130
|
+
state.terminal = isTerminal(event);
|
|
131
|
+
return event;
|
|
132
|
+
}
|
|
133
|
+
function assertParserHealthy(failed) {
|
|
134
|
+
if (failed) {
|
|
135
|
+
throw new ExecutionHostProtocolError();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function isAbortError(error) {
|
|
139
|
+
return error instanceof Error && error.name === 'AbortError';
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=execution-host-event-stream.js.map
|