@agen-ai/agent-runtime 0.2.2 → 0.2.4

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.
@@ -1,6 +1,7 @@
1
- import type { AgentAuthenticationFlow, AgentError, AgentRequestResolution, AgentSessionBinding, AgentSessionBranchSource, AgentSessionConfiguration, AgentSessionId, AgentTurnId, AgentTurnInputContent, AgentTurnInteractionMode, AgentTurnInputPart, AgentTurnInterruptionReason } from "@agen-ai/agent-protocol";
1
+ import type { AgentAuthenticationFlow, AgentCollaborationControlInput, AgentCollaborationNode, AgentCollaborationSpawnInput, AgentConfigurationCatalog, AgentConfigurationSelectionInput, AgentError, AgentGeneratedResourceDescriptor, AgentGeneratedResourceId, AgentIntegrationCatalog, AgentManagedContentCatalog, AgentOperationCatalog, AgentOperationInvocation, AgentOperationResult, AgentRequestResolution, AgentSessionBinding, AgentSessionBranchSource, AgentSessionConfiguration, AgentSessionId, AgentTurnId, AgentTurnInputContent, AgentTurnInteractionMode, AgentTurnInputPart, AgentTurnInterruptionReason } from "@agen-ai/agent-protocol";
2
2
  import type { MaybePromise } from "./foundation.js";
3
3
  import type { AgentProviderOutput } from "./outputs.js";
4
+ import type { AgentArtifactCandidate } from "./artifacts.js";
4
5
  export interface AgentProviderSessionContext {
5
6
  readonly sessionId: AgentSessionId;
6
7
  readonly workingDirectory: string;
@@ -19,6 +20,7 @@ export interface AgentProviderBranchSessionInput extends AgentProviderSessionCon
19
20
  readonly onBindingCreated: AgentSessionBindingCreatedObserver;
20
21
  }
21
22
  export type AgentProviderExecutionStartedObserver = () => void;
23
+ export type AgentProviderOutputObserver = (output: AgentProviderOutput) => MaybePromise<void>;
22
24
  export interface AgentProviderRunTurnInput {
23
25
  readonly turnId: AgentTurnId;
24
26
  readonly interactionMode: AgentTurnInteractionMode;
@@ -38,9 +40,38 @@ export interface AgentProviderInterruptTurnInput {
38
40
  readonly requestedAt?: string;
39
41
  readonly signal?: AbortSignal;
40
42
  }
41
- export interface AgentProviderApplyConfigurationInput {
42
- readonly configuration: AgentSessionConfiguration;
43
+ export interface AgentProviderListInput {
44
+ readonly signal?: AbortSignal;
45
+ }
46
+ export interface AgentProviderApplyConfigurationSelectionInput {
47
+ readonly selection: AgentConfigurationSelectionInput;
48
+ readonly signal?: AbortSignal;
49
+ readonly onProviderExecutionStarted?: AgentProviderExecutionStartedObserver;
50
+ }
51
+ export interface AgentProviderInvokeOperationInput {
52
+ readonly invocation: AgentOperationInvocation;
53
+ readonly observationTurnId: AgentTurnId;
54
+ readonly signal?: AbortSignal;
55
+ readonly onProviderExecutionStarted?: AgentProviderExecutionStartedObserver;
56
+ readonly onOutput?: AgentProviderOutputObserver;
57
+ }
58
+ export interface AgentProviderSpawnCollaborationInput {
59
+ readonly spawn: AgentCollaborationSpawnInput;
43
60
  readonly signal?: AbortSignal;
61
+ readonly onProviderExecutionStarted?: AgentProviderExecutionStartedObserver;
62
+ }
63
+ export interface AgentProviderControlCollaborationInput {
64
+ readonly control: AgentCollaborationControlInput;
65
+ readonly signal?: AbortSignal;
66
+ readonly onProviderExecutionStarted?: AgentProviderExecutionStartedObserver;
67
+ }
68
+ export interface AgentProviderGetGeneratedResourceInput {
69
+ readonly resourceId: AgentGeneratedResourceId;
70
+ readonly signal?: AbortSignal;
71
+ }
72
+ export interface AgentGeneratedResourceInspection {
73
+ readonly descriptor: AgentGeneratedResourceDescriptor;
74
+ readonly candidate?: AgentArtifactCandidate;
44
75
  }
45
76
  export interface AgentProviderSteerTurnInput extends AgentTurnInputContent {
46
77
  readonly turnId: AgentTurnId;
@@ -82,7 +113,40 @@ export type AgentSessionConfigurationControl = Readonly<{
82
113
  kind: "managed";
83
114
  }> | Readonly<{
84
115
  kind: "selectable";
85
- applyConfiguration: (input: AgentProviderApplyConfigurationInput) => MaybePromise<AgentProviderOperationResult>;
116
+ listConfiguration: (input?: AgentProviderListInput) => MaybePromise<AgentConfigurationCatalog>;
117
+ applyConfigurationSelection: (input: AgentProviderApplyConfigurationSelectionInput) => MaybePromise<AgentProviderOperationResult>;
118
+ }>;
119
+ export type AgentOperationControl = Readonly<{
120
+ kind: "unsupported";
121
+ }> | Readonly<{
122
+ kind: "supported";
123
+ listOperations: (input?: AgentProviderListInput) => MaybePromise<AgentOperationCatalog>;
124
+ invokeOperation: (input: AgentProviderInvokeOperationInput) => MaybePromise<AgentOperationResult>;
125
+ }>;
126
+ export type AgentManagedContentInventory = Readonly<{
127
+ kind: "unsupported";
128
+ }> | Readonly<{
129
+ kind: "supported";
130
+ listManagedContent: (input?: AgentProviderListInput) => MaybePromise<AgentManagedContentCatalog>;
131
+ }>;
132
+ export type AgentIntegrationObservation = Readonly<{
133
+ kind: "unsupported";
134
+ }> | Readonly<{
135
+ kind: "supported";
136
+ observeIntegrations: (input?: AgentProviderListInput) => MaybePromise<AgentIntegrationCatalog>;
137
+ }>;
138
+ export type AgentCollaborationControl = Readonly<{
139
+ kind: "unsupported";
140
+ }> | Readonly<{
141
+ kind: "supported";
142
+ spawnCollaboration: (input: AgentProviderSpawnCollaborationInput) => MaybePromise<AgentCollaborationNode>;
143
+ controlCollaboration: (input: AgentProviderControlCollaborationInput) => MaybePromise<AgentCollaborationNode>;
144
+ }>;
145
+ export type AgentGeneratedResourceAccess = Readonly<{
146
+ kind: "unsupported";
147
+ }> | Readonly<{
148
+ kind: "supported";
149
+ getGeneratedResource: (input: AgentProviderGetGeneratedResourceInput) => MaybePromise<AgentGeneratedResourceInspection>;
86
150
  }>;
87
151
  export interface AgentProviderSession {
88
152
  readonly binding: AgentSessionBinding;
@@ -91,6 +155,11 @@ export interface AgentProviderSession {
91
155
  readonly interruption: AgentTurnInterruption;
92
156
  readonly steering: AgentTurnSteering;
93
157
  readonly configuration: AgentSessionConfigurationControl;
158
+ readonly operations: AgentOperationControl;
159
+ readonly managedContent: AgentManagedContentInventory;
160
+ readonly integrations: AgentIntegrationObservation;
161
+ readonly collaboration: AgentCollaborationControl;
162
+ readonly generatedResources: AgentGeneratedResourceAccess;
94
163
  readonly close: (input: AgentProviderCloseSessionInput) => MaybePromise<void>;
95
164
  }
96
165
  export type AgentSessionResumption = Readonly<{
@@ -1,4 +1,4 @@
1
- import { type AgentRequest, type AgentRequestResolution, type AgentSessionBinding, type AgentSessionBranchSource, type AgentSessionConfiguration, type AgentSessionId, type AgentTurnId, type AgentTurnInputContent } from "@agen-ai/agent-protocol";
1
+ import { type AgentCollaborationSpawnInput, type AgentConfigurationSelectionInput, type AgentGeneratedResourceId, type AgentOperationInvocation, type AgentRequest, type AgentRequestResolution, type AgentSessionBinding, type AgentSessionBranchSource, type AgentSessionConfiguration, type AgentSessionId, type AgentTurnId, type AgentTurnInputContent } from "@agen-ai/agent-protocol";
2
2
  import type { AgentProviderDriver, AgentProviderInstanceDefinition } from "../providerDriver.js";
3
3
  import type { AgentProviderRunTurnInput } from "../sessions.js";
4
4
  export interface AgentProviderConformanceScenario {
@@ -6,7 +6,10 @@ export interface AgentProviderConformanceScenario {
6
6
  readonly definition: AgentProviderInstanceDefinition;
7
7
  readonly workingDirectory: string;
8
8
  readonly configuration: AgentSessionConfiguration;
9
- readonly updatedConfiguration?: AgentSessionConfiguration;
9
+ readonly configurationSelection?: AgentConfigurationSelectionInput;
10
+ readonly operationInvocation?: AgentOperationInvocation;
11
+ readonly collaborationSpawn?: AgentCollaborationSpawnInput;
12
+ readonly generatedResourceId?: AgentGeneratedResourceId;
10
13
  readonly createSessionId: AgentSessionId;
11
14
  readonly resumeSessionId: AgentSessionId;
12
15
  readonly branchSessionId?: AgentSessionId;
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  matchesAgentSessionBinding,
3
- parseAgentRequestResolutionFor
3
+ parseAgentRequestResolutionFor,
4
+ parseAgentTurnId
4
5
  } from "@agen-ai/agent-protocol";
5
6
  import { isAgentOperationAbortError } from "../foundation.js";
6
7
  import {
@@ -275,12 +276,24 @@ async function runAgentProviderConformance(scenario) {
275
276
  checks.push("interruption");
276
277
  if (instance.capabilities.configuration.kind === "selectable") {
277
278
  requireCheck(
278
- created.configuration.kind === "selectable" && scenario.updatedConfiguration !== void 0,
279
+ created.configuration.kind === "selectable" && scenario.configurationSelection !== void 0,
279
280
  "configuration",
280
- "Selectable configuration requires a handler and updated fixture."
281
+ "Selectable configuration requires a handler and selection fixture."
281
282
  );
282
- const result = await created.configuration.applyConfiguration({
283
- configuration: scenario.updatedConfiguration
283
+ const catalog = await created.configuration.listConfiguration();
284
+ requireCheck(
285
+ catalog.fields.some(
286
+ (field) => field.key === scenario.configurationSelection?.key
287
+ ),
288
+ "configuration",
289
+ "Configuration catalog did not offer the selected field."
290
+ );
291
+ let executionStarted = 0;
292
+ const result = await created.configuration.applyConfigurationSelection({
293
+ selection: scenario.configurationSelection,
294
+ onProviderExecutionStarted: () => {
295
+ executionStarted += 1;
296
+ }
284
297
  });
285
298
  requireOperationStatus(
286
299
  result,
@@ -288,6 +301,11 @@ async function runAgentProviderConformance(scenario) {
288
301
  "configuration",
289
302
  "Selectable configuration did not complete atomically."
290
303
  );
304
+ requireCheck(
305
+ executionStarted === 1,
306
+ "configuration",
307
+ "Configuration selection did not report exactly one execution start."
308
+ );
291
309
  } else {
292
310
  requireCheck(
293
311
  created.configuration.kind === "managed",
@@ -296,6 +314,149 @@ async function runAgentProviderConformance(scenario) {
296
314
  );
297
315
  }
298
316
  checks.push("configuration");
317
+ if (instance.capabilities.operations.kind === "supported") {
318
+ requireCheck(
319
+ created.operations.kind === "supported" && scenario.operationInvocation !== void 0,
320
+ "operations",
321
+ "Supported operations require matching ports and an invocation fixture."
322
+ );
323
+ const catalog = await created.operations.listOperations();
324
+ requireCheck(
325
+ catalog.operations.some(
326
+ (operation) => operation.operationId === scenario.operationInvocation?.operationId
327
+ ),
328
+ "operations",
329
+ "Operation catalog did not offer the invocation fixture."
330
+ );
331
+ let executionStarted = 0;
332
+ const result = await created.operations.invokeOperation({
333
+ invocation: scenario.operationInvocation,
334
+ observationTurnId: parseAgentTurnId(
335
+ scenario.operationInvocation.invocationId
336
+ ),
337
+ onProviderExecutionStarted: () => {
338
+ executionStarted += 1;
339
+ }
340
+ });
341
+ requireCheck(
342
+ result.status === "completed" && executionStarted === 1,
343
+ "operations",
344
+ "Operation invocation did not complete with one execution-start receipt."
345
+ );
346
+ } else {
347
+ requireCheck(
348
+ created.operations.kind === "unsupported",
349
+ "operations",
350
+ "Unsupported operations exposed callable ports."
351
+ );
352
+ }
353
+ checks.push("operations");
354
+ if (instance.capabilities.managedContent.kind === "supported") {
355
+ requireCheck(
356
+ created.managedContent.kind === "supported",
357
+ "managed_content",
358
+ "Supported managed content has no inventory port."
359
+ );
360
+ await created.managedContent.listManagedContent();
361
+ } else {
362
+ requireCheck(
363
+ created.managedContent.kind === "unsupported",
364
+ "managed_content",
365
+ "Unsupported managed content exposed an inventory port."
366
+ );
367
+ }
368
+ checks.push("managed_content");
369
+ if (instance.capabilities.integrations.kind === "supported") {
370
+ requireCheck(
371
+ created.integrations.kind === "supported",
372
+ "integrations",
373
+ "Supported integrations have no observation port."
374
+ );
375
+ await created.integrations.observeIntegrations();
376
+ } else {
377
+ requireCheck(
378
+ created.integrations.kind === "unsupported",
379
+ "integrations",
380
+ "Unsupported integrations exposed an observation port."
381
+ );
382
+ }
383
+ checks.push("integrations");
384
+ if (instance.capabilities.collaboration.kind === "supported") {
385
+ requireCheck(
386
+ created.collaboration.kind === "supported" && scenario.collaborationSpawn !== void 0,
387
+ "collaboration",
388
+ "Supported collaboration requires matching ports and a spawn fixture."
389
+ );
390
+ let executionStarted = 0;
391
+ const spawned = await created.collaboration.spawnCollaboration({
392
+ spawn: scenario.collaborationSpawn,
393
+ onProviderExecutionStarted: () => {
394
+ executionStarted += 1;
395
+ }
396
+ });
397
+ const stopped = await created.collaboration.controlCollaboration({
398
+ control: {
399
+ action: "stop",
400
+ collaborationId: spawned.collaborationId,
401
+ reason: "user_requested"
402
+ },
403
+ onProviderExecutionStarted: () => {
404
+ executionStarted += 1;
405
+ }
406
+ });
407
+ const closed = await created.collaboration.controlCollaboration({
408
+ control: {
409
+ action: "close",
410
+ collaborationId: stopped.collaborationId
411
+ },
412
+ onProviderExecutionStarted: () => {
413
+ executionStarted += 1;
414
+ }
415
+ });
416
+ const replayedClose = await created.collaboration.controlCollaboration({
417
+ control: {
418
+ action: "close",
419
+ collaborationId: stopped.collaborationId
420
+ },
421
+ onProviderExecutionStarted: () => {
422
+ executionStarted += 1;
423
+ }
424
+ });
425
+ requireCheck(
426
+ closed.status === "canceled" && closed.outcome?.kind === "canceled" && closed.closedAt !== void 0 && replayedClose === closed && executionStarted === 3,
427
+ "collaboration",
428
+ "Collaboration lifecycle did not preserve control and execution receipts."
429
+ );
430
+ } else {
431
+ requireCheck(
432
+ created.collaboration.kind === "unsupported",
433
+ "collaboration",
434
+ "Unsupported collaboration exposed callable ports."
435
+ );
436
+ }
437
+ checks.push("collaboration");
438
+ if (instance.capabilities.generatedResources.kind === "supported") {
439
+ requireCheck(
440
+ created.generatedResources.kind === "supported" && scenario.generatedResourceId !== void 0,
441
+ "generated_resources",
442
+ "Supported generated resources require an access port and fixture."
443
+ );
444
+ const resource = await created.generatedResources.getGeneratedResource({
445
+ resourceId: scenario.generatedResourceId
446
+ });
447
+ requireCheck(
448
+ resource.descriptor.resourceId === scenario.generatedResourceId,
449
+ "generated_resources",
450
+ "Generated resource access returned another resource."
451
+ );
452
+ } else {
453
+ requireCheck(
454
+ created.generatedResources.kind === "unsupported",
455
+ "generated_resources",
456
+ "Unsupported generated resources exposed an access port."
457
+ );
458
+ }
459
+ checks.push("generated_resources");
299
460
  await created.close({ reason: "idle" });
300
461
  await created.close({ reason: "idle" });
301
462
  checks.push("idempotent_session_close");
@@ -3,6 +3,7 @@ import {
3
3
  parseAgentInstanceId,
4
4
  parseAgentIsoDateTime,
5
5
  parseAgentItemId,
6
+ parseAgentOperationId,
6
7
  parseAgentApprovalOptionId,
7
8
  parseAgentProviderConversationId,
8
9
  parseAgentProviderHistoryAnchor,
@@ -35,7 +36,7 @@ function defaultCapabilities(providerKey) {
35
36
  }
36
37
  };
37
38
  return parseAgentCapabilities({
38
- protocolVersion: 7,
39
+ protocolVersion: 8,
39
40
  providerKey,
40
41
  sessions: { create: true, resume: true, branch: { kind: "through_turn" } },
41
42
  turns: {
@@ -48,7 +49,18 @@ function defaultCapabilities(providerKey) {
48
49
  kind: "supported",
49
50
  modes: [{ persistence: "once", scopeKinds: ["exact_action"] }]
50
51
  },
51
- elicitation: { kind: "structured" }
52
+ elicitation: {
53
+ kind: "supported",
54
+ fieldKinds: [
55
+ "text",
56
+ "single_select",
57
+ "multi_select",
58
+ "boolean",
59
+ "confirmation"
60
+ ],
61
+ maxFields: 16,
62
+ sensitiveFields: true
63
+ }
52
64
  },
53
65
  context: {
54
66
  usage: { kind: "unsupported" },
@@ -63,19 +75,61 @@ function defaultCapabilities(providerKey) {
63
75
  },
64
76
  configuration: {
65
77
  kind: "selectable",
66
- fields: [
67
- { key: "mode", optionIds: ["agent"] },
68
- {
69
- key: "model",
70
- optionIds: ["fake-model", "fake-model-2"]
71
- }
72
- ]
78
+ fieldKinds: [
79
+ "boolean",
80
+ "single_select",
81
+ "bounded_integer",
82
+ "bounded_text"
83
+ ],
84
+ maxFields: 100
85
+ },
86
+ operations: {
87
+ kind: "supported",
88
+ operationKinds: [
89
+ "session_control",
90
+ "managed_content_invoke",
91
+ "configuration_select",
92
+ "integration_control",
93
+ "collaboration_control",
94
+ "resource_generate"
95
+ ],
96
+ fieldKinds: [
97
+ "text",
98
+ "boolean",
99
+ "single_select",
100
+ "multi_select",
101
+ "integer"
102
+ ],
103
+ executionModes: ["immediate", "request_continuation", "durable_job"],
104
+ maxOperations: 100,
105
+ maxFieldsPerOperation: 16
73
106
  },
74
- interactionExtensions: {
75
- slashCommands: false,
76
- mcp: false,
77
- subagents: false,
78
- imageGeneration: false
107
+ managedContent: {
108
+ kind: "supported",
109
+ contentKinds: ["skill", "rule", "prompt", "agent_definition"],
110
+ maxEntries: 100
111
+ },
112
+ integrations: {
113
+ kind: "supported",
114
+ integrationKinds: ["mcp"],
115
+ maxIntegrations: 32,
116
+ maxServersPerIntegration: 32,
117
+ maxToolsPerServer: 100,
118
+ maxResourcesPerServer: 100
119
+ },
120
+ collaboration: {
121
+ kind: "supported",
122
+ roles: ["delegate", "reviewer", "researcher", "specialist"],
123
+ controlActions: ["spawn", "steer", "stop", "close", "inspect"],
124
+ maxDepth: 8,
125
+ maxChildrenPerNode: 16,
126
+ maxActiveNodes: 64
127
+ },
128
+ generatedResources: {
129
+ kind: "supported",
130
+ resourceKinds: ["image", "document", "archive"],
131
+ maxResourcesPerTurn: 16,
132
+ maxBytesPerResource: 25 * 1024 * 1024
79
133
  },
80
134
  authentication: { kind: "unsupported" },
81
135
  versionReporting: true
@@ -93,7 +147,7 @@ function sessionBinding(state, sessionId) {
93
147
  };
94
148
  }
95
149
  function eventBase(sessionId, turnId, occurredAt) {
96
- return { protocolVersion: 7, sessionId, turnId, occurredAt };
150
+ return { protocolVersion: 8, sessionId, turnId, occurredAt };
97
151
  }
98
152
  function requestForTurn(turnId) {
99
153
  return {
@@ -131,6 +185,13 @@ function completedResult(outputs = []) {
131
185
  }
132
186
  function fakeSession(input) {
133
187
  const pendingRequests = /* @__PURE__ */ new Map();
188
+ const collaborationNodes = /* @__PURE__ */ new Map();
189
+ const nextCollaborationObservedAt = (previous) => {
190
+ const observed = input.now();
191
+ return Date.parse(observed) > Date.parse(previous) ? observed : parseAgentIsoDateTime(
192
+ new Date(Date.parse(previous) + 1).toISOString()
193
+ );
194
+ };
134
195
  let closed = false;
135
196
  const runTurn = async function* (turnInput) {
136
197
  throwIfAgentOperationAborted(turnInput.signal);
@@ -256,14 +317,156 @@ function fakeSession(input) {
256
317
  } : { kind: "unsupported" },
257
318
  configuration: input.capabilities.configuration.kind === "selectable" ? {
258
319
  kind: "selectable",
259
- applyConfiguration: async (configurationInput) => {
320
+ listConfiguration: async (listInput = {}) => {
321
+ throwIfAgentOperationAborted(listInput.signal);
322
+ return {
323
+ revision: 1,
324
+ fields: [{
325
+ key: "model",
326
+ revision: 1,
327
+ label: "Model",
328
+ scope: "session",
329
+ applicationTiming: "next_session",
330
+ mutable: true,
331
+ fieldKind: "single_select",
332
+ currentValue: "fake-model",
333
+ options: [
334
+ { optionId: "fake-model", label: "Fake model" },
335
+ { optionId: "fake-model-2", label: "Fake model 2" }
336
+ ]
337
+ }]
338
+ };
339
+ },
340
+ applyConfigurationSelection: async (configurationInput) => {
260
341
  throwIfAgentOperationAborted(configurationInput.signal);
342
+ configurationInput.onProviderExecutionStarted?.();
261
343
  input.state.configurationRevisions.push(
262
- configurationInput.configuration.revision
344
+ `${configurationInput.selection.expectedCatalogRevision}:${configurationInput.selection.key}`
263
345
  );
264
346
  return completedResult();
265
347
  }
266
348
  } : { kind: "managed" },
349
+ operations: input.capabilities.operations.kind === "supported" ? {
350
+ kind: "supported",
351
+ listOperations: async (listInput = {}) => {
352
+ throwIfAgentOperationAborted(listInput.signal);
353
+ return {
354
+ revision: 1,
355
+ operations: [{
356
+ operationId: parseAgentOperationId("fake.session.reset"),
357
+ revision: 1,
358
+ kind: "session_control",
359
+ title: "Reset fake session",
360
+ context: "session",
361
+ timing: "idle_session",
362
+ executionMode: "immediate",
363
+ fields: [],
364
+ confirmation: "required",
365
+ idempotency: "required",
366
+ resultKind: "none"
367
+ }]
368
+ };
369
+ },
370
+ invokeOperation: async (operationInput) => {
371
+ throwIfAgentOperationAborted(operationInput.signal);
372
+ operationInput.onProviderExecutionStarted?.();
373
+ return {
374
+ invocationId: operationInput.invocation.invocationId,
375
+ status: "completed"
376
+ };
377
+ }
378
+ } : { kind: "unsupported" },
379
+ managedContent: input.capabilities.managedContent.kind === "supported" ? {
380
+ kind: "supported",
381
+ listManagedContent: async (listInput = {}) => {
382
+ throwIfAgentOperationAborted(listInput.signal);
383
+ return { revision: 1, entries: [] };
384
+ }
385
+ } : { kind: "unsupported" },
386
+ integrations: input.capabilities.integrations.kind === "supported" ? {
387
+ kind: "supported",
388
+ observeIntegrations: async (listInput = {}) => {
389
+ throwIfAgentOperationAborted(listInput.signal);
390
+ return {
391
+ revision: 1,
392
+ observedAt: input.now(),
393
+ integrations: []
394
+ };
395
+ }
396
+ } : { kind: "unsupported" },
397
+ collaboration: input.capabilities.collaboration.kind === "supported" ? {
398
+ kind: "supported",
399
+ spawnCollaboration: async (collaborationInput) => {
400
+ throwIfAgentOperationAborted(collaborationInput.signal);
401
+ collaborationInput.onProviderExecutionStarted?.();
402
+ const parent = collaborationInput.spawn.parentCollaborationId === void 0 ? void 0 : collaborationNodes.get(
403
+ collaborationInput.spawn.parentCollaborationId
404
+ );
405
+ const now = nextCollaborationObservedAt(
406
+ collaborationInput.spawn.createdAt
407
+ );
408
+ const node = {
409
+ collaborationId: collaborationInput.spawn.collaborationId,
410
+ rootCollaborationId: parent?.rootCollaborationId ?? collaborationInput.spawn.collaborationId,
411
+ ...collaborationInput.spawn.parentCollaborationId === void 0 ? {} : {
412
+ parentCollaborationId: collaborationInput.spawn.parentCollaborationId
413
+ },
414
+ role: collaborationInput.spawn.role,
415
+ title: collaborationInput.spawn.title,
416
+ status: "running",
417
+ objective: collaborationInput.spawn.objective,
418
+ usage: { kind: "unavailable" },
419
+ createdAt: collaborationInput.spawn.createdAt,
420
+ updatedAt: now
421
+ };
422
+ collaborationNodes.set(node.collaborationId, node);
423
+ return node;
424
+ },
425
+ controlCollaboration: async (collaborationInput) => {
426
+ throwIfAgentOperationAborted(collaborationInput.signal);
427
+ collaborationInput.onProviderExecutionStarted?.();
428
+ const previous = collaborationNodes.get(
429
+ collaborationInput.control.collaborationId
430
+ );
431
+ if (previous === void 0) {
432
+ throw new TypeError("Fake collaboration does not exist.");
433
+ }
434
+ const now = nextCollaborationObservedAt(previous.updatedAt);
435
+ const node = {
436
+ ...previous,
437
+ updatedAt: now,
438
+ ...collaborationInput.control.action === "stop" ? {
439
+ status: "canceled",
440
+ terminalAt: previous.terminalAt ?? now,
441
+ outcome: {
442
+ kind: "canceled",
443
+ reason: collaborationInput.control.reason
444
+ }
445
+ } : collaborationInput.control.action === "close" ? { closedAt: previous.closedAt ?? now } : {}
446
+ };
447
+ collaborationNodes.set(node.collaborationId, node);
448
+ return node;
449
+ }
450
+ } : { kind: "unsupported" },
451
+ generatedResources: input.capabilities.generatedResources.kind === "supported" ? {
452
+ kind: "supported",
453
+ getGeneratedResource: async (resourceInput) => {
454
+ throwIfAgentOperationAborted(resourceInput.signal);
455
+ return {
456
+ descriptor: {
457
+ resourceId: resourceInput.resourceId,
458
+ kind: "image",
459
+ status: "pending",
460
+ displayName: "Fake generated resource",
461
+ producer: {
462
+ kind: "session",
463
+ sessionId: input.context.sessionId
464
+ },
465
+ createdAt: input.now()
466
+ }
467
+ };
468
+ }
469
+ } : { kind: "unsupported" },
267
470
  close
268
471
  };
269
472
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agen-ai/agent-runtime",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
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.2.2"
30
+ "@agen-ai/agent-protocol": "^0.2.4"
31
31
  },
32
32
  "devDependencies": {
33
33
  "tsup": "^8.5.0"