@agen-ai/agent-runtime 0.4.0 → 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 +116 -8
- package/dist/adapterValidation.js +45 -5
- package/dist/artifacts.js +0 -1
- package/dist/contractErrors.d.ts +2 -2
- package/dist/contractErrors.js +5 -7
- package/dist/hostBindings/opening.d.ts +2 -0
- package/dist/hostBindings/opening.js +58 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/outputValidation.js +2 -2
- package/dist/providerDriver.js +0 -1
- package/dist/providerInstanceRegistry.js +2 -1
- 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 +4 -1
- package/dist/sessionValidation.js +29 -21
- package/dist/sessions.d.ts +3 -0
- package/dist/testing/conformance.js +0 -1
- package/dist/testing/fakeProvider.js +5 -6
- package/dist/turnExecution/requests.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import {
|
|
3
|
+
parseAgentError,
|
|
4
|
+
parseAgentSessionDecisionChoiceId,
|
|
5
|
+
parseAgentSessionDecisionRequest
|
|
6
|
+
} from "@agen-ai/agent-protocol";
|
|
7
|
+
import { AgentProviderContractError } from "../contractErrors.js";
|
|
8
|
+
import { hasExactOwnKeys } from "../internal/objectShape.js";
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_AGENT_SESSION_INTERACTION_LIMITS
|
|
11
|
+
} from "./types.js";
|
|
12
|
+
function record(input) {
|
|
13
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) throw new TypeError("Expected an interaction object.");
|
|
14
|
+
return input;
|
|
15
|
+
}
|
|
16
|
+
function interactionContractError(providerKey, message) {
|
|
17
|
+
return new AgentProviderContractError(providerKey, "invalid_session_interaction", message);
|
|
18
|
+
}
|
|
19
|
+
function validateSessionInteractionSupport(capabilities, adapter) {
|
|
20
|
+
const input = adapter.sessionInteractions;
|
|
21
|
+
if (input === void 0) return Object.freeze({ kind: "unsupported" });
|
|
22
|
+
try {
|
|
23
|
+
const value = record(input);
|
|
24
|
+
if (value.kind === "unsupported" && hasExactOwnKeys(value, ["kind"])) return Object.freeze({ kind: "unsupported" });
|
|
25
|
+
if (!hasExactOwnKeys(value, ["kind", "openingOperations", "requestKinds", "producerOwnership"]) || value.kind !== "supported" || value.producerOwnership !== "exclusive" || !Array.isArray(value.openingOperations) || value.openingOperations.length === 0 || !Array.isArray(value.requestKinds) || value.requestKinds.length !== 1 || value.requestKinds[0] !== "decision") throw new TypeError();
|
|
26
|
+
const operations = [];
|
|
27
|
+
for (const operation of value.openingOperations) {
|
|
28
|
+
if (operation !== "create" && operation !== "resume" && operation !== "branch") throw new TypeError();
|
|
29
|
+
if (operations.includes(operation)) throw new TypeError();
|
|
30
|
+
if (operation === "resume" && (!capabilities.sessions.resume || adapter.resumption.kind !== "supported")) throw new TypeError();
|
|
31
|
+
if (operation === "branch" && (capabilities.sessions.branch.kind !== "through_turn" || adapter.branching.kind !== "through_turn")) throw new TypeError();
|
|
32
|
+
operations.push(operation);
|
|
33
|
+
}
|
|
34
|
+
const order = ["create", "resume", "branch"];
|
|
35
|
+
if (operations.some((operation, index) => index > 0 && order.indexOf(operation) < order.indexOf(operations[index - 1]))) throw new TypeError();
|
|
36
|
+
const [first, ...rest] = operations;
|
|
37
|
+
if (first === void 0) throw new TypeError();
|
|
38
|
+
return Object.freeze({
|
|
39
|
+
kind: "supported",
|
|
40
|
+
producerOwnership: "exclusive",
|
|
41
|
+
openingOperations: Object.freeze([first, ...rest]),
|
|
42
|
+
requestKinds: Object.freeze(["decision"])
|
|
43
|
+
});
|
|
44
|
+
} catch {
|
|
45
|
+
throw interactionContractError(capabilities.providerKey, "Provider declared invalid session interaction support.");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const limitRanges = {
|
|
49
|
+
maxRetainedRequests: [1, 32],
|
|
50
|
+
maxRetainedBytes: [65536, 2097152],
|
|
51
|
+
requestTimeoutMs: [1e3, 18e5],
|
|
52
|
+
responseTimeoutMs: [1e3, 12e4],
|
|
53
|
+
cleanupTimeoutMs: [1e3, 12e4]
|
|
54
|
+
};
|
|
55
|
+
function validateSessionInteractionContext(input) {
|
|
56
|
+
const value = record(input);
|
|
57
|
+
const onRequest = value.onRequest;
|
|
58
|
+
if (!hasExactOwnKeys(value, Object.hasOwn(value, "limits") ? ["onRequest", "limits"] : ["onRequest"]) || typeof onRequest !== "function") throw new TypeError("Session interactions require a callable handler and known fields.");
|
|
59
|
+
const supplied = value.limits === void 0 ? {} : record(value.limits);
|
|
60
|
+
if (Reflect.ownKeys(supplied).some((key) => typeof key !== "string" || !Object.hasOwn(limitRanges, key))) {
|
|
61
|
+
throw new TypeError("Session interaction limits contain an unknown field.");
|
|
62
|
+
}
|
|
63
|
+
const limits = { ...DEFAULT_AGENT_SESSION_INTERACTION_LIMITS };
|
|
64
|
+
for (const key of Object.keys(limitRanges)) {
|
|
65
|
+
const number = supplied[key];
|
|
66
|
+
if (number === void 0) continue;
|
|
67
|
+
const [minimum, maximum] = limitRanges[key];
|
|
68
|
+
if (typeof number !== "number" || !Number.isSafeInteger(number) || number < minimum || number > maximum) {
|
|
69
|
+
throw new RangeError(`Session interaction ${key} must be an integer between ${minimum} and ${maximum}.`);
|
|
70
|
+
}
|
|
71
|
+
limits[key] = number;
|
|
72
|
+
}
|
|
73
|
+
return Object.freeze({ onRequest: onRequest.bind(input), limits: Object.freeze(limits) });
|
|
74
|
+
}
|
|
75
|
+
function captureSessionInteractionCandidate(input, observe) {
|
|
76
|
+
const value = record(input);
|
|
77
|
+
const terminal = value.terminal;
|
|
78
|
+
const observation = Promise.resolve(terminal);
|
|
79
|
+
void observation.catch(() => {
|
|
80
|
+
});
|
|
81
|
+
observe(observation);
|
|
82
|
+
const request = value.request;
|
|
83
|
+
const signal = value.signal;
|
|
84
|
+
const respond = value.respond;
|
|
85
|
+
if (!hasExactOwnKeys(value, ["request", "signal", "terminal", "respond"]) || !(signal instanceof AbortSignal) || typeof respond !== "function" || !terminal || typeof record(terminal).then !== "function") throw new TypeError("Provider offered an invalid session interaction handle.");
|
|
86
|
+
return Object.freeze({
|
|
87
|
+
request,
|
|
88
|
+
signal,
|
|
89
|
+
terminal: observation,
|
|
90
|
+
respond: respond.bind(input)
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function validateSessionInteractionCandidate(input, sessionId, requestTimeoutMs) {
|
|
94
|
+
const parsed = parseAgentSessionDecisionRequest(input.request);
|
|
95
|
+
if (parsed.sessionId !== sessionId || !path.isAbsolute(parsed.target.path) || path.normalize(parsed.target.path) !== parsed.target.path) {
|
|
96
|
+
throw new TypeError("Session interaction does not match its session or canonical workspace target.");
|
|
97
|
+
}
|
|
98
|
+
const expiry = Math.min(Date.parse(parsed.expiresAt), Date.now() + requestTimeoutMs);
|
|
99
|
+
if (expiry <= Date.now()) throw new TypeError("Provider offered an expired session interaction.");
|
|
100
|
+
const request = parseAgentSessionDecisionRequest({ ...parsed, expiresAt: new Date(expiry).toISOString() });
|
|
101
|
+
return Object.freeze({ ...input, request });
|
|
102
|
+
}
|
|
103
|
+
function validateSessionInteractionTerminal(input) {
|
|
104
|
+
const value = record(input);
|
|
105
|
+
if (value.kind === "answered" && hasExactOwnKeys(value, ["kind", "choiceId"])) {
|
|
106
|
+
return Object.freeze({ kind: "answered", choiceId: parseAgentSessionDecisionChoiceId(value.choiceId) });
|
|
107
|
+
}
|
|
108
|
+
if ((value.kind === "failed" || value.kind === "rejected" || value.kind === "delivery_uncertain") && hasExactOwnKeys(value, ["kind", "error"])) return Object.freeze({ kind: value.kind, error: parseAgentError(value.error) });
|
|
109
|
+
if ((value.kind === "withdrawn" || value.kind === "expired" || value.kind === "session_closed") && hasExactOwnKeys(value, ["kind"])) return Object.freeze({ kind: value.kind });
|
|
110
|
+
throw new TypeError("Provider returned an invalid session interaction terminal.");
|
|
111
|
+
}
|
|
112
|
+
export {
|
|
113
|
+
captureSessionInteractionCandidate,
|
|
114
|
+
interactionContractError,
|
|
115
|
+
validateSessionInteractionCandidate,
|
|
116
|
+
validateSessionInteractionContext,
|
|
117
|
+
validateSessionInteractionSupport,
|
|
118
|
+
validateSessionInteractionTerminal
|
|
119
|
+
};
|
|
@@ -2,6 +2,7 @@ import { type AgentCapabilities, type AgentProviderKey, type AgentSessionBinding
|
|
|
2
2
|
import { type AgentHostBindingLease } from "./hostBindings/lifetime.js";
|
|
3
3
|
import { type MaybePromise } from "./foundation.js";
|
|
4
4
|
import type { AgentProviderSession, AgentSessionBindingCreatedObserver } from "./sessions.js";
|
|
5
|
+
import type { SessionInteractionOwner } from "./sessionInteractions/lifetime.js";
|
|
5
6
|
export declare function validateAgentProviderSession(input: {
|
|
6
7
|
readonly capabilities: AgentCapabilities;
|
|
7
8
|
readonly sessionId: AgentSessionId;
|
|
@@ -9,6 +10,7 @@ export declare function validateAgentProviderSession(input: {
|
|
|
9
10
|
readonly expectedBinding?: AgentSessionBinding;
|
|
10
11
|
readonly sourceBinding?: AgentSessionBinding;
|
|
11
12
|
readonly hostBindingLease?: AgentHostBindingLease;
|
|
13
|
+
readonly sessionInteractionOwner?: SessionInteractionOwner;
|
|
12
14
|
}): AgentProviderSession;
|
|
13
15
|
export declare function closeRejectedAgentProviderSession(session: AgentProviderSession | null, error: unknown, hostBinding?: Readonly<{
|
|
14
16
|
providerKey: AgentProviderKey;
|
|
@@ -16,7 +18,7 @@ export declare function closeRejectedAgentProviderSession(session: AgentProvider
|
|
|
16
18
|
}>, opening?: Readonly<{
|
|
17
19
|
providerKey: AgentProviderKey;
|
|
18
20
|
input: object;
|
|
19
|
-
}
|
|
21
|
+
}>, interactions?: SessionInteractionOwner): Promise<never>;
|
|
20
22
|
export declare function openIdentityCreatingAgentProviderSession(input: {
|
|
21
23
|
readonly capabilities: AgentCapabilities;
|
|
22
24
|
readonly sessionId: AgentSessionId;
|
|
@@ -24,6 +26,7 @@ export declare function openIdentityCreatingAgentProviderSession(input: {
|
|
|
24
26
|
readonly sourceBinding?: AgentSessionBinding;
|
|
25
27
|
readonly hostBindingLease?: AgentHostBindingLease;
|
|
26
28
|
readonly openingInput?: object;
|
|
29
|
+
readonly sessionInteractionOwner?: SessionInteractionOwner;
|
|
27
30
|
readonly open: (observer: AgentSessionBindingCreatedObserver) => MaybePromise<AgentProviderSession>;
|
|
28
31
|
}): Promise<AgentProviderSession>;
|
|
29
32
|
//# sourceMappingURL=sessionValidation.d.ts.map
|
|
@@ -46,6 +46,11 @@ import {
|
|
|
46
46
|
import { validateAgentTurnSteeringResult } from "./steeringValidation.js";
|
|
47
47
|
import { createValidatedAgentTurnExecution } from "./turnExecution/execution.js";
|
|
48
48
|
import { validateAgentProviderTurnInterruptionResult } from "./turnExecution/receipts.js";
|
|
49
|
+
function validateCloseReason(reason) {
|
|
50
|
+
if (reason !== void 0 && !["idle", "shutdown", "replaced", "contract_rejected", "error", "other"].includes(reason)) {
|
|
51
|
+
throw new TypeError("Provider session close reason is unsupported.");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
49
54
|
function validateSessionPorts(capabilities, session) {
|
|
50
55
|
if (!hasExactOwnKeys(session, [
|
|
51
56
|
"binding",
|
|
@@ -703,6 +708,7 @@ function validateAgentProviderSession(input) {
|
|
|
703
708
|
);
|
|
704
709
|
};
|
|
705
710
|
const requireUsable = () => {
|
|
711
|
+
input.sessionInteractionOwner?.requireUsable();
|
|
706
712
|
requireOpen();
|
|
707
713
|
if (unusable) {
|
|
708
714
|
throwAgentProviderContractError(
|
|
@@ -742,6 +748,7 @@ function validateAgentProviderSession(input) {
|
|
|
742
748
|
await input2.observeOutput?.(candidate);
|
|
743
749
|
};
|
|
744
750
|
try {
|
|
751
|
+
requireUsable();
|
|
745
752
|
const candidate = await input2.invoke(onProviderExecutionStarted, onOutput);
|
|
746
753
|
if (!executionStarted) {
|
|
747
754
|
throwAgentProviderContractError(
|
|
@@ -1386,39 +1393,34 @@ function validateAgentProviderSession(input) {
|
|
|
1386
1393
|
return inspection;
|
|
1387
1394
|
}
|
|
1388
1395
|
});
|
|
1389
|
-
const
|
|
1390
|
-
if (closed) return Promise.resolve();
|
|
1391
|
-
if (closePromise) return closePromise;
|
|
1396
|
+
const closeOwned = (closeInput, explicit) => {
|
|
1397
|
+
if (closed && !input.sessionInteractionOwner) return Promise.resolve();
|
|
1398
|
+
if (!input.sessionInteractionOwner && closePromise) return closePromise;
|
|
1392
1399
|
throwIfAgentOperationAborted(closeInput.signal);
|
|
1393
|
-
|
|
1394
|
-
"idle",
|
|
1395
|
-
"shutdown",
|
|
1396
|
-
"replaced",
|
|
1397
|
-
"contract_rejected",
|
|
1398
|
-
"error",
|
|
1399
|
-
"other"
|
|
1400
|
-
].includes(closeInput.reason)) {
|
|
1401
|
-
throw new TypeError("Provider session close reason is unsupported.");
|
|
1402
|
-
}
|
|
1400
|
+
validateCloseReason(closeInput.reason);
|
|
1403
1401
|
unusable = true;
|
|
1404
1402
|
sessionLifetime.abort(new DOMException("The provider session was closed.", "AbortError"));
|
|
1405
1403
|
input.hostBindingLease?.stop();
|
|
1406
1404
|
const closingTurn = activeTurn;
|
|
1407
1405
|
closingTurn?.owner.stop(new DOMException("The provider session was closed.", "AbortError"));
|
|
1408
|
-
|
|
1406
|
+
const cleanup = async () => {
|
|
1409
1407
|
if (!providerClosed) {
|
|
1410
1408
|
await input.candidate.close(closeInput);
|
|
1411
1409
|
providerClosed = true;
|
|
1412
1410
|
}
|
|
1411
|
+
await input.sessionInteractionOwner?.join();
|
|
1413
1412
|
await closingTurn?.owner.join();
|
|
1414
1413
|
await input.hostBindingLease?.release();
|
|
1415
|
-
}).then(() => {
|
|
1416
1414
|
closed = true;
|
|
1417
|
-
}
|
|
1415
|
+
};
|
|
1416
|
+
if (input.sessionInteractionOwner) return input.sessionInteractionOwner.close(cleanup, explicit);
|
|
1417
|
+
closePromise = Promise.resolve().then(cleanup).finally(() => {
|
|
1418
1418
|
closePromise = null;
|
|
1419
1419
|
});
|
|
1420
1420
|
return closePromise;
|
|
1421
1421
|
};
|
|
1422
|
+
const close = (closeInput) => closeOwned(closeInput, true);
|
|
1423
|
+
input.sessionInteractionOwner?.installClose(() => closeOwned({ reason: "error" }, false));
|
|
1422
1424
|
return Object.freeze({
|
|
1423
1425
|
binding,
|
|
1424
1426
|
startTurn,
|
|
@@ -1433,9 +1435,10 @@ function validateAgentProviderSession(input) {
|
|
|
1433
1435
|
close
|
|
1434
1436
|
});
|
|
1435
1437
|
}
|
|
1436
|
-
async function closeRejectedAgentProviderSession(session, error, hostBinding, opening) {
|
|
1438
|
+
async function closeRejectedAgentProviderSession(session, error, hostBinding, opening, interactions) {
|
|
1437
1439
|
if (!session) throw error;
|
|
1438
1440
|
hostBinding?.lease.stop();
|
|
1441
|
+
interactions?.stop();
|
|
1439
1442
|
let providerClosed = false;
|
|
1440
1443
|
const cleanup = async () => {
|
|
1441
1444
|
if (!providerClosed) {
|
|
@@ -1445,24 +1448,26 @@ async function closeRejectedAgentProviderSession(session, error, hostBinding, op
|
|
|
1445
1448
|
await session.close({ reason: "contract_rejected" });
|
|
1446
1449
|
providerClosed = true;
|
|
1447
1450
|
}
|
|
1451
|
+
await interactions?.join();
|
|
1448
1452
|
await hostBinding?.lease.release();
|
|
1449
1453
|
};
|
|
1450
1454
|
try {
|
|
1451
|
-
await cleanup
|
|
1455
|
+
if (interactions) await interactions.close(cleanup, false);
|
|
1456
|
+
else await cleanup();
|
|
1452
1457
|
} catch (cleanupError) {
|
|
1453
1458
|
if (hostBinding) {
|
|
1454
1459
|
const retained = createAgentHostBindingCleanupError({
|
|
1455
1460
|
providerKey: hostBinding.providerKey,
|
|
1456
1461
|
lease: hostBinding.lease,
|
|
1457
1462
|
errors: [error, cleanupError],
|
|
1458
|
-
retryCleanup: cleanup
|
|
1463
|
+
retryCleanup: () => interactions ? interactions.close(cleanup, false) : cleanup()
|
|
1459
1464
|
});
|
|
1460
1465
|
throw opening ? associateAgentSessionCleanupError(retained, opening.input) : retained;
|
|
1461
1466
|
}
|
|
1462
1467
|
if (opening) throw associateAgentSessionCleanupError(new AgentProviderSessionCleanupError({
|
|
1463
1468
|
providerKey: opening.providerKey,
|
|
1464
1469
|
errors: [error, cleanupError],
|
|
1465
|
-
retryCleanup: cleanup
|
|
1470
|
+
retryCleanup: () => interactions ? interactions.close(cleanup, false) : cleanup()
|
|
1466
1471
|
}), opening.input);
|
|
1467
1472
|
throw new AggregateError(
|
|
1468
1473
|
[error, cleanupError],
|
|
@@ -1533,10 +1538,12 @@ async function openIdentityCreatingAgentProviderSession(input) {
|
|
|
1533
1538
|
capabilities: input.capabilities,
|
|
1534
1539
|
sessionId: input.sessionId,
|
|
1535
1540
|
candidate,
|
|
1541
|
+
...input.sessionInteractionOwner === void 0 ? {} : { sessionInteractionOwner: input.sessionInteractionOwner },
|
|
1536
1542
|
...input.hostBindingLease === void 0 ? {} : { hostBindingLease: input.hostBindingLease },
|
|
1537
1543
|
...input.sourceBinding === void 0 ? {} : { sourceBinding: input.sourceBinding }
|
|
1538
1544
|
});
|
|
1539
1545
|
tracker.requireMatch(session.binding);
|
|
1546
|
+
input.sessionInteractionOwner?.adopt();
|
|
1540
1547
|
return session;
|
|
1541
1548
|
} catch (error) {
|
|
1542
1549
|
return closeRejectedAgentProviderSession(
|
|
@@ -1546,7 +1553,8 @@ async function openIdentityCreatingAgentProviderSession(input) {
|
|
|
1546
1553
|
providerKey: input.capabilities.providerKey,
|
|
1547
1554
|
lease: input.hostBindingLease
|
|
1548
1555
|
},
|
|
1549
|
-
input.openingInput === void 0 ? void 0 : { providerKey: input.capabilities.providerKey, input: input.openingInput }
|
|
1556
|
+
input.openingInput === void 0 ? void 0 : { providerKey: input.capabilities.providerKey, input: input.openingInput },
|
|
1557
|
+
input.sessionInteractionOwner
|
|
1550
1558
|
);
|
|
1551
1559
|
}
|
|
1552
1560
|
}
|
package/dist/sessions.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { MaybePromise } from "./foundation.js";
|
|
|
3
3
|
import type { AgentSessionHostBinding, AgentSessionHostBindingSupport } from "./hostBindings/types.js";
|
|
4
4
|
import type { AgentProviderOutput } from "./outputs.js";
|
|
5
5
|
import type { AgentArtifactCandidate } from "./artifacts.js";
|
|
6
|
+
import type { AgentSessionInteractionContext, AgentSessionInteractionSupport } from "./sessionInteractions/types.js";
|
|
6
7
|
import type { AgentEnvironmentObservationPort } from "./environment/types.js";
|
|
7
8
|
export interface AgentProviderSessionContext {
|
|
8
9
|
readonly sessionId: AgentSessionId;
|
|
@@ -10,6 +11,7 @@ export interface AgentProviderSessionContext {
|
|
|
10
11
|
readonly configuration: AgentSessionConfiguration;
|
|
11
12
|
readonly signal?: AbortSignal;
|
|
12
13
|
readonly hostBinding?: AgentSessionHostBinding;
|
|
14
|
+
readonly interactions?: AgentSessionInteractionContext;
|
|
13
15
|
}
|
|
14
16
|
export type AgentSessionBindingCreatedObserver = (binding: AgentSessionBinding) => void;
|
|
15
17
|
export interface AgentProviderCreateSessionInput extends AgentProviderSessionContext {
|
|
@@ -212,6 +214,7 @@ export type AgentProviderAuthentication = Readonly<{
|
|
|
212
214
|
cancel: (input: AgentProviderAuthenticationCancelInput) => MaybePromise<AgentProviderOperationResult>;
|
|
213
215
|
}>;
|
|
214
216
|
export interface AgentProviderAdapter {
|
|
217
|
+
readonly sessionInteractions?: AgentSessionInteractionSupport;
|
|
215
218
|
readonly hostBinding?: AgentSessionHostBindingSupport;
|
|
216
219
|
readonly createSession: (input: AgentProviderCreateSessionInput) => MaybePromise<AgentProviderSession>;
|
|
217
220
|
readonly resumption: AgentSessionResumption;
|
|
@@ -15,7 +15,6 @@ class AgentProviderConformanceError extends Error {
|
|
|
15
15
|
this.check = check;
|
|
16
16
|
this.name = "AgentProviderConformanceError";
|
|
17
17
|
}
|
|
18
|
-
check;
|
|
19
18
|
}
|
|
20
19
|
function requireCheck(condition, check, message) {
|
|
21
20
|
if (!condition) throw new AgentProviderConformanceError(check, message);
|
|
@@ -44,7 +44,7 @@ function defaultCapabilities(providerKey) {
|
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
return parseAgentCapabilities({
|
|
47
|
-
protocolVersion:
|
|
47
|
+
protocolVersion: 11,
|
|
48
48
|
providerKey,
|
|
49
49
|
sessions: { create: true, resume: true, branch: { kind: "through_turn" } },
|
|
50
50
|
turns: {
|
|
@@ -55,6 +55,7 @@ function defaultCapabilities(providerKey) {
|
|
|
55
55
|
requests: {
|
|
56
56
|
approval: {
|
|
57
57
|
kind: "supported",
|
|
58
|
+
providerManagedRemembrance: false,
|
|
58
59
|
modes: [{ persistence: "once", scopeKinds: ["exact_action"] }]
|
|
59
60
|
},
|
|
60
61
|
elicitation: {
|
|
@@ -165,7 +166,7 @@ function sessionBinding(state, sessionId) {
|
|
|
165
166
|
};
|
|
166
167
|
}
|
|
167
168
|
function eventBase(sessionId, turnId, occurredAt) {
|
|
168
|
-
return { protocolVersion:
|
|
169
|
+
return { protocolVersion: 11, sessionId, turnId, occurredAt };
|
|
169
170
|
}
|
|
170
171
|
function fakeEnvironmentSnapshot(environmentId) {
|
|
171
172
|
return parseAgentEnvironmentSnapshot({
|
|
@@ -251,15 +252,13 @@ function requestForTurn(turnId) {
|
|
|
251
252
|
optionId: parseAgentApprovalOptionId("approval:allow-once"),
|
|
252
253
|
label: "Allow once",
|
|
253
254
|
decision: "approved",
|
|
254
|
-
persistence: "once",
|
|
255
|
-
scope: { kind: "exact_action" }
|
|
255
|
+
consequence: { kind: "scoped", persistence: "once", scope: { kind: "exact_action" } }
|
|
256
256
|
},
|
|
257
257
|
{
|
|
258
258
|
optionId: parseAgentApprovalOptionId("approval:deny-once"),
|
|
259
259
|
label: "Deny",
|
|
260
260
|
decision: "denied",
|
|
261
|
-
persistence: "once",
|
|
262
|
-
scope: { kind: "exact_action" }
|
|
261
|
+
consequence: { kind: "scoped", persistence: "once", scope: { kind: "exact_action" } }
|
|
263
262
|
}
|
|
264
263
|
]
|
|
265
264
|
};
|
|
@@ -25,7 +25,7 @@ function createAgentTurnRequestAdmission(input) {
|
|
|
25
25
|
};
|
|
26
26
|
const suspend = () => {
|
|
27
27
|
const suspendedGeneration = generation;
|
|
28
|
-
const suspension =
|
|
28
|
+
const suspension = Symbol("interruption");
|
|
29
29
|
suspendedGeneration.suspensions.add(suspension);
|
|
30
30
|
for (const [requestId, pending] of input.pendingRequests) {
|
|
31
31
|
suspendedGeneration.withheldRequests.set(requestId, pending);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agen-ai/agent-runtime",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Provider-neutral driver, instance, adapter, session, output, and conformance contracts for coding-agent runtimes.",
|
|
6
6
|
"type": "module",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@agen-ai/agent-protocol": "^0.4.
|
|
34
|
+
"@agen-ai/agent-protocol": "^0.4.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"tsup": "^8.5.0"
|