@tangle-network/agent-provider-tangle 1.1.8 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,10 +11,16 @@ import { Sandbox } from "@tangle-network/sandbox";
11
11
  import { createTangleProvider } from "@tangle-network/agent-provider-tangle";
12
12
 
13
13
  const provider = createTangleProvider({
14
- client: new Sandbox({ apiKey: process.env.TANGLE_API_KEY }),
14
+ client: new Sandbox({
15
+ apiKey: process.env.TANGLE_API_KEY,
16
+ baseUrl: process.env.TANGLE_SANDBOX_URL || "https://sandbox.tangle.tools",
17
+ }),
15
18
  });
16
19
  ```
17
20
 
21
+ `Sandbox` requires an explicit `baseUrl`.
22
+ Set `TANGLE_SANDBOX_URL` to use another deployment.
23
+
18
24
  ## `create()` returns a ready environment
19
25
 
20
26
  `provider.create()` does not return until the sandbox reports `running`.
@@ -32,7 +38,10 @@ Composing an environment also reads the sandbox's deployment capability document
32
38
 
33
39
  ```ts
34
40
  const provider = createTangleProvider({
35
- client: new Sandbox({ apiKey: process.env.TANGLE_API_KEY }),
41
+ client: new Sandbox({
42
+ apiKey: process.env.TANGLE_API_KEY,
43
+ baseUrl: process.env.TANGLE_SANDBOX_URL || "https://sandbox.tangle.tools",
44
+ }),
36
45
  readyTimeoutMs: 180_000,
37
46
  });
38
47
 
@@ -280,7 +289,10 @@ The adapter does not trust the requested nonce, child metadata, or any legacy
280
289
 
281
290
  ```ts
282
291
  const provider = createTangleProvider({
283
- client: new Sandbox({ apiKey: process.env.TANGLE_API_KEY }),
292
+ client: new Sandbox({
293
+ apiKey: process.env.TANGLE_API_KEY,
294
+ baseUrl: process.env.TANGLE_SANDBOX_URL || "https://sandbox.tangle.tools",
295
+ }),
284
296
  confidentialAttestationVerifier: async ({ report, attestation }) =>
285
297
  (await verifyTangleQuote({ report, attestation })) ?? null,
286
298
  });
@@ -360,7 +372,10 @@ Set `teamId` inside `exactProcess` to scope create, lookup, and recovery to one
360
372
 
361
373
  ```ts
362
374
  const provider = createTangleProvider({
363
- client: new Sandbox({ apiKey: process.env.TANGLE_API_KEY }),
375
+ client: new Sandbox({
376
+ apiKey: process.env.TANGLE_API_KEY,
377
+ baseUrl: process.env.TANGLE_SANDBOX_URL || "https://sandbox.tangle.tools",
378
+ }),
364
379
  exactProcess: {},
365
380
  });
366
381
 
@@ -376,8 +376,28 @@ export function validatedSandboxPromptResult(result) {
376
376
  if (!content.success) {
377
377
  throw new Error("Tangle prompt result exceeded its JSON bound", { cause: content.error });
378
378
  }
379
- // Response text is content; all other fields retain their metadata limits.
380
- assertBoundedJson(Object.fromEntries(Object.entries(record).filter(([field]) => field !== "response" && field !== "text" && field !== "finalText")));
379
+ // What the agent produced is content and is bounded as content by the check above; the fields
380
+ // that describe the turn keep their metadata limits.
381
+ //
382
+ // `toolInvocations` belongs with the response text, not with the metadata. It carries whatever a
383
+ // tool returned, and one `webfetch` of a paper or an API page is routinely tens or hundreds of
384
+ // kilobytes, while the metadata bound is CONTRACT_MAX_STRING_LENGTH — 16,384 characters per
385
+ // string. `isBoundedEventContentJson` was written for exactly this material ("content may contain
386
+ // a single large transcript or tool result") and the whole record has already passed it at
387
+ // CONTRACT_MAX_JSON_BYTES.
388
+ //
389
+ // Holding tool output to the metadata bound rejected a turn the Sandbox SDK had already accepted:
390
+ // it serializes each tool value up to MAX_SERIALIZED_TOOL_VALUE_BYTES (4 MiB), a 256x mismatch.
391
+ // Because this validator runs inside the terminal result read, AFTER the live stream has drained
392
+ // and the usage receipt has been credited, the rejection did not fail the tool call — it
393
+ // converted a finished, fully paid turn into an unreconcilable retained execution that a
394
+ // supervisor reports as a child that did no work at all. Measured 2026-09-11 in one Discovery Lab
395
+ // worktree: 143 of 199 children across 16 pursuits, every one at `iterations: 0`, and the
396
+ // enumerate and extract stages that fetch papers were the ones that died.
397
+ assertBoundedJson(Object.fromEntries(Object.entries(record).filter(([field]) => field !== "response" &&
398
+ field !== "text" &&
399
+ field !== "finalText" &&
400
+ field !== "toolInvocations")));
381
401
  if (typeof record.success !== "boolean") {
382
402
  throw new Error("Tangle prompt result omitted its success status");
383
403
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-provider-tangle",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "description": "AgentEnvironmentProvider adapter for Tangle sandboxes",
5
5
  "type": "module",
6
6
  "license": "MIT",