@agen-ai/agent-runtime 0.3.1 → 0.4.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.
- package/README.md +288 -29
- package/dist/adapterValidation.d.ts +1 -1
- package/dist/adapterValidation.js +199 -92
- package/dist/artifacts.js +0 -1
- package/dist/contractErrors.d.ts +16 -3
- package/dist/contractErrors.js +42 -6
- package/dist/hostBindings/index.d.ts +4 -0
- package/dist/hostBindings/index.js +9 -0
- package/dist/hostBindings/lifetime.d.ts +25 -0
- package/dist/hostBindings/lifetime.js +147 -0
- package/dist/hostBindings/opening.d.ts +14 -0
- package/dist/hostBindings/opening.js +82 -0
- package/dist/hostBindings/schema.d.ts +9 -0
- package/dist/hostBindings/schema.js +169 -0
- package/dist/hostBindings/types.d.ts +71 -0
- package/dist/hostBindings/types.js +0 -0
- package/dist/hostBindings/validation.d.ts +14 -0
- package/dist/hostBindings/validation.js +107 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7 -0
- package/dist/internal/objectShape.d.ts +2 -0
- package/dist/internal/objectShape.js +7 -0
- package/dist/outputValidation.js +3 -2
- package/dist/providerDriver.js +0 -1
- package/dist/providerInstanceRegistry.js +2 -1
- package/dist/sessionCleanup.d.ts +9 -0
- package/dist/sessionCleanup.js +17 -0
- package/dist/sessionInteractions/index.d.ts +2 -0
- package/dist/sessionInteractions/index.js +1 -0
- package/dist/sessionInteractions/lifetime.d.ts +52 -0
- package/dist/sessionInteractions/lifetime.js +251 -0
- package/dist/sessionInteractions/request.d.ts +42 -0
- package/dist/sessionInteractions/request.js +308 -0
- package/dist/sessionInteractions/types.d.ts +54 -0
- package/dist/sessionInteractions/types.js +10 -0
- package/dist/sessionInteractions/validation.d.ts +21 -0
- package/dist/sessionInteractions/validation.js +119 -0
- package/dist/sessionValidation.d.ts +15 -2
- package/dist/sessionValidation.js +155 -318
- package/dist/sessions.d.ts +31 -4
- package/dist/testing/conformance.d.ts +3 -3
- package/dist/testing/conformance.js +24 -31
- package/dist/testing/fakeProvider.js +59 -49
- package/dist/turnExecution/execution.d.ts +26 -0
- package/dist/turnExecution/execution.js +214 -0
- package/dist/turnExecution/receipts.d.ts +6 -0
- package/dist/turnExecution/receipts.js +39 -0
- package/dist/turnExecution/requests.d.ts +19 -0
- package/dist/turnExecution/requests.js +56 -0
- package/package.json +2 -2
|
@@ -13,6 +13,11 @@ import {
|
|
|
13
13
|
throwIfAgentOperationAborted
|
|
14
14
|
} from "./foundation.js";
|
|
15
15
|
import { containsAgentControlCharacter } from "./internal/controlCharacters.js";
|
|
16
|
+
import { withAgentSessionHostBinding } from "./hostBindings/lifetime.js";
|
|
17
|
+
import { invokeAgentSessionOpening } from "./hostBindings/opening.js";
|
|
18
|
+
import { validateAgentSessionHostBindingSupport } from "./hostBindings/validation.js";
|
|
19
|
+
import { createSessionInteractionOwner } from "./sessionInteractions/lifetime.js";
|
|
20
|
+
import { validateSessionInteractionSupport } from "./sessionInteractions/validation.js";
|
|
16
21
|
import {
|
|
17
22
|
validateAgentProviderOperationResult,
|
|
18
23
|
validateAgentProviderOutputForContext
|
|
@@ -22,6 +27,7 @@ import {
|
|
|
22
27
|
openIdentityCreatingAgentProviderSession,
|
|
23
28
|
validateAgentProviderSession
|
|
24
29
|
} from "./sessionValidation.js";
|
|
30
|
+
const validatedAdapters = /* @__PURE__ */ new WeakMap();
|
|
25
31
|
function parseWorkingDirectory(value) {
|
|
26
32
|
if (value.length < 1 || value.length > 4096 || !path.isAbsolute(value) || path.normalize(value) !== value || containsAgentControlCharacter(value)) {
|
|
27
33
|
throw new TypeError(
|
|
@@ -40,8 +46,9 @@ function assertAuthenticationOutputKind(providerKey, output) {
|
|
|
40
46
|
"Authentication may emit only authentication, lifecycle, or evidence output."
|
|
41
47
|
);
|
|
42
48
|
}
|
|
43
|
-
function validateAgentProviderAdapter(capabilityInput,
|
|
49
|
+
function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
44
50
|
const capabilities = parseAgentCapabilities(capabilityInput);
|
|
51
|
+
const adapter = validatedAdapters.get(adapterInput) ?? adapterInput;
|
|
45
52
|
if (adapter === null || typeof adapter !== "object" || typeof adapter.createSession !== "function" || adapter.resumption === null || typeof adapter.resumption !== "object" || !["supported", "unsupported"].includes(adapter.resumption.kind) || adapter.resumption.kind === "supported" && typeof adapter.resumption.resumeSession !== "function" || adapter.branching === null || typeof adapter.branching !== "object" || !["through_turn", "unsupported"].includes(adapter.branching.kind) || adapter.branching.kind === "through_turn" && typeof adapter.branching.branchSession !== "function" || adapter.authentication === null || typeof adapter.authentication !== "object" || !["supported", "unsupported"].includes(adapter.authentication.kind) || adapter.authentication.kind === "supported" && (typeof adapter.authentication.start !== "function" || typeof adapter.authentication.cancel !== "function")) {
|
|
46
53
|
throwAgentProviderContractError(
|
|
47
54
|
capabilities.providerKey,
|
|
@@ -57,83 +64,153 @@ function validateAgentProviderAdapter(capabilityInput, adapter) {
|
|
|
57
64
|
);
|
|
58
65
|
}
|
|
59
66
|
const declaredResumption = adapter.resumption;
|
|
67
|
+
const sessionInteractions = validateSessionInteractionSupport(capabilities, adapter);
|
|
68
|
+
let hostBinding;
|
|
69
|
+
try {
|
|
70
|
+
hostBinding = validateAgentSessionHostBindingSupport(adapter.hostBinding);
|
|
71
|
+
} catch {
|
|
72
|
+
return throwAgentProviderContractError(
|
|
73
|
+
capabilities.providerKey,
|
|
74
|
+
"invalid_adapter",
|
|
75
|
+
"Provider declared invalid session host binding support."
|
|
76
|
+
);
|
|
77
|
+
}
|
|
60
78
|
const resumption = declaredResumption.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
61
79
|
kind: "supported",
|
|
62
|
-
resumeSession: async (resumeInput) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
parsed.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
);
|
|
80
|
-
const binding = parsed.binding;
|
|
81
|
-
const candidate = await declaredResumption.resumeSession({
|
|
82
|
-
sessionId: parsed.sessionId,
|
|
83
|
-
workingDirectory,
|
|
84
|
-
binding,
|
|
85
|
-
configuration: parsed.configuration,
|
|
86
|
-
...resumeInput.signal === void 0 ? {} : { signal: resumeInput.signal }
|
|
87
|
-
});
|
|
88
|
-
try {
|
|
89
|
-
return validateAgentProviderSession({
|
|
80
|
+
resumeSession: async (resumeInput) => withAgentSessionHostBinding({
|
|
81
|
+
providerKey: capabilities.providerKey,
|
|
82
|
+
binding: resumeInput.hostBinding,
|
|
83
|
+
openingInput: resumeInput,
|
|
84
|
+
support: hostBinding,
|
|
85
|
+
open: async (lease) => {
|
|
86
|
+
throwIfAgentOperationAborted(resumeInput.signal);
|
|
87
|
+
const parsed = parseAgentSessionOpenInput({
|
|
88
|
+
operation: "resume",
|
|
89
|
+
sessionId: resumeInput.sessionId,
|
|
90
|
+
binding: resumeInput.binding,
|
|
91
|
+
configuration: resumeInput.configuration
|
|
92
|
+
});
|
|
93
|
+
if (parsed.operation !== "resume") {
|
|
94
|
+
throw new TypeError("Expected a resume session input.");
|
|
95
|
+
}
|
|
96
|
+
assertAgentSessionConfigurationSupported(
|
|
90
97
|
capabilities,
|
|
98
|
+
parsed.configuration
|
|
99
|
+
);
|
|
100
|
+
const workingDirectory = parseWorkingDirectory(
|
|
101
|
+
resumeInput.workingDirectory
|
|
102
|
+
);
|
|
103
|
+
const binding = parsed.binding;
|
|
104
|
+
const interactions = createSessionInteractionOwner({
|
|
105
|
+
providerKey: capabilities.providerKey,
|
|
91
106
|
sessionId: parsed.sessionId,
|
|
92
|
-
|
|
93
|
-
|
|
107
|
+
operation: "resume",
|
|
108
|
+
support: sessionInteractions,
|
|
109
|
+
...resumeInput.interactions === void 0 ? {} : { context: resumeInput.interactions },
|
|
110
|
+
...resumeInput.signal === void 0 ? {} : { signal: resumeInput.signal }
|
|
111
|
+
});
|
|
112
|
+
const candidate = await invokeAgentSessionOpening({
|
|
113
|
+
providerKey: capabilities.providerKey,
|
|
114
|
+
openingInput: resumeInput,
|
|
115
|
+
lease,
|
|
116
|
+
...interactions === void 0 ? {} : { interactions },
|
|
117
|
+
open: (context) => declaredResumption.resumeSession(context),
|
|
118
|
+
candidateInput: {
|
|
119
|
+
sessionId: parsed.sessionId,
|
|
120
|
+
workingDirectory,
|
|
121
|
+
binding,
|
|
122
|
+
configuration: parsed.configuration,
|
|
123
|
+
...lease === void 0 ? {} : { hostBinding: lease.binding },
|
|
124
|
+
...interactions === void 0 ? {} : { interactions: interactions.facade },
|
|
125
|
+
...(interactions?.openingSignal ?? resumeInput.signal) === void 0 ? {} : { signal: interactions?.openingSignal ?? resumeInput.signal }
|
|
126
|
+
}
|
|
94
127
|
});
|
|
95
|
-
|
|
96
|
-
|
|
128
|
+
try {
|
|
129
|
+
const session = validateAgentProviderSession({
|
|
130
|
+
capabilities,
|
|
131
|
+
sessionId: parsed.sessionId,
|
|
132
|
+
candidate,
|
|
133
|
+
expectedBinding: binding,
|
|
134
|
+
...interactions === void 0 ? {} : { sessionInteractionOwner: interactions },
|
|
135
|
+
...lease === void 0 ? {} : { hostBindingLease: lease }
|
|
136
|
+
});
|
|
137
|
+
interactions?.adopt();
|
|
138
|
+
return session;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return closeRejectedAgentProviderSession(
|
|
141
|
+
candidate,
|
|
142
|
+
error,
|
|
143
|
+
lease === void 0 ? void 0 : { providerKey: capabilities.providerKey, lease },
|
|
144
|
+
{ providerKey: capabilities.providerKey, input: resumeInput },
|
|
145
|
+
interactions
|
|
146
|
+
);
|
|
147
|
+
}
|
|
97
148
|
}
|
|
98
|
-
}
|
|
149
|
+
})
|
|
99
150
|
});
|
|
100
151
|
const declaredBranching = adapter.branching;
|
|
101
152
|
const branching = declaredBranching.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
102
153
|
kind: "through_turn",
|
|
103
|
-
branchSession: async (branchInput) => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
parsed.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
sourceBinding
|
|
127
|
-
|
|
154
|
+
branchSession: async (branchInput) => withAgentSessionHostBinding({
|
|
155
|
+
providerKey: capabilities.providerKey,
|
|
156
|
+
binding: branchInput.hostBinding,
|
|
157
|
+
openingInput: branchInput,
|
|
158
|
+
support: hostBinding,
|
|
159
|
+
open: async (lease) => {
|
|
160
|
+
throwIfAgentOperationAborted(branchInput.signal);
|
|
161
|
+
const parsed = parseAgentSessionOpenInput({
|
|
162
|
+
operation: "branch",
|
|
163
|
+
sessionId: branchInput.sessionId,
|
|
164
|
+
source: branchInput.source,
|
|
165
|
+
configuration: branchInput.configuration
|
|
166
|
+
});
|
|
167
|
+
if (parsed.operation !== "branch") {
|
|
168
|
+
throw new TypeError("Expected a branch session input.");
|
|
169
|
+
}
|
|
170
|
+
assertAgentSessionConfigurationSupported(
|
|
171
|
+
capabilities,
|
|
172
|
+
parsed.configuration
|
|
173
|
+
);
|
|
174
|
+
const workingDirectory = parseWorkingDirectory(
|
|
175
|
+
branchInput.workingDirectory
|
|
176
|
+
);
|
|
177
|
+
const sourceBinding = parsed.source.binding;
|
|
178
|
+
const interactions = createSessionInteractionOwner({
|
|
179
|
+
providerKey: capabilities.providerKey,
|
|
128
180
|
sessionId: parsed.sessionId,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
onBindingCreated: observer,
|
|
181
|
+
operation: "branch",
|
|
182
|
+
support: sessionInteractions,
|
|
183
|
+
...branchInput.interactions === void 0 ? {} : { context: branchInput.interactions },
|
|
133
184
|
...branchInput.signal === void 0 ? {} : { signal: branchInput.signal }
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
|
|
185
|
+
});
|
|
186
|
+
return openIdentityCreatingAgentProviderSession({
|
|
187
|
+
capabilities,
|
|
188
|
+
sessionId: parsed.sessionId,
|
|
189
|
+
observer: branchInput.onBindingCreated,
|
|
190
|
+
sourceBinding,
|
|
191
|
+
openingInput: branchInput,
|
|
192
|
+
...interactions === void 0 ? {} : { sessionInteractionOwner: interactions },
|
|
193
|
+
...lease === void 0 ? {} : { hostBindingLease: lease },
|
|
194
|
+
open: (observer) => invokeAgentSessionOpening({
|
|
195
|
+
providerKey: capabilities.providerKey,
|
|
196
|
+
openingInput: branchInput,
|
|
197
|
+
lease,
|
|
198
|
+
...interactions === void 0 ? {} : { interactions },
|
|
199
|
+
open: (context) => declaredBranching.branchSession(context),
|
|
200
|
+
candidateInput: {
|
|
201
|
+
sessionId: parsed.sessionId,
|
|
202
|
+
workingDirectory,
|
|
203
|
+
source: parsed.source,
|
|
204
|
+
configuration: parsed.configuration,
|
|
205
|
+
onBindingCreated: observer,
|
|
206
|
+
...lease === void 0 ? {} : { hostBinding: lease.binding },
|
|
207
|
+
...interactions === void 0 ? {} : { interactions: interactions.facade },
|
|
208
|
+
...(interactions?.openingSignal ?? branchInput.signal) === void 0 ? {} : { signal: interactions?.openingSignal ?? branchInput.signal }
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
})
|
|
137
214
|
});
|
|
138
215
|
const declaredAuthentication = adapter.authentication;
|
|
139
216
|
const authenticationFlows = capabilities.authentication.kind === "supported" ? capabilities.authentication.flows : [];
|
|
@@ -204,38 +281,68 @@ function validateAgentProviderAdapter(capabilityInput, adapter) {
|
|
|
204
281
|
return result;
|
|
205
282
|
}
|
|
206
283
|
});
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
parsed
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
284
|
+
const validated = Object.freeze({
|
|
285
|
+
hostBinding,
|
|
286
|
+
sessionInteractions,
|
|
287
|
+
createSession: async (createInput) => withAgentSessionHostBinding({
|
|
288
|
+
providerKey: capabilities.providerKey,
|
|
289
|
+
binding: createInput.hostBinding,
|
|
290
|
+
openingInput: createInput,
|
|
291
|
+
support: hostBinding,
|
|
292
|
+
open: async (lease) => {
|
|
293
|
+
throwIfAgentOperationAborted(createInput.signal);
|
|
294
|
+
const parsed = parseAgentSessionOpenInput({
|
|
295
|
+
operation: "create",
|
|
296
|
+
sessionId: createInput.sessionId,
|
|
297
|
+
configuration: createInput.configuration
|
|
298
|
+
});
|
|
299
|
+
assertAgentSessionConfigurationSupported(
|
|
300
|
+
capabilities,
|
|
301
|
+
parsed.configuration
|
|
302
|
+
);
|
|
303
|
+
const workingDirectory = parseWorkingDirectory(
|
|
304
|
+
createInput.workingDirectory
|
|
305
|
+
);
|
|
306
|
+
const interactions = createSessionInteractionOwner({
|
|
307
|
+
providerKey: capabilities.providerKey,
|
|
227
308
|
sessionId: parsed.sessionId,
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
309
|
+
operation: "create",
|
|
310
|
+
support: sessionInteractions,
|
|
311
|
+
...createInput.interactions === void 0 ? {} : { context: createInput.interactions },
|
|
231
312
|
...createInput.signal === void 0 ? {} : { signal: createInput.signal }
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
|
|
313
|
+
});
|
|
314
|
+
return openIdentityCreatingAgentProviderSession({
|
|
315
|
+
capabilities,
|
|
316
|
+
sessionId: parsed.sessionId,
|
|
317
|
+
observer: createInput.onBindingCreated,
|
|
318
|
+
openingInput: createInput,
|
|
319
|
+
...interactions === void 0 ? {} : { sessionInteractionOwner: interactions },
|
|
320
|
+
...lease === void 0 ? {} : { hostBindingLease: lease },
|
|
321
|
+
open: (observer) => invokeAgentSessionOpening({
|
|
322
|
+
providerKey: capabilities.providerKey,
|
|
323
|
+
openingInput: createInput,
|
|
324
|
+
lease,
|
|
325
|
+
...interactions === void 0 ? {} : { interactions },
|
|
326
|
+
open: (context) => adapter.createSession(context),
|
|
327
|
+
candidateInput: {
|
|
328
|
+
sessionId: parsed.sessionId,
|
|
329
|
+
workingDirectory,
|
|
330
|
+
configuration: parsed.configuration,
|
|
331
|
+
onBindingCreated: observer,
|
|
332
|
+
...lease === void 0 ? {} : { hostBinding: lease.binding },
|
|
333
|
+
...interactions === void 0 ? {} : { interactions: interactions.facade },
|
|
334
|
+
...(interactions?.openingSignal ?? createInput.signal) === void 0 ? {} : { signal: interactions?.openingSignal ?? createInput.signal }
|
|
335
|
+
}
|
|
336
|
+
})
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}),
|
|
235
340
|
resumption,
|
|
236
341
|
branching,
|
|
237
342
|
authentication
|
|
238
343
|
});
|
|
344
|
+
validatedAdapters.set(validated, adapter);
|
|
345
|
+
return validated;
|
|
239
346
|
}
|
|
240
347
|
export {
|
|
241
348
|
validateAgentProviderAdapter
|
package/dist/artifacts.js
CHANGED
package/dist/contractErrors.d.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
import type { AgentProviderKey } from "@agen-ai/agent-protocol";
|
|
2
|
-
|
|
2
|
+
import type { MaybePromise } from "./foundation.js";
|
|
3
|
+
export declare const AGENT_PROVIDER_CONTRACT_ERROR_CODES: readonly ["capability_port_mismatch", "invalid_adapter", "invalid_session", "invalid_binding", "binding_callback_missing", "binding_callback_repeated", "binding_callback_mismatch", "resume_binding_mismatch", "branch_binding_reused", "session_closed", "session_unusable", "concurrent_turn", "active_turn_mismatch", "invalid_operation_result", "invalid_inventory", "invalid_collaboration_transition", "input_operation_mismatch", "output_session_mismatch", "output_turn_mismatch", "output_authentication_attempt_mismatch", "output_operation_mismatch", "output_collaboration_mismatch", "output_resource_mismatch", "output_capability_mismatch", "input_capability_mismatch", "invalid_turn_sequence", "request_resolution_mismatch", "configuration_key_unsupported", "configuration_value_unsupported", "request_pending", "invalid_host_binding", "host_binding_unsupported", "host_binding_reused", "host_binding_closed", "host_tool_name_conflict", "host_tool_input_invalid", "host_tool_result_invalid", "host_tool_capacity_exhausted", "invalid_session_interaction", "session_interactions_unsupported"];
|
|
3
4
|
export type AgentProviderContractErrorCode = (typeof AGENT_PROVIDER_CONTRACT_ERROR_CODES)[number];
|
|
4
|
-
export type AgentProviderDelegatedOperation = "steer_turn" | "invoke_operation" | "apply_configuration" | "spawn_collaboration" | "control_collaboration";
|
|
5
|
+
export type AgentProviderDelegatedOperation = "resolve_request" | "steer_turn" | "invoke_operation" | "apply_configuration" | "spawn_collaboration" | "control_collaboration";
|
|
5
6
|
export declare class AgentProviderContractError extends Error {
|
|
6
7
|
readonly providerKey: AgentProviderKey;
|
|
7
8
|
readonly code: AgentProviderContractErrorCode;
|
|
8
|
-
constructor(providerKey: AgentProviderKey, code: AgentProviderContractErrorCode, message: string);
|
|
9
|
+
constructor(providerKey: AgentProviderKey, code: AgentProviderContractErrorCode, message: string, options?: ErrorOptions);
|
|
10
|
+
}
|
|
11
|
+
export declare class AgentProviderSessionCleanupError extends AggregateError {
|
|
12
|
+
readonly providerKey: AgentProviderKey;
|
|
13
|
+
readonly retryCleanup: () => Promise<void>;
|
|
14
|
+
constructor(input: Readonly<{
|
|
15
|
+
providerKey: AgentProviderKey;
|
|
16
|
+
errors: readonly unknown[];
|
|
17
|
+
retryCleanup: () => MaybePromise<void>;
|
|
18
|
+
}>);
|
|
19
|
+
}
|
|
20
|
+
export declare class AgentProviderHostBindingCleanupError extends AgentProviderSessionCleanupError {
|
|
21
|
+
constructor(input: ConstructorParameters<typeof AgentProviderSessionCleanupError>[0]);
|
|
9
22
|
}
|
|
10
23
|
export declare class AgentProviderDelegatedOperationError extends Error {
|
|
11
24
|
readonly providerKey: AgentProviderKey;
|
package/dist/contractErrors.js
CHANGED
|
@@ -28,17 +28,53 @@ const AGENT_PROVIDER_CONTRACT_ERROR_CODES = [
|
|
|
28
28
|
"request_resolution_mismatch",
|
|
29
29
|
"configuration_key_unsupported",
|
|
30
30
|
"configuration_value_unsupported",
|
|
31
|
-
"request_pending"
|
|
31
|
+
"request_pending",
|
|
32
|
+
"invalid_host_binding",
|
|
33
|
+
"host_binding_unsupported",
|
|
34
|
+
"host_binding_reused",
|
|
35
|
+
"host_binding_closed",
|
|
36
|
+
"host_tool_name_conflict",
|
|
37
|
+
"host_tool_input_invalid",
|
|
38
|
+
"host_tool_result_invalid",
|
|
39
|
+
"host_tool_capacity_exhausted",
|
|
40
|
+
"invalid_session_interaction",
|
|
41
|
+
"session_interactions_unsupported"
|
|
32
42
|
];
|
|
33
43
|
class AgentProviderContractError extends Error {
|
|
34
|
-
constructor(providerKey, code, message) {
|
|
35
|
-
super(message);
|
|
44
|
+
constructor(providerKey, code, message, options) {
|
|
45
|
+
super(message, options);
|
|
36
46
|
this.providerKey = providerKey;
|
|
37
47
|
this.code = code;
|
|
38
48
|
this.name = "AgentProviderContractError";
|
|
39
49
|
}
|
|
50
|
+
}
|
|
51
|
+
class AgentProviderSessionCleanupError extends AggregateError {
|
|
40
52
|
providerKey;
|
|
41
|
-
|
|
53
|
+
retryCleanup;
|
|
54
|
+
constructor(input) {
|
|
55
|
+
super(input.errors, "Provider session cleanup remains incomplete.");
|
|
56
|
+
this.name = "AgentProviderSessionCleanupError";
|
|
57
|
+
this.providerKey = input.providerKey;
|
|
58
|
+
let completed = false;
|
|
59
|
+
let pending = null;
|
|
60
|
+
this.retryCleanup = () => {
|
|
61
|
+
if (completed) return Promise.resolve();
|
|
62
|
+
if (pending) return pending;
|
|
63
|
+
pending = Promise.resolve().then(() => input.retryCleanup()).then(() => {
|
|
64
|
+
completed = true;
|
|
65
|
+
}).finally(() => {
|
|
66
|
+
pending = null;
|
|
67
|
+
});
|
|
68
|
+
return pending;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
class AgentProviderHostBindingCleanupError extends AgentProviderSessionCleanupError {
|
|
73
|
+
constructor(input) {
|
|
74
|
+
super(input);
|
|
75
|
+
this.name = "AgentProviderHostBindingCleanupError";
|
|
76
|
+
this.message = "Provider session host binding cleanup remains incomplete.";
|
|
77
|
+
}
|
|
42
78
|
}
|
|
43
79
|
class AgentProviderDelegatedOperationError extends Error {
|
|
44
80
|
constructor(providerKey, operation, cause) {
|
|
@@ -50,8 +86,6 @@ class AgentProviderDelegatedOperationError extends Error {
|
|
|
50
86
|
this.operation = operation;
|
|
51
87
|
this.name = "AgentProviderDelegatedOperationError";
|
|
52
88
|
}
|
|
53
|
-
providerKey;
|
|
54
|
-
operation;
|
|
55
89
|
providerExecution = "started";
|
|
56
90
|
}
|
|
57
91
|
function throwAgentProviderContractError(providerKey, code, message) {
|
|
@@ -61,5 +95,7 @@ export {
|
|
|
61
95
|
AGENT_PROVIDER_CONTRACT_ERROR_CODES,
|
|
62
96
|
AgentProviderContractError,
|
|
63
97
|
AgentProviderDelegatedOperationError,
|
|
98
|
+
AgentProviderHostBindingCleanupError,
|
|
99
|
+
AgentProviderSessionCleanupError,
|
|
64
100
|
throwAgentProviderContractError
|
|
65
101
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
import { validateAgentSessionHostBinding, validateAgentHostToolInvocation, validateAgentHostToolResult } from "./validation.js";
|
|
3
|
+
import { AGENT_HOST_TOOL_SCHEMA_DIALECT } from "./schema.js";
|
|
4
|
+
export {
|
|
5
|
+
AGENT_HOST_TOOL_SCHEMA_DIALECT,
|
|
6
|
+
validateAgentHostToolInvocation,
|
|
7
|
+
validateAgentHostToolResult,
|
|
8
|
+
validateAgentSessionHostBinding
|
|
9
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type AgentProviderKey } from "@agen-ai/agent-protocol";
|
|
2
|
+
import { AgentProviderHostBindingCleanupError } from "../contractErrors.js";
|
|
3
|
+
import { type MaybePromise } from "../foundation.js";
|
|
4
|
+
import type { AgentProviderSession } from "../sessions.js";
|
|
5
|
+
import type { AgentSessionHostBinding, AgentSessionHostBindingSupport } from "./types.js";
|
|
6
|
+
export interface AgentHostBindingLease {
|
|
7
|
+
readonly binding: AgentSessionHostBinding;
|
|
8
|
+
readonly initialize: (support: AgentSessionHostBindingSupport) => void;
|
|
9
|
+
readonly stop: () => void;
|
|
10
|
+
readonly release: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createAgentHostBindingCleanupError(input: Readonly<{
|
|
13
|
+
providerKey: AgentProviderKey;
|
|
14
|
+
lease: AgentHostBindingLease;
|
|
15
|
+
errors: readonly unknown[];
|
|
16
|
+
retryCleanup: () => MaybePromise<void>;
|
|
17
|
+
}>): AgentProviderHostBindingCleanupError;
|
|
18
|
+
export declare function withAgentSessionHostBinding(input: Readonly<{
|
|
19
|
+
providerKey: AgentProviderKey;
|
|
20
|
+
binding?: AgentSessionHostBinding;
|
|
21
|
+
openingInput?: object;
|
|
22
|
+
support: AgentSessionHostBindingSupport;
|
|
23
|
+
open: (lease?: AgentHostBindingLease) => MaybePromise<AgentProviderSession>;
|
|
24
|
+
}>): Promise<AgentProviderSession>;
|
|
25
|
+
//# sourceMappingURL=lifetime.d.ts.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { AgentProviderContractError, AgentProviderHostBindingCleanupError } from "../contractErrors.js";
|
|
2
|
+
import { throwIfAgentOperationAborted } from "../foundation.js";
|
|
3
|
+
import { associateAgentSessionCleanupError } from "../sessionCleanup.js";
|
|
4
|
+
import { dataRecord } from "./schema.js";
|
|
5
|
+
import { hostBindingEnvelope, validateAgentHostToolInvocation, validateAgentHostToolResult, validateAgentSessionHostBinding } from "./validation.js";
|
|
6
|
+
const claimedBindings = /* @__PURE__ */ new WeakSet();
|
|
7
|
+
const cleanupLeases = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function createAgentHostBindingCleanupError(input) {
|
|
9
|
+
const error = new AgentProviderHostBindingCleanupError(input);
|
|
10
|
+
cleanupLeases.set(error, input.lease);
|
|
11
|
+
return error;
|
|
12
|
+
}
|
|
13
|
+
function claimBinding(providerKey, input) {
|
|
14
|
+
const fail = (code, message) => {
|
|
15
|
+
throw new AgentProviderContractError(providerKey, code, message);
|
|
16
|
+
};
|
|
17
|
+
let original;
|
|
18
|
+
try {
|
|
19
|
+
original = hostBindingEnvelope(input);
|
|
20
|
+
} catch {
|
|
21
|
+
return fail("invalid_host_binding", "Host binding requires a valid identity and callable ownership ports.");
|
|
22
|
+
}
|
|
23
|
+
if (claimedBindings.has(original)) fail("host_binding_reused", "Host binding is already claimed by a session opening.");
|
|
24
|
+
claimedBindings.add(original);
|
|
25
|
+
const releaseCallback = original.release.bind(original);
|
|
26
|
+
const lifetime = new AbortController();
|
|
27
|
+
const invocations = /* @__PURE__ */ new Map();
|
|
28
|
+
let facade;
|
|
29
|
+
let released = false;
|
|
30
|
+
let releasePromise = null;
|
|
31
|
+
const stop = () => {
|
|
32
|
+
lifetime.abort(new DOMException("The host binding was closed.", "AbortError"));
|
|
33
|
+
};
|
|
34
|
+
const release = () => {
|
|
35
|
+
if (released) return Promise.resolve();
|
|
36
|
+
if (releasePromise) return releasePromise;
|
|
37
|
+
stop();
|
|
38
|
+
releasePromise = Promise.resolve().then(async () => {
|
|
39
|
+
await Promise.allSettled(invocations.values());
|
|
40
|
+
await releaseCallback();
|
|
41
|
+
released = true;
|
|
42
|
+
}).finally(() => {
|
|
43
|
+
releasePromise = null;
|
|
44
|
+
});
|
|
45
|
+
return releasePromise;
|
|
46
|
+
};
|
|
47
|
+
const initialize = (support) => {
|
|
48
|
+
if (support.kind === "unsupported") return fail("host_binding_unsupported", "Provider does not support session host bindings.");
|
|
49
|
+
let validated;
|
|
50
|
+
try {
|
|
51
|
+
if (original.instructions !== void 0) {
|
|
52
|
+
const instructions = dataRecord(original.instructions);
|
|
53
|
+
if (!support.instructionPlacements.includes(instructions.placement)) {
|
|
54
|
+
fail("host_binding_unsupported", "Provider does not support the requested instruction placement.");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
validated = validateAgentSessionHostBinding({ binding: original, support });
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (error instanceof AgentProviderContractError) throw error;
|
|
60
|
+
return fail("invalid_host_binding", "Host binding metadata is invalid.");
|
|
61
|
+
}
|
|
62
|
+
const invoke = (input2) => {
|
|
63
|
+
if (lifetime.signal.aborted) fail("host_binding_closed", "Host binding no longer accepts invocations.");
|
|
64
|
+
let invocation;
|
|
65
|
+
try {
|
|
66
|
+
invocation = validateAgentHostToolInvocation({ binding: validated, invocation: input2 });
|
|
67
|
+
} catch {
|
|
68
|
+
return fail("host_tool_input_invalid", "Host tool invocation has invalid arguments.");
|
|
69
|
+
}
|
|
70
|
+
const { invocationId } = invocation;
|
|
71
|
+
throwIfAgentOperationAborted(input2.signal);
|
|
72
|
+
if (invocations.has(invocationId)) fail("host_tool_input_invalid", "Host tool invocation is already active.");
|
|
73
|
+
if (invocations.size >= 16) fail("host_tool_capacity_exhausted", "Host binding has reached its invocation limit.");
|
|
74
|
+
const signal = input2.signal === void 0 ? lifetime.signal : AbortSignal.any([lifetime.signal, input2.signal]);
|
|
75
|
+
const promise = Promise.resolve().then(async () => {
|
|
76
|
+
let result;
|
|
77
|
+
try {
|
|
78
|
+
throwIfAgentOperationAborted(signal);
|
|
79
|
+
result = await validated.invoke({ ...invocation, signal });
|
|
80
|
+
} catch {
|
|
81
|
+
return Object.freeze({ kind: "error", error: Object.freeze({
|
|
82
|
+
category: "unknown",
|
|
83
|
+
code: "host_tool_failed",
|
|
84
|
+
message: "The host tool did not return a result.",
|
|
85
|
+
recovery: Object.freeze({ kind: "unknown" })
|
|
86
|
+
}) });
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
return validateAgentHostToolResult(result);
|
|
90
|
+
} catch {
|
|
91
|
+
return fail("host_tool_result_invalid", "Host tool returned an invalid or oversized result.");
|
|
92
|
+
}
|
|
93
|
+
}).finally(() => {
|
|
94
|
+
invocations.delete(invocationId);
|
|
95
|
+
});
|
|
96
|
+
invocations.set(invocationId, promise);
|
|
97
|
+
return promise;
|
|
98
|
+
};
|
|
99
|
+
facade = Object.freeze({
|
|
100
|
+
...validated,
|
|
101
|
+
invoke,
|
|
102
|
+
release: () => fail("invalid_host_binding", "Only the session owner may release a host binding.")
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
return {
|
|
106
|
+
get binding() {
|
|
107
|
+
if (!facade) return fail("invalid_host_binding", "Host binding has not been initialized.");
|
|
108
|
+
return facade;
|
|
109
|
+
},
|
|
110
|
+
initialize,
|
|
111
|
+
stop,
|
|
112
|
+
release
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async function withAgentSessionHostBinding(input) {
|
|
116
|
+
let lease;
|
|
117
|
+
try {
|
|
118
|
+
if (input.binding !== void 0) {
|
|
119
|
+
lease = claimBinding(input.providerKey, input.binding);
|
|
120
|
+
lease.initialize(input.support);
|
|
121
|
+
}
|
|
122
|
+
return await input.open(lease);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (lease && error instanceof AgentProviderHostBindingCleanupError && cleanupLeases.get(error) === lease) {
|
|
125
|
+
throw input.openingInput ? associateAgentSessionCleanupError(error, input.openingInput) : error;
|
|
126
|
+
}
|
|
127
|
+
if (lease) {
|
|
128
|
+
lease.stop();
|
|
129
|
+
try {
|
|
130
|
+
await lease.release();
|
|
131
|
+
} catch (cleanupError) {
|
|
132
|
+
const retained = createAgentHostBindingCleanupError({
|
|
133
|
+
providerKey: input.providerKey,
|
|
134
|
+
lease,
|
|
135
|
+
errors: [error, cleanupError],
|
|
136
|
+
retryCleanup: lease.release
|
|
137
|
+
});
|
|
138
|
+
throw input.openingInput ? associateAgentSessionCleanupError(retained, input.openingInput) : retained;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export {
|
|
145
|
+
createAgentHostBindingCleanupError,
|
|
146
|
+
withAgentSessionHostBinding
|
|
147
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AgentProviderKey } from "@agen-ai/agent-protocol";
|
|
2
|
+
import type { MaybePromise } from "../foundation.js";
|
|
3
|
+
import type { AgentProviderSession, AgentProviderSessionContext } from "../sessions.js";
|
|
4
|
+
import type { SessionInteractionOwner } from "../sessionInteractions/lifetime.js";
|
|
5
|
+
import { type AgentHostBindingLease } from "./lifetime.js";
|
|
6
|
+
export declare function invokeAgentSessionOpening<Input extends AgentProviderSessionContext>(input: Readonly<{
|
|
7
|
+
providerKey: AgentProviderKey;
|
|
8
|
+
openingInput: object;
|
|
9
|
+
candidateInput: Input;
|
|
10
|
+
lease: AgentHostBindingLease | undefined;
|
|
11
|
+
interactions?: SessionInteractionOwner;
|
|
12
|
+
open: (context: Input) => MaybePromise<AgentProviderSession>;
|
|
13
|
+
}>): Promise<AgentProviderSession>;
|
|
14
|
+
//# sourceMappingURL=opening.d.ts.map
|