@tangle-network/agent-provider-tangle 0.14.1 → 0.14.3
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 +54 -54
- package/dist/tangle-failure-reason.js +4 -1
- 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 +290 -70
- package/package.json +9 -9
|
@@ -21,7 +21,9 @@ const MAX_MARKER_CHUNKS = 512;
|
|
|
21
21
|
* accepts it is exact-optional, so an explicit `undefined` is not an absent key.
|
|
22
22
|
*/
|
|
23
23
|
export function confidentialVerifierOption(verifier) {
|
|
24
|
-
return verifier === undefined
|
|
24
|
+
return verifier === undefined
|
|
25
|
+
? {}
|
|
26
|
+
: { confidentialAttestationVerifier: verifier };
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* Build the exact workspace contract over the managed Sandbox operations.
|
|
@@ -51,20 +53,32 @@ export function createTangleWorkspaceBranching(options) {
|
|
|
51
53
|
if (local) {
|
|
52
54
|
return local.request.requestDigest === request.requestDigest
|
|
53
55
|
? { state: "known", record: local }
|
|
54
|
-
: {
|
|
56
|
+
: {
|
|
57
|
+
state: "conflict",
|
|
58
|
+
existingRequestDigest: local.request.requestDigest,
|
|
59
|
+
};
|
|
55
60
|
}
|
|
56
61
|
const recovered = await findCheckpointByKey(box, request.idempotencyKey, signal);
|
|
57
62
|
if (recovered === undefined) {
|
|
58
|
-
return {
|
|
63
|
+
return {
|
|
64
|
+
state: "undecided",
|
|
65
|
+
message: "Sandbox checkpoint inventory is unavailable",
|
|
66
|
+
};
|
|
59
67
|
}
|
|
60
68
|
if (!recovered)
|
|
61
69
|
return { state: "absent" };
|
|
62
70
|
if (recovered.marker.requestDigest !== request.requestDigest) {
|
|
63
|
-
return {
|
|
71
|
+
return {
|
|
72
|
+
state: "conflict",
|
|
73
|
+
existingRequestDigest: recovered.marker.requestDigest,
|
|
74
|
+
};
|
|
64
75
|
}
|
|
65
76
|
const record = checkpointRecordFromSnapshot(recovered.marker.request, recovered.snapshot);
|
|
66
77
|
if (!record) {
|
|
67
|
-
return {
|
|
78
|
+
return {
|
|
79
|
+
state: "undecided",
|
|
80
|
+
message: "Sandbox checkpoint metadata is invalid",
|
|
81
|
+
};
|
|
68
82
|
}
|
|
69
83
|
checkpoints.set(request.idempotencyKey, record);
|
|
70
84
|
return { state: "known", record };
|
|
@@ -75,26 +89,45 @@ export function createTangleWorkspaceBranching(options) {
|
|
|
75
89
|
if (local) {
|
|
76
90
|
return local.request.requestDigest === request.requestDigest
|
|
77
91
|
? { state: "known", record: local }
|
|
78
|
-
: {
|
|
92
|
+
: {
|
|
93
|
+
state: "conflict",
|
|
94
|
+
existingRequestDigest: local.request.requestDigest,
|
|
95
|
+
};
|
|
79
96
|
}
|
|
80
97
|
const recovered = await findForkByKey(client, box, provider, request.idempotencyKey, signal);
|
|
81
98
|
if (recovered === undefined) {
|
|
82
|
-
return {
|
|
99
|
+
return {
|
|
100
|
+
state: "undecided",
|
|
101
|
+
message: "Sandbox child inventory is unavailable",
|
|
102
|
+
};
|
|
83
103
|
}
|
|
84
104
|
if (!recovered)
|
|
85
105
|
return { state: "absent" };
|
|
86
106
|
if (recovered.marker.requestDigest !== request.requestDigest) {
|
|
87
|
-
return {
|
|
107
|
+
return {
|
|
108
|
+
state: "conflict",
|
|
109
|
+
existingRequestDigest: recovered.marker.requestDigest,
|
|
110
|
+
};
|
|
88
111
|
}
|
|
89
112
|
const child = await completeForkChild(client, recovered.child, signal);
|
|
90
113
|
if (!child) {
|
|
91
|
-
return {
|
|
114
|
+
return {
|
|
115
|
+
state: "undecided",
|
|
116
|
+
message: "Sandbox fork child identity is incomplete",
|
|
117
|
+
};
|
|
92
118
|
}
|
|
93
119
|
const environment = await environmentFromChild(recovered.marker.request, child, provider, child.createdAt, options.confidentialAttestationVerifier, signal);
|
|
94
120
|
if (!environment) {
|
|
95
|
-
return {
|
|
96
|
-
|
|
97
|
-
|
|
121
|
+
return {
|
|
122
|
+
state: "undecided",
|
|
123
|
+
message: "Sandbox fork child identity is incomplete",
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const record = {
|
|
127
|
+
request: recovered.marker.request,
|
|
128
|
+
environment,
|
|
129
|
+
child,
|
|
130
|
+
};
|
|
98
131
|
forks.set(request.idempotencyKey, record);
|
|
99
132
|
return { state: "known", record };
|
|
100
133
|
};
|
|
@@ -297,14 +330,34 @@ export function createTangleWorkspaceBranching(options) {
|
|
|
297
330
|
const returnedChild = result.children[0];
|
|
298
331
|
const child = await completeForkChild(client, returnedChild, operation?.signal);
|
|
299
332
|
if (!child) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
return
|
|
333
|
+
const compensation = forkMarkerFromMetadata(returnedChild.metadata) === undefined
|
|
334
|
+
? await compensateUnmarkedForkChild(result, returnedChild, operation?.signal)
|
|
335
|
+
: "not_attempted";
|
|
336
|
+
const removed = compensation === "destroyed" || compensation === "already_absent";
|
|
337
|
+
return forkUnknown(request, removed
|
|
338
|
+
? "Sandbox fork returned a child without a complete identity; the newly created child was removed"
|
|
339
|
+
: compensation === "unconfirmed"
|
|
340
|
+
? "Sandbox fork returned a child without a complete identity; child cleanup was not confirmed"
|
|
341
|
+
: "Sandbox fork returned a child without a complete identity", !removed);
|
|
342
|
+
}
|
|
343
|
+
const childMarker = forkMarkerFromMetadata(child.metadata);
|
|
344
|
+
if (childMarker) {
|
|
345
|
+
if (!markerBelongsToSource(childMarker, provider, box.id)) {
|
|
346
|
+
return forkUnknown(request, "Sandbox fork returned a child marked for another source", true);
|
|
347
|
+
}
|
|
348
|
+
if (childMarker.idempotencyKey !== request.idempotencyKey ||
|
|
349
|
+
childMarker.requestDigest !== request.requestDigest) {
|
|
350
|
+
return forkConflict(request, childMarker.requestDigest);
|
|
351
|
+
}
|
|
305
352
|
}
|
|
306
353
|
if (!childMarker) {
|
|
307
|
-
|
|
354
|
+
const compensation = await compensateUnmarkedForkChild(result, child, operation?.signal);
|
|
355
|
+
const removed = compensation === "destroyed" || compensation === "already_absent";
|
|
356
|
+
return forkUnknown(request, removed
|
|
357
|
+
? "Sandbox fork acknowledgement omitted its provider recovery marker; the newly created child was removed"
|
|
358
|
+
: compensation === "unconfirmed"
|
|
359
|
+
? "Sandbox fork acknowledgement omitted its provider recovery marker; child cleanup was not confirmed"
|
|
360
|
+
: "Sandbox fork acknowledgement omitted its provider recovery marker", !removed);
|
|
308
361
|
}
|
|
309
362
|
const environment = await environmentFromChild(request, child, provider, child.createdAt, options.confidentialAttestationVerifier, operation?.signal);
|
|
310
363
|
if (!environment) {
|
|
@@ -469,7 +522,8 @@ function checkpointRecordFromSnapshot(request, snapshot) {
|
|
|
469
522
|
async function environmentFromChild(request, child, provider, createdAt, verifier, signal) {
|
|
470
523
|
signal?.throwIfAborted();
|
|
471
524
|
const environmentId = safeIdentifier(child.id);
|
|
472
|
-
if (!environmentId ||
|
|
525
|
+
if (!environmentId ||
|
|
526
|
+
environmentId === request.checkpoint.source.environmentId) {
|
|
473
527
|
return undefined;
|
|
474
528
|
}
|
|
475
529
|
if (createdAt === undefined)
|
|
@@ -505,7 +559,9 @@ async function environmentFromChild(request, child, provider, createdAt, verifie
|
|
|
505
559
|
createdAt: normalizedCreatedAt,
|
|
506
560
|
placement: request.placement,
|
|
507
561
|
confidentialRequested: request.confidential?.requested === true,
|
|
508
|
-
...(attestation === undefined
|
|
562
|
+
...(attestation === undefined
|
|
563
|
+
? {}
|
|
564
|
+
: { confidentialAttestation: attestation }),
|
|
509
565
|
...(attestation === undefined ? {} : { confidential: true }),
|
|
510
566
|
...(metadata === undefined ? {} : { metadata }),
|
|
511
567
|
});
|
|
@@ -514,7 +570,8 @@ async function environmentFromChild(request, child, provider, createdAt, verifie
|
|
|
514
570
|
}
|
|
515
571
|
async function confidentialAttestationForChild(request, child, provider, verifier, signal) {
|
|
516
572
|
const confidential = ConfidentialExecutionRequestSchema.parse(request.confidential);
|
|
517
|
-
if (!confidential.requested ||
|
|
573
|
+
if (!confidential.requested ||
|
|
574
|
+
typeof child.getTeeAttestation !== "function") {
|
|
518
575
|
return undefined;
|
|
519
576
|
}
|
|
520
577
|
let response;
|
|
@@ -587,7 +644,8 @@ async function confidentialAttestationForChild(request, child, provider, verifie
|
|
|
587
644
|
!safeIdentifier(verification.providerKeyId) ||
|
|
588
645
|
!safeString(verification.providerSignature) ||
|
|
589
646
|
verification.providerSignature === quote ||
|
|
590
|
-
(verification.measurement !== undefined &&
|
|
647
|
+
(verification.measurement !== undefined &&
|
|
648
|
+
verification.measurement !== measurement)) {
|
|
591
649
|
return undefined;
|
|
592
650
|
}
|
|
593
651
|
const attestation = ConfidentialAttestationSchema.safeParse({
|
|
@@ -608,7 +666,7 @@ async function confidentialAttestationForChild(request, child, provider, verifie
|
|
|
608
666
|
: undefined;
|
|
609
667
|
}
|
|
610
668
|
function validTeeReport(report) {
|
|
611
|
-
return !!report &&
|
|
669
|
+
return (!!report &&
|
|
612
670
|
safeString(report.tee_type) !== undefined &&
|
|
613
671
|
Array.isArray(report.evidence) &&
|
|
614
672
|
report.evidence.length <= MAX_TEE_EVIDENCE_BYTES &&
|
|
@@ -617,14 +675,14 @@ function validTeeReport(report) {
|
|
|
617
675
|
report.measurement.length <= MAX_TEE_MEASUREMENT_BYTES &&
|
|
618
676
|
report.measurement.every((value) => Number.isInteger(value) && value >= 0 && value <= 255) &&
|
|
619
677
|
Number.isFinite(report.timestamp) &&
|
|
620
|
-
report.timestamp > 0;
|
|
678
|
+
report.timestamp > 0);
|
|
621
679
|
}
|
|
622
680
|
function validSnapshotResult(result) {
|
|
623
|
-
return !!result &&
|
|
681
|
+
return (!!result &&
|
|
624
682
|
safeIdentifier(result.snapshotId) !== undefined &&
|
|
625
683
|
validDate(result.createdAt) &&
|
|
626
684
|
Array.isArray(result.tags) &&
|
|
627
|
-
result.tags.every((tag) => safeString(tag) !== undefined);
|
|
685
|
+
result.tags.every((tag) => safeString(tag) !== undefined));
|
|
628
686
|
}
|
|
629
687
|
function validSnapshotInfo(snapshot, sandboxId) {
|
|
630
688
|
return (validSnapshotResult(snapshot) &&
|
|
@@ -632,14 +690,14 @@ function validSnapshotInfo(snapshot, sandboxId) {
|
|
|
632
690
|
(sandboxId === undefined || snapshot.sandboxId === sandboxId));
|
|
633
691
|
}
|
|
634
692
|
function validForkResult(result) {
|
|
635
|
-
return !!result &&
|
|
693
|
+
return (!!result &&
|
|
636
694
|
Array.isArray(result.children) &&
|
|
637
695
|
result.children.every((child) => child !== null &&
|
|
638
696
|
typeof child === "object" &&
|
|
639
697
|
safeIdentifier(child.id) !== undefined) &&
|
|
640
698
|
result.requestedCount === 1 &&
|
|
641
699
|
result.materializedCount === result.children.length &&
|
|
642
|
-
typeof result.complete === "boolean";
|
|
700
|
+
typeof result.complete === "boolean");
|
|
643
701
|
}
|
|
644
702
|
function checkpointMarkerTags(request) {
|
|
645
703
|
const marker = {
|
|
@@ -803,7 +861,9 @@ async function findManagedCheckpoint(box, provider, id, expected, signal) {
|
|
|
803
861
|
canonicalCandidateDigest(expected.source))) {
|
|
804
862
|
return false;
|
|
805
863
|
}
|
|
806
|
-
return (await checkpointOperationSucceeded(box, marker, signal))
|
|
864
|
+
return (await checkpointOperationSucceeded(box, marker, signal))
|
|
865
|
+
? true
|
|
866
|
+
: "unknown";
|
|
807
867
|
}
|
|
808
868
|
catch {
|
|
809
869
|
signal?.throwIfAborted();
|
|
@@ -840,7 +900,9 @@ async function findForkChildById(client, box, provider, id, signal) {
|
|
|
840
900
|
const marker = forkMarkerFromMetadata(child.metadata);
|
|
841
901
|
if (!marker || !markerBelongsToSource(marker, provider, box.id))
|
|
842
902
|
return undefined;
|
|
843
|
-
return (await forkOperationSucceeded(box, marker, signal))
|
|
903
|
+
return (await forkOperationSucceeded(box, marker, signal))
|
|
904
|
+
? child
|
|
905
|
+
: undefined;
|
|
844
906
|
}
|
|
845
907
|
catch {
|
|
846
908
|
signal?.throwIfAborted();
|
|
@@ -848,21 +910,26 @@ async function findForkChildById(client, box, provider, id, signal) {
|
|
|
848
910
|
}
|
|
849
911
|
}
|
|
850
912
|
/**
|
|
851
|
-
* Resolve a complete child identity when an
|
|
913
|
+
* Resolve a complete child identity when an acknowledgement omits durable data.
|
|
852
914
|
*
|
|
853
|
-
*
|
|
854
|
-
*
|
|
855
|
-
*
|
|
915
|
+
* A branch response can precede a richer registry read during a rolling
|
|
916
|
+
* deployment. Recover the exact child when its creation time or provider
|
|
917
|
+
* marker is absent. Never invent either field from the request.
|
|
856
918
|
*/
|
|
857
919
|
async function completeForkChild(client, child, signal) {
|
|
858
|
-
if (child.createdAt !== undefined
|
|
920
|
+
if (child.createdAt !== undefined &&
|
|
921
|
+
forkMarkerFromMetadata(child.metadata) !== undefined) {
|
|
859
922
|
return child;
|
|
860
|
-
|
|
923
|
+
}
|
|
924
|
+
if (typeof client.get !== "function" ||
|
|
925
|
+
safeIdentifier(child.id) === undefined) {
|
|
861
926
|
return undefined;
|
|
862
927
|
}
|
|
863
928
|
try {
|
|
864
929
|
const resolved = await awaitWithSignal(client.get(child.id, signal ? { signal } : undefined), signal);
|
|
865
|
-
if (!resolved ||
|
|
930
|
+
if (!resolved ||
|
|
931
|
+
resolved.id !== child.id ||
|
|
932
|
+
resolved.createdAt === undefined) {
|
|
866
933
|
return undefined;
|
|
867
934
|
}
|
|
868
935
|
return resolved;
|
|
@@ -872,6 +939,26 @@ async function completeForkChild(client, child, signal) {
|
|
|
872
939
|
return undefined;
|
|
873
940
|
}
|
|
874
941
|
}
|
|
942
|
+
/** Remove only a child this exact call confirmed it created. */
|
|
943
|
+
async function compensateUnmarkedForkChild(result, child, signal) {
|
|
944
|
+
if (result.idempotency?.outcome !== "created")
|
|
945
|
+
return "not_attempted";
|
|
946
|
+
if (typeof child.delete !== "function")
|
|
947
|
+
return "unconfirmed";
|
|
948
|
+
try {
|
|
949
|
+
const acknowledgement = (await awaitWithSignal(child.delete(), signal));
|
|
950
|
+
if (acknowledgement?.sandboxId !== child.id ||
|
|
951
|
+
(acknowledgement.outcome !== "destroyed" &&
|
|
952
|
+
acknowledgement.outcome !== "already_absent")) {
|
|
953
|
+
return "unconfirmed";
|
|
954
|
+
}
|
|
955
|
+
return acknowledgement.outcome;
|
|
956
|
+
}
|
|
957
|
+
catch {
|
|
958
|
+
signal?.throwIfAborted();
|
|
959
|
+
return "unconfirmed";
|
|
960
|
+
}
|
|
961
|
+
}
|
|
875
962
|
async function findBlockingForks(box, client, provider, checkpointId, signal) {
|
|
876
963
|
const candidates = await listMarkedForkChildren(client, box, provider, undefined, signal);
|
|
877
964
|
if (candidates === undefined)
|
|
@@ -959,7 +1046,9 @@ async function listMarkedForkChildren(client, box, provider, key, signal) {
|
|
|
959
1046
|
return undefined;
|
|
960
1047
|
const marked = [];
|
|
961
1048
|
for (const child of children) {
|
|
962
|
-
if (!child ||
|
|
1049
|
+
if (!child ||
|
|
1050
|
+
typeof child !== "object" ||
|
|
1051
|
+
safeIdentifier(child.id) === undefined) {
|
|
963
1052
|
return undefined;
|
|
964
1053
|
}
|
|
965
1054
|
if (child.id === box.id)
|
|
@@ -998,13 +1087,16 @@ function currentCheckpointMarkerFromTags(tags, key, base) {
|
|
|
998
1087
|
const keyTag = tags.find((tag) => tag.startsWith(`${base}-key-`));
|
|
999
1088
|
if (keyTag &&
|
|
1000
1089
|
key !== undefined &&
|
|
1001
|
-
keyTag.slice(`${base}-key-`.length) !==
|
|
1090
|
+
keyTag.slice(`${base}-key-`.length) !==
|
|
1091
|
+
markerKeyDigest(key).replace(":", "-")) {
|
|
1002
1092
|
return undefined;
|
|
1003
1093
|
}
|
|
1004
1094
|
const chunks = tags
|
|
1005
1095
|
.map((tag) => {
|
|
1006
1096
|
const match = tag.match(new RegExp(`^${escapeRegExp(base)}-material-(\\d+)-(\\d+)-([A-Za-z0-9_-]+)$`));
|
|
1007
|
-
return match
|
|
1097
|
+
return match
|
|
1098
|
+
? { index: Number(match[1]), total: Number(match[2]), chunk: match[3] }
|
|
1099
|
+
: undefined;
|
|
1008
1100
|
})
|
|
1009
1101
|
.filter((value) => value !== undefined)
|
|
1010
1102
|
.sort((left, right) => left.index - right.index);
|
|
@@ -1054,12 +1146,17 @@ function checkpointMarkerFromUnknown(value, key, legacy = false) {
|
|
|
1054
1146
|
if (!value || typeof value !== "object")
|
|
1055
1147
|
return undefined;
|
|
1056
1148
|
const parsed = value;
|
|
1057
|
-
if (parsed.version !== 1 ||
|
|
1149
|
+
if (parsed.version !== 1 ||
|
|
1150
|
+
parsed.kind !== "checkpoint" ||
|
|
1151
|
+
typeof parsed.idempotencyKey !== "string" ||
|
|
1152
|
+
typeof parsed.requestDigest !== "string")
|
|
1058
1153
|
return undefined;
|
|
1059
1154
|
if (key !== undefined && parsed.idempotencyKey !== key)
|
|
1060
1155
|
return undefined;
|
|
1061
1156
|
const request = WorkspaceCheckpointRequestSchema.safeParse(parsed.request);
|
|
1062
|
-
if (!request.success ||
|
|
1157
|
+
if (!request.success ||
|
|
1158
|
+
request.data.idempotencyKey !== parsed.idempotencyKey ||
|
|
1159
|
+
request.data.requestDigest !== parsed.requestDigest)
|
|
1063
1160
|
return undefined;
|
|
1064
1161
|
return {
|
|
1065
1162
|
version: 1,
|
|
@@ -1080,14 +1177,25 @@ function forkMarkerFromMetadata(metadata, key) {
|
|
|
1080
1177
|
if (!value || typeof value !== "object")
|
|
1081
1178
|
return undefined;
|
|
1082
1179
|
const parsed = value;
|
|
1083
|
-
if (parsed.version !== 1 ||
|
|
1180
|
+
if (parsed.version !== 1 ||
|
|
1181
|
+
parsed.kind !== "fork" ||
|
|
1182
|
+
typeof parsed.idempotencyKey !== "string" ||
|
|
1183
|
+
typeof parsed.requestDigest !== "string")
|
|
1084
1184
|
return undefined;
|
|
1085
1185
|
if (key !== undefined && parsed.idempotencyKey !== key)
|
|
1086
1186
|
return undefined;
|
|
1087
1187
|
const request = WorkspaceForkRequestSchema.safeParse(parsed.request);
|
|
1088
|
-
if (!request.success ||
|
|
1188
|
+
if (!request.success ||
|
|
1189
|
+
request.data.idempotencyKey !== parsed.idempotencyKey ||
|
|
1190
|
+
request.data.requestDigest !== parsed.requestDigest)
|
|
1089
1191
|
return undefined;
|
|
1090
|
-
return {
|
|
1192
|
+
return {
|
|
1193
|
+
version: 1,
|
|
1194
|
+
kind: "fork",
|
|
1195
|
+
idempotencyKey: parsed.idempotencyKey,
|
|
1196
|
+
requestDigest: parsed.requestDigest,
|
|
1197
|
+
request: request.data,
|
|
1198
|
+
};
|
|
1091
1199
|
}
|
|
1092
1200
|
/**
|
|
1093
1201
|
* Turn a failed create into a conflict only from provider-owned material.
|
|
@@ -1135,7 +1243,11 @@ async function forkConflictFromRemote(client, box, provider, request, verifier,
|
|
|
1135
1243
|
*/
|
|
1136
1244
|
function lookupOutcomeFromSandbox(lookup, kind) {
|
|
1137
1245
|
if (!lookup || lookup.kind !== kind) {
|
|
1138
|
-
return {
|
|
1246
|
+
return {
|
|
1247
|
+
absent: false,
|
|
1248
|
+
message: `Sandbox returned no ${kind} lookup`,
|
|
1249
|
+
retryable: true,
|
|
1250
|
+
};
|
|
1139
1251
|
}
|
|
1140
1252
|
if (lookup.outcome === "conflict") {
|
|
1141
1253
|
return {
|
|
@@ -1144,70 +1256,173 @@ function lookupOutcomeFromSandbox(lookup, kind) {
|
|
|
1144
1256
|
retryable: false,
|
|
1145
1257
|
};
|
|
1146
1258
|
}
|
|
1147
|
-
if (lookup.outcome !== "not_found" &&
|
|
1148
|
-
|
|
1259
|
+
if (lookup.outcome !== "not_found" &&
|
|
1260
|
+
(lookup.outcome === "unknown" || lookup.state !== "succeeded")) {
|
|
1261
|
+
return {
|
|
1262
|
+
absent: false,
|
|
1263
|
+
message: `Sandbox ${kind} operation is not decided`,
|
|
1264
|
+
retryable: true,
|
|
1265
|
+
};
|
|
1149
1266
|
}
|
|
1150
1267
|
return { absent: true };
|
|
1151
1268
|
}
|
|
1152
1269
|
function checkpointSuccess(request, checkpoint, status) {
|
|
1153
|
-
return WorkspaceCheckpointResultSchema.parse({
|
|
1270
|
+
return WorkspaceCheckpointResultSchema.parse({
|
|
1271
|
+
status,
|
|
1272
|
+
idempotencyKey: request.idempotencyKey,
|
|
1273
|
+
requestDigest: request.requestDigest,
|
|
1274
|
+
checkpoint,
|
|
1275
|
+
});
|
|
1154
1276
|
}
|
|
1155
1277
|
function checkpointConflict(request, existingRequestDigest) {
|
|
1156
|
-
return WorkspaceCheckpointResultSchema.parse({
|
|
1278
|
+
return WorkspaceCheckpointResultSchema.parse({
|
|
1279
|
+
status: "conflict",
|
|
1280
|
+
idempotencyKey: request.idempotencyKey,
|
|
1281
|
+
requestDigest: request.requestDigest,
|
|
1282
|
+
existingRequestDigest,
|
|
1283
|
+
});
|
|
1157
1284
|
}
|
|
1158
1285
|
function checkpointUnknown(request, message, retryable) {
|
|
1159
|
-
return WorkspaceCheckpointResultSchema.parse({
|
|
1286
|
+
return WorkspaceCheckpointResultSchema.parse({
|
|
1287
|
+
status: "unknown",
|
|
1288
|
+
idempotencyKey: request.idempotencyKey,
|
|
1289
|
+
requestDigest: request.requestDigest,
|
|
1290
|
+
message: boundedString(message, "Tangle checkpoint error"),
|
|
1291
|
+
retryable,
|
|
1292
|
+
});
|
|
1160
1293
|
}
|
|
1161
1294
|
function checkpointFound(request, checkpoint) {
|
|
1162
|
-
return WorkspaceCheckpointLookupResultSchema.parse({
|
|
1295
|
+
return WorkspaceCheckpointLookupResultSchema.parse({
|
|
1296
|
+
status: "found",
|
|
1297
|
+
idempotencyKey: request.idempotencyKey,
|
|
1298
|
+
requestDigest: request.requestDigest,
|
|
1299
|
+
checkpoint,
|
|
1300
|
+
});
|
|
1163
1301
|
}
|
|
1164
1302
|
function checkpointNotFound(request) {
|
|
1165
|
-
return WorkspaceCheckpointLookupResultSchema.parse({
|
|
1303
|
+
return WorkspaceCheckpointLookupResultSchema.parse({
|
|
1304
|
+
status: "not_found",
|
|
1305
|
+
idempotencyKey: request.idempotencyKey,
|
|
1306
|
+
requestDigest: request.requestDigest,
|
|
1307
|
+
});
|
|
1166
1308
|
}
|
|
1167
1309
|
function checkpointLookupConflict(request, existingRequestDigest) {
|
|
1168
|
-
return WorkspaceCheckpointLookupResultSchema.parse({
|
|
1310
|
+
return WorkspaceCheckpointLookupResultSchema.parse({
|
|
1311
|
+
status: "conflict",
|
|
1312
|
+
idempotencyKey: request.idempotencyKey,
|
|
1313
|
+
requestDigest: request.requestDigest,
|
|
1314
|
+
existingRequestDigest,
|
|
1315
|
+
});
|
|
1169
1316
|
}
|
|
1170
1317
|
function checkpointLookupUnknown(request, message, retryable) {
|
|
1171
|
-
return WorkspaceCheckpointLookupResultSchema.parse({
|
|
1318
|
+
return WorkspaceCheckpointLookupResultSchema.parse({
|
|
1319
|
+
status: "unknown",
|
|
1320
|
+
idempotencyKey: request.idempotencyKey,
|
|
1321
|
+
requestDigest: request.requestDigest,
|
|
1322
|
+
message: boundedString(message, "Tangle checkpoint lookup error"),
|
|
1323
|
+
retryable,
|
|
1324
|
+
});
|
|
1172
1325
|
}
|
|
1173
1326
|
function forkSuccess(request, environment, status) {
|
|
1174
|
-
return WorkspaceForkResultSchema.parse({
|
|
1327
|
+
return WorkspaceForkResultSchema.parse({
|
|
1328
|
+
status,
|
|
1329
|
+
idempotencyKey: request.idempotencyKey,
|
|
1330
|
+
requestDigest: request.requestDigest,
|
|
1331
|
+
environment,
|
|
1332
|
+
});
|
|
1175
1333
|
}
|
|
1176
1334
|
function forkConflict(request, existingRequestDigest) {
|
|
1177
|
-
return WorkspaceForkResultSchema.parse({
|
|
1335
|
+
return WorkspaceForkResultSchema.parse({
|
|
1336
|
+
status: "conflict",
|
|
1337
|
+
idempotencyKey: request.idempotencyKey,
|
|
1338
|
+
requestDigest: request.requestDigest,
|
|
1339
|
+
existingRequestDigest,
|
|
1340
|
+
});
|
|
1178
1341
|
}
|
|
1179
1342
|
function forkUnknown(request, message, retryable) {
|
|
1180
|
-
return WorkspaceForkResultSchema.parse({
|
|
1343
|
+
return WorkspaceForkResultSchema.parse({
|
|
1344
|
+
status: "unknown",
|
|
1345
|
+
idempotencyKey: request.idempotencyKey,
|
|
1346
|
+
requestDigest: request.requestDigest,
|
|
1347
|
+
message: boundedString(message, "Tangle fork error"),
|
|
1348
|
+
retryable,
|
|
1349
|
+
});
|
|
1181
1350
|
}
|
|
1182
1351
|
function forkFound(request, environment) {
|
|
1183
|
-
return WorkspaceForkLookupResultSchema.parse({
|
|
1352
|
+
return WorkspaceForkLookupResultSchema.parse({
|
|
1353
|
+
status: "found",
|
|
1354
|
+
idempotencyKey: request.idempotencyKey,
|
|
1355
|
+
requestDigest: request.requestDigest,
|
|
1356
|
+
environment,
|
|
1357
|
+
});
|
|
1184
1358
|
}
|
|
1185
1359
|
function forkNotFound(request) {
|
|
1186
|
-
return WorkspaceForkLookupResultSchema.parse({
|
|
1360
|
+
return WorkspaceForkLookupResultSchema.parse({
|
|
1361
|
+
status: "not_found",
|
|
1362
|
+
idempotencyKey: request.idempotencyKey,
|
|
1363
|
+
requestDigest: request.requestDigest,
|
|
1364
|
+
});
|
|
1187
1365
|
}
|
|
1188
1366
|
function forkLookupConflict(request, existingRequestDigest) {
|
|
1189
|
-
return WorkspaceForkLookupResultSchema.parse({
|
|
1367
|
+
return WorkspaceForkLookupResultSchema.parse({
|
|
1368
|
+
status: "conflict",
|
|
1369
|
+
idempotencyKey: request.idempotencyKey,
|
|
1370
|
+
requestDigest: request.requestDigest,
|
|
1371
|
+
existingRequestDigest,
|
|
1372
|
+
});
|
|
1190
1373
|
}
|
|
1191
1374
|
function forkLookupUnknown(request, message, retryable) {
|
|
1192
|
-
return WorkspaceForkLookupResultSchema.parse({
|
|
1375
|
+
return WorkspaceForkLookupResultSchema.parse({
|
|
1376
|
+
status: "unknown",
|
|
1377
|
+
idempotencyKey: request.idempotencyKey,
|
|
1378
|
+
requestDigest: request.requestDigest,
|
|
1379
|
+
message: boundedString(message, "Tangle fork lookup error"),
|
|
1380
|
+
retryable,
|
|
1381
|
+
});
|
|
1193
1382
|
}
|
|
1194
1383
|
function cleanupDeleted(request) {
|
|
1195
|
-
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1384
|
+
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1385
|
+
...request,
|
|
1386
|
+
status: "deleted",
|
|
1387
|
+
});
|
|
1196
1388
|
}
|
|
1197
1389
|
function cleanupAlreadyAbsent(request) {
|
|
1198
|
-
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1390
|
+
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1391
|
+
...request,
|
|
1392
|
+
status: "already_absent",
|
|
1393
|
+
});
|
|
1199
1394
|
}
|
|
1200
1395
|
function cleanupConflict(request, existingRequestDigest) {
|
|
1201
|
-
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1396
|
+
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1397
|
+
...request,
|
|
1398
|
+
status: "conflict",
|
|
1399
|
+
existingRequestDigest,
|
|
1400
|
+
message: "Cleanup operation id is bound to another target",
|
|
1401
|
+
});
|
|
1202
1402
|
}
|
|
1203
1403
|
function cleanupInUse(request, blockingTargetIds) {
|
|
1204
|
-
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1404
|
+
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1405
|
+
...request,
|
|
1406
|
+
status: "in_use",
|
|
1407
|
+
blockingTargetIds,
|
|
1408
|
+
message: "Checkpoint is still referenced by forked environments",
|
|
1409
|
+
});
|
|
1205
1410
|
}
|
|
1206
1411
|
function cleanupUnknown(request, message, retryable) {
|
|
1207
|
-
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1412
|
+
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1413
|
+
...request,
|
|
1414
|
+
status: "unknown",
|
|
1415
|
+
message: boundedString(message, "Tangle cleanup error"),
|
|
1416
|
+
retryable,
|
|
1417
|
+
});
|
|
1208
1418
|
}
|
|
1209
1419
|
function cleanupTransportFailure(request, message, retryable) {
|
|
1210
|
-
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1420
|
+
return WorkspaceCleanupAcknowledgementSchema.parse({
|
|
1421
|
+
...request,
|
|
1422
|
+
status: "transport_failure",
|
|
1423
|
+
message: boundedString(message, "Tangle cleanup transport error"),
|
|
1424
|
+
retryable,
|
|
1425
|
+
});
|
|
1211
1426
|
}
|
|
1212
1427
|
function isoDate(value) {
|
|
1213
1428
|
const date = value instanceof Date ? value : new Date(value);
|
|
@@ -1226,12 +1441,17 @@ function cloneJson(value) {
|
|
|
1226
1441
|
return structuredClone(value);
|
|
1227
1442
|
}
|
|
1228
1443
|
function safeIdentifier(value) {
|
|
1229
|
-
if (typeof value !== "string" ||
|
|
1444
|
+
if (typeof value !== "string" ||
|
|
1445
|
+
value.length === 0 ||
|
|
1446
|
+
value.length > 512 ||
|
|
1447
|
+
value.trim() !== value)
|
|
1230
1448
|
return undefined;
|
|
1231
1449
|
return value;
|
|
1232
1450
|
}
|
|
1233
1451
|
function safeString(value) {
|
|
1234
|
-
if (typeof value !== "string" ||
|
|
1452
|
+
if (typeof value !== "string" ||
|
|
1453
|
+
value.length === 0 ||
|
|
1454
|
+
value.length > MAX_STRING_LENGTH)
|
|
1235
1455
|
return undefined;
|
|
1236
1456
|
return value;
|
|
1237
1457
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-provider-tangle",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.3",
|
|
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.
|
|
92
|
+
"@tangle-network/agent-interface": "^1.8.0"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
|
-
"@tangle-network/sandbox": ">=0.
|
|
95
|
+
"@tangle-network/sandbox": ">=0.34.0 <1.0.0"
|
|
96
96
|
},
|
|
97
97
|
"peerDependenciesMeta": {
|
|
98
98
|
"@tangle-network/sandbox": {
|
|
@@ -100,12 +100,12 @@
|
|
|
100
100
|
}
|
|
101
101
|
},
|
|
102
102
|
"devDependencies": {
|
|
103
|
-
"@tangle-network/agent-eval": "0.
|
|
104
|
-
"@tangle-network/agent-runtime": "0.
|
|
105
|
-
"@tangle-network/sandbox": "0.
|
|
106
|
-
"@types/node": "
|
|
107
|
-
"typescript": "
|
|
108
|
-
"vitest": "
|
|
103
|
+
"@tangle-network/agent-eval": "0.170.0",
|
|
104
|
+
"@tangle-network/agent-runtime": "0.178.0",
|
|
105
|
+
"@tangle-network/sandbox": "0.34.3",
|
|
106
|
+
"@types/node": "26.4.0",
|
|
107
|
+
"typescript": "7.0.2",
|
|
108
|
+
"vitest": "4.1.11",
|
|
109
109
|
"@tangle-network/agent-provider-testkit": "0.8.4"
|
|
110
110
|
},
|
|
111
111
|
"scripts": {
|