@gitroll/tacitt-cli 0.6.1 → 0.6.2
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/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { _ as readStateDump, a as readAgentPresence, b as traceStartup, d as helpText, f as parseOptions, g as startupFailure, h as permissionDiagnostic, i as invoke, l as awaitingPassport, m as longCommands, n as readOperation, o as createRuntime, p as businessCommands, r as waitOperation, s as executorEventSchema, t as cancelOperation, u as createRenderActivity, v as createExecutionPort, y as startHost$1 } from "./query-
|
|
2
|
+
import { _ as readStateDump, a as readAgentPresence, b as traceStartup, d as helpText, f as parseOptions, g as startupFailure, h as permissionDiagnostic, i as invoke, l as awaitingPassport, m as longCommands, n as readOperation, o as createRuntime, p as businessCommands, r as waitOperation, s as executorEventSchema, t as cancelOperation, u as createRenderActivity, v as createExecutionPort, y as startHost$1 } from "./query-CQ6Tr5zC.mjs";
|
|
3
3
|
import { nt as makePrivateDirectory, rt as openPrivateFile } from "./src-JoT3L94j.mjs";
|
|
4
4
|
import { $t as safeField, Qt as safeCode, Xt as ApplicationError } from "./locate-JYtFmKu-.mjs";
|
|
5
5
|
import { Zn as reviewTransportBytes, et as readWorkspaceOutcomes, oi as stateSchema, st as resolveFailureLocation } from "./src--Ln5GHdz.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as executorRequestSchema, f as parseOptions, g as startupFailure, i as invoke, m as longCommands, n as readOperation, o as createRuntime, r as waitOperation } from "./query-
|
|
1
|
+
import { c as executorRequestSchema, f as parseOptions, g as startupFailure, i as invoke, m as longCommands, n as readOperation, o as createRuntime, r as waitOperation } from "./query-CQ6Tr5zC.mjs";
|
|
2
2
|
import { $t as safeField, Qt as safeCode, Xt as ApplicationError } from "./locate-JYtFmKu-.mjs";
|
|
3
3
|
import "./src--Ln5GHdz.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
@@ -13,7 +13,8 @@ import { execFile, spawn } from "node:child_process";
|
|
|
13
13
|
import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
|
|
14
14
|
import { createInterface } from "node:readline";
|
|
15
15
|
import { Writable } from "node:stream";
|
|
16
|
-
import { parseArgs, promisify, types } from "node:util";
|
|
16
|
+
import { isDeepStrictEqual, parseArgs, promisify, types } from "node:util";
|
|
17
|
+
import { pathToFileURL } from "node:url";
|
|
17
18
|
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
18
19
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
19
20
|
import { fastify } from "fastify";
|
|
@@ -10275,6 +10276,27 @@ async function* sessionArtifacts(storage, find, journeyId, artifact, signal) {
|
|
|
10275
10276
|
}
|
|
10276
10277
|
};
|
|
10277
10278
|
}
|
|
10279
|
+
/** Own one live upload iterator; advancing it releases the preceding session ZIP. */
|
|
10280
|
+
async function prepareSessionArtifacts(storage, find, journeyId, artifact, signal) {
|
|
10281
|
+
const source = sessionArtifacts(storage, find, journeyId, artifact, signal);
|
|
10282
|
+
let closed = false;
|
|
10283
|
+
async function* iterate() {
|
|
10284
|
+
try {
|
|
10285
|
+
yield* source;
|
|
10286
|
+
} finally {
|
|
10287
|
+
closed = true;
|
|
10288
|
+
}
|
|
10289
|
+
}
|
|
10290
|
+
const items = iterate();
|
|
10291
|
+
return {
|
|
10292
|
+
items,
|
|
10293
|
+
async close() {
|
|
10294
|
+
if (closed) return;
|
|
10295
|
+
closed = true;
|
|
10296
|
+
await items.return(void 0);
|
|
10297
|
+
}
|
|
10298
|
+
};
|
|
10299
|
+
}
|
|
10278
10300
|
//#endregion
|
|
10279
10301
|
//#region apps/cli/src/journey/send-artifacts.ts
|
|
10280
10302
|
function createJourneySendArtifacts(storage) {
|
|
@@ -10293,6 +10315,7 @@ function createJourneySendArtifacts(storage) {
|
|
|
10293
10315
|
return output;
|
|
10294
10316
|
}
|
|
10295
10317
|
return {
|
|
10318
|
+
prepareSessions: (journeyId, artifact, signal) => prepareSessionArtifacts(storage, find, journeyId, artifact, signal),
|
|
10296
10319
|
sessions: (journeyId, artifact, signal) => sessionArtifacts(storage, find, journeyId, artifact, signal),
|
|
10297
10320
|
async describe(journey, work, signal) {
|
|
10298
10321
|
const output = await find(journey.journeyId, work.id, work.revision);
|
|
@@ -10377,6 +10400,74 @@ async function putPrimary(primary, byteLength, upload, signal) {
|
|
|
10377
10400
|
}
|
|
10378
10401
|
}
|
|
10379
10402
|
//#endregion
|
|
10403
|
+
//#region apps/cli/src/account/journey/session-preparation.ts
|
|
10404
|
+
/** Phase-local facts retain no bytes; only upload steps acquire live iterators. */
|
|
10405
|
+
function createSessionPreparation(dependencies) {
|
|
10406
|
+
const prepare = dependencies.artifacts.prepareSessions;
|
|
10407
|
+
const prepared = [];
|
|
10408
|
+
const facts = /* @__PURE__ */ new Map();
|
|
10409
|
+
const sessions = async function* (journeyId, artifact, signal) {
|
|
10410
|
+
if (!prepare) {
|
|
10411
|
+
const original = dependencies.artifacts.sessions;
|
|
10412
|
+
if (original) yield* original(journeyId, artifact, signal);
|
|
10413
|
+
return;
|
|
10414
|
+
}
|
|
10415
|
+
const result = await prepare(journeyId, artifact, signal);
|
|
10416
|
+
prepared.push(result);
|
|
10417
|
+
for await (const item of result.items) {
|
|
10418
|
+
signal.throwIfAborted();
|
|
10419
|
+
yield item;
|
|
10420
|
+
}
|
|
10421
|
+
};
|
|
10422
|
+
const sessionFacts = async function* (journeyId, artifact, signal) {
|
|
10423
|
+
const key = JSON.stringify([
|
|
10424
|
+
journeyId,
|
|
10425
|
+
artifact.workId,
|
|
10426
|
+
artifact.revision,
|
|
10427
|
+
artifact.sha256
|
|
10428
|
+
]);
|
|
10429
|
+
let pending = facts.get(key);
|
|
10430
|
+
if (!pending) {
|
|
10431
|
+
pending = (async () => {
|
|
10432
|
+
const original = dependencies.artifacts.sessionFacts ?? dependencies.artifacts.sessions;
|
|
10433
|
+
const items = [];
|
|
10434
|
+
if (original) for await (const item of original(journeyId, artifact, signal)) {
|
|
10435
|
+
const { nativeSessionId, relativePath, harness, lastAt, metadata, sha256, byteLength, crc32 } = item;
|
|
10436
|
+
items.push({
|
|
10437
|
+
nativeSessionId,
|
|
10438
|
+
relativePath,
|
|
10439
|
+
harness,
|
|
10440
|
+
lastAt,
|
|
10441
|
+
metadata,
|
|
10442
|
+
sha256,
|
|
10443
|
+
byteLength,
|
|
10444
|
+
crc32
|
|
10445
|
+
});
|
|
10446
|
+
}
|
|
10447
|
+
return items;
|
|
10448
|
+
})();
|
|
10449
|
+
facts.set(key, pending);
|
|
10450
|
+
}
|
|
10451
|
+
for (const item of await pending) {
|
|
10452
|
+
signal.throwIfAborted();
|
|
10453
|
+
yield item;
|
|
10454
|
+
}
|
|
10455
|
+
};
|
|
10456
|
+
return {
|
|
10457
|
+
dependencies: {
|
|
10458
|
+
...dependencies,
|
|
10459
|
+
artifacts: {
|
|
10460
|
+
...dependencies.artifacts,
|
|
10461
|
+
sessions,
|
|
10462
|
+
sessionFacts
|
|
10463
|
+
}
|
|
10464
|
+
},
|
|
10465
|
+
async close() {
|
|
10466
|
+
await createCleanup().run(...prepared.map((result) => () => result.close()));
|
|
10467
|
+
}
|
|
10468
|
+
};
|
|
10469
|
+
}
|
|
10470
|
+
//#endregion
|
|
10380
10471
|
//#region apps/cli/src/account/journey/session-key.ts
|
|
10381
10472
|
/** Engine native identity, or harness-root-relative path identity when native identity is absent. */
|
|
10382
10473
|
async function sessionKeyFor(input) {
|
|
@@ -10395,12 +10486,25 @@ async function sessionKeyFor(input) {
|
|
|
10395
10486
|
//#region apps/cli/src/account/journey/session-access.ts
|
|
10396
10487
|
/** Check the entire pending Send before admitting any session mutation. */
|
|
10397
10488
|
async function sessionAccessBlocked(dependencies, journeyId, items, inventory, signal) {
|
|
10398
|
-
const sessions = dependencies.artifacts.sessions;
|
|
10489
|
+
const sessions = dependencies.artifacts.sessionFacts ?? dependencies.artifacts.sessions;
|
|
10399
10490
|
if (!sessions) return false;
|
|
10400
10491
|
const requestedAccess = /* @__PURE__ */ new Map();
|
|
10401
10492
|
const requestedDigests = /* @__PURE__ */ new Map();
|
|
10402
10493
|
for (const item of items) {
|
|
10403
|
-
if (item.
|
|
10494
|
+
if (item.status === "blocked" || item.sessionAssembly || !item.sessionMembership) continue;
|
|
10495
|
+
const destination = inventory.works.find((work) => work.logicalWorkId === item.workId);
|
|
10496
|
+
if (destination?.access === "removed") throw new ApplicationError("WORK_REMOVED");
|
|
10497
|
+
for (const key of item.sessionMembership.keys) {
|
|
10498
|
+
const access = requestedAccess.get(key);
|
|
10499
|
+
if (access !== void 0 && access !== item.access) return true;
|
|
10500
|
+
requestedAccess.set(key, item.access);
|
|
10501
|
+
const source = inventory.works.find((work) => work.sessions.some((entry) => entry.key === key));
|
|
10502
|
+
if (source && source.logicalWorkId !== item.workId && source.access !== item.access) return true;
|
|
10503
|
+
if (destination && destination.access !== item.access && !destination.sessions.some((entry) => entry.key === key)) return true;
|
|
10504
|
+
}
|
|
10505
|
+
}
|
|
10506
|
+
for (const item of items) {
|
|
10507
|
+
if (item.sessionAssembly || item.sessionMembership || ["completed", "blocked"].includes(item.status)) continue;
|
|
10404
10508
|
const destination = inventory.works.find((work) => work.logicalWorkId === item.workId);
|
|
10405
10509
|
if (destination?.access === "removed") throw new ApplicationError("WORK_REMOVED");
|
|
10406
10510
|
for await (const session of sessions(journeyId, item.artifact, signal)) {
|
|
@@ -10420,14 +10524,14 @@ async function sessionAccessBlocked(dependencies, journeyId, items, inventory, s
|
|
|
10420
10524
|
}
|
|
10421
10525
|
/** Keep overlapping session ownership serial through membership, including retained members. */
|
|
10422
10526
|
async function sessionIndependentItems(dependencies, journeyId, items, inventory, signal) {
|
|
10423
|
-
const sessions = dependencies.artifacts.sessions;
|
|
10527
|
+
const sessions = dependencies.artifacts.sessionFacts ?? dependencies.artifacts.sessions;
|
|
10424
10528
|
if (!sessions) return [];
|
|
10425
10529
|
const pending = items.filter((item) => item.status === "uploading" || item.status === "ready").toSorted((left, right) => Number(right.status === "uploading") - Number(left.status === "uploading") || right.artifact.byteLength - left.artifact.byteLength);
|
|
10426
10530
|
const claimed = /* @__PURE__ */ new Set();
|
|
10427
10531
|
const independent = [];
|
|
10428
10532
|
for (const item of pending) {
|
|
10429
10533
|
const keys = /* @__PURE__ */ new Set([...inventory.works.find((work) => work.logicalWorkId === item.workId)?.sessions.map((session) => session.key) ?? [], ...item.sessionMembership?.keys ?? []]);
|
|
10430
|
-
for await (const session of sessions(journeyId, item.artifact, signal)) keys.add(await sessionKeyFor(session));
|
|
10534
|
+
if (!item.sessionMembership && !item.sessionAssembly) for await (const session of sessions(journeyId, item.artifact, signal)) keys.add(await sessionKeyFor(session));
|
|
10431
10535
|
if (![...keys].some((key) => claimed.has(key))) independent.push(item);
|
|
10432
10536
|
for (const key of keys) claimed.add(key);
|
|
10433
10537
|
}
|
|
@@ -11188,7 +11292,7 @@ function renewed(item, error) {
|
|
|
11188
11292
|
//#endregion
|
|
11189
11293
|
//#region apps/cli/src/account/journey/session-step.ts
|
|
11190
11294
|
/** Reconcile against completed server facts on every retry, including after process loss. */
|
|
11191
|
-
async function stepSessionWork(dependencies, journeyId, context, item, connection, signal) {
|
|
11295
|
+
async function stepSessionWork(dependencies, journeyId, context, item, connection, signal, checkpoint) {
|
|
11192
11296
|
const remote = connection.sessions;
|
|
11193
11297
|
const sessions = dependencies.artifacts.sessions;
|
|
11194
11298
|
if (!remote || !sessions) throw new ApplicationError("INVALID_STATE");
|
|
@@ -11267,7 +11371,6 @@ async function stepSessionWork(dependencies, journeyId, context, item, connectio
|
|
|
11267
11371
|
throw error;
|
|
11268
11372
|
}
|
|
11269
11373
|
}
|
|
11270
|
-
const assembly = await remote.assembly(item.workId, signal);
|
|
11271
11374
|
const inventory = await remote.inventory(signal);
|
|
11272
11375
|
const stored = new Map([...inventory.unassigned, ...inventory.works.flatMap((work) => work.sessions)].map((session) => [session.key, session]));
|
|
11273
11376
|
const keys = [];
|
|
@@ -11283,13 +11386,17 @@ async function stepSessionWork(dependencies, journeyId, context, item, connectio
|
|
|
11283
11386
|
lastAt: session.lastAt,
|
|
11284
11387
|
harness: session.harness
|
|
11285
11388
|
};
|
|
11286
|
-
if (item.sessionUpload?.key !== key || item.sessionUpload.sha256 !== session.sha256)
|
|
11287
|
-
|
|
11288
|
-
|
|
11289
|
-
|
|
11290
|
-
|
|
11291
|
-
|
|
11292
|
-
|
|
11389
|
+
if (item.sessionUpload?.key !== key || item.sessionUpload.sha256 !== session.sha256) {
|
|
11390
|
+
await guard();
|
|
11391
|
+
item = {
|
|
11392
|
+
...item,
|
|
11393
|
+
sessionUpload: {
|
|
11394
|
+
key,
|
|
11395
|
+
sha256: session.sha256
|
|
11396
|
+
}
|
|
11397
|
+
};
|
|
11398
|
+
await checkpoint(item);
|
|
11399
|
+
}
|
|
11293
11400
|
await guard();
|
|
11294
11401
|
try {
|
|
11295
11402
|
await remote.complete({
|
|
@@ -11311,13 +11418,14 @@ async function stepSessionWork(dependencies, journeyId, context, item, connectio
|
|
|
11311
11418
|
}
|
|
11312
11419
|
}
|
|
11313
11420
|
await guard();
|
|
11314
|
-
|
|
11421
|
+
item = {
|
|
11315
11422
|
...item,
|
|
11316
11423
|
sessionUpload: null
|
|
11317
11424
|
};
|
|
11318
11425
|
}
|
|
11319
11426
|
await guard();
|
|
11320
|
-
const
|
|
11427
|
+
const assembly = await remote.assembly(item.workId, signal);
|
|
11428
|
+
const current = (await remote.inventory(signal)).works.find((work) => work.logicalWorkId === item.workId);
|
|
11321
11429
|
if (current && current.access !== item.access) {
|
|
11322
11430
|
const resolution = await connection.resolve(resolveInput(item, context.bindingId), signal);
|
|
11323
11431
|
const [candidate] = resolution.candidates;
|
|
@@ -11558,9 +11666,12 @@ async function captureProfile(connection, guard, signal, failure) {
|
|
|
11558
11666
|
//#region apps/cli/src/account/journey/advance.ts
|
|
11559
11667
|
/** A Work Passport is done with: assessed, or stopped unless Resume retries it. */
|
|
11560
11668
|
const settled = (item) => ["completed", "blocked"].includes(item.status);
|
|
11669
|
+
/** Stored state equality: key order and explicit undefined fields do not count. */
|
|
11670
|
+
const sameJson = (left, right) => isDeepStrictEqual(JSON.parse(JSON.stringify(left)), JSON.parse(JSON.stringify(right)));
|
|
11561
11671
|
/** The stored Send still holds exactly this Work state, whatever else changed meanwhile. */
|
|
11562
11672
|
function sameItem(items, item) {
|
|
11563
|
-
|
|
11673
|
+
const current = items.find((value) => value.workId === item.workId);
|
|
11674
|
+
return current !== void 0 && sameJson(current, item);
|
|
11564
11675
|
}
|
|
11565
11676
|
/** Shared sign-in, account and per-item rules for native Send and Manual upload. */
|
|
11566
11677
|
async function advanceItems(host, signal) {
|
|
@@ -11679,7 +11790,7 @@ async function advanceItems(host, signal) {
|
|
|
11679
11790
|
status: "sign-in",
|
|
11680
11791
|
error: null
|
|
11681
11792
|
});
|
|
11682
|
-
if (
|
|
11793
|
+
if (sameJson(items, send.items) && send.error === error) return host.applied();
|
|
11683
11794
|
return host.save(aggregate({
|
|
11684
11795
|
...send,
|
|
11685
11796
|
error,
|
|
@@ -11737,7 +11848,7 @@ function completeAtUpload(send, sessions) {
|
|
|
11737
11848
|
};
|
|
11738
11849
|
}
|
|
11739
11850
|
async function advanceSend(dependencies, address, signal, chain) {
|
|
11740
|
-
|
|
11851
|
+
let snapshot = requireSend(await dependencies.storage.loadSend(address.journeyId, address.sendId));
|
|
11741
11852
|
if (chain) chain.revision = snapshot.send.revision;
|
|
11742
11853
|
if ((await dependencies.storage.loadSend(address.journeyId))?.send?.id !== snapshot.send.id) return {
|
|
11743
11854
|
...snapshot,
|
|
@@ -11748,13 +11859,36 @@ async function advanceSend(dependencies, address, signal, chain) {
|
|
|
11748
11859
|
...snapshot,
|
|
11749
11860
|
status: "applied"
|
|
11750
11861
|
};
|
|
11751
|
-
const
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
|
|
11755
|
-
|
|
11756
|
-
items
|
|
11757
|
-
|
|
11862
|
+
const checkpoints = /* @__PURE__ */ new Map();
|
|
11863
|
+
const fulfilled = /* @__PURE__ */ new Set();
|
|
11864
|
+
let saving = Promise.resolve();
|
|
11865
|
+
async function active(item) {
|
|
11866
|
+
const current = requireSend(await dependencies.storage.loadSend(address.journeyId));
|
|
11867
|
+
if (current.send.id !== snapshot.send.id || !sameItem(current.send.items, checkpoints.get(item.workId) ?? item) || current.send.status === "paused" || current.journey.phase === "paused") throw new ApplicationError("REVISION_CONFLICT");
|
|
11868
|
+
assertScope(current.journey, current.send);
|
|
11869
|
+
return current;
|
|
11870
|
+
}
|
|
11871
|
+
const save = (proposed) => {
|
|
11872
|
+
const next = {
|
|
11873
|
+
...proposed,
|
|
11874
|
+
items: proposed.items.map((item) => {
|
|
11875
|
+
const checkpoint = checkpoints.get(item.workId);
|
|
11876
|
+
return checkpoint && !fulfilled.has(item.workId) ? {
|
|
11877
|
+
...checkpoint,
|
|
11878
|
+
...item,
|
|
11879
|
+
sessionUpload: checkpoint.sessionUpload
|
|
11880
|
+
} : item;
|
|
11881
|
+
})
|
|
11882
|
+
};
|
|
11883
|
+
return !completed ? saveSend(dependencies, snapshot, completeAtUpload(next, usesSessionSend(dependencies, next))) : sameJson(next.items, snapshot.send.items) ? Promise.resolve({
|
|
11884
|
+
...snapshot,
|
|
11885
|
+
status: "applied"
|
|
11886
|
+
}) : saveSend(dependencies, snapshot, {
|
|
11887
|
+
...snapshot.send,
|
|
11888
|
+
items: next.items
|
|
11889
|
+
});
|
|
11890
|
+
};
|
|
11891
|
+
const send = withoutQuestions(snapshot.send);
|
|
11758
11892
|
try {
|
|
11759
11893
|
assertScope(snapshot.journey, snapshot.send);
|
|
11760
11894
|
} catch (error) {
|
|
@@ -11776,67 +11910,94 @@ async function advanceSend(dependencies, address, signal, chain) {
|
|
|
11776
11910
|
...snapshot,
|
|
11777
11911
|
status: "applied"
|
|
11778
11912
|
};
|
|
11779
|
-
const send = withoutQuestions(snapshot.send);
|
|
11780
11913
|
if (send !== snapshot.send) return save(send);
|
|
11781
11914
|
let independentItems = [];
|
|
11782
|
-
|
|
11783
|
-
|
|
11784
|
-
|
|
11785
|
-
|
|
11786
|
-
|
|
11787
|
-
|
|
11788
|
-
|
|
11789
|
-
|
|
11790
|
-
|
|
11791
|
-
|
|
11792
|
-
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
return null;
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11801
|
-
|
|
11802
|
-
|
|
11915
|
+
const preparation = createSessionPreparation(dependencies);
|
|
11916
|
+
const cleanup = createCleanup();
|
|
11917
|
+
try {
|
|
11918
|
+
return await advanceItems({
|
|
11919
|
+
send,
|
|
11920
|
+
failure: dependencies.failure,
|
|
11921
|
+
...usesSessionSend(dependencies, send) ? {
|
|
11922
|
+
batch: () => {
|
|
11923
|
+
const limit = send.parallelCompletes ? 3 : 1;
|
|
11924
|
+
return independentItems.length ? pickBatch(independentItems, Date.now(), limit) : pickBatch(send.items, Date.now(), limit);
|
|
11925
|
+
},
|
|
11926
|
+
preflight: async (connection, preflightSignal) => {
|
|
11927
|
+
if (!connection.sessions) throw new ApplicationError("INVALID_STATE");
|
|
11928
|
+
if (!send.items.some((item) => item.status === "uploading" && !item.sessionAssembly && !item.receipt && !item.reservation)) return null;
|
|
11929
|
+
const inventory = await connection.sessions.inventory(preflightSignal);
|
|
11930
|
+
if (!await sessionAccessBlocked(preparation.dependencies, snapshot.journey.journeyId, send.items, inventory, preflightSignal)) {
|
|
11931
|
+
independentItems = await sessionIndependentItems(preparation.dependencies, snapshot.journey.journeyId, send.items, inventory, preflightSignal);
|
|
11932
|
+
return null;
|
|
11933
|
+
}
|
|
11934
|
+
await connection.assertCurrent(preflightSignal);
|
|
11935
|
+
return save({
|
|
11936
|
+
...send,
|
|
11803
11937
|
status: "blocked",
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
connect: chain?.connect ?? dependencies.auth.connect,
|
|
11811
|
-
profile: (connection, profileSignal) => prepareProfile(dependencies, snapshot, connection, profileSignal),
|
|
11812
|
-
context: (item) => {
|
|
11813
|
-
const binding = snapshot.journey.works.find((value) => value.id === item.workId)?.binding;
|
|
11814
|
-
return {
|
|
11815
|
-
snapshot: true,
|
|
11816
|
-
...chain ? { fresh: chain.fresh } : {},
|
|
11817
|
-
active: async () => {
|
|
11818
|
-
const current = requireSend(await dependencies.storage.loadSend(snapshot.journey.journeyId));
|
|
11819
|
-
if (current.send.id !== snapshot.send.id || !sameItem(current.send.items, item) || current.send.status === "paused" || current.journey.phase === "paused") throw new ApplicationError("REVISION_CONFLICT");
|
|
11820
|
-
assertScope(current.journey, current.send);
|
|
11938
|
+
items: send.items.map((item) => item.sessionAssembly || item.status === "completed" ? item : {
|
|
11939
|
+
...item,
|
|
11940
|
+
status: "blocked",
|
|
11941
|
+
error: "SESSION_MOVE_ACCESS_REQUIRED"
|
|
11942
|
+
})
|
|
11943
|
+
});
|
|
11821
11944
|
},
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11830
|
-
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11945
|
+
step: (context, item, connection, stepSignal) => stepSessionWork(preparation.dependencies, snapshot.journey.journeyId, context, item, connection, stepSignal, (next) => {
|
|
11946
|
+
const pending = saving.then(async () => {
|
|
11947
|
+
const current = await active(item);
|
|
11948
|
+
if (current.send.revision !== snapshot.send.revision || current.journey.revision !== snapshot.journey.revision) throw new ApplicationError("REVISION_CONFLICT");
|
|
11949
|
+
stepSignal.throwIfAborted();
|
|
11950
|
+
const result = await saveSend(dependencies, current, {
|
|
11951
|
+
...current.send,
|
|
11952
|
+
items: current.send.items.map((value) => value.workId === next.workId ? next : value)
|
|
11953
|
+
});
|
|
11954
|
+
if (result.status === "stale") throw new ApplicationError("REVISION_CONFLICT");
|
|
11955
|
+
snapshot = requireSend(result);
|
|
11956
|
+
const saved = snapshot.send.items.find((value) => value.workId === next.workId);
|
|
11957
|
+
if (!saved) throw new ApplicationError("INVALID_STATE");
|
|
11958
|
+
checkpoints.set(next.workId, saved);
|
|
11959
|
+
});
|
|
11960
|
+
saving = pending.catch(() => void 0);
|
|
11961
|
+
return pending;
|
|
11962
|
+
}).then((result) => {
|
|
11963
|
+
fulfilled.add(item.workId);
|
|
11964
|
+
return result;
|
|
11965
|
+
})
|
|
11966
|
+
} : {},
|
|
11967
|
+
connect: chain?.connect ?? dependencies.auth.connect,
|
|
11968
|
+
profile: (connection, profileSignal) => prepareProfile(dependencies, snapshot, connection, profileSignal),
|
|
11969
|
+
context: (item) => {
|
|
11970
|
+
const binding = snapshot.journey.works.find((value) => value.id === item.workId)?.binding;
|
|
11971
|
+
return {
|
|
11972
|
+
snapshot: true,
|
|
11973
|
+
...chain ? { fresh: chain.fresh } : {},
|
|
11974
|
+
active: async () => {
|
|
11975
|
+
await active(item);
|
|
11976
|
+
},
|
|
11977
|
+
bindingId: binding?.subject === send.subject ? binding.bundleRecordId : void 0,
|
|
11978
|
+
upload: async (artifact, upload, uploadSignal) => {
|
|
11979
|
+
const started = performance.now();
|
|
11980
|
+
await dependencies.artifacts.upload(snapshot.journey.journeyId, artifact, upload, uploadSignal);
|
|
11981
|
+
dependencies.uploaded?.(artifact.workId, artifact.byteLength, Math.round(performance.now() - started));
|
|
11982
|
+
}
|
|
11983
|
+
};
|
|
11984
|
+
},
|
|
11985
|
+
save,
|
|
11986
|
+
applied: () => ({
|
|
11987
|
+
...snapshot,
|
|
11988
|
+
status: "applied"
|
|
11989
|
+
}),
|
|
11990
|
+
stale: async () => ({
|
|
11991
|
+
...requireSend(await dependencies.storage.loadSend(address.journeyId, address.sendId)),
|
|
11992
|
+
status: "stale"
|
|
11993
|
+
})
|
|
11994
|
+
}, signal);
|
|
11995
|
+
} catch (error) {
|
|
11996
|
+
cleanup.failed(error);
|
|
11997
|
+
throw error;
|
|
11998
|
+
} finally {
|
|
11999
|
+
await cleanup.run(() => preparation.close());
|
|
12000
|
+
}
|
|
11840
12001
|
}
|
|
11841
12002
|
/** The first wait after a bare refusal of staged bytes, doubled per refusal up to the cap. */
|
|
11842
12003
|
const busyBaseMs = 2e3;
|
|
@@ -15210,7 +15371,13 @@ async function createRuntime(options, callbacks = {}) {
|
|
|
15210
15371
|
let bundles;
|
|
15211
15372
|
if (import.meta.url.endsWith(".ts")) {
|
|
15212
15373
|
traceStartup("worker-build-start");
|
|
15213
|
-
|
|
15374
|
+
const shared = process.env["SESS_PILOT_TEST_WORKER_BUNDLES"];
|
|
15375
|
+
if (shared) bundles = {
|
|
15376
|
+
directory: shared,
|
|
15377
|
+
url: (name) => pathToFileURL(join(shared, `${name}.mjs`)),
|
|
15378
|
+
dispose: async () => {}
|
|
15379
|
+
};
|
|
15380
|
+
else bundles = await (await import(new URL("../../../scripts/workers/build.ts", import.meta.url).href)).buildWorkerBundles();
|
|
15214
15381
|
traceStartup("worker-build-end");
|
|
15215
15382
|
}
|
|
15216
15383
|
try {
|