@tangle-network/agent-interface 0.42.0 → 0.43.0

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 CHANGED
@@ -7,8 +7,11 @@ shapes; higher-level packages import from here rather than redefining them.
7
7
 
8
8
  ## Durable runs, interactions, and context
9
9
 
10
- `AgentRunControlRef` identifies a retained run without depending on a live JavaScript object.
10
+ `AgentRunControlRef` identifies a retained run without depending on a live JavaScript object and may carry the provider's admission digest so reconstruction can reject changed-input reuse.
11
11
  `RuntimeEventEnvelope` adds stable run, event, sequence, cursor, and timestamp fields around the existing `StreamEvent` union, and its runtime schema validates every canonical event variant.
12
+ Providers advertise `retainedControl` only when exact run, result, event, cancellation, replay, detach, turn, and session identity are all implemented together.
13
+ `AgentSession.cancelRun()` accepts a canonical request digest bound to one operation and `AgentRunControlRef`, so a caller can safely repeat the same cancellation after losing the first acknowledgement.
14
+ Its acknowledgement repeats the operation, digest, and run coordinates and distinguishes a known cancellation effect from conflict or unknown state.
12
15
 
13
16
  An environment advertises `interactions` only when it can originate and answer typed requests.
14
17
  `AgentEnvironmentCapabilitiesSchema` strictly validates the complete capability document at runtime, including all-or-nothing durable branching declarations.
@@ -4,7 +4,7 @@ import type { AgentCandidateTermination } from "./agent-candidate.js";
4
4
  import type { InputPart, StreamEvent, TokenUsage } from "./index.js";
5
5
  import { type InteractionAcknowledgement, type InteractionCapabilities, type InteractionResponseCommand } from "./interaction.js";
6
6
  import { type ContextTransferReceipt, type ContextTransferRequest, type NativeContextBoundaryProof, type NativeContextContinuationRequest, type NativeContextContinuationTurn } from "./portable-context.js";
7
- import { type AgentRunControlRef } from "./runtime-control.js";
7
+ import { type AgentRunCancellationAcknowledgement, type AgentRunCancellationRequest, type AgentRunControlRef } from "./runtime-control.js";
8
8
  import type { AgentWorkspaceBranching } from "./workspace-branching.js";
9
9
  /** Portable profile reference: inline profile or provider catalog id. */
10
10
  export type AgentProfileRef = AgentProfile | string;
@@ -425,6 +425,7 @@ export declare const AgentNativeContextContinuationResultSchema: z.ZodUnion<read
425
425
  environmentId: z.ZodString;
426
426
  sessionId: z.ZodOptional<z.ZodString>;
427
427
  executionId: z.ZodOptional<z.ZodString>;
428
+ requestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
428
429
  }, z.core.$strict>;
429
430
  }, z.core.$strict>, z.ZodObject<{
430
431
  acknowledgement: z.ZodIntersection<z.ZodObject<{
@@ -523,6 +524,10 @@ export interface AgentSession {
523
524
  * repeating it with a different request returns a conflict without dispatch.
524
525
  */
525
526
  continueNative?(request: NativeContextContinuationRequest, options: AgentNativeContextContinuationOptions): Promise<AgentNativeContextContinuationResult>;
527
+ /** Retry-safe cancellation bound to one exact run and caller operation. */
528
+ cancelRun?(request: AgentRunCancellationRequest, options?: {
529
+ signal?: AbortSignal;
530
+ }): Promise<AgentRunCancellationAcknowledgement>;
526
531
  cancel(): Promise<void>;
527
532
  }
528
533
  export interface AgentEnvironment {
@@ -566,6 +571,13 @@ export interface AgentEnvironmentCapabilities {
566
571
  list: boolean;
567
572
  messages: boolean;
568
573
  };
574
+ /** Present only when every retained-run identity and retry promise is implemented. */
575
+ retainedControl?: {
576
+ exactRunIdentity: boolean;
577
+ resultIdentity: boolean;
578
+ eventIdentity: boolean;
579
+ cancellationIdempotency: boolean;
580
+ };
569
581
  /** Absent when verified, retry-safe same-session continuation is unsupported. */
570
582
  nativeContinuation?: {
571
583
  /** Boundary comparison and operation admission are one atomic provider action. */
@@ -636,6 +648,12 @@ export declare const AgentEnvironmentCapabilitiesSchema: z.ZodObject<{
636
648
  list: z.ZodBoolean;
637
649
  messages: z.ZodBoolean;
638
650
  }, z.core.$strict>;
651
+ retainedControl: z.ZodOptional<z.ZodObject<{
652
+ exactRunIdentity: z.ZodBoolean;
653
+ resultIdentity: z.ZodBoolean;
654
+ eventIdentity: z.ZodBoolean;
655
+ cancellationIdempotency: z.ZodBoolean;
656
+ }, z.core.$strict>>;
639
657
  nativeContinuation: z.ZodOptional<z.ZodObject<{
640
658
  atomicBoundary: z.ZodBoolean;
641
659
  requestIdempotency: z.ZodBoolean;
@@ -138,6 +138,14 @@ export const AgentEnvironmentCapabilitiesSchema = z
138
138
  list: z.boolean(),
139
139
  messages: z.boolean(),
140
140
  }),
141
+ retainedControl: z
142
+ .strictObject({
143
+ exactRunIdentity: z.boolean(),
144
+ resultIdentity: z.boolean(),
145
+ eventIdentity: z.boolean(),
146
+ cancellationIdempotency: z.boolean(),
147
+ })
148
+ .optional(),
141
149
  nativeContinuation: z
142
150
  .strictObject({
143
151
  atomicBoundary: z.boolean(),
@@ -170,6 +178,21 @@ export const AgentEnvironmentCapabilitiesSchema = z
170
178
  .optional(),
171
179
  })
172
180
  .superRefine((capabilities, refinement) => {
181
+ if (capabilities.retainedControl !== undefined &&
182
+ (!capabilities.retainedControl.exactRunIdentity ||
183
+ !capabilities.retainedControl.resultIdentity ||
184
+ !capabilities.retainedControl.eventIdentity ||
185
+ !capabilities.retainedControl.cancellationIdempotency ||
186
+ !capabilities.streaming.replay ||
187
+ !capabilities.streaming.detach ||
188
+ !capabilities.streaming.turnIdempotency ||
189
+ !capabilities.sessions.continue)) {
190
+ refinement.addIssue({
191
+ code: "custom",
192
+ path: ["retainedControl"],
193
+ message: "retained control requires exact run, result, event, cancellation, replay, detach, turn, and session identity together",
194
+ });
195
+ }
173
196
  if (capabilities.nativeContinuation !== undefined &&
174
197
  (!capabilities.nativeContinuation.atomicBoundary ||
175
198
  !capabilities.nativeContinuation.requestIdempotency ||
@@ -23,6 +23,7 @@ export declare const InteractionFieldSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
23
23
  type: z.ZodLiteral<"text">;
24
24
  multiline: z.ZodOptional<z.ZodBoolean>;
25
25
  placeholder: z.ZodOptional<z.ZodString>;
26
+ maxLength: z.ZodOptional<z.ZodNumber>;
26
27
  default: z.ZodOptional<z.ZodString>;
27
28
  name: z.ZodString;
28
29
  label: z.ZodString;
@@ -57,6 +58,7 @@ export declare const InteractionFieldSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
57
58
  }, z.core.$strict>, z.ZodObject<{
58
59
  type: z.ZodLiteral<"secret">;
59
60
  placeholder: z.ZodOptional<z.ZodString>;
61
+ maxLength: z.ZodOptional<z.ZodNumber>;
60
62
  name: z.ZodString;
61
63
  label: z.ZodString;
62
64
  required: z.ZodOptional<z.ZodBoolean>;
@@ -67,6 +69,7 @@ export declare const InteractionAnswerSpecSchema: z.ZodObject<{
67
69
  type: z.ZodLiteral<"text">;
68
70
  multiline: z.ZodOptional<z.ZodBoolean>;
69
71
  placeholder: z.ZodOptional<z.ZodString>;
72
+ maxLength: z.ZodOptional<z.ZodNumber>;
70
73
  default: z.ZodOptional<z.ZodString>;
71
74
  name: z.ZodString;
72
75
  label: z.ZodString;
@@ -101,6 +104,7 @@ export declare const InteractionAnswerSpecSchema: z.ZodObject<{
101
104
  }, z.core.$strict>, z.ZodObject<{
102
105
  type: z.ZodLiteral<"secret">;
103
106
  placeholder: z.ZodOptional<z.ZodString>;
107
+ maxLength: z.ZodOptional<z.ZodNumber>;
104
108
  name: z.ZodString;
105
109
  label: z.ZodString;
106
110
  required: z.ZodOptional<z.ZodBoolean>;
@@ -204,6 +208,7 @@ export declare const InteractionRequestSchema: z.ZodObject<{
204
208
  type: z.ZodLiteral<"text">;
205
209
  multiline: z.ZodOptional<z.ZodBoolean>;
206
210
  placeholder: z.ZodOptional<z.ZodString>;
211
+ maxLength: z.ZodOptional<z.ZodNumber>;
207
212
  default: z.ZodOptional<z.ZodString>;
208
213
  name: z.ZodString;
209
214
  label: z.ZodString;
@@ -238,6 +243,7 @@ export declare const InteractionRequestSchema: z.ZodObject<{
238
243
  }, z.core.$strict>, z.ZodObject<{
239
244
  type: z.ZodLiteral<"secret">;
240
245
  placeholder: z.ZodOptional<z.ZodString>;
246
+ maxLength: z.ZodOptional<z.ZodNumber>;
241
247
  name: z.ZodString;
242
248
  label: z.ZodString;
243
249
  required: z.ZodOptional<z.ZodBoolean>;
@@ -37,6 +37,8 @@ export const InteractionFieldSchema = z
37
37
  type: z.literal("text"),
38
38
  multiline: z.boolean().optional(),
39
39
  placeholder: z.string().optional(),
40
+ /** Maximum answer length chosen by the request author. Omission means no contract limit. */
41
+ maxLength: z.number().int().positive().optional(),
40
42
  default: z.string().optional(),
41
43
  }),
42
44
  z.strictObject({
@@ -76,9 +78,22 @@ export const InteractionFieldSchema = z
76
78
  ...FieldBase,
77
79
  type: z.literal("secret"),
78
80
  placeholder: z.string().optional(),
81
+ /** Maximum answer length chosen by the request author. Omission means no contract limit. */
82
+ maxLength: z.number().int().positive().optional(),
79
83
  }),
80
84
  ])
81
85
  .superRefine((field, context) => {
86
+ if (field.type === "text" &&
87
+ field.default !== undefined &&
88
+ field.maxLength !== undefined &&
89
+ field.default.length > field.maxLength) {
90
+ context.addIssue({
91
+ code: "custom",
92
+ path: ["default"],
93
+ message: "text field default exceeds maxLength",
94
+ });
95
+ return;
96
+ }
82
97
  if (field.type === "number") {
83
98
  if (field.min !== undefined &&
84
99
  field.max !== undefined &&
@@ -489,10 +504,15 @@ export function validateInteractionAnswer(spec, data) {
489
504
  }
490
505
  switch (field.type) {
491
506
  case "text":
492
- case "secret":
493
- if (typeof v !== "string")
507
+ case "secret": {
508
+ if (typeof v !== "string") {
494
509
  errors.push(`field "${field.name}" must be a string`);
510
+ }
511
+ else if (field.maxLength !== undefined && v.length > field.maxLength) {
512
+ errors.push(`field "${field.name}" exceeds maxLength ${field.maxLength}`);
513
+ }
495
514
  break;
515
+ }
496
516
  case "number":
497
517
  if (typeof v !== "number" || !Number.isFinite(v)) {
498
518
  errors.push(`field "${field.name}" must be a finite number`);
@@ -683,6 +683,7 @@ export declare const NativeContextContinuationRequestSchema: z.ZodObject<{
683
683
  environmentId: z.ZodString;
684
684
  sessionId: z.ZodOptional<z.ZodString>;
685
685
  executionId: z.ZodOptional<z.ZodString>;
686
+ requestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
686
687
  }, z.core.$strict>;
687
688
  expectedBoundary: z.ZodObject<{
688
689
  runId: z.ZodString;
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import type { StreamEvent } from "./index.js";
3
+ import type { Sha256Digest } from "./agent-candidate.js";
3
4
  /** Provider-neutral coordinates sufficient to recreate control of one run. */
4
5
  export interface AgentRunControlRef {
5
6
  runId: string;
@@ -7,6 +8,8 @@ export interface AgentRunControlRef {
7
8
  environmentId: string;
8
9
  sessionId?: string;
9
10
  executionId?: string;
11
+ /** Provider admission digest for detecting changed-input run reuse. */
12
+ requestDigest?: Sha256Digest;
10
13
  }
11
14
  export declare const AgentRunControlRefSchema: z.ZodObject<{
12
15
  runId: z.ZodString;
@@ -14,7 +17,67 @@ export declare const AgentRunControlRefSchema: z.ZodObject<{
14
17
  environmentId: z.ZodString;
15
18
  sessionId: z.ZodOptional<z.ZodString>;
16
19
  executionId: z.ZodOptional<z.ZodString>;
20
+ requestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
17
21
  }, z.core.$strict>;
22
+ export type AgentRunCancellationEffect = "cancel_requested" | "cancelled" | "not_live" | "unknown";
23
+ export interface AgentRunCancellationRequestMaterial {
24
+ operationId: string;
25
+ run: AgentRunControlRef;
26
+ reason?: string;
27
+ }
28
+ export interface AgentRunCancellationRequest extends AgentRunCancellationRequestMaterial {
29
+ requestDigest: Sha256Digest;
30
+ }
31
+ export declare function agentRunCancellationRequestDigest(request: AgentRunCancellationRequestMaterial): Sha256Digest;
32
+ export declare const AgentRunCancellationRequestSchema: z.ZodObject<{
33
+ operationId: z.ZodString;
34
+ requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
35
+ run: z.ZodObject<{
36
+ runId: z.ZodString;
37
+ provider: z.ZodString;
38
+ environmentId: z.ZodString;
39
+ sessionId: z.ZodOptional<z.ZodString>;
40
+ executionId: z.ZodOptional<z.ZodString>;
41
+ requestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
42
+ }, z.core.$strict>;
43
+ reason: z.ZodOptional<z.ZodString>;
44
+ }, z.core.$strict>;
45
+ export interface AgentRunCancellationAcknowledgement {
46
+ operationId: string;
47
+ requestDigest: Sha256Digest;
48
+ run: AgentRunControlRef;
49
+ status: "accepted" | "replayed" | "conflict" | "unknown";
50
+ effect: AgentRunCancellationEffect;
51
+ message?: string;
52
+ retryable?: boolean;
53
+ }
54
+ export declare const AgentRunCancellationAcknowledgementSchema: z.ZodObject<{
55
+ operationId: z.ZodString;
56
+ requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
57
+ run: z.ZodObject<{
58
+ runId: z.ZodString;
59
+ provider: z.ZodString;
60
+ environmentId: z.ZodString;
61
+ sessionId: z.ZodOptional<z.ZodString>;
62
+ executionId: z.ZodOptional<z.ZodString>;
63
+ requestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
64
+ }, z.core.$strict>;
65
+ status: z.ZodEnum<{
66
+ unknown: "unknown";
67
+ conflict: "conflict";
68
+ accepted: "accepted";
69
+ replayed: "replayed";
70
+ }>;
71
+ effect: z.ZodEnum<{
72
+ unknown: "unknown";
73
+ cancelled: "cancelled";
74
+ cancel_requested: "cancel_requested";
75
+ not_live: "not_live";
76
+ }>;
77
+ message: z.ZodOptional<z.ZodString>;
78
+ retryable: z.ZodOptional<z.ZodBoolean>;
79
+ }, z.core.$strict>;
80
+ export declare function agentRunCancellationAcknowledgementMatchesRequest(request: AgentRunCancellationRequest, acknowledgement: AgentRunCancellationAcknowledgement): boolean;
18
81
  /** Runtime validator for every member of the existing canonical event union. */
19
82
  export declare const CanonicalStreamEventSchema: z.ZodType<StreamEvent>;
20
83
  /** Ordered, replayable envelope around the existing canonical event union. */
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { canonicalCandidateDigest, sha256DigestSchema, } from "./agent-candidate-schema-common.js";
2
3
  import { InteractionRequestSchema } from "./interaction.js";
3
4
  import { DurablePlanSchema } from "./plan.js";
4
5
  const stableIdSchema = z
@@ -12,7 +13,62 @@ export const AgentRunControlRefSchema = z.strictObject({
12
13
  environmentId: stableIdSchema,
13
14
  sessionId: stableIdSchema.optional(),
14
15
  executionId: stableIdSchema.optional(),
16
+ requestDigest: sha256DigestSchema.optional(),
15
17
  });
18
+ export function agentRunCancellationRequestDigest(request) {
19
+ return canonicalCandidateDigest({
20
+ operationId: request.operationId,
21
+ run: AgentRunControlRefSchema.parse(request.run),
22
+ ...(request.reason === undefined ? {} : { reason: request.reason }),
23
+ });
24
+ }
25
+ export const AgentRunCancellationRequestSchema = z
26
+ .strictObject({
27
+ operationId: stableIdSchema,
28
+ requestDigest: sha256DigestSchema,
29
+ run: AgentRunControlRefSchema,
30
+ reason: z.string().min(1).max(2_048).optional(),
31
+ })
32
+ .superRefine((request, refinement) => {
33
+ if (request.requestDigest !== agentRunCancellationRequestDigest(request)) {
34
+ refinement.addIssue({
35
+ code: "custom",
36
+ path: ["requestDigest"],
37
+ message: "run cancellation request digest does not match its content",
38
+ });
39
+ }
40
+ });
41
+ export const AgentRunCancellationAcknowledgementSchema = z
42
+ .strictObject({
43
+ operationId: stableIdSchema,
44
+ requestDigest: sha256DigestSchema,
45
+ run: AgentRunControlRefSchema,
46
+ status: z.enum(["accepted", "replayed", "conflict", "unknown"]),
47
+ effect: z.enum(["cancel_requested", "cancelled", "not_live", "unknown"]),
48
+ message: z.string().min(1).optional(),
49
+ retryable: z.boolean().optional(),
50
+ })
51
+ .superRefine((acknowledgement, refinement) => {
52
+ const known = acknowledgement.effect !== "unknown";
53
+ if (((acknowledgement.status === "accepted" || acknowledgement.status === "replayed") && !known) ||
54
+ ((acknowledgement.status === "conflict" || acknowledgement.status === "unknown") && known)) {
55
+ refinement.addIssue({
56
+ code: "custom",
57
+ path: ["effect"],
58
+ message: "cancellation status and effect certainty do not agree",
59
+ });
60
+ }
61
+ });
62
+ export function agentRunCancellationAcknowledgementMatchesRequest(request, acknowledgement) {
63
+ const exactRequest = AgentRunCancellationRequestSchema.safeParse(request);
64
+ const exactAcknowledgement = AgentRunCancellationAcknowledgementSchema.safeParse(acknowledgement);
65
+ if (!exactRequest.success || !exactAcknowledgement.success)
66
+ return false;
67
+ return (exactAcknowledgement.data.operationId === exactRequest.data.operationId &&
68
+ exactAcknowledgement.data.requestDigest === exactRequest.data.requestDigest &&
69
+ canonicalCandidateDigest(exactAcknowledgement.data.run) ===
70
+ canonicalCandidateDigest(exactRequest.data.run));
71
+ }
16
72
  const unknownRecordSchema = z.record(z.string(), z.unknown());
17
73
  const partBase = {
18
74
  id: stableIdSchema,
@@ -19,6 +19,7 @@ export declare const WorkspaceCheckpointRequestSchema: z.ZodObject<{
19
19
  environmentId: z.ZodString;
20
20
  sessionId: z.ZodOptional<z.ZodString>;
21
21
  executionId: z.ZodOptional<z.ZodString>;
22
+ requestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
22
23
  }, z.core.$strict>;
23
24
  name: z.ZodOptional<z.ZodString>;
24
25
  metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
@@ -43,6 +44,7 @@ export declare const WorkspaceCheckpointRefSchema: z.ZodObject<{
43
44
  environmentId: z.ZodString;
44
45
  sessionId: z.ZodOptional<z.ZodString>;
45
46
  executionId: z.ZodOptional<z.ZodString>;
47
+ requestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
46
48
  }, z.core.$strict>;
47
49
  idempotencyKey: z.ZodString;
48
50
  requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
@@ -114,6 +116,7 @@ export declare const WorkspaceForkRequestSchema: z.ZodObject<{
114
116
  environmentId: z.ZodString;
115
117
  sessionId: z.ZodOptional<z.ZodString>;
116
118
  executionId: z.ZodOptional<z.ZodString>;
119
+ requestDigest: z.ZodOptional<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
117
120
  }, z.core.$strict>;
118
121
  idempotencyKey: z.ZodString;
119
122
  requestDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-interface",
3
- "version": "0.42.0",
3
+ "version": "0.43.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",