@agen-ai/agent-runtime 0.1.0 → 0.2.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 +17 -3
- package/dist/outputValidation.js +35 -2
- package/dist/sessionValidation.js +112 -5
- package/dist/testing/fakeProvider.js +46 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ its binding and conversation-local operations.
|
|
|
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
|
leases, or storage policy. A host must authorize and select an instance before calling this SPI.
|
|
12
|
+
The current coordinated deployment tuple is Agent Protocol V7, private host V15/catalog V9, and Workspaces event V9.
|
|
12
13
|
|
|
13
14
|
## Entrypoints
|
|
14
15
|
|
|
@@ -38,6 +39,12 @@ exactly once before returning the matching session. Capability-dependent operati
|
|
|
38
39
|
`supported`/`unsupported` discriminants, and the runtime rejects handlers that disagree with the
|
|
39
40
|
instance capability declaration.
|
|
40
41
|
|
|
42
|
+
Approval continuations are refusal-first. Before delegating to the candidate adapter, the
|
|
43
|
+
validated session proves that the request is still pending and unexpired and that a selected
|
|
44
|
+
`optionId` was offered by that exact request. Provider-emitted approval requests must correlate to
|
|
45
|
+
a live item or exact proposed-plan artifact, and every option must fit an advertised
|
|
46
|
+
persistence/scope mode.
|
|
47
|
+
|
|
41
48
|
The host should serialize mutating operations for a given session. Separate session objects may
|
|
42
49
|
run concurrently, so provider implementations must isolate their conversation-local state.
|
|
43
50
|
`runTurn` and `resolveRequest` both preserve consumer backpressure: the provider does not resume
|
|
@@ -53,6 +60,12 @@ turn terminalized; unless the result also carries a terminal event, the validate
|
|
|
53
60
|
unusable and must be closed and rematerialized. A close failure makes the session unusable while
|
|
54
61
|
leaving close itself retryable.
|
|
55
62
|
|
|
63
|
+
When context usage is advertised, the validated session enforces the declared measurement scopes
|
|
64
|
+
and cumulative fields across turns. Identical consecutive samples and decreasing cumulative
|
|
65
|
+
counters are rejected. Occupancy may decrease only after a completed advertised compaction item;
|
|
66
|
+
the next accepted sample consumes that allowance. Context output remains subject to the same
|
|
67
|
+
per-output backpressure and terminal ordering as every other provider event.
|
|
68
|
+
|
|
56
69
|
When `capabilities.turns.steer` is true, the session exposes `steering.steerTurn`. Steering accepts
|
|
57
70
|
the existing turn ID plus the same canonical `parts` and optional `summary` used to start a turn.
|
|
58
71
|
It does not create or own an output stream: model output continues on the original `runTurn`
|
|
@@ -123,12 +136,13 @@ turn/request ordering, request resolution, steering, interruption, configuration
|
|
|
123
136
|
close, and idempotent disposal. Unsupported operations must remain explicit discriminants and
|
|
124
137
|
must not expose handlers.
|
|
125
138
|
|
|
126
|
-
The package is at `0.1
|
|
139
|
+
The package is at `0.2.1` while the public SPI is being proven with external adapters. Minor
|
|
127
140
|
releases may include breaking changes during this beta period, and those changes will be called out
|
|
128
141
|
in the release notes.
|
|
129
142
|
|
|
130
|
-
The
|
|
131
|
-
|
|
143
|
+
The public runtime implements Agent Protocol V7. Its package version remains independent of private
|
|
144
|
+
host, catalog, persistence, and member-projection versions. Version `0.2.0` directly replaces the
|
|
145
|
+
V6/`0.1.0` API; see the repository `MIGRATING-TO-0.2.md` guide.
|
|
132
146
|
|
|
133
147
|
Run the clean packed-consumer proof before any release:
|
|
134
148
|
|
package/dist/outputValidation.js
CHANGED
|
@@ -51,12 +51,43 @@ function isContentStreamCapabilitySupported(capabilities, streamKind) {
|
|
|
51
51
|
}
|
|
52
52
|
return unsupportedCapabilitySemantic(streamKind);
|
|
53
53
|
}
|
|
54
|
+
function isApprovalRequestCapabilitySupported(capabilities, event) {
|
|
55
|
+
const request = event.payload.request;
|
|
56
|
+
if (request.requestKind !== "approval") return false;
|
|
57
|
+
const capability = capabilities.requests.approval;
|
|
58
|
+
return capability.kind === "supported" && request.options.every(
|
|
59
|
+
(option) => capability.modes.some(
|
|
60
|
+
(mode) => mode.persistence === option.persistence && mode.scopeKinds.includes(option.scope.kind)
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
function isContextUsageCapabilitySupported(capabilities, event) {
|
|
65
|
+
const capability = capabilities.context.usage;
|
|
66
|
+
if (capability.kind !== "supported" || !capability.measurementScopes.includes(
|
|
67
|
+
event.payload.measurementScope
|
|
68
|
+
)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
if (event.payload.cumulative !== void 0 && Object.keys(event.payload.cumulative).some(
|
|
72
|
+
(field) => !capability.cumulativeFields.includes(
|
|
73
|
+
field
|
|
74
|
+
)
|
|
75
|
+
)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return event.payload.compaction === void 0 || capabilities.context.compaction.kind === "supported";
|
|
79
|
+
}
|
|
54
80
|
function isEventCapabilitySupported(capabilities, event) {
|
|
55
81
|
switch (event.type) {
|
|
56
82
|
case "item.started":
|
|
57
83
|
case "item.updated":
|
|
58
|
-
case "item.completed":
|
|
84
|
+
case "item.completed": {
|
|
85
|
+
if (event.payload.itemKind === "context_compaction") {
|
|
86
|
+
const compaction = capabilities.context.compaction;
|
|
87
|
+
return compaction.kind === "supported" && (event.payload.details.trigger === "unknown" || compaction.triggers.includes(event.payload.details.trigger));
|
|
88
|
+
}
|
|
59
89
|
return isItemKindCapabilitySupported(capabilities, event.payload.itemKind);
|
|
90
|
+
}
|
|
60
91
|
case "content.delta":
|
|
61
92
|
return capabilities.output.streaming && isContentStreamCapabilitySupported(
|
|
62
93
|
capabilities,
|
|
@@ -72,9 +103,11 @@ function isEventCapabilitySupported(capabilities, event) {
|
|
|
72
103
|
event.payload.artifact.kind
|
|
73
104
|
);
|
|
74
105
|
case "request.opened":
|
|
75
|
-
return event.payload.request.requestKind === "approval" ? capabilities
|
|
106
|
+
return event.payload.request.requestKind === "approval" ? isApprovalRequestCapabilitySupported(capabilities, event) : capabilities.requests.elicitation.kind === "structured" || capabilities.requests.elicitation.kind === "text" && event.payload.request.fields.every(
|
|
76
107
|
(field) => field.kind === "text"
|
|
77
108
|
);
|
|
109
|
+
case "context.usage.updated":
|
|
110
|
+
return isContextUsageCapabilitySupported(capabilities, event);
|
|
78
111
|
case "turn.started":
|
|
79
112
|
case "turn.state_changed":
|
|
80
113
|
case "turn.completed":
|
|
@@ -64,8 +64,74 @@ const FINAL_DIFF_TRAILING_EVENT_TYPES = [
|
|
|
64
64
|
"runtime.warning",
|
|
65
65
|
"turn.completed"
|
|
66
66
|
];
|
|
67
|
+
function assertApprovalSubjectCorrelation(input) {
|
|
68
|
+
const request = input.event.payload.request;
|
|
69
|
+
if (request.requestKind !== "approval") return;
|
|
70
|
+
if (request.subject.kind === "plan") {
|
|
71
|
+
if (input.state.proposedPlans.get(request.subject.artifactId) !== request.requestId) {
|
|
72
|
+
invalidTurnSequence(
|
|
73
|
+
input.providerKey,
|
|
74
|
+
"Provider approval request does not identify a proposed plan from this turn."
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const status = input.state.observedItems.get(request.subject.itemId);
|
|
80
|
+
if (status !== "pending" && status !== "in_progress") {
|
|
81
|
+
invalidTurnSequence(
|
|
82
|
+
input.providerKey,
|
|
83
|
+
"Provider approval request does not identify a live item from this turn."
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function observeContextUsage(input) {
|
|
88
|
+
const previous = input.state.latestByScope.get(input.usage.measurementScope);
|
|
89
|
+
if (previous !== void 0) {
|
|
90
|
+
if (JSON.stringify(previous) === JSON.stringify(input.usage)) {
|
|
91
|
+
invalidTurnSequence(
|
|
92
|
+
input.providerKey,
|
|
93
|
+
"Provider emitted a duplicate context usage sample."
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
if (input.usage.usedTokens < previous.usedTokens && !input.state.compactionReadyScopes.has(input.usage.measurementScope)) {
|
|
97
|
+
invalidTurnSequence(
|
|
98
|
+
input.providerKey,
|
|
99
|
+
"Provider context occupancy cannot decrease without completed compaction."
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const cumulative = input.usage.cumulative;
|
|
104
|
+
if (cumulative !== void 0) {
|
|
105
|
+
const previousCumulative = input.state.cumulativeByScope.get(
|
|
106
|
+
input.usage.measurementScope
|
|
107
|
+
);
|
|
108
|
+
for (const field of Object.keys(cumulative)) {
|
|
109
|
+
const value = cumulative[field];
|
|
110
|
+
const previousValue = previousCumulative?.[field];
|
|
111
|
+
if (value !== void 0 && previousValue !== void 0 && value < previousValue) {
|
|
112
|
+
invalidTurnSequence(
|
|
113
|
+
input.providerKey,
|
|
114
|
+
"Provider context cumulative counters cannot decrease."
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
input.state.cumulativeByScope.set(input.usage.measurementScope, {
|
|
119
|
+
...previousCumulative,
|
|
120
|
+
...cumulative
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
input.state.latestByScope.set(input.usage.measurementScope, input.usage);
|
|
124
|
+
input.state.compactionReadyScopes.delete(input.usage.measurementScope);
|
|
125
|
+
}
|
|
67
126
|
function observeTurnEvent(input) {
|
|
68
|
-
const {
|
|
127
|
+
const {
|
|
128
|
+
contextUsageState,
|
|
129
|
+
event,
|
|
130
|
+
openedRequestIds,
|
|
131
|
+
pendingRequests,
|
|
132
|
+
providerKey,
|
|
133
|
+
state
|
|
134
|
+
} = input;
|
|
69
135
|
if (state.terminal) {
|
|
70
136
|
invalidTurnSequence(
|
|
71
137
|
providerKey,
|
|
@@ -108,6 +174,24 @@ function observeTurnEvent(input) {
|
|
|
108
174
|
);
|
|
109
175
|
}
|
|
110
176
|
}
|
|
177
|
+
if (event.type === "item.started" || event.type === "item.updated" || event.type === "item.completed") {
|
|
178
|
+
state.observedItems.set(event.payload.itemId, event.payload.status);
|
|
179
|
+
if (event.payload.itemKind === "context_compaction" && event.type === "item.completed" && event.payload.status === "completed") {
|
|
180
|
+
for (const scope of ["session", "materialization"]) {
|
|
181
|
+
contextUsageState.compactionReadyScopes.add(scope);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (event.type === "turn.plan.proposed") {
|
|
186
|
+
state.proposedPlans.set(event.payload.artifactId, event.payload.requestId);
|
|
187
|
+
}
|
|
188
|
+
if (event.type === "context.usage.updated") {
|
|
189
|
+
observeContextUsage({
|
|
190
|
+
providerKey,
|
|
191
|
+
usage: event.payload,
|
|
192
|
+
state: contextUsageState
|
|
193
|
+
});
|
|
194
|
+
}
|
|
111
195
|
if (event.type === "request.opened") {
|
|
112
196
|
if (pendingRequests.size > 0) {
|
|
113
197
|
invalidTurnSequence(
|
|
@@ -122,6 +206,7 @@ function observeTurnEvent(input) {
|
|
|
122
206
|
"Provider reused a request ID within a session."
|
|
123
207
|
);
|
|
124
208
|
}
|
|
209
|
+
assertApprovalSubjectCorrelation({ providerKey, event, state });
|
|
125
210
|
openedRequestIds.add(requestId);
|
|
126
211
|
pendingRequests.set(requestId, {
|
|
127
212
|
request: event.payload.request,
|
|
@@ -182,7 +267,8 @@ function observeTurnOperationOutputs(input) {
|
|
|
182
267
|
event: output.event,
|
|
183
268
|
state: input.state,
|
|
184
269
|
pendingRequests: input.pendingRequests,
|
|
185
|
-
openedRequestIds: input.openedRequestIds
|
|
270
|
+
openedRequestIds: input.openedRequestIds,
|
|
271
|
+
contextUsageState: input.contextUsageState
|
|
186
272
|
});
|
|
187
273
|
}
|
|
188
274
|
}
|
|
@@ -196,6 +282,8 @@ function reconstructWaitingTurn(input) {
|
|
|
196
282
|
return {
|
|
197
283
|
state: {
|
|
198
284
|
fileChangeMode: input.fileChangeMode,
|
|
285
|
+
observedItems: /* @__PURE__ */ new Map(),
|
|
286
|
+
proposedPlans: /* @__PURE__ */ new Map(),
|
|
199
287
|
started: true,
|
|
200
288
|
terminal: false,
|
|
201
289
|
waiting: true,
|
|
@@ -289,6 +377,11 @@ function validateAgentProviderSession(input) {
|
|
|
289
377
|
validateSessionPorts(capabilities, input.candidate);
|
|
290
378
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
291
379
|
const openedRequestIds = /* @__PURE__ */ new Set();
|
|
380
|
+
const contextUsageState = {
|
|
381
|
+
latestByScope: /* @__PURE__ */ new Map(),
|
|
382
|
+
cumulativeByScope: /* @__PURE__ */ new Map(),
|
|
383
|
+
compactionReadyScopes: /* @__PURE__ */ new Set()
|
|
384
|
+
};
|
|
292
385
|
let activeTurn = null;
|
|
293
386
|
let closePromise = null;
|
|
294
387
|
let closed = false;
|
|
@@ -370,6 +463,8 @@ function validateAgentProviderSession(input) {
|
|
|
370
463
|
pendingRequests: /* @__PURE__ */ new Map(),
|
|
371
464
|
state: {
|
|
372
465
|
fileChangeMode: capabilities.output.fileChanges,
|
|
466
|
+
observedItems: /* @__PURE__ */ new Map(),
|
|
467
|
+
proposedPlans: /* @__PURE__ */ new Map(),
|
|
373
468
|
started: false,
|
|
374
469
|
terminal: false,
|
|
375
470
|
waiting: false,
|
|
@@ -394,7 +489,8 @@ function validateAgentProviderSession(input) {
|
|
|
394
489
|
event: output.event,
|
|
395
490
|
state: currentTurn.state,
|
|
396
491
|
pendingRequests: currentTurn.pendingRequests,
|
|
397
|
-
openedRequestIds
|
|
492
|
+
openedRequestIds,
|
|
493
|
+
contextUsageState
|
|
398
494
|
});
|
|
399
495
|
}
|
|
400
496
|
yield output;
|
|
@@ -443,6 +539,13 @@ function validateAgentProviderSession(input) {
|
|
|
443
539
|
"Provider request resolution does not match the opened request."
|
|
444
540
|
);
|
|
445
541
|
}
|
|
542
|
+
if (pending.request.expiresAt !== void 0 && Date.parse(pending.request.expiresAt) <= Date.now() && resolution.disposition !== "canceled") {
|
|
543
|
+
throwAgentProviderContractError(
|
|
544
|
+
providerKey,
|
|
545
|
+
"request_resolution_mismatch",
|
|
546
|
+
"Provider request resolution identifies an expired request."
|
|
547
|
+
);
|
|
548
|
+
}
|
|
446
549
|
const nextPendingRequests = new Map(pendingRequests);
|
|
447
550
|
nextPendingRequests.delete(resolution.requestId);
|
|
448
551
|
if (activeTurn !== null) {
|
|
@@ -457,6 +560,8 @@ function validateAgentProviderSession(input) {
|
|
|
457
560
|
pendingRequests: nextPendingRequests,
|
|
458
561
|
state: {
|
|
459
562
|
fileChangeMode: capabilities.output.fileChanges,
|
|
563
|
+
observedItems: /* @__PURE__ */ new Map(),
|
|
564
|
+
proposedPlans: /* @__PURE__ */ new Map(),
|
|
460
565
|
started: true,
|
|
461
566
|
terminal: false,
|
|
462
567
|
waiting: false,
|
|
@@ -481,7 +586,8 @@ function validateAgentProviderSession(input) {
|
|
|
481
586
|
event: output.event,
|
|
482
587
|
state: currentTurn.state,
|
|
483
588
|
pendingRequests: currentTurn.pendingRequests,
|
|
484
|
-
openedRequestIds
|
|
589
|
+
openedRequestIds,
|
|
590
|
+
contextUsageState
|
|
485
591
|
});
|
|
486
592
|
}
|
|
487
593
|
yield output;
|
|
@@ -555,7 +661,8 @@ function validateAgentProviderSession(input) {
|
|
|
555
661
|
outputs: result.outputs,
|
|
556
662
|
state: targetedTurn.state,
|
|
557
663
|
pendingRequests: targetedTurn.pendingRequests,
|
|
558
|
-
openedRequestIds
|
|
664
|
+
openedRequestIds,
|
|
665
|
+
contextUsageState
|
|
559
666
|
});
|
|
560
667
|
if (terminalized && !targetedTurn.state.terminal) {
|
|
561
668
|
completeTurnSequence({
|
|
@@ -2,6 +2,8 @@ import {
|
|
|
2
2
|
parseAgentCapabilities,
|
|
3
3
|
parseAgentInstanceId,
|
|
4
4
|
parseAgentIsoDateTime,
|
|
5
|
+
parseAgentItemId,
|
|
6
|
+
parseAgentApprovalOptionId,
|
|
5
7
|
parseAgentProviderConversationId,
|
|
6
8
|
parseAgentProviderHistoryAnchor,
|
|
7
9
|
parseAgentProviderKey,
|
|
@@ -33,7 +35,7 @@ function defaultCapabilities(providerKey) {
|
|
|
33
35
|
}
|
|
34
36
|
};
|
|
35
37
|
return parseAgentCapabilities({
|
|
36
|
-
protocolVersion:
|
|
38
|
+
protocolVersion: 7,
|
|
37
39
|
providerKey,
|
|
38
40
|
sessions: { create: true, resume: true, branch: { kind: "through_turn" } },
|
|
39
41
|
turns: {
|
|
@@ -41,7 +43,17 @@ function defaultCapabilities(providerKey) {
|
|
|
41
43
|
interrupt: true,
|
|
42
44
|
steer: { kind: "supported", input }
|
|
43
45
|
},
|
|
44
|
-
requests: {
|
|
46
|
+
requests: {
|
|
47
|
+
approval: {
|
|
48
|
+
kind: "supported",
|
|
49
|
+
modes: [{ persistence: "once", scopeKinds: ["exact_action"] }]
|
|
50
|
+
},
|
|
51
|
+
elicitation: { kind: "structured" }
|
|
52
|
+
},
|
|
53
|
+
context: {
|
|
54
|
+
usage: { kind: "unsupported" },
|
|
55
|
+
compaction: { kind: "unsupported" }
|
|
56
|
+
},
|
|
45
57
|
input,
|
|
46
58
|
output: {
|
|
47
59
|
streaming: true,
|
|
@@ -81,14 +93,34 @@ function sessionBinding(state, sessionId) {
|
|
|
81
93
|
};
|
|
82
94
|
}
|
|
83
95
|
function eventBase(sessionId, turnId, occurredAt) {
|
|
84
|
-
return { protocolVersion:
|
|
96
|
+
return { protocolVersion: 7, sessionId, turnId, occurredAt };
|
|
85
97
|
}
|
|
86
98
|
function requestForTurn(turnId) {
|
|
87
99
|
return {
|
|
88
100
|
requestKind: "approval",
|
|
89
101
|
requestId: parseAgentRequestId(`fake-request:${turnId}`),
|
|
90
102
|
prompt: "Approve the deterministic fake operation?",
|
|
91
|
-
subject: {
|
|
103
|
+
subject: {
|
|
104
|
+
kind: "other",
|
|
105
|
+
title: "Fake provider operation",
|
|
106
|
+
itemId: parseAgentItemId(`fake-item:${turnId}`)
|
|
107
|
+
},
|
|
108
|
+
options: [
|
|
109
|
+
{
|
|
110
|
+
optionId: parseAgentApprovalOptionId("approval:allow-once"),
|
|
111
|
+
label: "Allow once",
|
|
112
|
+
decision: "approved",
|
|
113
|
+
persistence: "once",
|
|
114
|
+
scope: { kind: "exact_action" }
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
optionId: parseAgentApprovalOptionId("approval:deny-once"),
|
|
118
|
+
label: "Deny",
|
|
119
|
+
decision: "denied",
|
|
120
|
+
persistence: "once",
|
|
121
|
+
scope: { kind: "exact_action" }
|
|
122
|
+
}
|
|
123
|
+
]
|
|
92
124
|
};
|
|
93
125
|
}
|
|
94
126
|
function completedResult(outputs = []) {
|
|
@@ -109,6 +141,15 @@ function fakeSession(input) {
|
|
|
109
141
|
type: "turn.started",
|
|
110
142
|
payload: { message: "Fake provider turn started." }
|
|
111
143
|
});
|
|
144
|
+
yield createAgentEventOutput({
|
|
145
|
+
...eventBase(input.context.sessionId, turnInput.turnId, occurredAt),
|
|
146
|
+
type: "item.started",
|
|
147
|
+
payload: {
|
|
148
|
+
itemId: parseAgentItemId(`fake-item:${turnInput.turnId}`),
|
|
149
|
+
itemKind: "assistant_message",
|
|
150
|
+
status: "in_progress"
|
|
151
|
+
}
|
|
152
|
+
});
|
|
112
153
|
if (input.capabilities.output.streaming) {
|
|
113
154
|
yield createAgentEventOutput({
|
|
114
155
|
...eventBase(input.context.sessionId, turnInput.turnId, occurredAt),
|
|
@@ -120,7 +161,7 @@ function fakeSession(input) {
|
|
|
120
161
|
}
|
|
121
162
|
});
|
|
122
163
|
}
|
|
123
|
-
if (input.capabilities.requests.approval) {
|
|
164
|
+
if (input.capabilities.requests.approval.kind === "supported") {
|
|
124
165
|
const request = requestForTurn(turnInput.turnId);
|
|
125
166
|
pendingRequests.set(request.requestId, {
|
|
126
167
|
request,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agen-ai/agent-runtime",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.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",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"./package.json": "./package.json"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@agen-ai/agent-protocol": "^0.1
|
|
30
|
+
"@agen-ai/agent-protocol": "^0.2.1"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"tsup": "^8.5.0"
|