@tangle-network/agent-provider-tangle 0.14.4 → 1.0.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.
@@ -72,7 +72,15 @@ export function defaultTangleSandboxCapabilities(harness) {
72
72
  eventIdentity: true,
73
73
  cancellationIdempotency: true,
74
74
  },
75
- workspace: { read: true, write: true, exec: true, git: false, upload: true, download: true },
75
+ workspace: {
76
+ read: true,
77
+ write: true,
78
+ exec: true,
79
+ git: false,
80
+ upload: true,
81
+ download: true,
82
+ cwdBases: { repository: true, host: false },
83
+ },
76
84
  // The complete Sandbox SDK surface backs this contract. Narrowing below
77
85
  // removes every flag when any recovery or cleanup method is absent.
78
86
  branching: {
@@ -1,9 +1,9 @@
1
1
  import type { BackendType, CreateSandboxOptions } from "@tangle-network/sandbox";
2
- import type { CreateAgentEnvironmentInput } from "@tangle-network/agent-interface/environment-provider";
3
- export declare function sandboxOptionsFromCreateInput(input: CreateAgentEnvironmentInput, defaultBackend: BackendType): CreateSandboxOptions;
2
+ import type { CreateAgentEnvironmentInput, WorkspaceRequest } from "@tangle-network/agent-interface/environment-provider";
3
+ export declare function sandboxOptionsFromCreateInput(input: CreateAgentEnvironmentInput, defaultBackend: BackendType, parsedWorkspace?: WorkspaceRequest): CreateSandboxOptions;
4
4
  /** Reject value-bearing secret maps before any custom mapper can drop them. */
5
- export declare function assertNoInlineSecretValues(input: CreateAgentEnvironmentInput): void;
5
+ export declare function assertNoInlineSecretValues(input: CreateAgentEnvironmentInput, parsedWorkspace?: WorkspaceRequest): void;
6
6
  /** A custom mapper must not smuggle a value map into the Sandbox request. */
7
7
  export declare function assertMappedSecretNames(options: CreateSandboxOptions): void;
8
- export declare function assertCreateInputShape(input: CreateAgentEnvironmentInput): void;
8
+ export declare function assertCreateInputShape(input: CreateAgentEnvironmentInput, parsedWorkspace?: WorkspaceRequest): WorkspaceRequest | undefined;
9
9
  export declare function assertMappedCreateOptions(options: CreateSandboxOptions): void;
@@ -1,8 +1,9 @@
1
+ import { WorkspaceRequestSchema, workspaceCwdPathForBase, } from "@tangle-network/agent-interface/environment-provider";
1
2
  import { assertBoundedJson, boundedIdentifier, boundedString, MAX_ARRAY_LENGTH, MAX_MAP_ENTRIES, } from "./tangle-contract-safety.js";
2
3
  import { sandboxResourcesFromResourceRequest } from "./tangle-resources.js";
3
- export function sandboxOptionsFromCreateInput(input, defaultBackend) {
4
- assertCreateInputShape(input);
5
- assertNoInlineSecretValues(input);
4
+ export function sandboxOptionsFromCreateInput(input, defaultBackend, parsedWorkspace) {
5
+ const workspace = assertCreateInputShape(input, parsedWorkspace) ?? {};
6
+ assertNoInlineSecretValues(input, workspace);
6
7
  if (input.providerOptions && Object.keys(input.providerOptions).length > 0) {
7
8
  throw new Error("Tangle create providerOptions are not supported");
8
9
  }
@@ -19,23 +20,10 @@ export function sandboxOptionsFromCreateInput(input, defaultBackend) {
19
20
  boundedIdentifier(input.backend, "Tangle backend");
20
21
  if (input.env !== undefined)
21
22
  assertStringRecord(input.env, "Tangle");
22
- const workspace = input.workspace ?? {};
23
23
  if (workspace.providerOptions && Object.keys(workspace.providerOptions).length > 0) {
24
24
  throw new Error("Tangle workspace providerOptions are not supported");
25
25
  }
26
- if (workspace.providerOptions)
27
- assertBoundedRecord(workspace.providerOptions, "Tangle workspace providerOptions");
28
- if (workspace.environment !== undefined) {
29
- boundedIdentifier(workspace.environment, "Tangle workspace environment");
30
- }
31
- if (workspace.image !== undefined)
32
- boundedString(workspace.image, "Tangle workspace image");
33
- if (workspace.cwd !== undefined)
34
- boundedString(workspace.cwd, "Tangle workspace cwd");
35
- if (workspace.repoUrl !== undefined)
36
- boundedString(workspace.repoUrl, "Tangle repository URL");
37
- if (workspace.gitRef !== undefined)
38
- boundedIdentifier(workspace.gitRef, "Tangle git ref");
26
+ const workspaceCwd = workspaceCwdPathForBase(workspace.cwd, "repository", "Tangle");
39
27
  if (input.resources?.providerOptions && Object.keys(input.resources.providerOptions).length > 0) {
40
28
  throw new Error("Tangle resource providerOptions are not supported");
41
29
  }
@@ -44,24 +32,16 @@ export function sandboxOptionsFromCreateInput(input, defaultBackend) {
44
32
  if (input.idempotencyKey !== undefined) {
45
33
  boundedIdentifier(input.idempotencyKey, "Tangle idempotency key");
46
34
  }
47
- if (input.workspace?.cwd === "")
48
- throw new Error("Tangle workspace cwd cannot be empty");
49
- if (workspace.image === "")
50
- throw new Error("Tangle workspace image cannot be empty");
51
- if (workspace.repoUrl === "")
52
- throw new Error("Tangle repository URL cannot be empty");
53
35
  const resources = sandboxResourcesFromResourceRequest(input.resources);
54
- if (workspace.environment !== undefined && workspace.image !== undefined) {
55
- throw new Error("Tangle workspace cannot specify both environment and image");
56
- }
57
36
  // Sandbox injects secrets by name from its own store. Accepting a name/value
58
37
  // record and dropping it would create an environment with no credentials and
59
38
  // no error, surfacing later as an unexplained tool failure.
60
39
  const environment = workspace.image ?? workspace.environment;
61
40
  const base = {};
62
- return {
41
+ const mapped = {
63
42
  ...base,
64
43
  ...(environment !== undefined ? { environment } : {}),
44
+ ...(workspaceCwd === undefined ? {} : { cwd: workspaceCwd }),
65
45
  ...(workspace.repoUrl
66
46
  ? {
67
47
  git: {
@@ -82,9 +62,10 @@ export function sandboxOptionsFromCreateInput(input, defaultBackend) {
82
62
  profile: inlineAgentProfile(input.profile),
83
63
  },
84
64
  };
65
+ return mapped;
85
66
  }
86
67
  /** Reject value-bearing secret maps before any custom mapper can drop them. */
87
- export function assertNoInlineSecretValues(input) {
68
+ export function assertNoInlineSecretValues(input, parsedWorkspace) {
88
69
  if (input.providerOptions !== undefined) {
89
70
  if (!input.providerOptions || typeof input.providerOptions !== "object" || Array.isArray(input.providerOptions)) {
90
71
  throw new Error("Tangle create providerOptions must be a JSON object");
@@ -95,11 +76,8 @@ export function assertNoInlineSecretValues(input) {
95
76
  }
96
77
  }
97
78
  if (input.workspace?.providerOptions !== undefined) {
98
- if (!input.workspace.providerOptions || typeof input.workspace.providerOptions !== "object" || Array.isArray(input.workspace.providerOptions)) {
99
- throw new Error("Tangle workspace providerOptions must be a JSON object");
100
- }
101
- assertBoundedJson(input.workspace.providerOptions);
102
- if (Object.keys(input.workspace.providerOptions).length > 0) {
79
+ const workspace = parsedWorkspace ?? WorkspaceRequestSchema.parse(input.workspace);
80
+ if (workspace.providerOptions && Object.keys(workspace.providerOptions).length > 0) {
103
81
  throw new Error("Tangle workspace providerOptions are not supported");
104
82
  }
105
83
  }
@@ -136,7 +114,7 @@ export function assertMappedSecretNames(options) {
136
114
  boundedIdentifier(secret, "Tangle mapped secret name");
137
115
  }
138
116
  }
139
- export function assertCreateInputShape(input) {
117
+ export function assertCreateInputShape(input, parsedWorkspace) {
140
118
  if (!input || typeof input !== "object" || Array.isArray(input)) {
141
119
  throw new Error("Tangle create input must be an object");
142
120
  }
@@ -166,16 +144,6 @@ export function assertCreateInputShape(input) {
166
144
  }
167
145
  assertBoundedJson(input.profile);
168
146
  }
169
- if (input.workspace !== undefined) {
170
- if (!input.workspace || typeof input.workspace !== "object" || Array.isArray(input.workspace)) {
171
- throw new Error("Tangle workspace must be an object");
172
- }
173
- const workspaceKeys = new Set(Object.keys(input.workspace));
174
- for (const key of ["environment", "image", "repoUrl", "gitRef", "cwd", "providerOptions"])
175
- workspaceKeys.delete(key);
176
- if (workspaceKeys.size > 0)
177
- throw new Error("Tangle workspace contains unsupported fields");
178
- }
179
147
  if (input.resources !== undefined) {
180
148
  if (!input.resources || typeof input.resources !== "object" || Array.isArray(input.resources)) {
181
149
  throw new Error("Tangle resources must be an object");
@@ -186,6 +154,11 @@ export function assertCreateInputShape(input) {
186
154
  if (resourceKeys.size > 0)
187
155
  throw new Error("Tangle resources contain unsupported fields");
188
156
  }
157
+ if (input.workspace === undefined)
158
+ return undefined;
159
+ const workspace = parsedWorkspace ?? WorkspaceRequestSchema.parse(input.workspace);
160
+ workspaceCwdPathForBase(workspace.cwd, "repository", "Tangle");
161
+ return workspace;
189
162
  }
190
163
  export function assertMappedCreateOptions(options) {
191
164
  if (!options || typeof options !== "object" || Array.isArray(options)) {
@@ -35,7 +35,6 @@ export function sandboxSessionAsAgentSession(session, controlRef, provider, envi
35
35
  ? tangleInteractionResponder({
36
36
  session,
37
37
  sessionId: session.id,
38
- provider,
39
38
  environmentId,
40
39
  })
41
40
  : undefined;
@@ -199,7 +199,6 @@ export async function sandboxInstanceAsEnvironment(box, providerName, client, de
199
199
  return tangleInteractionResponder({
200
200
  session,
201
201
  sessionId,
202
- provider: providerName,
203
202
  environmentId,
204
203
  })(command, options);
205
204
  },
@@ -4,7 +4,6 @@ export interface TangleInteractionResponderOptions {
4
4
  session: SandboxSessionLike;
5
5
  /** The session the bound ask must belong to. */
6
6
  sessionId: string;
7
- provider: string;
8
7
  environmentId: string;
9
8
  }
10
9
  /**
@@ -20,20 +20,22 @@ function acknowledge(command, status, extras = {}) {
20
20
  });
21
21
  }
22
22
  /**
23
- * The coordinates this environment can answer for. A command naming another
24
- * provider, environment, or session is refused here rather than sent, because
25
- * the Sandbox SDK rejects such a command by throwing, and a caller holding a
26
- * durable operation needs the refusal as an acknowledgement it can record.
23
+ * The coordinates this environment can answer for before the command reaches
24
+ * the deployment. Tangle hosts a backend adapter inside the sandbox, so the
25
+ * interaction binding's provider names that inner adapter (for example,
26
+ * `opencode`) rather than this outer provider. The deployment compares that
27
+ * provider with its durable interaction record. Environment and session are
28
+ * still checked here because the Sandbox SDK rejects those coordinates before
29
+ * it can return an acknowledgement.
27
30
  */
28
31
  function foreignBinding(command, options) {
29
32
  const binding = command.binding;
30
- if (binding.provider === options.provider &&
31
- binding.environmentId === options.environmentId &&
33
+ if (binding.environmentId === options.environmentId &&
32
34
  binding.sessionId === options.sessionId) {
33
35
  return undefined;
34
36
  }
35
37
  return acknowledge(command, "binding_mismatch", {
36
- message: `response command binding names another provider, environment, or session than ${options.provider}/${options.environmentId}/${options.sessionId}`,
38
+ message: `response command binding names another environment or session than ${options.environmentId}/${options.sessionId}`,
37
39
  });
38
40
  }
39
41
  /**
@@ -8,7 +8,7 @@ export declare function promptOptionsFromTurnInput(input: AgentTurnInput, target
8
8
  environmentId: string;
9
9
  sessionId?: string;
10
10
  }): PromptOptions;
11
- type SandboxRunStatus = "success" | "failed" | "blocked_on_approval" | "awaiting_question" | "awaiting_plan_decision";
11
+ type SandboxRunStatus = "success" | "failed" | "blocked_on_approval" | "awaiting_question" | "awaiting_interaction" | "awaiting_plan_decision";
12
12
  type ValidatedSandboxPromptResult = Record<string, unknown> & {
13
13
  success: boolean;
14
14
  status: SandboxRunStatus;
@@ -97,6 +97,7 @@ export function validatedSandboxPromptResult(result) {
97
97
  "failed",
98
98
  "blocked_on_approval",
99
99
  "awaiting_question",
100
+ "awaiting_interaction",
100
101
  "awaiting_plan_decision",
101
102
  ]);
102
103
  if (typeof record.status !== "string" ||
@@ -134,6 +135,7 @@ export function validatedSandboxPromptResult(result) {
134
135
  const AWAITING_STATUSES = new Set([
135
136
  "blocked_on_approval",
136
137
  "awaiting_question",
138
+ "awaiting_interaction",
137
139
  "awaiting_plan_decision",
138
140
  ]);
139
141
  export function agentTurnResultFromPromptRecord(record, options = {}) {
@@ -43,9 +43,9 @@ export function createTangleProvider(options) {
43
43
  const resolveCapabilities = async () => narrowedProviderCapabilities(await resolveDeclaredCapabilities());
44
44
  const createRecords = new Map();
45
45
  const createEnvironment = async (input) => {
46
- assertCreateInputShape(input);
46
+ const parsedWorkspace = assertCreateInputShape(input);
47
47
  input.signal?.throwIfAborted();
48
- assertNoInlineSecretValues(input);
48
+ assertNoInlineSecretValues(input, parsedWorkspace);
49
49
  if (input.providerOptions && Object.keys(input.providerOptions).length > 0) {
50
50
  throw new Error("Tangle create providerOptions are not supported");
51
51
  }
@@ -55,7 +55,7 @@ export function createTangleProvider(options) {
55
55
  const declaredCapabilities = await resolveDeclaredCapabilities();
56
56
  narrowedProviderCapabilities(declaredCapabilities);
57
57
  const createOptions = options.mapCreateInput?.(input) ??
58
- sandboxOptionsFromCreateInput(input, options.defaultBackend ?? "opencode");
58
+ sandboxOptionsFromCreateInput(input, options.defaultBackend ?? "opencode", parsedWorkspace);
59
59
  assertMappedCreateOptions(createOptions);
60
60
  if (input.idempotencyKey !== undefined &&
61
61
  createOptions.idempotencyKey !== input.idempotencyKey) {
@@ -202,6 +202,8 @@ export interface SandboxWorkspaceOperationLookupLike {
202
202
  outcome: "found" | "not_found" | "conflict" | "unknown";
203
203
  kind: "checkpoint" | "fork";
204
204
  state?: "pending" | "succeeded" | "failed";
205
+ /** The durable operation result, when the service records one. */
206
+ result?: Record<string, unknown>;
205
207
  }
206
208
  /** Fan-out acknowledgement returned by SandboxInstance.fork(). */
207
209
  export interface SandboxForkAcknowledgementLike {
@@ -116,7 +116,7 @@ export function createTangleWorkspaceBranching(options) {
116
116
  message: "Sandbox fork child identity is incomplete",
117
117
  };
118
118
  }
119
- const environment = await environmentFromChild(recovered.marker.request, child, provider, child.createdAt, options.confidentialAttestationVerifier, signal);
119
+ const environment = await environmentFromChild(recovered.marker.request, child, provider, recovered.createdAt ?? child.createdAt, options.confidentialAttestationVerifier, signal);
120
120
  if (!environment) {
121
121
  return {
122
122
  state: "undecided",
@@ -699,6 +699,22 @@ function validForkResult(result) {
699
699
  result.materializedCount === result.children.length &&
700
700
  typeof result.complete === "boolean");
701
701
  }
702
+ function validOperationRecord(value) {
703
+ return value !== null && typeof value === "object" && !Array.isArray(value);
704
+ }
705
+ function validOperationDate(value) {
706
+ return ((typeof value === "string" || value instanceof Date) && validDate(value));
707
+ }
708
+ function validSnapshotOperationResult(value) {
709
+ return (validOperationRecord(value) &&
710
+ safeIdentifier(value.snapshotId) !== undefined &&
711
+ validOperationDate(value.createdAt));
712
+ }
713
+ function validForkOperationChildResult(value) {
714
+ return (validOperationRecord(value) &&
715
+ safeIdentifier(value.sandboxId ?? value.id) !== undefined &&
716
+ validOperationDate(value.createdAt));
717
+ }
702
718
  function checkpointMarkerTags(request) {
703
719
  const marker = {
704
720
  version: 1,
@@ -755,22 +771,30 @@ function forkMarkerMetadata(request) {
755
771
  * A marker only names a candidate resource. Nothing is returned to a caller
756
772
  * until the ledger reports the operation succeeded.
757
773
  */
758
- async function checkpointOperationSucceeded(box, marker, signal) {
774
+ async function checkpointOperationLookup(box, marker, signal) {
759
775
  const lookup = await awaitWithSignal(box.getSnapshotOperation?.(marker.idempotencyKey, {
760
776
  tags: marker.legacy
761
777
  ? legacyCheckpointMarkerTags(marker.request)
762
778
  : checkpointMarkerTags(marker.request),
763
779
  }), signal);
780
+ return lookup;
781
+ }
782
+ async function checkpointOperationSucceeded(box, marker, signal) {
783
+ const lookup = await checkpointOperationLookup(box, marker, signal);
764
784
  return (lookup?.outcome === "found" &&
765
785
  lookup.kind === "checkpoint" &&
766
786
  lookup.state === "succeeded");
767
787
  }
768
788
  /** The fork equivalent of {@link checkpointOperationSucceeded}. */
769
- async function forkOperationSucceeded(box, marker, signal) {
789
+ async function forkOperationLookup(box, marker, signal) {
770
790
  const lookup = await awaitWithSignal(box.getForkOperation?.(marker.idempotencyKey, {
771
791
  count: 1,
772
792
  metadata: forkMarkerMetadata(marker.request),
773
793
  }), signal);
794
+ return lookup;
795
+ }
796
+ async function forkOperationSucceeded(box, marker, signal) {
797
+ const lookup = await forkOperationLookup(box, marker, signal);
774
798
  return (lookup?.outcome === "found" &&
775
799
  lookup.kind === "fork" &&
776
800
  lookup.state === "succeeded");
@@ -818,8 +842,14 @@ async function findCheckpointByKey(box, key, signal) {
818
842
  if (!marker)
819
843
  continue;
820
844
  try {
821
- if (await checkpointOperationSucceeded(box, marker, signal)) {
822
- return { snapshot, marker };
845
+ const lookup = await checkpointOperationLookup(box, marker, signal);
846
+ if (lookup?.outcome === "found" &&
847
+ lookup.kind === "checkpoint" &&
848
+ lookup.state === "succeeded") {
849
+ const authoritative = snapshotFromOperationResult(snapshot, lookup);
850
+ if (authoritative === undefined)
851
+ return undefined;
852
+ return { snapshot: authoritative, marker };
823
853
  }
824
854
  unresolved = true;
825
855
  }
@@ -830,6 +860,23 @@ async function findCheckpointByKey(box, key, signal) {
830
860
  }
831
861
  return unresolved ? undefined : null;
832
862
  }
863
+ /**
864
+ * Prefer the durable operation result over inventory metadata.
865
+ *
866
+ * Snapshot inventory and the operation ledger can expose different creation
867
+ * timestamps. The ledger result is the acknowledgement returned by the
868
+ * idempotent operation, so recovery must rebuild the exact checkpoint ref
869
+ * from it when the service provides that result.
870
+ */
871
+ function snapshotFromOperationResult(snapshot, lookup) {
872
+ if (lookup.result === undefined)
873
+ return snapshot;
874
+ if (!validSnapshotOperationResult(lookup.result) ||
875
+ lookup.result.snapshotId !== snapshot.snapshotId) {
876
+ return undefined;
877
+ }
878
+ return { ...snapshot, createdAt: lookup.result.createdAt };
879
+ }
833
880
  /**
834
881
  * Confirm that one snapshot id is a settled checkpoint this provider created.
835
882
  *
@@ -877,8 +924,15 @@ async function findForkByKey(client, box, provider, key, signal) {
877
924
  let unresolved = false;
878
925
  for (const candidate of candidates) {
879
926
  try {
880
- if (await forkOperationSucceeded(box, candidate.marker, signal))
881
- return candidate;
927
+ const lookup = await forkOperationLookup(box, candidate.marker, signal);
928
+ if (lookup?.outcome === "found" &&
929
+ lookup.kind === "fork" &&
930
+ lookup.state === "succeeded") {
931
+ const authoritative = childFromOperationResult(candidate.child, lookup);
932
+ if (authoritative === undefined)
933
+ return undefined;
934
+ return { ...authoritative, marker: candidate.marker };
935
+ }
882
936
  unresolved = true;
883
937
  }
884
938
  catch {
@@ -888,6 +942,29 @@ async function findForkByKey(client, box, provider, key, signal) {
888
942
  }
889
943
  return unresolved ? undefined : null;
890
944
  }
945
+ /**
946
+ * Prefer the durable fork result over account-inventory metadata.
947
+ *
948
+ * Fork inventory can report a child timestamp from a later registry read. The
949
+ * operation ledger stores the original child acknowledgement, which is the
950
+ * stable value required to replay one exact fork reference after a restart.
951
+ */
952
+ function childFromOperationResult(child, lookup) {
953
+ if (lookup.result === undefined) {
954
+ return { child, createdAt: child.createdAt };
955
+ }
956
+ const result = lookup.result;
957
+ if (!validOperationRecord(result))
958
+ return undefined;
959
+ const children = result.children;
960
+ if (!Array.isArray(children))
961
+ return undefined;
962
+ const operationChild = children.find((candidate) => validForkOperationChildResult(candidate) &&
963
+ (candidate.sandboxId ?? candidate.id) === child.id);
964
+ if (!operationChild)
965
+ return undefined;
966
+ return { child, createdAt: operationChild.createdAt };
967
+ }
891
968
  async function findForkChildById(client, box, provider, id, signal) {
892
969
  try {
893
970
  if (typeof client.get !== "function")
@@ -1229,7 +1306,7 @@ async function forkConflictFromRemote(client, box, provider, request, verifier,
1229
1306
  const child = await completeForkChild(client, recovered.child, signal);
1230
1307
  if (!child)
1231
1308
  return undefined;
1232
- const environment = await environmentFromChild(recovered.marker.request, child, provider, child.createdAt, verifier, signal);
1309
+ const environment = await environmentFromChild(recovered.marker.request, child, provider, recovered.createdAt ?? child.createdAt, verifier, signal);
1233
1310
  return environment === undefined
1234
1311
  ? undefined
1235
1312
  : forkSuccess(request, environment, "replayed");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-provider-tangle",
3
- "version": "0.14.4",
3
+ "version": "1.0.0",
4
4
  "description": "AgentEnvironmentProvider adapter for Tangle sandboxes",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -89,10 +89,10 @@
89
89
  "LICENSE"
90
90
  ],
91
91
  "dependencies": {
92
- "@tangle-network/agent-interface": "^1.8.0"
92
+ "@tangle-network/agent-interface": "^2.0.0"
93
93
  },
94
94
  "peerDependencies": {
95
- "@tangle-network/sandbox": ">=0.34.4 <1.0.0"
95
+ "@tangle-network/sandbox": ">=0.34.6 <1.0.0"
96
96
  },
97
97
  "peerDependenciesMeta": {
98
98
  "@tangle-network/sandbox": {
@@ -101,12 +101,12 @@
101
101
  },
102
102
  "devDependencies": {
103
103
  "@tangle-network/agent-eval": "0.170.0",
104
- "@tangle-network/agent-runtime": "0.178.0",
105
- "@tangle-network/sandbox": "0.34.4",
104
+ "@tangle-network/agent-runtime": "0.184.0",
105
+ "@tangle-network/sandbox": "0.34.6",
106
106
  "@types/node": "26.4.0",
107
107
  "typescript": "7.0.2",
108
108
  "vitest": "4.1.11",
109
- "@tangle-network/agent-provider-testkit": "0.8.4"
109
+ "@tangle-network/agent-provider-testkit": "0.8.6"
110
110
  },
111
111
  "scripts": {
112
112
  "build": "tsc -p tsconfig.json",