@tangle-network/agent-provider-tangle 0.6.3 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -4
- package/dist/tangle-capabilities.d.ts +31 -16
- package/dist/tangle-capabilities.js +116 -78
- package/dist/tangle-environment-control.js +1 -8
- package/dist/tangle-environment-session.js +7 -1
- package/dist/tangle-environment-validation.d.ts +1 -8
- package/dist/tangle-environment-validation.js +0 -25
- package/dist/tangle-environment-values.d.ts +11 -1
- package/dist/tangle-environment-values.js +48 -13
- package/dist/tangle-environment.js +7 -53
- package/dist/tangle-prompt.d.ts +2 -3
- package/dist/tangle-provider.js +15 -8
- package/dist/tangle-types.d.ts +16 -14
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# @tangle-network/agent-provider-tangle
|
|
2
2
|
|
|
3
|
-
Wraps `@tangle-network/sandbox`
|
|
3
|
+
Wraps `@tangle-network/sandbox` as an `AgentEnvironmentProvider`.
|
|
4
|
+
The peer range is `>=0.19.6 <1.0.0`; retained-run cancellation (`session.cancelRun`) first shipped in 0.19.6, and this package is developed and tested against 0.21.1.
|
|
4
5
|
|
|
5
6
|
```ts
|
|
6
7
|
import { Sandbox } from '@tangle-network/sandbox'
|
|
@@ -15,13 +16,23 @@ Detached dispatch returns the immutable Sandbox execution receipt in `controlRef
|
|
|
15
16
|
The adapter validates its complete capability document and omits optional environment methods whose capabilities are disabled.
|
|
16
17
|
Reconstruct an exact session with `environment.session(reference.id, { controlRef: reference.controlRef })`; replay cursors are exclusive at both the agent interface and Sandbox session stream.
|
|
17
18
|
Result, replay, and cancel operations select that exact execution instead of whichever execution most recently changed the shared session.
|
|
18
|
-
|
|
19
|
+
Session status with an exact control reference reports a state only when the payload names that execution; a payload bound to a different or unnamed execution reports `unknown`.
|
|
20
|
+
|
|
21
|
+
The provider claims `retainedControl` only from probed facts.
|
|
22
|
+
A lazy instance handle minted from the linked Sandbox SDK over the client's `fetch` transport must prove `dispatchPrompt`, `session`, and `cancelRun`, and the client must expose `get` for reconstruction; the probe sends no request and creates no resource.
|
|
23
|
+
The probe measures the linked SDK's method surface, not the connected service; service-side truth needs the sidecar capability endpoint and is a follow-up.
|
|
24
|
+
A client that cannot prove those facts gets no claim, so the runtime rejects retained dispatch before any sandbox is created.
|
|
25
|
+
Each concrete sandbox narrows the declared document independently against its own measured method surface, so a capable sandbox keeps retained control even when the provider-level claim failed closed.
|
|
26
|
+
|
|
27
|
+
Pass the SDK client itself when retained control matters.
|
|
28
|
+
An object-spread wrapper (`{ ...client }`) drops class prototype methods, including `fetch`, so the provider treats the wrapper as a non-SDK client and claims no retained control.
|
|
29
|
+
A wrapper must delegate the SDK methods instead of copying properties.
|
|
19
30
|
After `session.prompt()` admits another turn, that session object's `controlRef` advances only when Sandbox returns the requested execution ID; a mismatched receipt fails without advancing local state.
|
|
20
31
|
Sandbox keeps execution identifiers optional for older or unproven service paths, so this adapter fails closed when a dispatch or prompt does not return one and never falls back to latest-session state.
|
|
21
32
|
Sessions reconstructed without a control reference may start a new prompt, but result lookup, cancellation, and cursor replay fail before calling Sandbox because those operations could otherwise select the newest unrelated execution.
|
|
22
33
|
It also rejects `contextTransfer` and `nativeContinuation` inputs explicitly until those operations have native Sandbox support instead of silently dropping them.
|
|
23
|
-
The
|
|
24
|
-
|
|
34
|
+
The adapter never advertises `branching.checkpoint` or `branching.fork`.
|
|
35
|
+
Sandbox exposes `snapshot`, `listSnapshots`, `deleteSnapshot`, and `branch(count)` with different semantics; durable workspace branching stays unadvertised until the full `AgentWorkspaceBranching` contract — retry, lookup, conflict, and cleanup together — is implemented over that surface.
|
|
25
36
|
|
|
26
37
|
Pass `exactProcess: {}` only when the Sandbox deployment supports `agent: false` creates and reports `metadata.runtimeMode: "control"`.
|
|
27
38
|
The optional capability creates an ephemeral sandbox with an authenticated control service but no managed agent workload or agent credentials, explicit resources, exact blocked/domain egress, bounded binary file reads, shell-free launch, and recoverable process output plus terminal reason.
|
|
@@ -4,39 +4,54 @@ import type { SandboxClientLike, SandboxInstanceLike } from "./tangle-types.js";
|
|
|
4
4
|
* The full capability document this adapter supports when the Sandbox client
|
|
5
5
|
* implements every optional method.
|
|
6
6
|
*
|
|
7
|
-
* This is an upper bound, not a claim. `
|
|
8
|
-
* to what
|
|
9
|
-
* cannot back becomes an action the
|
|
7
|
+
* This is an upper bound, not a claim. `capabilitiesForClient()` and
|
|
8
|
+
* `capabilitiesForSandbox()` narrow it to what the deployment actually
|
|
9
|
+
* exposes, because a capability the client cannot back becomes an action the
|
|
10
|
+
* caller selects and finds missing.
|
|
10
11
|
*/
|
|
11
12
|
export declare function defaultTangleSandboxCapabilities(harness?: HarnessType): AgentEnvironmentCapabilities;
|
|
12
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Deployment facts that gate declared capabilities. Every fact defaults to
|
|
15
|
+
* false when it cannot be established; a false fact clears the matching
|
|
16
|
+
* declared capability.
|
|
17
|
+
*/
|
|
13
18
|
export interface SandboxCapabilitySupport {
|
|
19
|
+
/** The provider can rebuild an environment by id (`client.get`). */
|
|
20
|
+
reconstruct: boolean;
|
|
14
21
|
dispatchPrompt: boolean;
|
|
15
22
|
session: boolean;
|
|
16
23
|
read: boolean;
|
|
17
24
|
write: boolean;
|
|
18
25
|
exec: boolean;
|
|
19
|
-
checkpoint: boolean;
|
|
20
|
-
fork: boolean;
|
|
21
26
|
placement: boolean;
|
|
22
27
|
destroy: boolean;
|
|
23
28
|
cancelRun: boolean;
|
|
24
29
|
}
|
|
25
30
|
export declare function sandboxCapabilitySupport(box: SandboxInstanceLike, client: SandboxClientLike): SandboxCapabilitySupport;
|
|
26
31
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* Establish client-stage facts before any sandbox exists. Two sources:
|
|
33
|
+
* the client's own members (get, describePlacement) and, for an SDK-backed
|
|
34
|
+
* client, the linked SDK surface via `linkedSdkProbeInstance`. Retained
|
|
35
|
+
* control fails closed: without a probe handle nothing proves `cancelRun`,
|
|
36
|
+
* so the provider must not claim it. Box-scoped workspace and streaming
|
|
37
|
+
* facts stay at the declared upper bound when no handle can be minted —
|
|
38
|
+
* each concrete sandbox re-narrows them in `capabilitiesForSandbox`.
|
|
34
39
|
*/
|
|
35
|
-
export declare function
|
|
40
|
+
export declare function clientCapabilitySupport(client: SandboxClientLike): SandboxCapabilitySupport;
|
|
36
41
|
/**
|
|
37
|
-
* Narrow a declared capability document to
|
|
42
|
+
* Narrow a declared capability document to established facts.
|
|
38
43
|
*
|
|
39
44
|
* Braid derives product actions from these flags, so an over-claimed flag is
|
|
40
|
-
* an offered action that throws at the moment the user selects it.
|
|
45
|
+
* an offered action that throws at the moment the user selects it. Retained
|
|
46
|
+
* control requires the complete fact set: exact dispatch, a session handle,
|
|
47
|
+
* canonical cancellation, and environment reconstruction by id.
|
|
41
48
|
*/
|
|
49
|
+
export declare function narrowedTangleCapabilities(declared: AgentEnvironmentCapabilities, support: SandboxCapabilitySupport): AgentEnvironmentCapabilities;
|
|
50
|
+
/**
|
|
51
|
+
* Narrow provider-level claims to facts the client can prove before any
|
|
52
|
+
* sandbox exists. `clientCapabilitySupport` documents which facts stay at
|
|
53
|
+
* the declared upper bound when the client offers no probe surface.
|
|
54
|
+
*/
|
|
55
|
+
export declare function capabilitiesForClient(declared: AgentEnvironmentCapabilities, client: SandboxClientLike): AgentEnvironmentCapabilities;
|
|
56
|
+
/** Narrow a declared capability document to what this Sandbox instance backs. */
|
|
42
57
|
export declare function capabilitiesForSandbox(declared: AgentEnvironmentCapabilities, support: SandboxCapabilitySupport): AgentEnvironmentCapabilities;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { harnessSystemPromptIntents } from "@tangle-network/agent-interface";
|
|
2
|
+
import { SandboxInstance } from "@tangle-network/sandbox";
|
|
2
3
|
/**
|
|
3
4
|
* The full capability document this adapter supports when the Sandbox client
|
|
4
5
|
* implements every optional method.
|
|
5
6
|
*
|
|
6
|
-
* This is an upper bound, not a claim. `
|
|
7
|
-
* to what
|
|
8
|
-
* cannot back becomes an action the
|
|
7
|
+
* This is an upper bound, not a claim. `capabilitiesForClient()` and
|
|
8
|
+
* `capabilitiesForSandbox()` narrow it to what the deployment actually
|
|
9
|
+
* exposes, because a capability the client cannot back becomes an action the
|
|
10
|
+
* caller selects and finds missing.
|
|
9
11
|
*/
|
|
10
12
|
export function defaultTangleSandboxCapabilities(harness) {
|
|
11
13
|
return {
|
|
@@ -31,11 +33,22 @@ export function defaultTangleSandboxCapabilities(harness) {
|
|
|
31
33
|
validation: true,
|
|
32
34
|
},
|
|
33
35
|
streaming: { live: true, replay: true, detach: true, turnIdempotency: true },
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
|
|
36
|
+
// Retained control is declared as intent here and stripped by narrowing
|
|
37
|
+
// wherever the facts cannot prove dispatchPrompt, session, cancelRun,
|
|
38
|
+
// and environment reconstruction by id. The four sub-flags are
|
|
39
|
+
// all-or-nothing by design: this adapter implements the identities
|
|
40
|
+
// together over one Sandbox surface, and the capability schema refuses
|
|
41
|
+
// a partial block, so they stand or fall on the same probed fact set.
|
|
42
|
+
sessions: { continue: true, list: false, messages: false },
|
|
43
|
+
retainedControl: {
|
|
44
|
+
exactRunIdentity: true,
|
|
45
|
+
resultIdentity: true,
|
|
46
|
+
eventIdentity: true,
|
|
47
|
+
cancellationIdempotency: true,
|
|
48
|
+
},
|
|
38
49
|
workspace: { read: true, write: true, exec: true, git: false, upload: true, download: true },
|
|
50
|
+
// Sandbox exposes snapshot/branch, not the checkpoint/fork contract, and
|
|
51
|
+
// durable branching needs retry, lookup, conflict, and cleanup together.
|
|
39
52
|
branching: { checkpoint: false, fork: false },
|
|
40
53
|
placement: true,
|
|
41
54
|
usage: false,
|
|
@@ -44,128 +57,153 @@ export function defaultTangleSandboxCapabilities(harness) {
|
|
|
44
57
|
confidential: false,
|
|
45
58
|
};
|
|
46
59
|
}
|
|
47
|
-
|
|
60
|
+
// One reserved id names both probe handles; neither ever reaches the service.
|
|
61
|
+
const CAPABILITY_PROBE_ID = "__tangle-capability-probe__";
|
|
48
62
|
export function sandboxCapabilitySupport(box, client) {
|
|
49
63
|
let session;
|
|
50
64
|
if (typeof box.session === "function") {
|
|
51
65
|
try {
|
|
52
66
|
// Sandbox session handles are lazy. Inspecting one does not call the
|
|
53
67
|
// service, and keeps retained-control claims tied to the actual handle.
|
|
54
|
-
session = box.session(
|
|
68
|
+
session = box.session(CAPABILITY_PROBE_ID);
|
|
55
69
|
}
|
|
56
70
|
catch {
|
|
57
71
|
// A client that cannot produce a session handle cannot prove retained control.
|
|
58
72
|
}
|
|
59
73
|
}
|
|
60
74
|
return {
|
|
75
|
+
reconstruct: typeof client.get === "function",
|
|
61
76
|
dispatchPrompt: typeof box.dispatchPrompt === "function",
|
|
62
77
|
session: typeof box.session === "function",
|
|
63
78
|
read: typeof box.read === "function",
|
|
64
79
|
write: typeof box.write === "function",
|
|
65
80
|
exec: typeof box.exec === "function",
|
|
66
|
-
checkpoint: typeof box.checkpoint === "function",
|
|
67
|
-
fork: typeof box.fork === "function",
|
|
68
81
|
placement: typeof client.describePlacement === "function",
|
|
69
82
|
destroy: typeof box.delete === "function",
|
|
70
83
|
cancelRun: typeof session?.cancelRun === "function",
|
|
71
84
|
};
|
|
72
85
|
}
|
|
73
86
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
87
|
+
* Mint a lazy instance handle from the sandbox SDK linked into this process.
|
|
88
|
+
* The handle measures the LINKED SDK's instance and session method surface —
|
|
89
|
+
* an adapter-capability fact, not deployment truth. It is valid exactly when
|
|
90
|
+
* the client is SDK-backed (carries the SDK `fetch` transport), because the
|
|
91
|
+
* sandboxes such a client returns are instances of these same classes.
|
|
92
|
+
* Deployment truth (what the connected service honors) needs the sidecar
|
|
93
|
+
* capability endpoint and is a follow-up. The handle and its probe session
|
|
94
|
+
* never leave the process: construction and `session(id)` are lazy in the
|
|
95
|
+
* SDK, so no request is sent and no billable resource is created.
|
|
81
96
|
*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
97
|
+
function linkedSdkProbeInstance(client) {
|
|
98
|
+
if (typeof client.fetch !== "function")
|
|
99
|
+
return undefined;
|
|
100
|
+
try {
|
|
101
|
+
return new SandboxInstance(client, {
|
|
102
|
+
id: CAPABILITY_PROBE_ID,
|
|
103
|
+
status: "stopped",
|
|
104
|
+
createdAt: new Date(0),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Establish client-stage facts before any sandbox exists. Two sources:
|
|
113
|
+
* the client's own members (get, describePlacement) and, for an SDK-backed
|
|
114
|
+
* client, the linked SDK surface via `linkedSdkProbeInstance`. Retained
|
|
115
|
+
* control fails closed: without a probe handle nothing proves `cancelRun`,
|
|
116
|
+
* so the provider must not claim it. Box-scoped workspace and streaming
|
|
117
|
+
* facts stay at the declared upper bound when no handle can be minted —
|
|
118
|
+
* each concrete sandbox re-narrows them in `capabilitiesForSandbox`.
|
|
119
|
+
*/
|
|
120
|
+
export function clientCapabilitySupport(client) {
|
|
121
|
+
const probe = linkedSdkProbeInstance(client);
|
|
122
|
+
if (probe)
|
|
123
|
+
return sandboxCapabilitySupport(probe, client);
|
|
124
|
+
return {
|
|
125
|
+
reconstruct: typeof client.get === "function",
|
|
126
|
+
dispatchPrompt: true,
|
|
127
|
+
session: true,
|
|
128
|
+
read: true,
|
|
129
|
+
write: true,
|
|
130
|
+
exec: true,
|
|
131
|
+
placement: typeof client.describePlacement === "function",
|
|
132
|
+
destroy: true,
|
|
133
|
+
cancelRun: false,
|
|
109
134
|
};
|
|
110
|
-
delete narrowed.interactions;
|
|
111
|
-
if (!canReconstructRetainedEnvironment)
|
|
112
|
-
delete narrowed.retainedControl;
|
|
113
|
-
delete narrowed.nativeContinuation;
|
|
114
|
-
return narrowed;
|
|
115
135
|
}
|
|
116
136
|
/**
|
|
117
|
-
* Narrow a declared capability document to
|
|
137
|
+
* Narrow a declared capability document to established facts.
|
|
118
138
|
*
|
|
119
139
|
* Braid derives product actions from these flags, so an over-claimed flag is
|
|
120
|
-
* an offered action that throws at the moment the user selects it.
|
|
140
|
+
* an offered action that throws at the moment the user selects it. Retained
|
|
141
|
+
* control requires the complete fact set: exact dispatch, a session handle,
|
|
142
|
+
* canonical cancellation, and environment reconstruction by id.
|
|
121
143
|
*/
|
|
122
|
-
export function
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
declared.streaming.
|
|
126
|
-
declared.streaming.
|
|
127
|
-
|
|
144
|
+
export function narrowedTangleCapabilities(declared, support) {
|
|
145
|
+
const supportsRetainedControl = declared.sessions.continue === true &&
|
|
146
|
+
declared.streaming.detach === true &&
|
|
147
|
+
declared.streaming.replay === true &&
|
|
148
|
+
declared.streaming.turnIdempotency === true &&
|
|
149
|
+
support.reconstruct &&
|
|
128
150
|
support.dispatchPrompt &&
|
|
129
151
|
support.session &&
|
|
130
152
|
support.cancelRun;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
...narrowed,
|
|
153
|
+
// A cleared fact forces false; a held fact passes the declared value
|
|
154
|
+
// through unchanged, so a malformed declaration still reaches the schema
|
|
155
|
+
// at the provider boundary instead of being laundered into a boolean.
|
|
156
|
+
const narrowed = {
|
|
157
|
+
...declared,
|
|
137
158
|
streaming: {
|
|
138
159
|
...declared.streaming,
|
|
139
|
-
detach: declared.streaming.detach
|
|
140
|
-
replay: declared.streaming.replay
|
|
141
|
-
turnIdempotency:
|
|
160
|
+
detach: support.dispatchPrompt ? declared.streaming.detach : false,
|
|
161
|
+
replay: support.session ? declared.streaming.replay : false,
|
|
162
|
+
turnIdempotency: support.session
|
|
163
|
+
? declared.streaming.turnIdempotency
|
|
164
|
+
: false,
|
|
142
165
|
},
|
|
143
166
|
sessions: {
|
|
144
167
|
...declared.sessions,
|
|
145
|
-
continue: declared.sessions.continue
|
|
168
|
+
continue: supportsRetainedControl ? declared.sessions.continue : false,
|
|
146
169
|
list: false,
|
|
147
170
|
messages: false,
|
|
148
171
|
},
|
|
149
172
|
workspace: {
|
|
150
173
|
...declared.workspace,
|
|
151
|
-
read: declared.workspace.read
|
|
152
|
-
write: declared.workspace.write
|
|
153
|
-
exec: declared.workspace.exec
|
|
174
|
+
read: support.read ? declared.workspace.read : false,
|
|
175
|
+
write: support.write ? declared.workspace.write : false,
|
|
176
|
+
exec: support.exec ? declared.workspace.exec : false,
|
|
154
177
|
git: false,
|
|
155
|
-
upload: declared.workspace.upload
|
|
156
|
-
download: declared.workspace.download
|
|
178
|
+
upload: support.write ? declared.workspace.upload : false,
|
|
179
|
+
download: support.read ? declared.workspace.download : false,
|
|
157
180
|
},
|
|
158
181
|
branching: {
|
|
159
|
-
...
|
|
182
|
+
...declared.branching,
|
|
160
183
|
checkpoint: false,
|
|
161
184
|
fork: false,
|
|
162
|
-
...(declared.branching.retrySafe !== undefined
|
|
163
|
-
? { retrySafe: false }
|
|
164
|
-
: {}),
|
|
185
|
+
...(declared.branching.retrySafe !== undefined ? { retrySafe: false } : {}),
|
|
165
186
|
...(declared.branching.lookup !== undefined ? { lookup: false } : {}),
|
|
166
187
|
...(declared.branching.cleanup !== undefined ? { cleanup: false } : {}),
|
|
167
188
|
},
|
|
168
|
-
placement:
|
|
189
|
+
placement: support.placement ? declared.placement : false,
|
|
169
190
|
usage: false,
|
|
170
191
|
};
|
|
192
|
+
delete narrowed.interactions;
|
|
193
|
+
delete narrowed.nativeContinuation;
|
|
194
|
+
if (!supportsRetainedControl)
|
|
195
|
+
delete narrowed.retainedControl;
|
|
196
|
+
return narrowed;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Narrow provider-level claims to facts the client can prove before any
|
|
200
|
+
* sandbox exists. `clientCapabilitySupport` documents which facts stay at
|
|
201
|
+
* the declared upper bound when the client offers no probe surface.
|
|
202
|
+
*/
|
|
203
|
+
export function capabilitiesForClient(declared, client) {
|
|
204
|
+
return narrowedTangleCapabilities(declared, clientCapabilitySupport(client));
|
|
205
|
+
}
|
|
206
|
+
/** Narrow a declared capability document to what this Sandbox instance backs. */
|
|
207
|
+
export function capabilitiesForSandbox(declared, support) {
|
|
208
|
+
return narrowedTangleCapabilities(declared, support);
|
|
171
209
|
}
|
|
@@ -33,17 +33,10 @@ export async function interruptAfterAbort(box, reference) {
|
|
|
33
33
|
// Only a receipt that proves this call admitted new work may be interrupted.
|
|
34
34
|
if (metadata?.dispatched !== true || metadata.alreadyExisted === true)
|
|
35
35
|
return;
|
|
36
|
-
const sessionId = reference.id;
|
|
37
36
|
const executionId = reference.controlRef?.executionId;
|
|
38
37
|
if (!box.session || executionId === undefined)
|
|
39
38
|
return;
|
|
40
|
-
|
|
41
|
-
await box.session(sessionId)?.interrupt({ executionId });
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// The original abort remains the caller-visible outcome; the provider has
|
|
45
|
-
// no stronger cleanup primitive when the late dispatch result is lost.
|
|
46
|
-
}
|
|
39
|
+
await interruptExecutionAfterAbort(box, reference.id, executionId);
|
|
47
40
|
}
|
|
48
41
|
export async function interruptExecutionAfterAbort(source, sessionId, executionId) {
|
|
49
42
|
try {
|
|
@@ -4,7 +4,7 @@ import { AgentRunCancellationAcknowledgementSchema, AgentRunCancellationRequestS
|
|
|
4
4
|
import { environmentEventFromSandboxEvent, isSandboxConnectionMarker, sandboxEventIdentity, } from "./tangle-events.js";
|
|
5
5
|
import { agentTurnResultFromPromptRecord, promptFromTurnInput, promptOptionsFromTurnInput, validatedSandboxPromptResult, } from "./tangle-prompt.js";
|
|
6
6
|
import { retainedSessionControlRef, resolveRetainedSessionControlRef, sameRunControlRef, sessionPromptExecutionId, } from "./tangle-session-control.js";
|
|
7
|
-
import { sessionStatusFromUnknown } from "./tangle-environment-values.js";
|
|
7
|
+
import { executionBoundSessionStatus, sessionStatusFromUnknown, } from "./tangle-environment-values.js";
|
|
8
8
|
import { awaitWithSignal, boundedIdentifier, } from "./tangle-contract-safety.js";
|
|
9
9
|
import { assertOptionKeys } from "./tangle-environment-validation.js";
|
|
10
10
|
import { hasReplayPayload, interruptExecutionAfterAbort, sessionPromptRequestDigest, } from "./tangle-environment-control.js";
|
|
@@ -47,6 +47,12 @@ export function sandboxSessionAsAgentSession(session, controlRef, provider, envi
|
|
|
47
47
|
options?.signal?.throwIfAborted();
|
|
48
48
|
if (!status)
|
|
49
49
|
return null;
|
|
50
|
+
const expectedExecutionId = activeControlRef?.executionId;
|
|
51
|
+
// Sandbox reports session-wide status. With an exact control reference,
|
|
52
|
+
// the answer is only valid when the payload binds to that execution.
|
|
53
|
+
if (expectedExecutionId !== undefined) {
|
|
54
|
+
return executionBoundSessionStatus(status, expectedExecutionId);
|
|
55
|
+
}
|
|
50
56
|
return sessionStatusFromUnknown(status.status);
|
|
51
57
|
},
|
|
52
58
|
async *events(options) {
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ExecRequest } from "@tangle-network/agent-interface/environment-provider";
|
|
2
2
|
export declare function assertOptionKeys(value: object | undefined, allowed: readonly string[], label: string): void;
|
|
3
3
|
export declare function assertRecord(value: unknown, label: string): asserts value is Record<string, unknown>;
|
|
4
4
|
export declare function assertExecOptions(options: ExecRequest | undefined): void;
|
|
5
|
-
export declare function assertCheckpointOptions(options: (CheckpointRequest & {
|
|
6
|
-
signal?: AbortSignal;
|
|
7
|
-
}) | undefined): void;
|
|
8
|
-
export declare function assertCheckpointRef(checkpoint: CheckpointRef): void;
|
|
9
|
-
export declare function assertForkOptions(options: (ForkRequest & {
|
|
10
|
-
signal?: AbortSignal;
|
|
11
|
-
}) | undefined): void;
|
|
@@ -36,28 +36,3 @@ export function assertExecOptions(options) {
|
|
|
36
36
|
throw new Error("Tangle exec timeoutMs must be a positive safe integer");
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
export function assertCheckpointOptions(options) {
|
|
40
|
-
assertOptionKeys(options, ["name", "metadata", "signal"], "Tangle checkpoint");
|
|
41
|
-
if (options?.name !== undefined)
|
|
42
|
-
boundedString(options.name, "Tangle checkpoint name");
|
|
43
|
-
if (options?.metadata !== undefined)
|
|
44
|
-
assertRecord(options.metadata, "Tangle checkpoint metadata");
|
|
45
|
-
}
|
|
46
|
-
export function assertCheckpointRef(checkpoint) {
|
|
47
|
-
if (!checkpoint || typeof checkpoint !== "object" || Array.isArray(checkpoint)) {
|
|
48
|
-
throw new Error("Tangle fork checkpoint must be an object");
|
|
49
|
-
}
|
|
50
|
-
assertOptionKeys(checkpoint, ["id", "provider", "metadata"], "Tangle fork checkpoint");
|
|
51
|
-
boundedIdentifier(checkpoint.id, "Tangle checkpoint id");
|
|
52
|
-
if (checkpoint.provider !== undefined)
|
|
53
|
-
boundedIdentifier(checkpoint.provider, "Tangle checkpoint provider");
|
|
54
|
-
if (checkpoint.metadata !== undefined)
|
|
55
|
-
assertRecord(checkpoint.metadata, "Tangle checkpoint metadata");
|
|
56
|
-
}
|
|
57
|
-
export function assertForkOptions(options) {
|
|
58
|
-
assertOptionKeys(options, ["name", "metadata", "signal"], "Tangle fork");
|
|
59
|
-
if (options?.name !== undefined)
|
|
60
|
-
boundedString(options.name, "Tangle fork name");
|
|
61
|
-
if (options?.metadata !== undefined)
|
|
62
|
-
assertRecord(options.metadata, "Tangle fork metadata");
|
|
63
|
-
}
|
|
@@ -2,7 +2,17 @@ import type { AgentEnvironmentStatus, AgentSessionStatus, PlacementInfo } from "
|
|
|
2
2
|
import type { SandboxInstanceLike } from "./tangle-types.js";
|
|
3
3
|
export declare function nonEmptyString(value: unknown): string | undefined;
|
|
4
4
|
export declare function optionalNonEmptyString(value: unknown, label: string): string | undefined;
|
|
5
|
-
export declare function checkpointIdFromResult(result: unknown): string;
|
|
6
5
|
export declare function placementInfoFromLoopPlacement(placement: unknown, box: SandboxInstanceLike): PlacementInfo;
|
|
7
6
|
export declare function statusFromUnknown(status: unknown): AgentEnvironmentStatus;
|
|
8
7
|
export declare function sessionStatusFromUnknown(status: unknown): AgentSessionStatus;
|
|
8
|
+
/**
|
|
9
|
+
* Bind a session-wide status payload to one exact execution.
|
|
10
|
+
*
|
|
11
|
+
* The Sandbox status endpoint reports the whole session. Its execution
|
|
12
|
+
* identity fields — activeExecutionId, latestExecutionId, runControlRef,
|
|
13
|
+
* failureReason.executionId — are the only proof of which execution the
|
|
14
|
+
* lifecycle state describes. A payload that names a different execution, or
|
|
15
|
+
* none, must not be attributed to the exact run, so the result degrades to
|
|
16
|
+
* "unknown" instead of fabricating an execution-scoped answer.
|
|
17
|
+
*/
|
|
18
|
+
export declare function executionBoundSessionStatus(payload: unknown, executionId: string): AgentSessionStatus;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { assertBoundedJson } from "./tangle-contract-safety.js";
|
|
2
1
|
const MAX_IDENTIFIER_LENGTH = 512;
|
|
3
2
|
export function nonEmptyString(value) {
|
|
4
3
|
return typeof value === "string" &&
|
|
@@ -19,18 +18,6 @@ export function optionalNonEmptyString(value, label) {
|
|
|
19
18
|
}
|
|
20
19
|
return value;
|
|
21
20
|
}
|
|
22
|
-
export function checkpointIdFromResult(result) {
|
|
23
|
-
assertBoundedJson(result);
|
|
24
|
-
const record = result && typeof result === "object" ? result : {};
|
|
25
|
-
const id = record.checkpointId ?? record.id;
|
|
26
|
-
if (typeof id !== "string" ||
|
|
27
|
-
id.length === 0 ||
|
|
28
|
-
id.length > MAX_IDENTIFIER_LENGTH ||
|
|
29
|
-
id.trim() !== id) {
|
|
30
|
-
throw new Error("sandbox checkpoint returned no checkpoint id");
|
|
31
|
-
}
|
|
32
|
-
return id;
|
|
33
|
-
}
|
|
34
21
|
export function placementInfoFromLoopPlacement(placement, box) {
|
|
35
22
|
if (!placement || typeof placement !== "object") {
|
|
36
23
|
return { kind: "sandbox", sandboxId: boundedId(box.id, "sandbox id") };
|
|
@@ -75,6 +62,10 @@ export function statusFromUnknown(status) {
|
|
|
75
62
|
return status;
|
|
76
63
|
if (status === "completed" || status === "cancelled")
|
|
77
64
|
return "stopped";
|
|
65
|
+
// A queued session is admitted work that has not started: pending, not
|
|
66
|
+
// unknown — "unknown" also means "not attributable" in exact-status binding.
|
|
67
|
+
if (status === "queued")
|
|
68
|
+
return "pending";
|
|
78
69
|
return "unknown";
|
|
79
70
|
}
|
|
80
71
|
export function sessionStatusFromUnknown(status) {
|
|
@@ -82,3 +73,47 @@ export function sessionStatusFromUnknown(status) {
|
|
|
82
73
|
return status;
|
|
83
74
|
return statusFromUnknown(status);
|
|
84
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Bind a session-wide status payload to one exact execution.
|
|
78
|
+
*
|
|
79
|
+
* The Sandbox status endpoint reports the whole session. Its execution
|
|
80
|
+
* identity fields — activeExecutionId, latestExecutionId, runControlRef,
|
|
81
|
+
* failureReason.executionId — are the only proof of which execution the
|
|
82
|
+
* lifecycle state describes. A payload that names a different execution, or
|
|
83
|
+
* none, must not be attributed to the exact run, so the result degrades to
|
|
84
|
+
* "unknown" instead of fabricating an execution-scoped answer.
|
|
85
|
+
*/
|
|
86
|
+
export function executionBoundSessionStatus(payload, executionId) {
|
|
87
|
+
const record = payload && typeof payload === "object" && !Array.isArray(payload)
|
|
88
|
+
? payload
|
|
89
|
+
: {};
|
|
90
|
+
const sessionStatus = sessionStatusFromUnknown(record.status);
|
|
91
|
+
const active = nonEmptyString(record.activeExecutionId);
|
|
92
|
+
const latest = nonEmptyString(record.latestExecutionId);
|
|
93
|
+
const admitted = record.runControlRef && typeof record.runControlRef === "object"
|
|
94
|
+
? nonEmptyString(record.runControlRef.executionId)
|
|
95
|
+
: undefined;
|
|
96
|
+
const failed = record.failureReason && typeof record.failureReason === "object"
|
|
97
|
+
? nonEmptyString(record.failureReason.executionId)
|
|
98
|
+
: undefined;
|
|
99
|
+
// An attributed failure outranks liveness: failureReason.executionId is the
|
|
100
|
+
// only field that names the execution its state describes, so it decides
|
|
101
|
+
// the failed case in both directions. Naming this execution proves the
|
|
102
|
+
// failure; naming another execution proves the failed state is not this
|
|
103
|
+
// run's, even when a contradictory payload also marks this execution live.
|
|
104
|
+
if (sessionStatus === "failed" && failed !== undefined) {
|
|
105
|
+
return failed === executionId ? "failed" : "unknown";
|
|
106
|
+
}
|
|
107
|
+
// A live execution owns the session's current state; any other live
|
|
108
|
+
// execution means this payload says nothing exact about the bound run.
|
|
109
|
+
if (active !== undefined) {
|
|
110
|
+
return active === executionId ? sessionStatus : "unknown";
|
|
111
|
+
}
|
|
112
|
+
// With nothing live, the state belongs to the newest execution. Trust the
|
|
113
|
+
// admitted-run reference only when no newer execution is named.
|
|
114
|
+
if (latest === executionId)
|
|
115
|
+
return sessionStatus;
|
|
116
|
+
if (latest === undefined && admitted === executionId)
|
|
117
|
+
return sessionStatus;
|
|
118
|
+
return "unknown";
|
|
119
|
+
}
|
|
@@ -2,11 +2,11 @@ import { AgentTurnInputSchema } from "@tangle-network/agent-interface";
|
|
|
2
2
|
import { environmentEventFromSandboxEvent } from "./tangle-events.js";
|
|
3
3
|
import { executionIdFromTurnInput, promptFromTurnInput, promptOptionsFromTurnInput, } from "./tangle-prompt.js";
|
|
4
4
|
import { resolveRetainedSessionControlRef } from "./tangle-session-control.js";
|
|
5
|
-
import {
|
|
5
|
+
import { placementInfoFromLoopPlacement, statusFromUnknown, } from "./tangle-environment-values.js";
|
|
6
6
|
import { execResultFromSandboxExecResult } from "./tangle-result-values.js";
|
|
7
7
|
import { capabilitiesForSandbox, sandboxCapabilitySupport } from "./tangle-capabilities.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { awaitWithSignal, assertBoundedJson, boundedIdentifier, boundedString, } from "./tangle-contract-safety.js";
|
|
9
|
+
import { assertExecOptions, assertOptionKeys, } from "./tangle-environment-validation.js";
|
|
10
10
|
import { interruptExecutionAfterAbort, } from "./tangle-environment-control.js";
|
|
11
11
|
import { dispatchEnvironmentRun } from "./tangle-environment-dispatch.js";
|
|
12
12
|
import { sandboxSessionAsAgentSession } from "./tangle-environment-session.js";
|
|
@@ -104,6 +104,10 @@ export function sandboxInstanceAsEnvironment(box, providerName, client, declared
|
|
|
104
104
|
throw new Error("sandbox session(id) returned an unrelated session");
|
|
105
105
|
}
|
|
106
106
|
const agentSession = sandboxSessionAsAgentSession(session, resolveRetainedSessionControlRef(options?.controlRef, id, providerName, environmentId), providerName, environmentId, dispatch, exactExecutionEvents);
|
|
107
|
+
// sessions.continue was granted from a probe-session fact; this
|
|
108
|
+
// backstop holds every concrete session to that fact, so a client
|
|
109
|
+
// whose sessions diverge from its probe surface fails loud here
|
|
110
|
+
// instead of failing at the first cancellation.
|
|
107
111
|
if (capabilities.sessions.continue &&
|
|
108
112
|
typeof agentSession.cancelRun !== "function") {
|
|
109
113
|
throw new Error("Tangle retained session support requires SandboxSession.cancelRun");
|
|
@@ -152,56 +156,6 @@ export function sandboxInstanceAsEnvironment(box, providerName, client, declared
|
|
|
152
156
|
},
|
|
153
157
|
}
|
|
154
158
|
: {}),
|
|
155
|
-
...(capabilities.branching.checkpoint && box.checkpoint
|
|
156
|
-
? {
|
|
157
|
-
async checkpoint(options) {
|
|
158
|
-
assertCheckpointOptions(options);
|
|
159
|
-
options?.signal?.throwIfAborted();
|
|
160
|
-
const result = await awaitWithSignal(box.checkpoint?.(options), options?.signal);
|
|
161
|
-
options?.signal?.throwIfAborted();
|
|
162
|
-
return { id: checkpointIdFromResult(result), provider: providerName };
|
|
163
|
-
},
|
|
164
|
-
}
|
|
165
|
-
: {}),
|
|
166
|
-
...(capabilities.branching.fork && box.fork
|
|
167
|
-
? {
|
|
168
|
-
async fork(checkpoint, options) {
|
|
169
|
-
assertCheckpointRef(checkpoint);
|
|
170
|
-
assertForkOptions(options);
|
|
171
|
-
if (checkpoint.provider !== undefined && checkpoint.provider !== providerName) {
|
|
172
|
-
throw new Error("Tangle fork checkpoint belongs to another provider");
|
|
173
|
-
}
|
|
174
|
-
boundedIdentifier(checkpoint.id, "Tangle checkpoint id");
|
|
175
|
-
options?.signal?.throwIfAborted();
|
|
176
|
-
const forked = await awaitWithSignal(box.fork?.(checkpoint.id, options), options?.signal);
|
|
177
|
-
if (!forked)
|
|
178
|
-
throw new Error("sandbox fork returned no environment");
|
|
179
|
-
try {
|
|
180
|
-
options?.signal?.throwIfAborted();
|
|
181
|
-
if (boundedIdentifier(forked.id, "Tangle fork environment id") === environmentId) {
|
|
182
|
-
throw new Error("Tangle fork returned the source environment");
|
|
183
|
-
}
|
|
184
|
-
return sandboxInstanceAsEnvironment(forked, providerName, client, capabilities);
|
|
185
|
-
}
|
|
186
|
-
catch (error) {
|
|
187
|
-
if (!forked.delete) {
|
|
188
|
-
const baseError = error instanceof Error ? error : new Error(String(error));
|
|
189
|
-
attachCleanupHandle(baseError, forked);
|
|
190
|
-
throw baseError;
|
|
191
|
-
}
|
|
192
|
-
try {
|
|
193
|
-
await forked.delete();
|
|
194
|
-
}
|
|
195
|
-
catch (cleanupError) {
|
|
196
|
-
const combined = new AggregateError([error, cleanupError], "Tangle fork validation and cleanup both failed");
|
|
197
|
-
attachCleanupHandle(combined, forked, cleanupError);
|
|
198
|
-
throw combined;
|
|
199
|
-
}
|
|
200
|
-
throw error;
|
|
201
|
-
}
|
|
202
|
-
},
|
|
203
|
-
}
|
|
204
|
-
: {}),
|
|
205
159
|
...(capabilities.placement
|
|
206
160
|
? {
|
|
207
161
|
async placement(options) {
|
package/dist/tangle-prompt.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import type { PromptResult } from "@tangle-network/sandbox";
|
|
1
|
+
import type { PromptOptions, PromptResult } from "@tangle-network/sandbox";
|
|
2
2
|
import type { AgentTurnInput, AgentTurnResult } from "@tangle-network/agent-interface/environment-provider";
|
|
3
3
|
import type { AgentExactRunControlRef, InputPart } from "@tangle-network/agent-interface";
|
|
4
|
-
import type { TanglePromptOptions } from "./tangle-types.js";
|
|
5
4
|
export declare function promptFromTurnInput(input: AgentTurnInput): string | InputPart[];
|
|
6
5
|
export declare function executionIdFromTurnInput(input: AgentTurnInput): string | undefined;
|
|
7
6
|
export declare function promptOptionsFromTurnInput(input: AgentTurnInput, target: {
|
|
8
7
|
provider: string;
|
|
9
8
|
environmentId: string;
|
|
10
9
|
sessionId?: string;
|
|
11
|
-
}):
|
|
10
|
+
}): PromptOptions;
|
|
12
11
|
type SandboxRunStatus = "success" | "failed" | "blocked_on_approval" | "awaiting_question" | "awaiting_plan_decision";
|
|
13
12
|
type ValidatedSandboxPromptResult = Record<string, unknown> & {
|
|
14
13
|
success: boolean;
|
package/dist/tangle-provider.js
CHANGED
|
@@ -15,7 +15,7 @@ export function createTangleProvider(options) {
|
|
|
15
15
|
providerName,
|
|
16
16
|
})
|
|
17
17
|
: undefined;
|
|
18
|
-
const
|
|
18
|
+
const resolveDeclaredCapabilities = async () => {
|
|
19
19
|
const configured = options.capabilities
|
|
20
20
|
? typeof options.capabilities === "function"
|
|
21
21
|
? await options.capabilities()
|
|
@@ -24,14 +24,17 @@ export function createTangleProvider(options) {
|
|
|
24
24
|
if (!exactProcess && configured.exactProcess) {
|
|
25
25
|
throw new Error("Tangle capabilities cannot advertise exactProcess without exactProcess configuration");
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
return exactProcess
|
|
28
28
|
? {
|
|
29
29
|
...configured,
|
|
30
30
|
exactProcess: { egress: ["blocked", "strict"] },
|
|
31
31
|
}
|
|
32
32
|
: configured;
|
|
33
|
-
return AgentEnvironmentCapabilitiesSchema.parse(capabilitiesForClient(withExactProcess, options.client));
|
|
34
33
|
};
|
|
34
|
+
// Provider-boundary document: client-stage facts only. It also validates
|
|
35
|
+
// the configured document, so create() and get() call it before any effect.
|
|
36
|
+
const narrowedProviderCapabilities = (declared) => AgentEnvironmentCapabilitiesSchema.parse(capabilitiesForClient(declared, options.client));
|
|
37
|
+
const resolveCapabilities = async () => narrowedProviderCapabilities(await resolveDeclaredCapabilities());
|
|
35
38
|
return {
|
|
36
39
|
name: providerName,
|
|
37
40
|
...(exactProcess ? { exactProcess } : {}),
|
|
@@ -44,7 +47,11 @@ export function createTangleProvider(options) {
|
|
|
44
47
|
if (input.providerOptions && Object.keys(input.providerOptions).length > 0) {
|
|
45
48
|
throw new Error("Tangle create providerOptions are not supported");
|
|
46
49
|
}
|
|
47
|
-
|
|
50
|
+
// The sandbox stage narrows from the declared document, not the
|
|
51
|
+
// provider-boundary one: the client stage cannot observe box-scoped
|
|
52
|
+
// facts, so measured instance facts must decide them per sandbox.
|
|
53
|
+
const declaredCapabilities = await resolveDeclaredCapabilities();
|
|
54
|
+
narrowedProviderCapabilities(declaredCapabilities);
|
|
48
55
|
const createOptions = options.mapCreateInput?.(input) ??
|
|
49
56
|
sandboxOptionsFromCreateInput(input, options.defaultBackend ?? "opencode");
|
|
50
57
|
assertMappedCreateOptions(createOptions);
|
|
@@ -76,7 +83,7 @@ export function createTangleProvider(options) {
|
|
|
76
83
|
}
|
|
77
84
|
try {
|
|
78
85
|
input.signal?.throwIfAborted();
|
|
79
|
-
const environment = sandboxInstanceAsEnvironment(box, providerName, options.client,
|
|
86
|
+
const environment = sandboxInstanceAsEnvironment(box, providerName, options.client, declaredCapabilities);
|
|
80
87
|
input.signal?.throwIfAborted();
|
|
81
88
|
return environment;
|
|
82
89
|
}
|
|
@@ -101,14 +108,14 @@ export function createTangleProvider(options) {
|
|
|
101
108
|
async get(id, operation) {
|
|
102
109
|
assertProviderOperationOptions(operation, "Tangle get");
|
|
103
110
|
boundedIdentifier(id, "Tangle environment id");
|
|
111
|
+
const declaredCapabilities = await resolveDeclaredCapabilities();
|
|
112
|
+
narrowedProviderCapabilities(declaredCapabilities);
|
|
104
113
|
operation?.signal?.throwIfAborted();
|
|
105
114
|
const box = await awaitWithSignal(options.client.get?.(id, operation), operation?.signal);
|
|
106
115
|
operation?.signal?.throwIfAborted();
|
|
107
116
|
if (!box || boundedIdentifier(box.id, "Tangle environment id") !== id)
|
|
108
117
|
return null;
|
|
109
|
-
return box
|
|
110
|
-
? sandboxInstanceAsEnvironment(box, providerName, options.client, await resolveCapabilities())
|
|
111
|
-
: null;
|
|
118
|
+
return sandboxInstanceAsEnvironment(box, providerName, options.client, declaredCapabilities);
|
|
112
119
|
},
|
|
113
120
|
}
|
|
114
121
|
: {}),
|
package/dist/tangle-types.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { BackendType, CreateSandboxOptions, ExecResult as SandboxExecResult, PromptOptions, PromptResult, SandboxEvent } from "@tangle-network/sandbox";
|
|
2
|
-
import type {
|
|
2
|
+
import type { AgentRunCancellationAcknowledgement, AgentRunCancellationRequest, InputPart } from "@tangle-network/agent-interface";
|
|
3
3
|
import type { AgentEnvironmentCapabilities, AgentEnvironmentProvider, CreateAgentEnvironmentInput } from "@tangle-network/agent-interface/environment-provider";
|
|
4
|
-
export type TanglePromptOptions = PromptOptions & {
|
|
5
|
-
runControlRef?: AgentExactRunControlRef;
|
|
6
|
-
};
|
|
7
4
|
export interface TangleExactProcessOptions {
|
|
8
5
|
teamId?: string;
|
|
9
6
|
}
|
|
@@ -12,6 +9,17 @@ export interface SandboxClientLike {
|
|
|
12
9
|
signal?: AbortSignal;
|
|
13
10
|
timeoutMs?: number;
|
|
14
11
|
}): Promise<SandboxInstanceLike>;
|
|
12
|
+
/**
|
|
13
|
+
* SDK HttpClient transport, present on `Sandbox` and `TangleSandboxClient`.
|
|
14
|
+
* Retained control requires it: the provider mints a lazy probe instance
|
|
15
|
+
* over this surface to read the linked SDK's method surface before any
|
|
16
|
+
* sandbox exists. An object-spread wrapper (`{ ...client }`) drops class
|
|
17
|
+
* prototype methods including this one, so such a wrapper never claims
|
|
18
|
+
* retained control; pass the SDK client itself or delegate its methods.
|
|
19
|
+
*/
|
|
20
|
+
fetch?(path: string, options?: RequestInit, fetchOptions?: {
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
}): Promise<Response>;
|
|
15
23
|
get?(id: string, requestOptions?: {
|
|
16
24
|
signal?: AbortSignal;
|
|
17
25
|
}): Promise<SandboxInstanceLike | null>;
|
|
@@ -56,9 +64,9 @@ export interface SandboxInstanceLike {
|
|
|
56
64
|
name?: string;
|
|
57
65
|
status?: unknown;
|
|
58
66
|
metadata?: Record<string, unknown>;
|
|
59
|
-
streamPrompt(message: string | InputPart[], options?:
|
|
60
|
-
prompt?(message: string | InputPart[], options?:
|
|
61
|
-
dispatchPrompt?(message: string | InputPart[], options?:
|
|
67
|
+
streamPrompt(message: string | InputPart[], options?: PromptOptions): AsyncIterable<SandboxEvent>;
|
|
68
|
+
prompt?(message: string | InputPart[], options?: PromptOptions): Promise<PromptResult>;
|
|
69
|
+
dispatchPrompt?(message: string | InputPart[], options?: PromptOptions): Promise<unknown>;
|
|
62
70
|
session?(id: string, options?: {
|
|
63
71
|
signal?: AbortSignal;
|
|
64
72
|
}): SandboxSessionLike;
|
|
@@ -98,12 +106,6 @@ export interface SandboxInstanceLike {
|
|
|
98
106
|
}): Promise<unknown>;
|
|
99
107
|
};
|
|
100
108
|
process?: SandboxProcessManagerLike;
|
|
101
|
-
checkpoint?(options?: {
|
|
102
|
-
signal?: AbortSignal;
|
|
103
|
-
} & Record<string, unknown>): Promise<unknown>;
|
|
104
|
-
fork?(checkpointId: string, options?: {
|
|
105
|
-
signal?: AbortSignal;
|
|
106
|
-
} & Record<string, unknown>): Promise<SandboxInstanceLike>;
|
|
107
109
|
refresh?(options?: {
|
|
108
110
|
signal?: AbortSignal;
|
|
109
111
|
}): Promise<void>;
|
|
@@ -125,7 +127,7 @@ export interface SandboxSessionLike {
|
|
|
125
127
|
executionId?: string;
|
|
126
128
|
signal?: AbortSignal;
|
|
127
129
|
}): Promise<PromptResult>;
|
|
128
|
-
prompt(message: string | InputPart[], options?:
|
|
130
|
+
prompt(message: string | InputPart[], options?: PromptOptions): Promise<PromptResult>;
|
|
129
131
|
interrupt(options?: {
|
|
130
132
|
executionId?: string;
|
|
131
133
|
signal?: AbortSignal;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-provider-tangle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "AgentEnvironmentProvider adapter for Tangle sandboxes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -67,10 +67,10 @@
|
|
|
67
67
|
"LICENSE"
|
|
68
68
|
],
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@tangle-network/agent-interface": "0.
|
|
70
|
+
"@tangle-network/agent-interface": "0.48.0"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
|
-
"@tangle-network/sandbox": ">=0.
|
|
73
|
+
"@tangle-network/sandbox": ">=0.19.6 <1.0.0"
|
|
74
74
|
},
|
|
75
75
|
"peerDependenciesMeta": {
|
|
76
76
|
"@tangle-network/sandbox": {
|
|
@@ -78,12 +78,13 @@
|
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@tangle-network/agent-
|
|
82
|
-
"@tangle-network/
|
|
81
|
+
"@tangle-network/agent-eval": "0.145.3",
|
|
82
|
+
"@tangle-network/agent-runtime": "0.132.13",
|
|
83
|
+
"@tangle-network/sandbox": "0.21.1",
|
|
83
84
|
"@types/node": "25.6.0",
|
|
84
85
|
"typescript": "^6.0.3",
|
|
85
86
|
"vitest": "^4.1.5",
|
|
86
|
-
"@tangle-network/agent-provider-testkit": "0.6.
|
|
87
|
+
"@tangle-network/agent-provider-testkit": "0.6.3"
|
|
87
88
|
},
|
|
88
89
|
"scripts": {
|
|
89
90
|
"build": "tsc -p tsconfig.json",
|