@tangle-network/agent-provider-tangle 0.14.0 → 0.14.2
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 +61 -54
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/tangle-confidential-attestation.d.ts +31 -0
- package/dist/tangle-confidential-attestation.js +165 -0
- package/dist/tangle-interactive.d.ts +2 -2
- package/dist/tangle-interactive.js +95 -140
- package/dist/tangle-types.d.ts +36 -45
- package/dist/tangle-workspace-branching.js +294 -73
- package/package.json +11 -9
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import { AgentInteractiveSessionAttachSchema, AgentInteractiveSessionControlClaimAcknowledgementSchema, AgentInteractiveSessionControlClaimRequestSchema, AgentInteractiveSessionPromptAcknowledgementSchema, AgentInteractiveSessionPromptCommandSchema, AgentInteractiveSessionRefSchema, AgentInteractiveSessionStatusSchema, AgentInteractiveSessionStopAcknowledgementSchema, AgentInteractiveSessionStopCommandSchema, agentInteractiveSessionControlClaimAcknowledgementMatchesRequest, agentInteractiveSessionControlClaimMatchesRef, agentInteractiveSessionPromptAcknowledgementMatchesCommand, agentInteractiveSessionRefMatchesStart, agentInteractiveSessionStopAcknowledgementMatchesCommand, canonicalCandidateDigest, exactAgentInteractiveSessionStart, } from "@tangle-network/agent-interface";
|
|
2
|
-
import { parseBackendType } from "@tangle-network/sandbox";
|
|
1
|
+
import { AgentInteractiveSessionAttachSchema, AgentInteractiveSessionControlClaimSchema, AgentInteractiveSessionControlClaimAcknowledgementSchema, AgentInteractiveSessionControlClaimRequestSchema, AgentInteractiveSessionPromptAcknowledgementSchema, AgentInteractiveSessionPromptCommandSchema, AgentInteractiveSessionRefSchema, AgentInteractiveSessionStatusSchema, AgentInteractiveSessionStopAcknowledgementSchema, AgentInteractiveSessionStopCommandSchema, TerminalReplayWindowSchema, TerminalSessionRefSchema, agentInteractiveSessionControlClaimAcknowledgementMatchesRequest, agentInteractiveSessionControlClaimMatchesRef, agentInteractiveSessionPromptAcknowledgementMatchesCommand, agentInteractiveSessionRefMatchesStart, agentInteractiveSessionStatusMatchesRef, agentInteractiveSessionStopAcknowledgementMatchesCommand, canonicalCandidateDigest, exactAgentInteractiveSessionStart, } from "@tangle-network/agent-interface";
|
|
3
2
|
import { assertOptionKeys } from "./tangle-environment-validation.js";
|
|
4
3
|
import { transportFailureReason } from "./tangle-failure-reason.js";
|
|
5
|
-
import { bindTangleInteractiveControl, closeTangleStreamQuietly, createTangleTerminalStreamCapture, prepareTangleTerminalAttachment, } from "./tangle-terminal.js";
|
|
6
4
|
/**
|
|
7
5
|
* Test the linked SDK surface without accepting any older interactive shape.
|
|
8
6
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* Sandbox owns the exact reference, control claim, terminal binding, and
|
|
8
|
+
* mutation acknowledgements. An older handle shape fails this test closed.
|
|
11
9
|
*/
|
|
12
10
|
export function sandboxBacksInteractiveAgent(box) {
|
|
13
11
|
if (typeof box.session !== "function")
|
|
14
12
|
return false;
|
|
15
13
|
try {
|
|
16
|
-
const candidate = box
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
const candidate = box
|
|
15
|
+
.session("__tangle-interactive-probe__")
|
|
16
|
+
.interactive?.();
|
|
17
|
+
return isSandboxInteractiveSession(candidate);
|
|
19
18
|
}
|
|
20
19
|
catch {
|
|
21
20
|
return false;
|
|
@@ -29,9 +28,9 @@ export function sandboxBacksInteractiveAgent(box) {
|
|
|
29
28
|
* never creates a second record for any of those facts.
|
|
30
29
|
*/
|
|
31
30
|
export function createTangleInteractiveAgentRegistry(box, providerName, environmentId) {
|
|
32
|
-
const exactHandle = (sessionId) => {
|
|
31
|
+
const exactHandle = (sessionId, binding) => {
|
|
33
32
|
const session = box.session?.(sessionId);
|
|
34
|
-
const candidate = session?.interactive?.();
|
|
33
|
+
const candidate = session?.interactive?.(binding);
|
|
35
34
|
if (!isSandboxInteractiveSession(candidate)) {
|
|
36
35
|
throw new Error("the linked Sandbox SDK does not expose the exact interactive control API");
|
|
37
36
|
}
|
|
@@ -50,10 +49,13 @@ export function createTangleInteractiveAgentRegistry(box, providerName, environm
|
|
|
50
49
|
throw new Error("the Sandbox returned a different interactive session ref");
|
|
51
50
|
}
|
|
52
51
|
};
|
|
53
|
-
const
|
|
52
|
+
const assertControlMatchesRef = (ref, control) => {
|
|
54
53
|
if (!agentInteractiveSessionControlClaimMatchesRef(ref, control)) {
|
|
55
54
|
throw new Error("the interactive control claim belongs to another process");
|
|
56
55
|
}
|
|
56
|
+
};
|
|
57
|
+
const assertActiveControl = (ref, control) => {
|
|
58
|
+
assertControlMatchesRef(ref, control);
|
|
57
59
|
if (Date.parse(control.expiresAt) <= Date.now()) {
|
|
58
60
|
throw new Error("the interactive control claim has expired");
|
|
59
61
|
}
|
|
@@ -62,70 +64,68 @@ export function createTangleInteractiveAgentRegistry(box, providerName, environm
|
|
|
62
64
|
async start(request, options) {
|
|
63
65
|
assertOptionKeys(options, ["signal"], "Tangle interactive agent start");
|
|
64
66
|
const exactRequest = exactAgentInteractiveSessionStart(request);
|
|
65
|
-
|
|
66
|
-
if (requestedHarness === undefined) {
|
|
67
|
+
if (exactRequest.profile.harness === undefined) {
|
|
67
68
|
throw new Error("interactive agent sessions require AgentProfile.harness");
|
|
68
69
|
}
|
|
69
|
-
let harness;
|
|
70
|
-
try {
|
|
71
|
-
harness = parseBackendType(requestedHarness);
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
throw new Error("the requested AgentProfile harness has no Tangle Sandbox runner");
|
|
75
|
-
}
|
|
76
70
|
options?.signal?.throwIfAborted();
|
|
77
71
|
const handle = exactHandle(exactRequest.run.sessionId);
|
|
78
72
|
let observed;
|
|
79
73
|
try {
|
|
80
|
-
observed = await handle.start(
|
|
81
|
-
harness,
|
|
82
|
-
...(exactRequest.profile.model?.default === undefined
|
|
83
|
-
? {}
|
|
84
|
-
: { model: exactRequest.profile.model.default }),
|
|
85
|
-
...(exactRequest.cwd === undefined ? {} : { cwd: exactRequest.cwd }),
|
|
86
|
-
...(exactRequest.cols === undefined ? {} : { cols: exactRequest.cols }),
|
|
87
|
-
...(exactRequest.rows === undefined ? {} : { rows: exactRequest.rows }),
|
|
88
|
-
profile: exactRequest.profile,
|
|
89
|
-
...(exactRequest.initialPrompt === undefined
|
|
90
|
-
? {}
|
|
91
|
-
: { initialPrompt: exactRequest.initialPrompt }),
|
|
92
|
-
idempotencyKey: exactRequest.run.runId,
|
|
93
|
-
requestDigest: exactRequest.run.requestDigest,
|
|
94
|
-
});
|
|
74
|
+
observed = await handle.start(exactRequest, options);
|
|
95
75
|
}
|
|
96
76
|
catch (error) {
|
|
97
77
|
options?.signal?.throwIfAborted();
|
|
98
78
|
throw new Error(transportFailureReason("interactive start", error));
|
|
99
79
|
}
|
|
100
80
|
options?.signal?.throwIfAborted();
|
|
101
|
-
const ref =
|
|
81
|
+
const ref = AgentInteractiveSessionRefSchema.parse(observed.ref);
|
|
82
|
+
const control = AgentInteractiveSessionControlClaimSchema.parse(observed.control);
|
|
102
83
|
if (!agentInteractiveSessionRefMatchesStart(exactRequest, ref)) {
|
|
103
84
|
throw new Error("the Sandbox returned an interactive session with a different admission receipt");
|
|
104
85
|
}
|
|
86
|
+
assertControlMatchesRef(ref, control);
|
|
87
|
+
if (observed.state === "running")
|
|
88
|
+
assertActiveControl(ref, control);
|
|
89
|
+
if (observed.state === "running" && observed.streamUrl.length === 0) {
|
|
90
|
+
throw new Error("the Sandbox returned a running session without a stream");
|
|
91
|
+
}
|
|
105
92
|
return ref;
|
|
106
93
|
},
|
|
107
94
|
get(value) {
|
|
108
95
|
const ref = exactRef(value);
|
|
109
|
-
const handle = exactHandle(ref.run.sessionId);
|
|
96
|
+
const handle = exactHandle(ref.run.sessionId, { ref });
|
|
97
|
+
const mutationHandle = (control) => exactHandle(ref.run.sessionId, { ref, control });
|
|
110
98
|
const readStatus = async (options) => {
|
|
111
99
|
assertOptionKeys(options, ["signal"], "Tangle interactive agent status");
|
|
112
100
|
options?.signal?.throwIfAborted();
|
|
113
101
|
let observed;
|
|
114
102
|
try {
|
|
115
|
-
observed = await handle.status();
|
|
103
|
+
observed = await handle.status(options);
|
|
116
104
|
}
|
|
117
105
|
catch (error) {
|
|
118
106
|
options?.signal?.throwIfAborted();
|
|
119
107
|
throw new Error(transportFailureReason("interactive status", error));
|
|
120
108
|
}
|
|
121
109
|
options?.signal?.throwIfAborted();
|
|
122
|
-
|
|
110
|
+
if (observed === null) {
|
|
111
|
+
return AgentInteractiveSessionStatusSchema.parse({
|
|
112
|
+
state: "unknown",
|
|
113
|
+
ref,
|
|
114
|
+
message: "the Sandbox no longer knows this interactive agent session",
|
|
115
|
+
retryable: false,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const status = AgentInteractiveSessionStatusSchema.parse(observed);
|
|
119
|
+
if (!agentInteractiveSessionStatusMatchesRef(ref, status)) {
|
|
120
|
+
throw new Error("the Sandbox reported a different interactive agent session identity");
|
|
121
|
+
}
|
|
122
|
+
return status;
|
|
123
123
|
};
|
|
124
124
|
const validateControl = async (control, options) => {
|
|
125
|
-
|
|
125
|
+
assertActiveControl(ref, control);
|
|
126
126
|
options?.signal?.throwIfAborted();
|
|
127
127
|
try {
|
|
128
|
-
await
|
|
128
|
+
await mutationHandle(control).validateControl(control, options);
|
|
129
129
|
}
|
|
130
130
|
catch (error) {
|
|
131
131
|
options?.signal?.throwIfAborted();
|
|
@@ -142,7 +142,7 @@ export function createTangleInteractiveAgentRegistry(box, providerName, environm
|
|
|
142
142
|
options?.signal?.throwIfAborted();
|
|
143
143
|
let raw;
|
|
144
144
|
try {
|
|
145
|
-
raw = await handle.claimControl(exactRequest);
|
|
145
|
+
raw = await handle.claimControl(exactRequest, options);
|
|
146
146
|
}
|
|
147
147
|
catch (error) {
|
|
148
148
|
options?.signal?.throwIfAborted();
|
|
@@ -160,59 +160,33 @@ export function createTangleInteractiveAgentRegistry(box, providerName, environm
|
|
|
160
160
|
assertOptionKeys(options, ["signal"], "Tangle interactive agent attach");
|
|
161
161
|
const exactRequest = AgentInteractiveSessionAttachSchema.parse(request ?? {});
|
|
162
162
|
await validateControl(exactRequest.control, options);
|
|
163
|
-
|
|
164
|
-
if (before.state !== "running") {
|
|
165
|
-
throw new Error("the exact interactive agent session is not running");
|
|
166
|
-
}
|
|
167
|
-
const terminals = box.terminals;
|
|
168
|
-
if (terminals === undefined || typeof terminals.get !== "function") {
|
|
169
|
-
throw new Error("the Sandbox client cannot read exact interactive terminal metadata");
|
|
170
|
-
}
|
|
171
|
-
const capture = createTangleTerminalStreamCapture(exactRequest);
|
|
172
|
-
let stream;
|
|
163
|
+
let terminal;
|
|
173
164
|
try {
|
|
174
|
-
|
|
175
|
-
control: exactRequest.control,
|
|
176
|
-
...(exactRequest.cols === undefined ? {} : { cols: exactRequest.cols }),
|
|
177
|
-
...(exactRequest.rows === undefined ? {} : { rows: exactRequest.rows }),
|
|
178
|
-
handlers: capture.handlers,
|
|
179
|
-
});
|
|
165
|
+
terminal = await mutationHandle(exactRequest.control).attachAgentTerminal(exactRequest, options);
|
|
180
166
|
}
|
|
181
167
|
catch (error) {
|
|
182
168
|
options?.signal?.throwIfAborted();
|
|
183
169
|
throw new Error(transportFailureReason("interactive attach", error));
|
|
184
170
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return Promise.resolve();
|
|
199
|
-
return validateControl(exactRequest.control, options);
|
|
200
|
-
},
|
|
201
|
-
});
|
|
202
|
-
if (prepared.status === "unknown") {
|
|
203
|
-
throw new Error(prepared.message);
|
|
204
|
-
}
|
|
205
|
-
if (prepared.acknowledgement.restored !== true) {
|
|
206
|
-
await prepared.session.detach();
|
|
207
|
-
throw new Error("the exact interactive attach did not restore the coding-agent PTY");
|
|
171
|
+
try {
|
|
172
|
+
options?.signal?.throwIfAborted();
|
|
173
|
+
const returnedControl = AgentInteractiveSessionControlClaimSchema.parse(terminal.control);
|
|
174
|
+
const returnedRef = TerminalSessionRefSchema.parse(terminal.ref);
|
|
175
|
+
TerminalReplayWindowSchema.parse(terminal.cursors);
|
|
176
|
+
if (canonicalCandidateDigest(returnedControl) !==
|
|
177
|
+
canonicalCandidateDigest(exactRequest.control) ||
|
|
178
|
+
returnedRef.terminalSessionId !== ref.run.sessionId ||
|
|
179
|
+
returnedRef.parentExecutionId !== ref.run.executionId ||
|
|
180
|
+
returnedRef.expiresAt !== exactRequest.control.expiresAt ||
|
|
181
|
+
!returnedRef.isRunning) {
|
|
182
|
+
throw new Error("the Sandbox returned a terminal with a different interactive identity");
|
|
183
|
+
}
|
|
208
184
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
throw new Error("the exact interactive agent exited while its terminal attached");
|
|
185
|
+
catch (error) {
|
|
186
|
+
await terminal.detach().catch(() => undefined);
|
|
187
|
+
throw error;
|
|
213
188
|
}
|
|
214
|
-
|
|
215
|
-
return terminal;
|
|
189
|
+
return validatedTerminal(terminal, exactRequest.control, validateControl, ref);
|
|
216
190
|
},
|
|
217
191
|
async sendPrompt(command, options) {
|
|
218
192
|
assertOptionKeys(options, ["signal"], "Tangle interactive agent prompt");
|
|
@@ -221,7 +195,7 @@ export function createTangleInteractiveAgentRegistry(box, providerName, environm
|
|
|
221
195
|
await validateControl(exactCommand.control, options);
|
|
222
196
|
let raw;
|
|
223
197
|
try {
|
|
224
|
-
raw = await
|
|
198
|
+
raw = await mutationHandle(exactCommand.control).sendPrompt(exactCommand, options);
|
|
225
199
|
}
|
|
226
200
|
catch (error) {
|
|
227
201
|
options?.signal?.throwIfAborted();
|
|
@@ -241,7 +215,7 @@ export function createTangleInteractiveAgentRegistry(box, providerName, environm
|
|
|
241
215
|
await validateControl(exactCommand.control, options);
|
|
242
216
|
let raw;
|
|
243
217
|
try {
|
|
244
|
-
raw = await
|
|
218
|
+
raw = await mutationHandle(exactCommand.control).stop(exactCommand, options);
|
|
245
219
|
}
|
|
246
220
|
catch (error) {
|
|
247
221
|
options?.signal?.throwIfAborted();
|
|
@@ -266,62 +240,43 @@ function isSandboxInteractiveSession(value) {
|
|
|
266
240
|
"start",
|
|
267
241
|
"claimControl",
|
|
268
242
|
"status",
|
|
269
|
-
"
|
|
243
|
+
"attachAgentTerminal",
|
|
270
244
|
"validateControl",
|
|
271
245
|
"sendPrompt",
|
|
272
246
|
"stop",
|
|
273
247
|
].every((key) => typeof candidate[key] === "function");
|
|
274
248
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
if (observed.state === "running") {
|
|
307
|
-
if (observed.streamUrl.length === 0) {
|
|
308
|
-
throw new Error("the Sandbox reported a running session without a stream");
|
|
309
|
-
}
|
|
310
|
-
return AgentInteractiveSessionStatusSchema.parse({ state: "running", ref });
|
|
311
|
-
}
|
|
312
|
-
return AgentInteractiveSessionStatusSchema.parse({
|
|
313
|
-
state: "exited",
|
|
314
|
-
ref,
|
|
315
|
-
endedAt: observed.endedAt,
|
|
316
|
-
reason: observed.reason,
|
|
317
|
-
...(Number.isSafeInteger(observed.exitCode)
|
|
318
|
-
? { exitCode: observed.exitCode }
|
|
319
|
-
: {}),
|
|
320
|
-
...(typeof observed.exitSignal === "string" && observed.exitSignal.length > 0
|
|
321
|
-
? { exitSignal: observed.exitSignal }
|
|
322
|
-
: {}),
|
|
323
|
-
});
|
|
249
|
+
function validatedTerminal(terminal, control, validate, expectedRef) {
|
|
250
|
+
const boundControl = Object.freeze({ ...control });
|
|
251
|
+
return {
|
|
252
|
+
get ref() {
|
|
253
|
+
const ref = TerminalSessionRefSchema.parse(terminal.ref);
|
|
254
|
+
if (ref.terminalSessionId !== expectedRef.run.sessionId ||
|
|
255
|
+
ref.parentExecutionId !== expectedRef.run.executionId) {
|
|
256
|
+
throw new Error("the Sandbox terminal changed its interactive session identity");
|
|
257
|
+
}
|
|
258
|
+
return ref;
|
|
259
|
+
},
|
|
260
|
+
get cursors() {
|
|
261
|
+
return TerminalReplayWindowSchema.parse(terminal.cursors);
|
|
262
|
+
},
|
|
263
|
+
control: boundControl,
|
|
264
|
+
async input(input, options) {
|
|
265
|
+
await validate(boundControl, options);
|
|
266
|
+
await terminal.input(input, options);
|
|
267
|
+
},
|
|
268
|
+
async resize(resize, options) {
|
|
269
|
+
await validate(boundControl, options);
|
|
270
|
+
await terminal.resize(resize, options);
|
|
271
|
+
},
|
|
272
|
+
detach: (options) => terminal.detach(options),
|
|
273
|
+
async close(options) {
|
|
274
|
+
await validate(boundControl, options);
|
|
275
|
+
return terminal.close(options);
|
|
276
|
+
},
|
|
277
|
+
events: (options) => terminal.events(options),
|
|
278
|
+
};
|
|
324
279
|
}
|
|
325
280
|
function sameExactSessionRef(expected, candidate) {
|
|
326
|
-
return canonicalCandidateDigest(expected) === canonicalCandidateDigest(candidate);
|
|
281
|
+
return (canonicalCandidateDigest(expected) === canonicalCandidateDigest(candidate));
|
|
327
282
|
}
|
package/dist/tangle-types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BackendRegistryEntry, BackendRegistryResponse, BackendType, CreateSandboxOptions, ExecResult as SandboxExecResult, PromptOptions, PromptResult, SandboxEvent } from "@tangle-network/sandbox";
|
|
2
|
-
import type { AgentRunCancellationAcknowledgement, AgentRunCancellationRequest,
|
|
2
|
+
import type { AgentRunCancellationAcknowledgement, AgentRunCancellationRequest, AgentInteractiveSessionControlClaim, AgentInteractiveSessionControlClaimAcknowledgement, AgentInteractiveSessionControlClaimRequest, AgentInteractiveSessionAttach, AgentInteractiveSessionPromptAcknowledgement, AgentInteractiveSessionPromptCommand, AgentInteractiveSessionRef, AgentInteractiveSessionStart, AgentInteractiveSessionStatus, AgentInteractiveSessionStopAcknowledgement, AgentInteractiveSessionStopCommand, AgentInteractiveTerminalSession, ConfidentialAttestation, ConfidentialExecutionEnvironment, InputPart, InteractionRequest, InteractionResponseCommand } from "@tangle-network/agent-interface";
|
|
3
3
|
import type { AgentEnvironmentCapabilities, AgentEnvironmentProvider, CreateAgentEnvironmentInput } from "@tangle-network/agent-interface/environment-provider";
|
|
4
4
|
/**
|
|
5
5
|
* The platform verdict for the create call that returned a sandbox.
|
|
@@ -335,57 +335,45 @@ export interface SandboxTerminalsLike {
|
|
|
335
335
|
handlers?: SandboxTerminalHandlersLike;
|
|
336
336
|
}): Promise<SandboxTerminalStreamLike>;
|
|
337
337
|
}
|
|
338
|
-
/**
|
|
339
|
-
export
|
|
340
|
-
sessionId: string;
|
|
341
|
-
harness: BackendType;
|
|
342
|
-
startedAt: string;
|
|
343
|
-
/** Provider-issued process incarnation. Replays return this exact value. */
|
|
344
|
-
incarnationId: string;
|
|
345
|
-
/** Canonical provider admission receipt for the effective route. */
|
|
346
|
-
preparationReceipt: AgentExecutionPreparationReceipt;
|
|
347
|
-
}
|
|
348
|
-
/** Start acknowledgement from the canonical Sandbox interactive API. */
|
|
349
|
-
export interface SandboxInteractiveSessionInfoLike extends SandboxInteractiveSessionIdentityLike {
|
|
350
|
-
streamUrl: string;
|
|
351
|
-
}
|
|
352
|
-
/** Lifecycle returned by the Sandbox exact interactive-session route. */
|
|
353
|
-
export type SandboxInteractiveSessionStatusLike = (SandboxInteractiveSessionInfoLike & {
|
|
338
|
+
/** Start result returned by the Sandbox exact interactive-session route. */
|
|
339
|
+
export type SandboxInteractiveSessionStartResultLike = {
|
|
354
340
|
state: "running";
|
|
355
|
-
|
|
341
|
+
ref: AgentInteractiveSessionRef;
|
|
342
|
+
control: AgentInteractiveSessionControlClaim;
|
|
343
|
+
streamUrl: string;
|
|
344
|
+
} | {
|
|
356
345
|
state: "exited";
|
|
346
|
+
ref: AgentInteractiveSessionRef;
|
|
347
|
+
control: AgentInteractiveSessionControlClaim;
|
|
357
348
|
endedAt: string;
|
|
358
349
|
exitCode?: number;
|
|
359
350
|
exitSignal?: string;
|
|
360
351
|
reason: "exited" | "stopped" | "lost";
|
|
361
|
-
}
|
|
352
|
+
};
|
|
362
353
|
/** Existing Sandbox SDK handle for one coding harness's native TUI. */
|
|
363
354
|
export interface SandboxInteractiveSessionLike {
|
|
364
|
-
start(
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
validateControl(control: AgentInteractiveSessionControlClaim): Promise<void>;
|
|
387
|
-
sendPrompt(command: AgentInteractiveSessionPromptCommand): Promise<AgentInteractiveSessionPromptAcknowledgement>;
|
|
388
|
-
stop(command: AgentInteractiveSessionStopCommand): Promise<AgentInteractiveSessionStopAcknowledgement>;
|
|
355
|
+
start(request: AgentInteractiveSessionStart, options?: {
|
|
356
|
+
signal?: AbortSignal;
|
|
357
|
+
}): Promise<SandboxInteractiveSessionStartResultLike>;
|
|
358
|
+
claimControl(request: AgentInteractiveSessionControlClaimRequest, options?: {
|
|
359
|
+
signal?: AbortSignal;
|
|
360
|
+
}): Promise<AgentInteractiveSessionControlClaimAcknowledgement>;
|
|
361
|
+
status(options?: {
|
|
362
|
+
signal?: AbortSignal;
|
|
363
|
+
}): Promise<AgentInteractiveSessionStatus | null>;
|
|
364
|
+
attachAgentTerminal(request: AgentInteractiveSessionAttach, options?: {
|
|
365
|
+
signal?: AbortSignal;
|
|
366
|
+
}): Promise<AgentInteractiveTerminalSession>;
|
|
367
|
+
/** Confirm that this claim is still the current writable generation. */
|
|
368
|
+
validateControl(control: AgentInteractiveSessionControlClaim, options?: {
|
|
369
|
+
signal?: AbortSignal;
|
|
370
|
+
}): Promise<void>;
|
|
371
|
+
sendPrompt(command: AgentInteractiveSessionPromptCommand, options?: {
|
|
372
|
+
signal?: AbortSignal;
|
|
373
|
+
}): Promise<AgentInteractiveSessionPromptAcknowledgement>;
|
|
374
|
+
stop(command: AgentInteractiveSessionStopCommand, options?: {
|
|
375
|
+
signal?: AbortSignal;
|
|
376
|
+
}): Promise<AgentInteractiveSessionStopAcknowledgement>;
|
|
389
377
|
}
|
|
390
378
|
export interface SandboxInstanceLike {
|
|
391
379
|
id: string;
|
|
@@ -502,7 +490,10 @@ export interface SandboxInstanceLike {
|
|
|
502
490
|
export interface SandboxSessionLike {
|
|
503
491
|
readonly id: string;
|
|
504
492
|
/** Exact native coding-agent TUI bound to this session id. */
|
|
505
|
-
interactive?(
|
|
493
|
+
interactive?(options?: {
|
|
494
|
+
ref?: AgentInteractiveSessionRef;
|
|
495
|
+
control?: AgentInteractiveSessionControlClaim;
|
|
496
|
+
}): unknown;
|
|
506
497
|
status(options?: {
|
|
507
498
|
signal?: AbortSignal;
|
|
508
499
|
}): Promise<unknown | null>;
|