@tangle-network/agent-interface 0.48.0 → 0.49.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.
@@ -0,0 +1,306 @@
1
+ import { z } from "zod";
2
+ import { boundedIdentifierSchema, boundedStringSchema, } from "./contract-limits.js";
3
+ export const ObservationStateSchema = z.enum([
4
+ "known",
5
+ "stale",
6
+ "unavailable",
7
+ "redacted",
8
+ "unknown",
9
+ ]);
10
+ export const ObservationProvenanceSchema = z.strictObject({
11
+ origin: z.enum(["measured", "reported", "estimated"]),
12
+ observedAt: z.iso.datetime().max(64),
13
+ source: boundedIdentifierSchema.optional(),
14
+ });
15
+ /** Build a freshness-tagged observation schema around one value schema. */
16
+ export function observationOf(value) {
17
+ return z.discriminatedUnion("state", [
18
+ z.strictObject({
19
+ state: z.literal("known"),
20
+ value,
21
+ provenance: ObservationProvenanceSchema,
22
+ }),
23
+ z.strictObject({
24
+ state: z.literal("stale"),
25
+ value,
26
+ provenance: ObservationProvenanceSchema,
27
+ reason: boundedStringSchema.min(1),
28
+ }),
29
+ z.strictObject({
30
+ state: z.literal("unavailable"),
31
+ reason: boundedStringSchema.min(1),
32
+ }),
33
+ z.strictObject({
34
+ state: z.literal("redacted"),
35
+ reason: boundedStringSchema.min(1),
36
+ }),
37
+ z.strictObject({ state: z.literal("unknown") }),
38
+ ]);
39
+ }
40
+ const nonNegativeNumberSchema = z.number().finite().nonnegative();
41
+ export const ProviderIdentitySchema = z.strictObject({
42
+ provider: boundedIdentifierSchema,
43
+ environmentId: boundedIdentifierSchema,
44
+ sessionId: boundedIdentifierSchema.optional(),
45
+ backend: boundedIdentifierSchema.optional(),
46
+ });
47
+ export const AgentEnvironmentStatusSchema = z.enum([
48
+ "pending",
49
+ "provisioning",
50
+ "running",
51
+ "stopped",
52
+ "failed",
53
+ "expired",
54
+ "unknown",
55
+ ]);
56
+ /** Lifecycle, cleanup, continuity, and persistence of one environment. */
57
+ export const EnvironmentLifecycleSchema = z.strictObject({
58
+ status: AgentEnvironmentStatusSchema,
59
+ cleanup: z
60
+ .strictObject({
61
+ policy: z.enum(["manual", "idle", "scheduled", "on-exit"]).optional(),
62
+ scheduledAt: z.iso.datetime().max(64).optional(),
63
+ confirmed: z.boolean().optional(),
64
+ })
65
+ .optional(),
66
+ continuity: z
67
+ .strictObject({
68
+ resumable: z.boolean(),
69
+ mode: z.enum(["native", "replayed", "none"]).optional(),
70
+ })
71
+ .optional(),
72
+ persistence: z
73
+ .strictObject({
74
+ durable: z.boolean(),
75
+ scope: z.enum(["ephemeral", "session", "durable"]).optional(),
76
+ })
77
+ .optional(),
78
+ });
79
+ /**
80
+ * Credential-free network location. There is no field for a user, password,
81
+ * token, or other secret, and the host and scheme reject embedded credentials.
82
+ */
83
+ export const SafeEndpointSchema = z
84
+ .strictObject({
85
+ scheme: boundedIdentifierSchema.optional(),
86
+ host: boundedIdentifierSchema,
87
+ port: z.number().int().min(1).max(65_535).optional(),
88
+ region: boundedIdentifierSchema.optional(),
89
+ })
90
+ .superRefine((endpoint, refinement) => {
91
+ if (/[@/\s]|:\/\//.test(endpoint.host)) {
92
+ refinement.addIssue({
93
+ code: "custom",
94
+ path: ["host"],
95
+ message: "endpoint host must not carry credentials, a scheme, or a path",
96
+ });
97
+ }
98
+ if (endpoint.scheme !== undefined && /[@:/\s]/.test(endpoint.scheme)) {
99
+ refinement.addIssue({
100
+ code: "custom",
101
+ path: ["scheme"],
102
+ message: "endpoint scheme must be a bare protocol name",
103
+ });
104
+ }
105
+ });
106
+ /** Requested or effective compute shape, including an optional accelerator. */
107
+ export const ResourceProfileSchema = z.strictObject({
108
+ cpu: z.number().finite().positive().optional(),
109
+ memoryMb: z.number().int().positive().optional(),
110
+ diskMb: z.number().int().positive().optional(),
111
+ accelerator: z
112
+ .strictObject({
113
+ kind: boundedIdentifierSchema,
114
+ count: z.number().int().positive(),
115
+ memoryMb: z.number().int().positive().optional(),
116
+ })
117
+ .optional(),
118
+ });
119
+ /** A point-in-time or peak resource sample. */
120
+ export const ResourceUseSampleSchema = z.strictObject({
121
+ cpu: nonNegativeNumberSchema.optional(),
122
+ memoryMb: nonNegativeNumberSchema.optional(),
123
+ diskMb: nonNegativeNumberSchema.optional(),
124
+ acceleratorMemoryMb: nonNegativeNumberSchema.optional(),
125
+ });
126
+ /** Where an environment was requested or verified to run. */
127
+ export const PlacementDescriptorSchema = z.strictObject({
128
+ kind: z.enum(["local", "sandbox", "fleet", "provider"]),
129
+ sandboxId: boundedIdentifierSchema.optional(),
130
+ fleetId: boundedIdentifierSchema.optional(),
131
+ machineId: boundedIdentifierSchema.optional(),
132
+ region: boundedIdentifierSchema.optional(),
133
+ });
134
+ /**
135
+ * Token usage and cost for one execution. Bound to the shared {@link TokenUsage}
136
+ * type so a change to the canonical shape is caught here.
137
+ */
138
+ export const ModelUsageSchema = z.strictObject({
139
+ inputTokens: z.number().int().nonnegative(),
140
+ outputTokens: z.number().int().nonnegative(),
141
+ totalTokens: z.number().int().nonnegative().optional(),
142
+ cacheReadInputTokens: z.number().int().nonnegative().optional(),
143
+ cacheCreationInputTokens: z.number().int().nonnegative().optional(),
144
+ reasoningTokens: z.number().int().nonnegative().optional(),
145
+ cost: z.number().finite().nonnegative().optional(),
146
+ });
147
+ /** Provider compute cost charged for one environment. */
148
+ export const ComputeBillingSchema = z.strictObject({
149
+ amount: nonNegativeNumberSchema,
150
+ currency: boundedIdentifierSchema,
151
+ });
152
+ /** Account plan, credits, quota, and billing period. */
153
+ export const AccountUsageSchema = z.strictObject({
154
+ plan: observationOf(boundedIdentifierSchema).optional(),
155
+ credits: observationOf(z.strictObject({
156
+ remaining: nonNegativeNumberSchema,
157
+ unit: boundedIdentifierSchema,
158
+ })).optional(),
159
+ quota: observationOf(z.strictObject({
160
+ limit: nonNegativeNumberSchema,
161
+ used: nonNegativeNumberSchema,
162
+ remaining: nonNegativeNumberSchema,
163
+ unit: boundedIdentifierSchema,
164
+ })).optional(),
165
+ period: observationOf(z.strictObject({
166
+ start: z.iso.datetime().max(64),
167
+ end: z.iso.datetime().max(64),
168
+ })).optional(),
169
+ });
170
+ /**
171
+ * Optional normalized observation of one execution environment.
172
+ *
173
+ * `subject` is the always-known identity used to bind a live observation to its
174
+ * replay. Every other surface is optional and freshness-tagged, so a provider
175
+ * that reports nothing still validates and no absent value is a measured zero.
176
+ */
177
+ export const AgentEnvironmentObservationSchema = z.strictObject({
178
+ subject: ProviderIdentitySchema,
179
+ capturedAt: z.iso.datetime().max(64),
180
+ identity: observationOf(ProviderIdentitySchema).optional(),
181
+ lifecycle: observationOf(EnvironmentLifecycleSchema).optional(),
182
+ endpoint: observationOf(SafeEndpointSchema).optional(),
183
+ placement: z
184
+ .strictObject({
185
+ requested: PlacementDescriptorSchema.optional(),
186
+ verified: observationOf(PlacementDescriptorSchema).optional(),
187
+ })
188
+ .optional(),
189
+ resources: z
190
+ .strictObject({
191
+ requested: ResourceProfileSchema.optional(),
192
+ effective: observationOf(ResourceProfileSchema).optional(),
193
+ })
194
+ .optional(),
195
+ resourceUse: z
196
+ .strictObject({
197
+ current: observationOf(ResourceUseSampleSchema).optional(),
198
+ peak: observationOf(ResourceUseSampleSchema).optional(),
199
+ })
200
+ .optional(),
201
+ modelUsage: observationOf(ModelUsageSchema).optional(),
202
+ computeBilling: observationOf(ComputeBillingSchema).optional(),
203
+ accountUsage: AccountUsageSchema.optional(),
204
+ });
205
+ function providerIdentityEquals(left, right) {
206
+ return (left.provider === right.provider &&
207
+ left.environmentId === right.environmentId &&
208
+ left.sessionId === right.sessionId &&
209
+ left.backend === right.backend);
210
+ }
211
+ function observedIdentityMatches(left, right) {
212
+ if (left === undefined && right === undefined)
213
+ return true;
214
+ if (left === undefined || right === undefined)
215
+ return false;
216
+ if (left.state !== right.state)
217
+ return false;
218
+ const leftValue = "value" in left ? left.value : undefined;
219
+ const rightValue = "value" in right ? right.value : undefined;
220
+ if (leftValue === undefined && rightValue === undefined)
221
+ return true;
222
+ if (leftValue === undefined || rightValue === undefined)
223
+ return false;
224
+ const leftSource = "provenance" in left ? left.provenance.source : undefined;
225
+ const rightSource = "provenance" in right ? right.provenance.source : undefined;
226
+ return providerIdentityEquals(leftValue, rightValue) && leftSource === rightSource;
227
+ }
228
+ /**
229
+ * A live observation and its replay must name the same environment and the
230
+ * same observed identity and provenance source. Time and freshness may differ,
231
+ * but the identifiers may not.
232
+ */
233
+ export function agentEnvironmentObservationIdentityMatches(live, replay) {
234
+ const parsedLive = AgentEnvironmentObservationSchema.safeParse(live);
235
+ const parsedReplay = AgentEnvironmentObservationSchema.safeParse(replay);
236
+ if (!parsedLive.success || !parsedReplay.success)
237
+ return false;
238
+ return (providerIdentityEquals(parsedLive.data.subject, parsedReplay.data.subject) &&
239
+ observedIdentityMatches(parsedLive.data.identity, parsedReplay.data.identity));
240
+ }
241
+ const USERINFO_URL_PATTERN = /[a-z][a-z0-9+.-]*:\/\/[^/@\s]*@/i;
242
+ /**
243
+ * Secret-shaped whole words. Matching whole words, not substrings, keeps a
244
+ * token-count field such as `inputTokens` from reading as an auth token.
245
+ */
246
+ const CREDENTIAL_WORDS = new Set([
247
+ "token",
248
+ "secret",
249
+ "secrets",
250
+ "password",
251
+ "passwd",
252
+ "passphrase",
253
+ "credential",
254
+ "credentials",
255
+ "authorization",
256
+ "bearer",
257
+ "key",
258
+ "keys",
259
+ ]);
260
+ /** Split a key into lowercase words across camelCase and separators. */
261
+ function keyWords(key) {
262
+ return key
263
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
264
+ .split(/[^a-zA-Z0-9]+/)
265
+ .map((word) => word.toLowerCase())
266
+ .filter(Boolean);
267
+ }
268
+ /**
269
+ * Report whether an observation payload carries a credential. A credential is a
270
+ * secret-shaped object key or a string value with embedded userinfo. Contract
271
+ * tests use this to prove the observation surface never transports a secret.
272
+ */
273
+ export function observationContainsCredential(value) {
274
+ const pending = [value];
275
+ const seen = new Set();
276
+ while (pending.length > 0) {
277
+ const current = pending.pop();
278
+ if (typeof current === "string") {
279
+ if (USERINFO_URL_PATTERN.test(current))
280
+ return true;
281
+ continue;
282
+ }
283
+ if (current === null || typeof current !== "object")
284
+ continue;
285
+ if (seen.has(current))
286
+ continue;
287
+ seen.add(current);
288
+ if (Array.isArray(current)) {
289
+ for (const item of current)
290
+ pending.push(item);
291
+ continue;
292
+ }
293
+ for (const [key, entry] of Object.entries(current)) {
294
+ if (keyWords(key).some((word) => CREDENTIAL_WORDS.has(word)))
295
+ return true;
296
+ pending.push(entry);
297
+ }
298
+ }
299
+ return false;
300
+ }
301
+ /** Throw when an observation payload carries a credential. */
302
+ export function assertObservationCredentialFree(value) {
303
+ if (observationContainsCredential(value)) {
304
+ throw new Error("observation payload must not carry a credential");
305
+ }
306
+ }
@@ -1,3 +1,5 @@
1
1
  export * from "./environment-requests.js";
2
2
  export * from "./environment-exact-process.js";
3
+ export * from "./environment-observation.js";
4
+ export * from "./environment-terminal.js";
3
5
  export * from "./environment-runtime.js";
@@ -1,3 +1,5 @@
1
1
  export * from "./environment-requests.js";
2
2
  export * from "./environment-exact-process.js";
3
+ export * from "./environment-observation.js";
4
+ export * from "./environment-terminal.js";
3
5
  export * from "./environment-runtime.js";
@@ -9,6 +9,8 @@ import { type AgentRunCancellationAcknowledgement, type AgentRunCancellationRequ
9
9
  import type { AgentWorkspaceBranching } from "./workspace-branching.js";
10
10
  import type { AgentEnvironmentQuery, AgentEnvironmentStatus, AgentEnvironmentSummary, AgentProfileRef, AgentSessionStatus, CheckpointRef, CheckpointRequest, ExecRequest, ExecResult, ForkRequest, PlacementInfo, ResourceRequest, WorkspaceRequest } from "./environment-requests.js";
11
11
  import type { AgentExactProcessEgressMode, AgentExactProcessProvider } from "./environment-exact-process.js";
12
+ import type { AgentEnvironmentObservation } from "./environment-observation.js";
13
+ import type { AgentTerminalSession, TerminalAttachRequest, TerminalAttachResult } from "./environment-terminal.js";
12
14
  export interface AgentTurnInput {
13
15
  prompt?: string;
14
16
  parts?: InputPart[];
@@ -653,6 +655,18 @@ export interface AgentEnvironment {
653
655
  placement?(options?: {
654
656
  signal?: AbortSignal;
655
657
  }): Promise<PlacementInfo>;
658
+ /** Normalized, freshness-tagged observation of this environment. */
659
+ observe?(options?: {
660
+ signal?: AbortSignal;
661
+ }): Promise<AgentEnvironmentObservation>;
662
+ /** Open or reattach an interactive terminal under a parent execution. */
663
+ attachTerminal?(request: TerminalAttachRequest, options?: {
664
+ signal?: AbortSignal;
665
+ }): Promise<TerminalAttachResult>;
666
+ /** Accessor for a live interactive terminal handle. */
667
+ terminal?(terminalSessionId: string, options?: {
668
+ signal?: AbortSignal;
669
+ }): AgentTerminalSession;
656
670
  refresh?(options?: {
657
671
  signal?: AbortSignal;
658
672
  }): Promise<void>;
@@ -712,6 +726,25 @@ export interface AgentEnvironmentCapabilities {
712
726
  exactProcess?: {
713
727
  egress: readonly AgentExactProcessEgressMode[];
714
728
  };
729
+ /** Per-surface flags for the normalized environment observation. */
730
+ observation?: {
731
+ identity: boolean;
732
+ lifecycle: boolean;
733
+ endpoint: boolean;
734
+ placement: boolean;
735
+ resources: boolean;
736
+ resourceUse: boolean;
737
+ modelUsage: boolean;
738
+ computeBilling: boolean;
739
+ accountUsage: boolean;
740
+ };
741
+ /** Present only when the provider serves an interactive terminal. */
742
+ interactiveTerminal?: {
743
+ attach: boolean;
744
+ input: boolean;
745
+ resize: boolean;
746
+ reattach: boolean;
747
+ };
715
748
  }
716
749
  /** Strict runtime validator for provider capability negotiation. */
717
750
  export declare const AgentEnvironmentCapabilitiesSchema: z.ZodObject<{
@@ -804,6 +837,23 @@ export declare const AgentEnvironmentCapabilitiesSchema: z.ZodObject<{
804
837
  strict: "strict";
805
838
  }>>;
806
839
  }, z.core.$strict>>;
840
+ observation: z.ZodOptional<z.ZodObject<{
841
+ identity: z.ZodBoolean;
842
+ lifecycle: z.ZodBoolean;
843
+ endpoint: z.ZodBoolean;
844
+ placement: z.ZodBoolean;
845
+ resources: z.ZodBoolean;
846
+ resourceUse: z.ZodBoolean;
847
+ modelUsage: z.ZodBoolean;
848
+ computeBilling: z.ZodBoolean;
849
+ accountUsage: z.ZodBoolean;
850
+ }, z.core.$strict>>;
851
+ interactiveTerminal: z.ZodOptional<z.ZodObject<{
852
+ attach: z.ZodBoolean;
853
+ input: z.ZodBoolean;
854
+ resize: z.ZodBoolean;
855
+ reattach: z.ZodBoolean;
856
+ }, z.core.$strict>>;
807
857
  }, z.core.$strict>;
808
858
  export interface CreateAgentEnvironmentInput {
809
859
  profile: AgentProfileRef;
@@ -167,6 +167,27 @@ export const AgentEnvironmentCapabilitiesSchema = z
167
167
  .max(CONTRACT_MAX_ARRAY_LENGTH),
168
168
  })
169
169
  .optional(),
170
+ observation: z
171
+ .strictObject({
172
+ identity: z.boolean(),
173
+ lifecycle: z.boolean(),
174
+ endpoint: z.boolean(),
175
+ placement: z.boolean(),
176
+ resources: z.boolean(),
177
+ resourceUse: z.boolean(),
178
+ modelUsage: z.boolean(),
179
+ computeBilling: z.boolean(),
180
+ accountUsage: z.boolean(),
181
+ })
182
+ .optional(),
183
+ interactiveTerminal: z
184
+ .strictObject({
185
+ attach: z.boolean(),
186
+ input: z.boolean(),
187
+ resize: z.boolean(),
188
+ reattach: z.boolean(),
189
+ })
190
+ .optional(),
170
191
  })
171
192
  .superRefine((capabilities, refinement) => {
172
193
  if (capabilities.retainedControl !== undefined &&
@@ -217,6 +238,16 @@ export const AgentEnvironmentCapabilitiesSchema = z
217
238
  message: "exact process egress modes must be unique",
218
239
  });
219
240
  }
241
+ const terminal = capabilities.interactiveTerminal;
242
+ if (terminal !== undefined &&
243
+ (terminal.input || terminal.resize || terminal.reattach) &&
244
+ !terminal.attach) {
245
+ refinement.addIssue({
246
+ code: "custom",
247
+ path: ["interactiveTerminal"],
248
+ message: "interactive terminal input, resize, and reattach each require attach",
249
+ });
250
+ }
220
251
  const extensions = capabilities.profile.extensions;
221
252
  if (extensions && new Set(extensions).size !== extensions.length) {
222
253
  refinement.addIssue({
@@ -0,0 +1,172 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Provider-neutral handle for one interactive terminal.
4
+ *
5
+ * The handle carries no raw process id and no environment map, so a terminal
6
+ * reference never leaks host process detail or injected secrets. Every terminal
7
+ * is bound to a parent execution and carries an explicit expiry, so an orphan
8
+ * or an expired terminal fails closed at the call sites that read it.
9
+ */
10
+ export declare const TerminalSessionRefSchema: z.ZodObject<{
11
+ terminalSessionId: z.ZodString;
12
+ parentExecutionId: z.ZodString;
13
+ name: z.ZodString;
14
+ shell: z.ZodString;
15
+ command: z.ZodOptional<z.ZodString>;
16
+ cwd: z.ZodString;
17
+ cols: z.ZodNumber;
18
+ rows: z.ZodNumber;
19
+ connectionId: z.ZodOptional<z.ZodString>;
20
+ createdAt: z.ZodISODateTime;
21
+ lastActivityAt: z.ZodISODateTime;
22
+ expiresAt: z.ZodISODateTime;
23
+ isRunning: z.ZodBoolean;
24
+ exitCode: z.ZodOptional<z.ZodNumber>;
25
+ exitSignal: z.ZodOptional<z.ZodString>;
26
+ attachCount: z.ZodNumber;
27
+ }, z.core.$strict>;
28
+ export type TerminalSessionRef = z.infer<typeof TerminalSessionRefSchema>;
29
+ /** Raw bytes written to the terminal, normalized to UTF-8 text. */
30
+ export declare const TerminalInputSchema: z.ZodObject<{
31
+ data: z.ZodString;
32
+ }, z.core.$strict>;
33
+ export type TerminalInput = z.infer<typeof TerminalInputSchema>;
34
+ /** New terminal geometry. */
35
+ export declare const TerminalResizeSchema: z.ZodObject<{
36
+ cols: z.ZodNumber;
37
+ rows: z.ZodNumber;
38
+ }, z.core.$strict>;
39
+ export type TerminalResize = z.infer<typeof TerminalResizeSchema>;
40
+ /**
41
+ * Create-or-reattach request. A present `terminalSessionId` reattaches to an
42
+ * existing terminal; its absence opens a new one under the parent execution.
43
+ * `mode` selects an `attach` to a live process or a `logical` resume that
44
+ * replays retained output.
45
+ */
46
+ export declare const TerminalAttachRequestSchema: z.ZodObject<{
47
+ parentExecutionId: z.ZodString;
48
+ terminalSessionId: z.ZodOptional<z.ZodString>;
49
+ connectionId: z.ZodOptional<z.ZodString>;
50
+ mode: z.ZodEnum<{
51
+ attach: "attach";
52
+ logical: "logical";
53
+ }>;
54
+ cols: z.ZodOptional<z.ZodNumber>;
55
+ rows: z.ZodOptional<z.ZodNumber>;
56
+ command: z.ZodOptional<z.ZodString>;
57
+ cwd: z.ZodOptional<z.ZodString>;
58
+ }, z.core.$strict>;
59
+ export type TerminalAttachRequest = z.infer<typeof TerminalAttachRequestSchema>;
60
+ /** Result of a create-or-reattach request. */
61
+ export declare const TerminalAttachResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
62
+ status: z.ZodEnum<{
63
+ attached: "attached";
64
+ reattached: "reattached";
65
+ }>;
66
+ mode: z.ZodEnum<{
67
+ attach: "attach";
68
+ logical: "logical";
69
+ }>;
70
+ ref: z.ZodObject<{
71
+ terminalSessionId: z.ZodString;
72
+ parentExecutionId: z.ZodString;
73
+ name: z.ZodString;
74
+ shell: z.ZodString;
75
+ command: z.ZodOptional<z.ZodString>;
76
+ cwd: z.ZodString;
77
+ cols: z.ZodNumber;
78
+ rows: z.ZodNumber;
79
+ connectionId: z.ZodOptional<z.ZodString>;
80
+ createdAt: z.ZodISODateTime;
81
+ lastActivityAt: z.ZodISODateTime;
82
+ expiresAt: z.ZodISODateTime;
83
+ isRunning: z.ZodBoolean;
84
+ exitCode: z.ZodOptional<z.ZodNumber>;
85
+ exitSignal: z.ZodOptional<z.ZodString>;
86
+ attachCount: z.ZodNumber;
87
+ }, z.core.$strict>;
88
+ attachCount: z.ZodNumber;
89
+ }, z.core.$strict>, z.ZodObject<{
90
+ status: z.ZodLiteral<"unavailable">;
91
+ reason: z.ZodString;
92
+ }, z.core.$strict>, z.ZodObject<{
93
+ status: z.ZodLiteral<"unknown">;
94
+ message: z.ZodString;
95
+ retryable: z.ZodBoolean;
96
+ }, z.core.$strict>], "status">;
97
+ export type TerminalAttachResult = z.infer<typeof TerminalAttachResultSchema>;
98
+ /**
99
+ * One ordered terminal output frame. `output` frames carry a monotonic `seq`
100
+ * that a consumer replays from, so a reconnect resumes without loss or
101
+ * duplication.
102
+ */
103
+ export declare const TerminalOutputEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
104
+ type: z.ZodLiteral<"ready">;
105
+ cols: z.ZodOptional<z.ZodNumber>;
106
+ rows: z.ZodOptional<z.ZodNumber>;
107
+ }, z.core.$strict>, z.ZodObject<{
108
+ type: z.ZodLiteral<"output">;
109
+ seq: z.ZodNumber;
110
+ data: z.ZodString;
111
+ }, z.core.$strict>, z.ZodObject<{
112
+ type: z.ZodLiteral<"resize">;
113
+ cols: z.ZodNumber;
114
+ rows: z.ZodNumber;
115
+ }, z.core.$strict>, z.ZodObject<{
116
+ type: z.ZodLiteral<"exit">;
117
+ exitCode: z.ZodOptional<z.ZodNumber>;
118
+ exitSignal: z.ZodOptional<z.ZodString>;
119
+ }, z.core.$strict>, z.ZodObject<{
120
+ type: z.ZodLiteral<"error">;
121
+ message: z.ZodString;
122
+ }, z.core.$strict>], "type">;
123
+ export type TerminalOutputEvent = z.infer<typeof TerminalOutputEventSchema>;
124
+ /** Acknowledgement of a detach or close. */
125
+ export declare const TerminalDetachAckSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
126
+ status: z.ZodLiteral<"detached">;
127
+ terminalSessionId: z.ZodString;
128
+ connectionId: z.ZodOptional<z.ZodString>;
129
+ }, z.core.$strict>, z.ZodObject<{
130
+ status: z.ZodLiteral<"closed">;
131
+ terminalSessionId: z.ZodString;
132
+ exitCode: z.ZodOptional<z.ZodNumber>;
133
+ exitSignal: z.ZodOptional<z.ZodString>;
134
+ }, z.core.$strict>, z.ZodObject<{
135
+ status: z.ZodLiteral<"unknown">;
136
+ terminalSessionId: z.ZodString;
137
+ message: z.ZodString;
138
+ retryable: z.ZodBoolean;
139
+ }, z.core.$strict>], "status">;
140
+ export type TerminalDetachAck = z.infer<typeof TerminalDetachAckSchema>;
141
+ /**
142
+ * Fail-closed usability check for a terminal reference. Returns true only when
143
+ * the reference parses, is running, and its expiry is in the future. A parse
144
+ * failure, a stopped terminal, or a past expiry denies use.
145
+ */
146
+ export declare function terminalSessionUsable(ref: TerminalSessionRef, nowIso: string): boolean;
147
+ /** Bind an attach result to the parent execution and terminal it targeted. */
148
+ export declare function terminalAttachResultMatchesRequest(request: TerminalAttachRequest, result: TerminalAttachResult): boolean;
149
+ /**
150
+ * Live handle for one interactive terminal. Signatures only; a provider adapter
151
+ * binds the transport in phase two.
152
+ */
153
+ export interface AgentTerminalSession {
154
+ readonly ref: TerminalSessionRef;
155
+ input(input: TerminalInput, options?: {
156
+ signal?: AbortSignal;
157
+ }): Promise<void>;
158
+ resize(resize: TerminalResize, options?: {
159
+ signal?: AbortSignal;
160
+ }): Promise<void>;
161
+ detach(options?: {
162
+ signal?: AbortSignal;
163
+ }): Promise<TerminalDetachAck>;
164
+ close(options?: {
165
+ signal?: AbortSignal;
166
+ }): Promise<TerminalDetachAck>;
167
+ /** Replays retained frames from `since`, then continues until the terminal exits. */
168
+ events(options?: {
169
+ since?: number;
170
+ signal?: AbortSignal;
171
+ }): AsyncIterable<TerminalOutputEvent>;
172
+ }