@agen-ai/agent-runtime 0.4.2 → 0.4.3
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 +24 -5
- package/dist/sessionAdmission.d.ts +2 -0
- package/dist/sessionAdmission.js +13 -0
- package/dist/sessionValidation.d.ts +2 -0
- package/dist/sessionValidation.js +135 -121
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ sessions; each returned session owns its binding and conversation-local operatio
|
|
|
9
9
|
The runtime depends only on `@agen-ai/agent-protocol`. It has no concept of tenants, SaaS
|
|
10
10
|
workspaces, assigned users, database rows, persistence sequence, visibility, billing, host boots,
|
|
11
11
|
distributed leases, or storage policy. A host must authorize and select an instance before calling this SPI.
|
|
12
|
-
This
|
|
12
|
+
This package implements Agent Protocol V12 at coordinated SDK version `0.4.3`,
|
|
13
13
|
including tagged decision responses and exact turn request unavailability. Published `0.4.1`
|
|
14
14
|
retains V11 and its qualification evidence; the earlier `0.4.0` release retains V10.
|
|
15
15
|
The runtime also provides neutral session forms, plan reviews, staged native continuations and
|
|
@@ -157,10 +157,11 @@ reopen an older request. A host must cancel human decisions when their execution
|
|
|
157
157
|
those tasks during cleanup. Keep the session or exact opening-cleanup receipt if cleanup fails;
|
|
158
158
|
disposing its registry or host resources before quiescence would lose the retained owner.
|
|
159
159
|
|
|
160
|
-
`runtime.retrying` reports a retry already owned by the provider on the active turn. It preserves
|
|
160
|
+
`runtime.retrying` reports a retry already owned by the provider on the active turn or operation. It preserves
|
|
161
161
|
turn ownership, pending requests, and per-output backpressure; it neither starts another execution
|
|
162
162
|
nor completes the turn. It is rejected before `turn.started`, after `turn.completed`, after a
|
|
163
|
-
`final_diff` terminal materialization
|
|
163
|
+
`final_diff` terminal materialization on a turn. Current source also admits it through an owned
|
|
164
|
+
session operation's awaited `onOutput`, with the exact `observationTurnId` and no `turn.started`. The event's neutral
|
|
164
165
|
failure category and recovery hint describe the observed condition. A recovery hint never authorizes
|
|
165
166
|
replaying work or changes an uncertain execution outcome. Contract failures, delegated-operation
|
|
166
167
|
started evidence, and retained cleanup responsibilities remain separate from those failure values.
|
|
@@ -188,6 +189,23 @@ provider-delegated steering failures throw `AgentProviderDelegatedOperationError
|
|
|
188
189
|
cause and explicit started-execution evidence so a host can retire the unusable session. Platform
|
|
189
190
|
scheduling and provider-native queue modes are intentionally outside this SPI.
|
|
190
191
|
|
|
192
|
+
Current source reserves the shared execution slot for `idle_session`/`immediate` operations after
|
|
193
|
+
descriptor validation, through native settlement and awaited output acceptance. Caller turns and
|
|
194
|
+
native continuations cannot overlap that reservation. Exact cached idempotent results are returned
|
|
195
|
+
before reserving another execution. Close stops admission and initiates native quiescence before
|
|
196
|
+
joining entered operation work; failed cleanup retains its stopped owner for retry. This lifecycle
|
|
197
|
+
correction and operation retry observations are included in `0.4.3`, using the existing
|
|
198
|
+
Agent Protocol V12 and operation SPI.
|
|
199
|
+
|
|
200
|
+
Discover the operation through `session.operations` and its offered descriptor, using an exact
|
|
201
|
+
application-configured ID. Pass the descriptor revision as `expectedRevision`, its exact fields,
|
|
202
|
+
a fresh invocation ID and an independent observation correlation; the catalog revision is a
|
|
203
|
+
different value. Confirmation is host-owned. A completed result proves command completion, while
|
|
204
|
+
an accepted completed `context_compaction` item proves an observed compaction effect. Do not infer
|
|
205
|
+
effects from English output text, manufacture token savings, or replay an uncertain operation.
|
|
206
|
+
The exported repository's `examples/operations.ts` demonstrates these cases against public APIs
|
|
207
|
+
and is compiled and executed in the isolated packed-consumer gate.
|
|
208
|
+
|
|
191
209
|
Configuration selection, operation invocation, and collaboration mutation use the same execution
|
|
192
210
|
receipt rule: stale or malformed input fails before provider delegation, while any failure after
|
|
193
211
|
the candidate reports execution start is wrapped as `AgentProviderDelegatedOperationError` and
|
|
@@ -533,13 +551,14 @@ close before joining its reader and actual callback tasks; failure also starts c
|
|
|
533
551
|
failures and cleanup failures remain observable. A callback that ignores cancellation
|
|
534
552
|
remains owned until its actual promise settles.
|
|
535
553
|
|
|
536
|
-
The coordinated SDK release is `0.4.
|
|
554
|
+
The coordinated SDK release is `0.4.3` and implements Agent Protocol V12.
|
|
555
|
+
The earlier `0.4.1` release retains V11.
|
|
537
556
|
The earlier `0.4.0` release retains V10.
|
|
538
557
|
The earlier public `0.3.0` and `0.3.1` releases implemented V9 and remain historical.
|
|
539
558
|
Keep installed packages in the seven-package SDK release family on the coordinated version; the
|
|
540
559
|
orchestration and ACP packages remain optional. Every materialized instance requires `environment` and
|
|
541
560
|
`accountQuota`; every session requires `environment`. The former standalone `integrations`
|
|
542
|
-
observation port is removed. The public runtime implements Agent Protocol
|
|
561
|
+
observation port is removed. The public runtime implements Agent Protocol V12 with one current
|
|
543
562
|
adapter/session surface. Package versions remain independent of private transport and product
|
|
544
563
|
persistence versions.
|
|
545
564
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { AgentProviderKey, AgentRequestId } from "@agen-ai/agent-protocol";
|
|
2
2
|
export declare function createAgentSessionAdmission<Execution = unknown>(providerKey: AgentProviderKey): {
|
|
3
|
+
trackOperation(): () => void;
|
|
4
|
+
joinOperations(): Promise<void>;
|
|
3
5
|
reserveExecution(): object;
|
|
4
6
|
installExecution(token: object, execution: Execution): void;
|
|
5
7
|
releaseExecution(token: object): void;
|
package/dist/sessionAdmission.js
CHANGED
|
@@ -6,7 +6,20 @@ function createAgentSessionAdmission(providerKey) {
|
|
|
6
6
|
let requestIdBytes = 0;
|
|
7
7
|
let slot;
|
|
8
8
|
let stopped = false;
|
|
9
|
+
const operations = /* @__PURE__ */ new Set();
|
|
9
10
|
return {
|
|
11
|
+
trackOperation() {
|
|
12
|
+
if (stopped) throwAgentProviderContractError(providerKey, "session_unusable", "Session admission is stopped.");
|
|
13
|
+
const completion = Promise.withResolvers();
|
|
14
|
+
operations.add(completion.promise);
|
|
15
|
+
return () => {
|
|
16
|
+
operations.delete(completion.promise);
|
|
17
|
+
completion.resolve();
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
async joinOperations() {
|
|
21
|
+
await Promise.all(operations);
|
|
22
|
+
},
|
|
10
23
|
reserveExecution() {
|
|
11
24
|
if (stopped) throwAgentProviderContractError(providerKey, "session_unusable", "Session admission is stopped.");
|
|
12
25
|
if (slot) throwAgentProviderContractError(providerKey, "concurrent_turn", "Provider session already owns an execution.");
|
|
@@ -49,6 +49,8 @@ interface ActiveAgentTurn {
|
|
|
49
49
|
}
|
|
50
50
|
export declare function createAgentSessionValidationOwner(capabilities: AgentCapabilities, sessionId: AgentSessionId): {
|
|
51
51
|
sessionAdmission: {
|
|
52
|
+
trackOperation(): () => void;
|
|
53
|
+
joinOperations(): Promise<void>;
|
|
52
54
|
reserveExecution(): object;
|
|
53
55
|
installExecution(token: object, execution: ActiveAgentTurn): void;
|
|
54
56
|
releaseExecution(token: object): void;
|
|
@@ -499,6 +499,7 @@ const SESSION_OPERATION_OBSERVATION_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
499
499
|
"resource.updated",
|
|
500
500
|
"runtime.warning",
|
|
501
501
|
"runtime.error",
|
|
502
|
+
"runtime.retrying",
|
|
502
503
|
"provider.diagnostic"
|
|
503
504
|
]);
|
|
504
505
|
function observeSessionOperationOutput(input) {
|
|
@@ -1048,142 +1049,154 @@ function validateAgentProviderSession(input) {
|
|
|
1048
1049
|
invokeOperation: async (operationInput) => {
|
|
1049
1050
|
requireUsable();
|
|
1050
1051
|
throwIfAgentOperationAborted(operationInput.signal);
|
|
1051
|
-
|
|
1052
|
-
|
|
1052
|
+
const settle = validationOwner.sessionAdmission.trackOperation();
|
|
1053
|
+
const signal = operationInput.signal === void 0 ? sessionLifetime.signal : AbortSignal.any([operationInput.signal, sessionLifetime.signal]);
|
|
1054
|
+
operationInput = { ...operationInput, signal };
|
|
1053
1055
|
try {
|
|
1054
|
-
|
|
1055
|
-
observationTurnId
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
);
|
|
1074
|
-
if (descriptor === void 0) {
|
|
1075
|
-
return throwAgentProviderContractError(
|
|
1076
|
-
providerKey,
|
|
1077
|
-
"input_operation_mismatch",
|
|
1078
|
-
"Operation invocation does not identify an offered operation."
|
|
1079
|
-
);
|
|
1080
|
-
}
|
|
1081
|
-
try {
|
|
1082
|
-
invocation = parseAgentOperationInvocationFor(
|
|
1083
|
-
descriptor,
|
|
1084
|
-
invocation
|
|
1056
|
+
let invocation;
|
|
1057
|
+
let observationTurnId;
|
|
1058
|
+
try {
|
|
1059
|
+
invocation = parseAgentOperationInvocation(operationInput.invocation);
|
|
1060
|
+
observationTurnId = parseAgentTurnId(
|
|
1061
|
+
operationInput.observationTurnId
|
|
1062
|
+
);
|
|
1063
|
+
} catch {
|
|
1064
|
+
return throwAgentProviderContractError(
|
|
1065
|
+
providerKey,
|
|
1066
|
+
"input_operation_mismatch",
|
|
1067
|
+
"Operation invocation is invalid."
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
const catalog = validateAgentOperationCatalogForCapabilities(
|
|
1071
|
+
capabilities,
|
|
1072
|
+
await declaredOperations.listOperations(
|
|
1073
|
+
operationInput.signal === void 0 ? {} : { signal: operationInput.signal }
|
|
1074
|
+
)
|
|
1085
1075
|
);
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
providerKey,
|
|
1089
|
-
"input_operation_mismatch",
|
|
1090
|
-
"Operation invocation is stale or outside the offered descriptor."
|
|
1076
|
+
const descriptor = catalog.operations.find(
|
|
1077
|
+
(operation) => operation.operationId === invocation.operationId
|
|
1091
1078
|
);
|
|
1092
|
-
|
|
1093
|
-
const existing = interactionState.operationInvocations.get(
|
|
1094
|
-
invocation.invocationId
|
|
1095
|
-
);
|
|
1096
|
-
if (existing !== void 0) {
|
|
1097
|
-
if (JSON.stringify(existing.invocation) !== JSON.stringify(invocation)) {
|
|
1079
|
+
if (descriptor === void 0) {
|
|
1098
1080
|
return throwAgentProviderContractError(
|
|
1099
1081
|
providerKey,
|
|
1100
1082
|
"input_operation_mismatch",
|
|
1101
|
-
"Operation invocation
|
|
1083
|
+
"Operation invocation does not identify an offered operation."
|
|
1102
1084
|
);
|
|
1103
1085
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1086
|
+
try {
|
|
1087
|
+
invocation = parseAgentOperationInvocationFor(
|
|
1088
|
+
descriptor,
|
|
1089
|
+
invocation
|
|
1090
|
+
);
|
|
1091
|
+
} catch {
|
|
1092
|
+
return throwAgentProviderContractError(
|
|
1093
|
+
providerKey,
|
|
1094
|
+
"input_operation_mismatch",
|
|
1095
|
+
"Operation invocation is stale or outside the offered descriptor."
|
|
1096
|
+
);
|
|
1106
1097
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
"input_operation_mismatch",
|
|
1110
|
-
"Operation invocation ID is already active or is not replayable."
|
|
1098
|
+
const existing = interactionState.operationInvocations.get(
|
|
1099
|
+
invocation.invocationId
|
|
1111
1100
|
);
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
};
|
|
1116
|
-
const observationState = {
|
|
1117
|
-
fileChangeMode: capabilities.output.fileChanges,
|
|
1118
|
-
observedItems: /* @__PURE__ */ new Map(),
|
|
1119
|
-
proposedPlans: /* @__PURE__ */ new Map(),
|
|
1120
|
-
generatedResourceIds: /* @__PURE__ */ new Set(),
|
|
1121
|
-
started: true,
|
|
1122
|
-
terminal: false,
|
|
1123
|
-
finalDiffObserved: false
|
|
1124
|
-
};
|
|
1125
|
-
interactionState.operationInvocations.set(
|
|
1126
|
-
invocation.invocationId,
|
|
1127
|
-
trackedInvocation
|
|
1128
|
-
);
|
|
1129
|
-
try {
|
|
1130
|
-
const result = await delegateProviderMutation({
|
|
1131
|
-
operation: "invoke_operation",
|
|
1132
|
-
observer: operationInput.onProviderExecutionStarted,
|
|
1133
|
-
invoke: (onProviderExecutionStarted, onOutput) => declaredOperations.invokeOperation({
|
|
1134
|
-
invocation,
|
|
1135
|
-
observationTurnId,
|
|
1136
|
-
onProviderExecutionStarted,
|
|
1137
|
-
onOutput,
|
|
1138
|
-
...operationInput.signal === void 0 ? {} : { signal: operationInput.signal }
|
|
1139
|
-
}),
|
|
1140
|
-
observeOutput: async (candidate) => {
|
|
1141
|
-
const output = validateAgentProviderOutputForContext(
|
|
1142
|
-
candidate,
|
|
1143
|
-
{
|
|
1144
|
-
...outputContext(observationTurnId),
|
|
1145
|
-
operationInvocationId: invocation.invocationId
|
|
1146
|
-
}
|
|
1147
|
-
);
|
|
1148
|
-
observeSessionOperationOutput({
|
|
1149
|
-
capabilities,
|
|
1150
|
-
providerKey,
|
|
1151
|
-
output,
|
|
1152
|
-
state: observationState,
|
|
1153
|
-
contextUsageState,
|
|
1154
|
-
interactionState
|
|
1155
|
-
});
|
|
1156
|
-
await operationInput.onOutput?.(output);
|
|
1157
|
-
},
|
|
1158
|
-
validate: (candidate) => {
|
|
1159
|
-
const result2 = validateAgentOperationResultTransition({
|
|
1101
|
+
if (existing !== void 0) {
|
|
1102
|
+
if (JSON.stringify(existing.invocation) !== JSON.stringify(invocation)) {
|
|
1103
|
+
return throwAgentProviderContractError(
|
|
1160
1104
|
providerKey,
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
descriptor,
|
|
1164
|
-
invocation,
|
|
1165
|
-
candidate
|
|
1166
|
-
),
|
|
1167
|
-
previous: interactionState.operationResults.get(
|
|
1168
|
-
invocation.invocationId
|
|
1169
|
-
)
|
|
1170
|
-
});
|
|
1171
|
-
interactionState.operationResults.set(
|
|
1172
|
-
result2.invocationId,
|
|
1173
|
-
result2
|
|
1105
|
+
"input_operation_mismatch",
|
|
1106
|
+
"Operation invocation ID was reused with conflicting input."
|
|
1174
1107
|
);
|
|
1175
|
-
return result2;
|
|
1176
1108
|
}
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
invocation.
|
|
1109
|
+
if (descriptor.idempotency === "required" && existing.result !== void 0) {
|
|
1110
|
+
return existing.result;
|
|
1111
|
+
}
|
|
1112
|
+
return throwAgentProviderContractError(
|
|
1113
|
+
providerKey,
|
|
1114
|
+
"input_operation_mismatch",
|
|
1115
|
+
"Operation invocation ID is already active or is not replayable."
|
|
1184
1116
|
);
|
|
1185
1117
|
}
|
|
1186
|
-
|
|
1118
|
+
requireUsable();
|
|
1119
|
+
signal.throwIfAborted();
|
|
1120
|
+
const reservation = descriptor.timing === "idle_session" && descriptor.executionMode === "immediate" ? validationOwner.reserveExecution() : void 0;
|
|
1121
|
+
const trackedInvocation = {
|
|
1122
|
+
invocation
|
|
1123
|
+
};
|
|
1124
|
+
const observationState = {
|
|
1125
|
+
fileChangeMode: capabilities.output.fileChanges,
|
|
1126
|
+
observedItems: /* @__PURE__ */ new Map(),
|
|
1127
|
+
proposedPlans: /* @__PURE__ */ new Map(),
|
|
1128
|
+
generatedResourceIds: /* @__PURE__ */ new Set(),
|
|
1129
|
+
started: true,
|
|
1130
|
+
terminal: false,
|
|
1131
|
+
finalDiffObserved: false
|
|
1132
|
+
};
|
|
1133
|
+
interactionState.operationInvocations.set(
|
|
1134
|
+
invocation.invocationId,
|
|
1135
|
+
trackedInvocation
|
|
1136
|
+
);
|
|
1137
|
+
try {
|
|
1138
|
+
const result = await delegateProviderMutation({
|
|
1139
|
+
operation: "invoke_operation",
|
|
1140
|
+
observer: operationInput.onProviderExecutionStarted,
|
|
1141
|
+
invoke: (onProviderExecutionStarted, onOutput) => declaredOperations.invokeOperation({
|
|
1142
|
+
invocation,
|
|
1143
|
+
observationTurnId,
|
|
1144
|
+
onProviderExecutionStarted,
|
|
1145
|
+
onOutput,
|
|
1146
|
+
...operationInput.signal === void 0 ? {} : { signal: operationInput.signal }
|
|
1147
|
+
}),
|
|
1148
|
+
observeOutput: async (candidate) => {
|
|
1149
|
+
const output = validateAgentProviderOutputForContext(
|
|
1150
|
+
candidate,
|
|
1151
|
+
{
|
|
1152
|
+
...outputContext(observationTurnId),
|
|
1153
|
+
operationInvocationId: invocation.invocationId
|
|
1154
|
+
}
|
|
1155
|
+
);
|
|
1156
|
+
observeSessionOperationOutput({
|
|
1157
|
+
capabilities,
|
|
1158
|
+
providerKey,
|
|
1159
|
+
output,
|
|
1160
|
+
state: observationState,
|
|
1161
|
+
contextUsageState,
|
|
1162
|
+
interactionState
|
|
1163
|
+
});
|
|
1164
|
+
await operationInput.onOutput?.(output);
|
|
1165
|
+
},
|
|
1166
|
+
validate: (candidate) => {
|
|
1167
|
+
const result2 = validateAgentOperationResultTransition({
|
|
1168
|
+
providerKey,
|
|
1169
|
+
candidate: validateAgentOperationResultForInvocation(
|
|
1170
|
+
providerKey,
|
|
1171
|
+
descriptor,
|
|
1172
|
+
invocation,
|
|
1173
|
+
candidate
|
|
1174
|
+
),
|
|
1175
|
+
previous: interactionState.operationResults.get(
|
|
1176
|
+
invocation.invocationId
|
|
1177
|
+
)
|
|
1178
|
+
});
|
|
1179
|
+
interactionState.operationResults.set(
|
|
1180
|
+
result2.invocationId,
|
|
1181
|
+
result2
|
|
1182
|
+
);
|
|
1183
|
+
return result2;
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
trackedInvocation.result = result;
|
|
1187
|
+
return result;
|
|
1188
|
+
} catch (error) {
|
|
1189
|
+
if (!(error instanceof AgentProviderDelegatedOperationError)) {
|
|
1190
|
+
interactionState.operationInvocations.delete(
|
|
1191
|
+
invocation.invocationId
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
throw error;
|
|
1195
|
+
} finally {
|
|
1196
|
+
if (reservation !== void 0) validationOwner.releaseExecution(reservation);
|
|
1197
|
+
}
|
|
1198
|
+
} finally {
|
|
1199
|
+
settle();
|
|
1187
1200
|
}
|
|
1188
1201
|
}
|
|
1189
1202
|
});
|
|
@@ -1450,6 +1463,7 @@ function validateAgentProviderSession(input) {
|
|
|
1450
1463
|
}
|
|
1451
1464
|
await input.sessionInteractionOwner?.join();
|
|
1452
1465
|
await closingTurn?.owner.join();
|
|
1466
|
+
await validationOwner.sessionAdmission.joinOperations();
|
|
1453
1467
|
await input.hostBindingLease?.release();
|
|
1454
1468
|
validationOwner.completeClose();
|
|
1455
1469
|
};
|
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.3",
|
|
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.3"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"tsup": "^8.5.0"
|