@rulvar/core 1.59.2 → 1.59.4
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/index.d.ts +53 -2
- package/dist/index.js +120 -14
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2652,6 +2652,7 @@ declare class Replayer {
|
|
|
2652
2652
|
private readonly runId;
|
|
2653
2653
|
private readonly store;
|
|
2654
2654
|
private readonly lease?;
|
|
2655
|
+
private readonly leaseOf?;
|
|
2655
2656
|
private readonly now;
|
|
2656
2657
|
private readonly priceUsd?;
|
|
2657
2658
|
private readonly onWarn?;
|
|
@@ -2683,6 +2684,14 @@ declare class Replayer {
|
|
|
2683
2684
|
* is asserted instead of fenced (the embedded default).
|
|
2684
2685
|
*/
|
|
2685
2686
|
lease?: Lease;
|
|
2687
|
+
/**
|
|
2688
|
+
* Late-bound lease lookup (P0.2): consulted at EVERY append,
|
|
2689
|
+
* winning over the static `lease` when it returns one. The engine
|
|
2690
|
+
* passes its segment-lease holder here, because the
|
|
2691
|
+
* engine-acquired genesis lease exists only after the ownership
|
|
2692
|
+
* boot, which runs after this constructor.
|
|
2693
|
+
*/
|
|
2694
|
+
leaseOf?: () => Lease | undefined;
|
|
2686
2695
|
});
|
|
2687
2696
|
/**
|
|
2688
2697
|
* Forward-matches one live call against the prior journal. Fresh
|
|
@@ -4094,8 +4103,14 @@ interface ToolRuntime {
|
|
|
4094
4103
|
* toolset holds any non-inprocess tool; the ctx layer mints the tool
|
|
4095
4104
|
* span and idempotency key and wires the provider. A throw becomes the
|
|
4096
4105
|
* call's error tool result exactly like an inprocess execute throw.
|
|
4106
|
+
*
|
|
4107
|
+
* `ordinal` is the call's 1-based position in this agent invocation's
|
|
4108
|
+
* tool loop (checkpoint-stable across suspension and crash resume); the
|
|
4109
|
+
* ctx layer folds it with the agent entry's seq into the idempotency
|
|
4110
|
+
* key, so two separate calls with identical arguments do not collide
|
|
4111
|
+
* while an at-least-once retry of one call keeps its key (P0.4).
|
|
4097
4112
|
*/
|
|
4098
|
-
executeExternal?: (def: ToolDef, args: Json) => Promise<unknown>;
|
|
4113
|
+
executeExternal?: (def: ToolDef, args: Json, ordinal: number) => Promise<unknown>;
|
|
4099
4114
|
}
|
|
4100
4115
|
/** One serving target of a phase: the primary or a failover fallback. */
|
|
4101
4116
|
interface PhaseTarget {
|
|
@@ -5676,6 +5691,25 @@ interface CreateEngineOptions {
|
|
|
5676
5691
|
security?: {
|
|
5677
5692
|
argsHashSalt?: string;
|
|
5678
5693
|
};
|
|
5694
|
+
/**
|
|
5695
|
+
* The genesis ownership protocol (P0.2): over a journal store with
|
|
5696
|
+
* the lease capability, a run or resume segment that was NOT handed
|
|
5697
|
+
* a lease acquires its own before its first durable mutation, renews
|
|
5698
|
+
* it at ttl/3 exactly like a queue worker, and releases it at
|
|
5699
|
+
* settle. Fresh start, in-process resume, and worker takeover then
|
|
5700
|
+
* share ONE owner/lease contract: at most one live driver per run
|
|
5701
|
+
* across processes, a second driver's acquire rejects with the typed
|
|
5702
|
+
* LeaseHeldError before any write or provider dispatch, and a
|
|
5703
|
+
* crashed owner's lease expires after the store ttl so a worker
|
|
5704
|
+
* sweep recovers the run. Default 'auto'. 'none' restores the
|
|
5705
|
+
* pre-1.59.4 behavior (no engine-acquired leases) for hosts that
|
|
5706
|
+
* coordinate ownership entirely outside the engine; a lease passed
|
|
5707
|
+
* via RunOptions.lease or ResumeOptions.lease always wins over both
|
|
5708
|
+
* modes (the caller owns acquire, renew, and release). Stores
|
|
5709
|
+
* without the lease capability are unaffected: the embedded
|
|
5710
|
+
* single-process default keeps the single-writer precondition.
|
|
5711
|
+
*/
|
|
5712
|
+
ownership?: "auto" | "none";
|
|
5679
5713
|
}
|
|
5680
5714
|
interface RunOptions {
|
|
5681
5715
|
/** Explicit id; otherwise the engine mints a ULID. */
|
|
@@ -5707,6 +5741,19 @@ interface RunOptions {
|
|
|
5707
5741
|
tags?: string[];
|
|
5708
5742
|
/** Host-initiated cancellation. */
|
|
5709
5743
|
signal?: AbortSignal;
|
|
5744
|
+
/**
|
|
5745
|
+
* A lease the caller already holds for this run (the genesis side of
|
|
5746
|
+
* the ResumeOptions.lease contract): the engine carries it on EVERY
|
|
5747
|
+
* durable mutation of the fresh segment (every journal append, every
|
|
5748
|
+
* putMeta, every transcript blob write) and never acquires, renews,
|
|
5749
|
+
* or releases it itself; lifecycle stays with the caller. Passing it
|
|
5750
|
+
* disables the engine's own ownership acquisition for this run
|
|
5751
|
+
* regardless of the `ownership` mode. Hosts that admit runs through
|
|
5752
|
+
* an external queue acquire the lease at admission time and hand it
|
|
5753
|
+
* here, so admission and the first dispatch are covered by ONE
|
|
5754
|
+
* fencing epoch.
|
|
5755
|
+
*/
|
|
5756
|
+
lease?: Lease;
|
|
5710
5757
|
}
|
|
5711
5758
|
/** Resume-time hit/miss/orphan accounting. */
|
|
5712
5759
|
interface ResumePreview extends ResumeReport {
|
|
@@ -7328,8 +7375,12 @@ interface RunInternals {
|
|
|
7328
7375
|
* worktree patches) exactly as the Replayer threads it into every
|
|
7329
7376
|
* journal append, so a store declaring fencedWrites refuses a
|
|
7330
7377
|
* superseded segment's blob overwrites (fenced run state RFC, F2).
|
|
7378
|
+
* The engine binds this as a live getter over its segment-lease
|
|
7379
|
+
* holder (P0.2), so the union with undefined is explicit: before
|
|
7380
|
+
* the ownership boot (and on non-leasable stores) it reads
|
|
7381
|
+
* undefined.
|
|
7331
7382
|
*/
|
|
7332
|
-
lease?: Lease;
|
|
7383
|
+
lease?: Lease | undefined;
|
|
7333
7384
|
adapters: ReadonlyMap<string, ProviderAdapter>;
|
|
7334
7385
|
defaults: {
|
|
7335
7386
|
routing?: Partial<Record<InvocationRole, ModelSpec>>;
|
package/dist/index.js
CHANGED
|
@@ -420,6 +420,7 @@ function wrapJournalStore(inner, hook) {
|
|
|
420
420
|
wrapped.acquire = (runId, owner) => inner.acquire(runId, owner);
|
|
421
421
|
wrapped.renew = (l) => inner.renew(l);
|
|
422
422
|
wrapped.release = (l) => inner.release(l);
|
|
423
|
+
if (typeof leasable.leaseTtlMs === "number") wrapped.leaseTtlMs = leasable.leaseTtlMs;
|
|
423
424
|
}
|
|
424
425
|
if (typeof inner.getMeta === "function") wrapped.getMeta = (runId) => inner.getMeta(runId);
|
|
425
426
|
return wrapped;
|
|
@@ -6779,6 +6780,7 @@ var Replayer = class {
|
|
|
6779
6780
|
runId;
|
|
6780
6781
|
store;
|
|
6781
6782
|
lease;
|
|
6783
|
+
leaseOf;
|
|
6782
6784
|
now;
|
|
6783
6785
|
priceUsd;
|
|
6784
6786
|
onWarn;
|
|
@@ -6796,6 +6798,7 @@ var Replayer = class {
|
|
|
6796
6798
|
this.runId = options.runId;
|
|
6797
6799
|
this.store = options.store;
|
|
6798
6800
|
if (options.lease !== void 0) this.lease = options.lease;
|
|
6801
|
+
if (options.leaseOf !== void 0) this.leaseOf = options.leaseOf;
|
|
6799
6802
|
this.now = options.now ?? realNow;
|
|
6800
6803
|
if (options.priceUsd !== void 0) this.priceUsd = options.priceUsd;
|
|
6801
6804
|
if (options.onWarn !== void 0) this.onWarn = options.onWarn;
|
|
@@ -7083,7 +7086,7 @@ var Replayer = class {
|
|
|
7083
7086
|
} });
|
|
7084
7087
|
const shapeIssues = validateEntryShape(entry);
|
|
7085
7088
|
if (shapeIssues.length > 0) throw new ConfigError(`journal entry shape violation (kind '${entry.kind}'): ` + shapeIssues.map((i) => i.message).join("; "));
|
|
7086
|
-
await this.store.append(this.runId, entry, this.lease);
|
|
7089
|
+
await this.store.append(this.runId, entry, this.leaseOf?.() ?? this.lease);
|
|
7087
7090
|
this.entries.push(entry);
|
|
7088
7091
|
if (entry.status === "suspended") this.foldInternal.registerSuspended(entry);
|
|
7089
7092
|
else if (entry.kind !== "resolution" && entry.kind !== "abandon") this.foldInternal.registerEntry(entry);
|
|
@@ -10402,7 +10405,7 @@ async function executeToolCall(options) {
|
|
|
10402
10405
|
try {
|
|
10403
10406
|
let value;
|
|
10404
10407
|
if (def.executor === "inprocess") value = await def.execute(validation.value, runtime.contextFor(call.name));
|
|
10405
|
-
else if (runtime.executeExternal !== void 0) value = await runtime.executeExternal(def, validation.value);
|
|
10408
|
+
else if (runtime.executeExternal !== void 0) value = await runtime.executeExternal(def, validation.value, options.ordinal);
|
|
10406
10409
|
else return finish({ error: `tool '${call.name}' declares executor '${def.executor}' but no executor is registered` }, "error");
|
|
10407
10410
|
const serialized = toJournalValue(value === void 0 ? null : value, `tool '${call.name}'`);
|
|
10408
10411
|
options.retryCounts.delete(call.name);
|
|
@@ -10829,6 +10832,7 @@ async function runAgent(options) {
|
|
|
10829
10832
|
runtime,
|
|
10830
10833
|
retryCounts: modelRetryCounts,
|
|
10831
10834
|
maxModelRetries: options.modelRetryAttempts ?? 2,
|
|
10835
|
+
ordinal: toolCallsUsed,
|
|
10832
10836
|
...events === void 0 ? {} : { events },
|
|
10833
10837
|
...gateAudit === void 0 ? {} : { audit: gateAudit },
|
|
10834
10838
|
now
|
|
@@ -13170,15 +13174,30 @@ function setLongTimeout(onDue, dueAtMs, now = Date.now) {
|
|
|
13170
13174
|
*/
|
|
13171
13175
|
/**
|
|
13172
13176
|
* Derives the idempotency key for one isolated tool dispatch. The key is
|
|
13173
|
-
* a pure function of the run, the
|
|
13174
|
-
*
|
|
13175
|
-
*
|
|
13176
|
-
*
|
|
13177
|
-
*
|
|
13177
|
+
* a pure function of the run, the LOGICAL INVOCATION (the seq of the
|
|
13178
|
+
* containing agent's journal entry plus that call's ordinal within the
|
|
13179
|
+
* agent's tool loop), the tool name, and the JCS-canonical arguments.
|
|
13180
|
+
*
|
|
13181
|
+
* The logical-invocation component is what makes the key both stable and
|
|
13182
|
+
* distinguishing (v1.59.x review P0.4): the agent-entry seq and the
|
|
13183
|
+
* per-agent tool-call ordinal are journal- and checkpoint-stable, so a
|
|
13184
|
+
* crash-and-resume re-dispatch of the SAME logical call (the at-least-
|
|
13185
|
+
* once window between execution and the turn checkpoint) reuses the same
|
|
13186
|
+
* dispatch entry and the restored ordinal, and therefore the same key;
|
|
13187
|
+
* while two SEPARATE calls in one run, even with byte-identical
|
|
13188
|
+
* arguments, occupy different ordinals and never collide. Without it two
|
|
13189
|
+
* intended effects sharing arguments would fold into one under external
|
|
13190
|
+
* deduplication.
|
|
13191
|
+
*
|
|
13192
|
+
* The key never enters run identity (it is absent from every content key
|
|
13193
|
+
* and toolset hash); it exists only for the provider's own side-effect
|
|
13194
|
+
* deduplication.
|
|
13178
13195
|
*/
|
|
13179
|
-
function deriveExecIdempotencyKey(runId, tool, args) {
|
|
13196
|
+
function deriveExecIdempotencyKey(runId, agentSeq, ordinal, tool, args) {
|
|
13180
13197
|
const canonical = jcsSerialize({
|
|
13181
13198
|
runId,
|
|
13199
|
+
agentSeq,
|
|
13200
|
+
ordinal,
|
|
13182
13201
|
tool,
|
|
13183
13202
|
args
|
|
13184
13203
|
});
|
|
@@ -13980,7 +13999,8 @@ function createCtx(internals, rootWorkflow) {
|
|
|
13980
13999
|
};
|
|
13981
14000
|
if (internals.executors !== void 0) {
|
|
13982
14001
|
const executors = internals.executors;
|
|
13983
|
-
|
|
14002
|
+
const agentSeq = running.seq;
|
|
14003
|
+
toolRuntime.executeExternal = async (def, args, ordinal) => {
|
|
13984
14004
|
const tag = def.executor;
|
|
13985
14005
|
const provider = executors[tag];
|
|
13986
14006
|
if (provider === void 0) throw new ConfigError(`no executor registered for '${def.executor}'; register one via createEngine({ executors }) (https://docs.rulvar.com/guide/isolated-executor)`);
|
|
@@ -13994,7 +14014,7 @@ function createCtx(internals, rootWorkflow) {
|
|
|
13994
14014
|
runId: internals.runId,
|
|
13995
14015
|
spanId: toolSpanId,
|
|
13996
14016
|
agentType,
|
|
13997
|
-
idempotencyKey: deriveExecIdempotencyKey(internals.runId, def.name, args),
|
|
14017
|
+
idempotencyKey: deriveExecIdempotencyKey(internals.runId, agentSeq, ordinal, def.name, args),
|
|
13998
14018
|
signal: toolSignal,
|
|
13999
14019
|
log: (level, msg, data) => internals.events.emit(data === void 0 ? {
|
|
14000
14020
|
type: "log",
|
|
@@ -17102,6 +17122,28 @@ function hashRunOutput(value) {
|
|
|
17102
17122
|
return;
|
|
17103
17123
|
}
|
|
17104
17124
|
}
|
|
17125
|
+
/**
|
|
17126
|
+
* Engine ownership identity: a process-local counter, not Math.random()
|
|
17127
|
+
* (the queue worker's identity convention): owner strings need
|
|
17128
|
+
* uniqueness within the store, and the dev-mode bare-randomness guard
|
|
17129
|
+
* stays armed while any run is live.
|
|
17130
|
+
*/
|
|
17131
|
+
let engineOrdinal = 0;
|
|
17132
|
+
function engineIdentity() {
|
|
17133
|
+
engineOrdinal += 1;
|
|
17134
|
+
return `rulvar-engine:${process.pid}:${engineOrdinal}`;
|
|
17135
|
+
}
|
|
17136
|
+
/** Lease capability guard, mirroring createWorker's detection. */
|
|
17137
|
+
function leaseCapable(store) {
|
|
17138
|
+
const candidate = store;
|
|
17139
|
+
return typeof candidate.acquire === "function" && typeof candidate.renew === "function" && typeof candidate.release === "function";
|
|
17140
|
+
}
|
|
17141
|
+
/**
|
|
17142
|
+
* The renew-cadence fallback when a leasable store exposes no
|
|
17143
|
+
* leaseTtlMs: the Appendix A interim reference ttl the shipped stores
|
|
17144
|
+
* default to (60000 ms).
|
|
17145
|
+
*/
|
|
17146
|
+
const ENGINE_DEFAULT_LEASE_TTL_MS = 6e4;
|
|
17105
17147
|
function createEngine(options) {
|
|
17106
17148
|
const adapters = buildAdapterRegistry(options.adapters);
|
|
17107
17149
|
const rawJournal = options.stores?.journal ?? new InMemoryStore();
|
|
@@ -17111,6 +17153,17 @@ function createEngine(options) {
|
|
|
17111
17153
|
const maskEvents = options.redaction?.maskEvents ?? true;
|
|
17112
17154
|
const eventMasker = options.redaction?.patterns === void 0 ? void 0 : compileSecretMasker(options.redaction.patterns, "createEngine redaction.patterns");
|
|
17113
17155
|
const defaults = options.defaults ?? {};
|
|
17156
|
+
const ownership = options.ownership ?? "auto";
|
|
17157
|
+
if (ownership !== "auto" && ownership !== "none") throw new ConfigError(`createEngine ownership must be 'auto' or 'none'; got '${String(ownership)}'`);
|
|
17158
|
+
const engineOwner = engineIdentity();
|
|
17159
|
+
let ownershipRenewMs = Math.max(1, Math.floor(ENGINE_DEFAULT_LEASE_TTL_MS / 3));
|
|
17160
|
+
if (ownership === "auto" && leaseCapable(journal)) {
|
|
17161
|
+
const storeTtlMs = journal.leaseTtlMs;
|
|
17162
|
+
if (storeTtlMs !== void 0) {
|
|
17163
|
+
if (!Number.isInteger(storeTtlMs) || storeTtlMs < 1 || storeTtlMs > 2147483647) throw new ConfigError(`the journal store's leaseTtlMs capability must report an integer between 1 and 2147483647 ms for the engine's ownership renew cadence; got ${String(storeTtlMs)}`);
|
|
17164
|
+
ownershipRenewMs = Math.max(1, Math.floor(storeTtlMs / 3));
|
|
17165
|
+
}
|
|
17166
|
+
}
|
|
17114
17167
|
if (defaults.retry !== void 0) validateRetryPolicy(defaults.retry, "createEngine defaults.retry");
|
|
17115
17168
|
if (options.concurrency?.perRun !== void 0) requirePositiveInteger(options.concurrency.perRun, "createEngine concurrency.perRun");
|
|
17116
17169
|
for (const [adapterId, cap] of Object.entries(options.concurrency?.perProvider ?? {})) requirePositiveInteger(cap, `createEngine concurrency.perProvider['${adapterId}']`);
|
|
@@ -17165,6 +17218,10 @@ function createEngine(options) {
|
|
|
17165
17218
|
if (compiled !== void 0 && options.runners?.sandbox === void 0) throw new ConfigError("running a CompiledWorkflow requires a sandbox runner: pass createEngine({ runners: { sandbox: new WorkerSandboxRunner() } }) from @rulvar/planner ");
|
|
17166
17219
|
const runId = resumeCtx?.runId ?? opts?.runId ?? mintRunId();
|
|
17167
17220
|
assertSafeRunId(runId, "engine.run");
|
|
17221
|
+
const suppliedLease = resumeCtx?.lease ?? opts?.lease;
|
|
17222
|
+
if (suppliedLease !== void 0 && suppliedLease.runId !== runId) throw new ConfigError(`the supplied lease is for run '${suppliedLease.runId}', not '${runId}'; a lease fences exactly the run it was acquired for`);
|
|
17223
|
+
const segmentLease = {};
|
|
17224
|
+
if (suppliedLease !== void 0) segmentLease.current = suppliedLease;
|
|
17168
17225
|
const registry = buildDeriverRegistry(options.extraDerivers);
|
|
17169
17226
|
const segmentsBefore = resumeCtx?.segmentsBefore ?? 0;
|
|
17170
17227
|
const telemetryBase = segmentsBefore * EVENT_SEGMENT_STRIDE;
|
|
@@ -17201,7 +17258,7 @@ function createEngine(options) {
|
|
|
17201
17258
|
}, rootSpanId),
|
|
17202
17259
|
keyRing: registryKeyRing(registry),
|
|
17203
17260
|
...resumeCtx === void 0 ? {} : { priorEntries: resumeCtx.priorEntries },
|
|
17204
|
-
|
|
17261
|
+
leaseOf: () => segmentLease.current,
|
|
17205
17262
|
strict: resumeCtx?.strict ?? false
|
|
17206
17263
|
});
|
|
17207
17264
|
for (const seqToInvalidate of invalidated) replayer.invalidate(seqToInvalidate);
|
|
@@ -17296,7 +17353,9 @@ function createEngine(options) {
|
|
|
17296
17353
|
external,
|
|
17297
17354
|
mintTranscriptRef: () => `${runId}/t${transcriptCounter++}`,
|
|
17298
17355
|
now: realNow,
|
|
17299
|
-
|
|
17356
|
+
get lease() {
|
|
17357
|
+
return segmentLease.current;
|
|
17358
|
+
}
|
|
17300
17359
|
};
|
|
17301
17360
|
const argsBinding = {};
|
|
17302
17361
|
if (resumeCtx === void 0) {
|
|
@@ -17324,15 +17383,60 @@ function createEngine(options) {
|
|
|
17324
17383
|
workflowName: wf.name,
|
|
17325
17384
|
workflowHash: compiled === void 0 ? hashWorkflowBody(wf) : hashWorkflowSource(compiled.source),
|
|
17326
17385
|
...compiled === void 0 ? {} : { workflowSourceRef: workflowSourceRef(runId) }
|
|
17327
|
-
},
|
|
17386
|
+
}, segmentLease.current);
|
|
17328
17387
|
if (activeSegments.has(runId)) throw new ConfigError(`run '${runId}' already has a live execution segment in this engine; await its settled result before starting another one (exactly one segment owns a run; https://docs.rulvar.com/guide/durability#resolving-a-settled-run)`);
|
|
17329
17388
|
activeSegments.add(runId);
|
|
17389
|
+
let ownershipTeardown = () => Promise.resolve();
|
|
17330
17390
|
const result = (async () => {
|
|
17391
|
+
let ownedLease;
|
|
17392
|
+
let renewTimer;
|
|
17393
|
+
const settleOwnership = async () => {
|
|
17394
|
+
if (renewTimer !== void 0) {
|
|
17395
|
+
clearInterval(renewTimer);
|
|
17396
|
+
renewTimer = void 0;
|
|
17397
|
+
}
|
|
17398
|
+
const held = ownedLease;
|
|
17399
|
+
ownedLease = void 0;
|
|
17400
|
+
if (held !== void 0) {
|
|
17401
|
+
segmentLease.current = void 0;
|
|
17402
|
+
try {
|
|
17403
|
+
await journal.release(held);
|
|
17404
|
+
} catch {}
|
|
17405
|
+
}
|
|
17406
|
+
};
|
|
17407
|
+
ownershipTeardown = settleOwnership;
|
|
17408
|
+
if (ownership === "auto" && segmentLease.current === void 0 && resumeCtx?.strict !== true && leaseCapable(journal)) {
|
|
17409
|
+
let acquired;
|
|
17410
|
+
try {
|
|
17411
|
+
acquired = await journal.acquire(runId, engineOwner);
|
|
17412
|
+
} catch (thrown) {
|
|
17413
|
+
if (deadlineTimer !== void 0) deadlineTimer.cancel();
|
|
17414
|
+
external.close();
|
|
17415
|
+
bus.end();
|
|
17416
|
+
throw thrown;
|
|
17417
|
+
}
|
|
17418
|
+
ownedLease = acquired;
|
|
17419
|
+
segmentLease.current = acquired;
|
|
17420
|
+
renewTimer = setInterval(() => {
|
|
17421
|
+
journal.renew(acquired).catch(() => {
|
|
17422
|
+
bus.emit({
|
|
17423
|
+
type: "log",
|
|
17424
|
+
level: "warn",
|
|
17425
|
+
msg: `run '${runId}' ownership lost: the lease could not be renewed and its fencing epoch may be superseded`
|
|
17426
|
+
}, rootSpanId);
|
|
17427
|
+
requestCancel("run ownership lost: lease fencing epoch superseded");
|
|
17428
|
+
if (renewTimer !== void 0) {
|
|
17429
|
+
clearInterval(renewTimer);
|
|
17430
|
+
renewTimer = void 0;
|
|
17431
|
+
}
|
|
17432
|
+
});
|
|
17433
|
+
}, ownershipRenewMs);
|
|
17434
|
+
}
|
|
17331
17435
|
let status = "ok";
|
|
17332
17436
|
let value;
|
|
17333
17437
|
let wireError;
|
|
17334
17438
|
let pending = [];
|
|
17335
|
-
if (compiled !== void 0 && resumeCtx?.strict !== true) await transcripts.put(workflowSourceRef(runId), new TextEncoder().encode(compiled.source),
|
|
17439
|
+
if (compiled !== void 0 && resumeCtx?.strict !== true) await transcripts.put(workflowSourceRef(runId), new TextEncoder().encode(compiled.source), segmentLease.current);
|
|
17336
17440
|
await putMeta("running");
|
|
17337
17441
|
bus.emit({
|
|
17338
17442
|
type: "run:start",
|
|
@@ -17459,9 +17563,11 @@ function createEngine(options) {
|
|
|
17459
17563
|
...replayer.resumeReport(),
|
|
17460
17564
|
invalidResolutions: replayer.fold.invalidResolutions()
|
|
17461
17565
|
});
|
|
17566
|
+
await settleOwnership();
|
|
17462
17567
|
return outcome;
|
|
17463
17568
|
})();
|
|
17464
17569
|
result.catch(() => void 0).finally(() => {
|
|
17570
|
+
ownershipTeardown();
|
|
17465
17571
|
activeSegments.delete(runId);
|
|
17466
17572
|
});
|
|
17467
17573
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.59.
|
|
3
|
+
"version": "1.59.4",
|
|
4
4
|
"description": "Rulvar core: L0 contracts, journal kernel, ctx primitives, agent runtime, model router, tool system, dynamic orchestrator, InMemory and JSONL stores, event stream.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|