@tangle-network/sandbox 0.9.6 → 0.10.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.
@@ -1,2 +1,2 @@
1
- import { a as TANGLE_JOBS_CONTRACT, c as AgentSandboxBlueprintAbi, d as SandboxCreateParamTypes, f as SandboxCreateResponseParamTypes, i as TANGLE_CHAIN_ID, l as ITangleJobsAbi, n as JOB_SANDBOX_CREATE, o as TANGLE_MAINNET_RPC, p as SandboxIdParamTypes, r as JOB_SANDBOX_DELETE, s as TangleSandboxClientConfig, t as TangleSandboxClient, u as JsonResponseParamTypes } from "../index-CAay0NFR.js";
1
+ import { a as TANGLE_JOBS_CONTRACT, c as AgentSandboxBlueprintAbi, d as SandboxCreateParamTypes, f as SandboxCreateResponseParamTypes, i as TANGLE_CHAIN_ID, l as ITangleJobsAbi, n as JOB_SANDBOX_CREATE, o as TANGLE_MAINNET_RPC, p as SandboxIdParamTypes, r as JOB_SANDBOX_DELETE, s as TangleSandboxClientConfig, t as TangleSandboxClient, u as JsonResponseParamTypes } from "../index-DS4SOkKG.js";
2
2
  export { AgentSandboxBlueprintAbi, ITangleJobsAbi, JOB_SANDBOX_CREATE, JOB_SANDBOX_DELETE, JsonResponseParamTypes, SandboxCreateParamTypes, SandboxCreateResponseParamTypes, SandboxIdParamTypes, TANGLE_CHAIN_ID, TANGLE_JOBS_CONTRACT, TANGLE_MAINNET_RPC, TangleSandboxClient, TangleSandboxClientConfig };
@@ -1,2 +1,2 @@
1
- import { a as TANGLE_JOBS_CONTRACT, c as ITangleJobsAbi, d as SandboxCreateResponseParamTypes, f as SandboxIdParamTypes, i as TANGLE_CHAIN_ID, l as JsonResponseParamTypes, n as JOB_SANDBOX_CREATE, o as TANGLE_MAINNET_RPC, r as JOB_SANDBOX_DELETE, s as AgentSandboxBlueprintAbi, t as TangleSandboxClient, u as SandboxCreateParamTypes } from "../tangle-DRzRB6z1.js";
1
+ import { a as TANGLE_JOBS_CONTRACT, c as ITangleJobsAbi, d as SandboxCreateResponseParamTypes, f as SandboxIdParamTypes, i as TANGLE_CHAIN_ID, l as JsonResponseParamTypes, n as JOB_SANDBOX_CREATE, o as TANGLE_MAINNET_RPC, r as JOB_SANDBOX_DELETE, s as AgentSandboxBlueprintAbi, t as TangleSandboxClient, u as SandboxCreateParamTypes } from "../tangle-DayyZe-i.js";
2
2
  export { AgentSandboxBlueprintAbi, ITangleJobsAbi, JOB_SANDBOX_CREATE, JOB_SANDBOX_DELETE, JsonResponseParamTypes, SandboxCreateParamTypes, SandboxCreateResponseParamTypes, SandboxIdParamTypes, TANGLE_CHAIN_ID, TANGLE_JOBS_CONTRACT, TANGLE_MAINNET_RPC, TangleSandboxClient };
@@ -1,4 +1,5 @@
1
- import { t as SandboxInstance } from "./sandbox-UQrmff8d.js";
1
+ import { t as SandboxInstance } from "./sandbox-CeimsfC8.js";
2
+ import { p as parseErrorResponse } from "./errors-DSz87Rkk.js";
2
3
  //#region src/tangle/abi.ts
3
4
  /**
4
5
  * Tangle Contract ABI Definitions
@@ -90,7 +91,7 @@ const ITangleJobsAbi = [
90
91
  {
91
92
  name: "jobIndex",
92
93
  type: "uint8",
93
- indexed: true
94
+ indexed: false
94
95
  },
95
96
  {
96
97
  name: "caller",
@@ -161,8 +162,8 @@ const SandboxCreateParamTypes = [
161
162
  type: "bool"
162
163
  },
163
164
  {
164
- name: "ssh_public_keys",
165
- type: "string[]"
165
+ name: "ssh_public_key",
166
+ type: "string"
166
167
  },
167
168
  {
168
169
  name: "web_terminal_enabled",
@@ -456,7 +457,7 @@ var TangleChainClient = class {
456
457
  options.env ? JSON.stringify(options.env) : "",
457
458
  options.metadata ? JSON.stringify(options.metadata) : "",
458
459
  options.sshEnabled ?? false,
459
- options.sshPublicKeys ?? (options.sshPublicKey ? [options.sshPublicKey] : []),
460
+ options.sshPublicKey ?? options.sshPublicKeys?.[0] ?? "",
460
461
  options.webTerminalEnabled ?? false,
461
462
  BigInt(options.maxLifetimeSeconds ?? 0),
462
463
  BigInt(options.idleTimeoutSeconds ?? 0),
@@ -572,6 +573,14 @@ var TangleChainClient = class {
572
573
  };
573
574
  //#endregion
574
575
  //#region src/tangle/client.ts
576
+ /**
577
+ * TangleSandboxClient — on-chain sandbox lifecycle via EVM calls.
578
+ *
579
+ * Implements HttpClient so `SandboxInstance` works unchanged. Lifecycle
580
+ * operations (create/stop/resume/delete) go on-chain via Tangle jobs, and
581
+ * runtime operations are routed directly to the sandbox runtime URL
582
+ * returned by the on-chain job result.
583
+ */
575
584
  function randomHexToken(bytes) {
576
585
  if (typeof globalThis.crypto === "undefined" || typeof globalThis.crypto.getRandomValues !== "function") throw new Error("randomHexToken: globalThis.crypto.getRandomValues is unavailable; this runtime cannot generate cryptographically secure nonces. Run on a host with WebCrypto support (Node 20+, browsers, Workers).");
577
586
  const buf = new Uint8Array(bytes);
@@ -613,6 +622,81 @@ function requirePathGroup(match, index) {
613
622
  if (value === void 0) throw new Error(`Path matcher missing group ${index}`);
614
623
  return value;
615
624
  }
625
+ function asRecord(value) {
626
+ return value && typeof value === "object" ? value : void 0;
627
+ }
628
+ function readString(record, keys) {
629
+ if (!record) return void 0;
630
+ for (const key of keys) {
631
+ const value = record[key];
632
+ if (typeof value === "string" && value.length > 0) return value;
633
+ }
634
+ }
635
+ function entryMetadata(entry) {
636
+ const metadata = {
637
+ ...entry.metadata ?? {},
638
+ ...entry.teeAttestationJson ? { teeAttestationJson: entry.teeAttestationJson } : {},
639
+ ...entry.teePublicKeyJson ? { teePublicKeyJson: entry.teePublicKeyJson } : {},
640
+ ...entry.attestationNonce ? { attestationNonce: entry.attestationNonce } : {}
641
+ };
642
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
643
+ }
644
+ function sandboxInfoFromEntry(entry) {
645
+ return {
646
+ id: entry.id,
647
+ name: entry.name,
648
+ status: entry.status === "deleted" ? "stopped" : entry.status,
649
+ connection: entry.runtimeUrl ? {
650
+ runtimeUrl: entry.runtimeUrl,
651
+ authToken: entry.runtimeToken
652
+ } : void 0,
653
+ metadata: entryMetadata(entry),
654
+ createdAt: entry.createdAt
655
+ };
656
+ }
657
+ function sandboxEntryFromWire(fallbackId, raw) {
658
+ const connection = asRecord(raw.connection);
659
+ const metadata = asRecord(raw.metadata);
660
+ const id = readString(raw, [
661
+ "id",
662
+ "sandboxId",
663
+ "sandbox_id"
664
+ ]) ?? fallbackId;
665
+ const runtimeUrl = readString(connection, [
666
+ "runtimeUrl",
667
+ "sidecarUrl",
668
+ "sidecar_url"
669
+ ]) ?? readString(raw, [
670
+ "runtimeUrl",
671
+ "sidecarUrl",
672
+ "sidecar_url"
673
+ ]) ?? "";
674
+ const runtimeToken = readString(connection, [
675
+ "authToken",
676
+ "runtimeToken",
677
+ "sidecarToken"
678
+ ]) ?? readString(raw, [
679
+ "authToken",
680
+ "runtimeToken",
681
+ "sidecarToken",
682
+ "token"
683
+ ]) ?? "";
684
+ const rawStatus = readString(raw, ["status"]) ?? "running";
685
+ const createdAtRaw = readString(raw, ["createdAt", "created_at"]);
686
+ const createdAt = createdAtRaw ? new Date(createdAtRaw) : /* @__PURE__ */ new Date();
687
+ return {
688
+ id,
689
+ name: readString(raw, ["name"]),
690
+ runtimeUrl,
691
+ runtimeToken,
692
+ status: rawStatus === "stopped" || rawStatus === "deleted" || rawStatus === "running" ? rawStatus : "running",
693
+ createdAt,
694
+ metadata,
695
+ teeAttestationJson: readString(raw, ["teeAttestationJson"]),
696
+ teePublicKeyJson: readString(raw, ["teePublicKeyJson"]),
697
+ attestationNonce: readString(raw, ["attestationNonce"])
698
+ };
699
+ }
616
700
  var TangleSandboxClient = class {
617
701
  chain;
618
702
  sandboxes = /* @__PURE__ */ new Map();
@@ -649,32 +733,32 @@ var TangleSandboxClient = class {
649
733
  if (runtimeUrl && !runtimeToken) throw new Error("Create job returned a runtime URL without an auth token");
650
734
  const entry = {
651
735
  id: sandboxId,
736
+ name: options?.name,
652
737
  runtimeUrl,
653
738
  runtimeToken,
654
739
  status: "running",
655
740
  createdAt: /* @__PURE__ */ new Date(),
741
+ metadata: createOptions.metadata,
656
742
  teeAttestationJson: responseJson.teeAttestationJson,
657
743
  teePublicKeyJson: responseJson.teePublicKeyJson,
658
744
  attestationNonce: attestationNonceFromOptions(createOptions)
659
745
  };
660
746
  this.sandboxes.set(sandboxId, entry);
661
- const info = {
662
- id: sandboxId,
663
- name: options?.name,
664
- status: "running",
665
- connection: runtimeUrl ? {
666
- runtimeUrl,
667
- authToken: runtimeToken
668
- } : void 0,
669
- metadata: {
670
- ...createOptions.metadata ?? {},
671
- ...entry.teeAttestationJson ? { teeAttestationJson: entry.teeAttestationJson } : {},
672
- ...entry.teePublicKeyJson ? { teePublicKeyJson: entry.teePublicKeyJson } : {},
673
- ...entry.attestationNonce ? { attestationNonce: entry.attestationNonce } : {}
674
- },
675
- createdAt: entry.createdAt
676
- };
677
- return new SandboxInstance(this, info);
747
+ return new SandboxInstance(this, sandboxInfoFromEntry(entry));
748
+ }
749
+ /**
750
+ * Get a sandbox by id. Rehydrates from the operator API when configured so
751
+ * app servers can resolve sandboxes created by earlier requests.
752
+ */
753
+ async get(id) {
754
+ const response = await this.fetch(`/v1/sandboxes/${encodeURIComponent(id)}`);
755
+ if (response.status === 404) return null;
756
+ if (!response.ok) {
757
+ const body = await response.text();
758
+ throw parseErrorResponse(response.status, body, void 0, response.headers);
759
+ }
760
+ const data = await response.json();
761
+ return new SandboxInstance(this, sandboxInfoFromEntry(sandboxEntryFromWire(id, data)));
678
762
  }
679
763
  /**
680
764
  * Route interception for SandboxInstance lifecycle calls.
@@ -696,22 +780,16 @@ var TangleSandboxClient = class {
696
780
  const getMatch = path.match(/^\/v1\/sandboxes\/([^/]+)$/);
697
781
  if (getMatch && method === "GET") {
698
782
  const id = decodeURIComponent(requirePathGroup(getMatch, 1));
699
- const entry = this.sandboxes.get(id);
783
+ let entry = this.sandboxes.get(id);
784
+ if (!entry && this.operatorApiUrl) {
785
+ const operatorResponse = await this.fetchOperatorApi(`/api/sandboxes/${encodeURIComponent(id)}`, { method: "GET" });
786
+ if (!operatorResponse.ok) return operatorResponse;
787
+ entry = sandboxEntryFromWire(id, await operatorResponse.json());
788
+ this.sandboxes.set(entry.id, entry);
789
+ }
700
790
  if (!entry) return new Response(JSON.stringify({ error: "Not found" }), { status: 404 });
701
- return new Response(JSON.stringify({
702
- id: entry.id,
703
- status: entry.status,
704
- connection: entry.runtimeUrl ? {
705
- runtimeUrl: entry.runtimeUrl,
706
- authToken: entry.runtimeToken
707
- } : void 0,
708
- metadata: {
709
- ...entry.teeAttestationJson ? { teeAttestationJson: entry.teeAttestationJson } : {},
710
- ...entry.teePublicKeyJson ? { teePublicKeyJson: entry.teePublicKeyJson } : {},
711
- ...entry.attestationNonce ? { attestationNonce: entry.attestationNonce } : {}
712
- },
713
- createdAt: entry.createdAt.toISOString()
714
- }), {
791
+ const info = sandboxInfoFromEntry(entry);
792
+ return new Response(JSON.stringify(info), {
715
793
  status: 200,
716
794
  headers: { "Content-Type": "application/json" }
717
795
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox",
3
- "version": "0.9.6",
3
+ "version": "0.10.0",
4
4
  "description": "Client SDK for the Tangle Sandbox platform - build AI agent applications with dev containers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -82,8 +82,8 @@
82
82
  "url": "https://github.com/tangle-network/agent-dev-container/issues"
83
83
  },
84
84
  "dependencies": {
85
- "@tangle-network/agent-core": "^0.3.3",
86
- "@tangle-network/agent-interface": "^0.13.0"
85
+ "@tangle-network/agent-core": "^0.4.0",
86
+ "@tangle-network/agent-interface": "^0.21.0"
87
87
  },
88
88
  "peerDependencies": {
89
89
  "@mastra/core": "^1.36.0",