chatroom-cli 1.55.5 → 1.55.6
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.js +1803 -781
- package/dist/index.js.map +34 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16656,13 +16656,15 @@ var init_fiberRefs = __esm(() => {
|
|
|
16656
16656
|
});
|
|
16657
16657
|
|
|
16658
16658
|
// ../../node_modules/.pnpm/effect@3.21.2/node_modules/effect/dist/esm/FiberRefs.js
|
|
16659
|
-
var get9, getOrDefault2, joinAs2, setAll2, updateManyAs2, empty20;
|
|
16659
|
+
var delete_2, get9, getOrDefault2, joinAs2, setAll2, updateAs2, updateManyAs2, empty20;
|
|
16660
16660
|
var init_FiberRefs = __esm(() => {
|
|
16661
16661
|
init_fiberRefs();
|
|
16662
|
+
delete_2 = delete_;
|
|
16662
16663
|
get9 = get8;
|
|
16663
16664
|
getOrDefault2 = getOrDefault;
|
|
16664
16665
|
joinAs2 = joinAs;
|
|
16665
16666
|
setAll2 = setAll;
|
|
16667
|
+
updateAs2 = updateAs;
|
|
16666
16668
|
updateManyAs2 = updateManyAs;
|
|
16667
16669
|
empty20 = empty19;
|
|
16668
16670
|
});
|
|
@@ -21657,12 +21659,13 @@ var init_ScheduleDecision = __esm(() => {
|
|
|
21657
21659
|
});
|
|
21658
21660
|
|
|
21659
21661
|
// ../../node_modules/.pnpm/effect@3.21.2/node_modules/effect/dist/esm/Scope.js
|
|
21660
|
-
var Scope, close, fork2;
|
|
21662
|
+
var Scope, close, extend2, fork2;
|
|
21661
21663
|
var init_Scope = __esm(() => {
|
|
21662
21664
|
init_core();
|
|
21663
21665
|
init_fiberRuntime();
|
|
21664
21666
|
Scope = scopeTag;
|
|
21665
21667
|
close = scopeClose;
|
|
21668
|
+
extend2 = scopeExtend;
|
|
21666
21669
|
fork2 = scopeFork;
|
|
21667
21670
|
});
|
|
21668
21671
|
|
|
@@ -22156,13 +22159,13 @@ var makeDual = (f) => function() {
|
|
|
22156
22159
|
const error = new AsyncFiberExceptionImpl(fiber);
|
|
22157
22160
|
Error.stackTraceLimit = limit;
|
|
22158
22161
|
return error;
|
|
22159
|
-
}, FiberFailureId, FiberFailureCauseId, FiberFailureImpl, fiberFailure = (cause2) => {
|
|
22162
|
+
}, isAsyncFiberException = (u) => isTagged(u, "AsyncFiberException") && ("fiber" in u), FiberFailureId, FiberFailureCauseId, FiberFailureImpl, fiberFailure = (cause2) => {
|
|
22160
22163
|
const limit = Error.stackTraceLimit;
|
|
22161
22164
|
Error.stackTraceLimit = 0;
|
|
22162
22165
|
const error = new FiberFailureImpl(cause2);
|
|
22163
22166
|
Error.stackTraceLimit = limit;
|
|
22164
22167
|
return error;
|
|
22165
|
-
}, fastPath = (effect) => {
|
|
22168
|
+
}, isFiberFailure = (u) => hasProperty(u, FiberFailureId), fastPath = (effect) => {
|
|
22166
22169
|
const op = effect;
|
|
22167
22170
|
switch (op._op) {
|
|
22168
22171
|
case "Failure":
|
|
@@ -22182,7 +22185,7 @@ var makeDual = (f) => function() {
|
|
|
22182
22185
|
return exitFail(new NoSuchElementException);
|
|
22183
22186
|
}
|
|
22184
22187
|
}
|
|
22185
|
-
}, unsafeRunSyncExit, unsafeRunPromise, unsafeRunPromiseExit, make36 = (options) => new RuntimeImpl(options.context, options.runtimeFlags, options.fiberRefs), runtime2 = () => withFiberRuntime((state, status3) => succeed(new RuntimeImpl(state.getFiberRef(currentContext), status3.runtimeFlags, state.getFiberRefs()))), defaultRuntimeFlags, defaultRuntime, unsafeRunEffect, unsafeForkEffect, unsafeRunPromiseEffect, unsafeRunPromiseExitEffect, unsafeRunSyncEffect, unsafeRunSyncExitEffect, asyncEffect = (register) => suspend(() => {
|
|
22188
|
+
}, unsafeRunSyncExit, unsafeRunPromise, unsafeRunPromiseExit, make36 = (options) => new RuntimeImpl(options.context, options.runtimeFlags, options.fiberRefs), runtime2 = () => withFiberRuntime((state, status3) => succeed(new RuntimeImpl(state.getFiberRef(currentContext), status3.runtimeFlags, state.getFiberRefs()))), defaultRuntimeFlags, defaultRuntime, updateRuntimeFlags2, disableRuntimeFlag, enableRuntimeFlag, updateContext2, provideService2, updateFiberRefs2, setFiberRef, deleteFiberRef, unsafeRunEffect, unsafeForkEffect, unsafeRunPromiseEffect, unsafeRunPromiseExitEffect, unsafeRunSyncEffect, unsafeRunSyncExitEffect, asyncEffect = (register) => suspend(() => {
|
|
22186
22189
|
let cleanup = undefined;
|
|
22187
22190
|
return flatMap7(deferredMake(), (deferred) => flatMap7(runtime2(), (runtime3) => uninterruptibleMask((restore) => zipRight(fork(restore(matchCauseEffect(register((cb) => unsafeRunCallback(runtime3)(intoDeferred(cb, deferred))), {
|
|
22188
22191
|
onFailure: (cause2) => deferredFailCause(deferred, cause2),
|
|
@@ -22203,6 +22206,7 @@ var init_runtime = __esm(() => {
|
|
|
22203
22206
|
init_Inspectable();
|
|
22204
22207
|
init_Option();
|
|
22205
22208
|
init_Pipeable();
|
|
22209
|
+
init_Predicate();
|
|
22206
22210
|
init_Scheduler();
|
|
22207
22211
|
init_Scope();
|
|
22208
22212
|
init_cause();
|
|
@@ -22355,6 +22359,30 @@ var init_runtime = __esm(() => {
|
|
|
22355
22359
|
runtimeFlags: defaultRuntimeFlags,
|
|
22356
22360
|
fiberRefs: /* @__PURE__ */ empty20()
|
|
22357
22361
|
});
|
|
22362
|
+
updateRuntimeFlags2 = /* @__PURE__ */ dual(2, (self2, f) => make36({
|
|
22363
|
+
context: self2.context,
|
|
22364
|
+
runtimeFlags: f(self2.runtimeFlags),
|
|
22365
|
+
fiberRefs: self2.fiberRefs
|
|
22366
|
+
}));
|
|
22367
|
+
disableRuntimeFlag = /* @__PURE__ */ dual(2, (self2, flag) => updateRuntimeFlags2(self2, disable2(flag)));
|
|
22368
|
+
enableRuntimeFlag = /* @__PURE__ */ dual(2, (self2, flag) => updateRuntimeFlags2(self2, enable2(flag)));
|
|
22369
|
+
updateContext2 = /* @__PURE__ */ dual(2, (self2, f) => make36({
|
|
22370
|
+
context: f(self2.context),
|
|
22371
|
+
runtimeFlags: self2.runtimeFlags,
|
|
22372
|
+
fiberRefs: self2.fiberRefs
|
|
22373
|
+
}));
|
|
22374
|
+
provideService2 = /* @__PURE__ */ dual(3, (self2, tag, service) => updateContext2(self2, add4(tag, service)));
|
|
22375
|
+
updateFiberRefs2 = /* @__PURE__ */ dual(2, (self2, f) => make36({
|
|
22376
|
+
context: self2.context,
|
|
22377
|
+
runtimeFlags: self2.runtimeFlags,
|
|
22378
|
+
fiberRefs: f(self2.fiberRefs)
|
|
22379
|
+
}));
|
|
22380
|
+
setFiberRef = /* @__PURE__ */ dual(3, (self2, fiberRef, value) => updateFiberRefs2(self2, updateAs2({
|
|
22381
|
+
fiberId: none4,
|
|
22382
|
+
fiberRef,
|
|
22383
|
+
value
|
|
22384
|
+
})));
|
|
22385
|
+
deleteFiberRef = /* @__PURE__ */ dual(2, (self2, fiberRef) => updateFiberRefs2(self2, delete_2(fiberRef)));
|
|
22358
22386
|
unsafeRunEffect = /* @__PURE__ */ unsafeRunCallback(defaultRuntime);
|
|
22359
22387
|
unsafeForkEffect = /* @__PURE__ */ unsafeFork2(defaultRuntime);
|
|
22360
22388
|
unsafeRunPromiseEffect = /* @__PURE__ */ unsafeRunPromise(defaultRuntime);
|
|
@@ -23824,7 +23852,7 @@ var ScheduleSymbolKey = "effect/Schedule", ScheduleTypeId, isSchedule = (u) => h
|
|
|
23824
23852
|
const end3 = endOfMinute(minute0);
|
|
23825
23853
|
const interval = make33(start3, end3);
|
|
23826
23854
|
return succeed([[end3, n + 1], n, continueWith2(interval)]);
|
|
23827
|
-
}), modifyDelay, modifyDelayEffect, onDecision, passthrough2 = (self2) => makeWithState(self2.initial, (now, input, state) => pipe(self2.step(now, input, state), map9(([state2, _, decision]) => [state2, input, decision]))), provideContext3,
|
|
23855
|
+
}), modifyDelay, modifyDelayEffect, onDecision, passthrough2 = (self2) => makeWithState(self2.initial, (now, input, state) => pipe(self2.step(now, input, state), map9(([state2, _, decision]) => [state2, input, decision]))), provideContext3, provideService3, recurUntil = (f) => untilInput(identity2(), f), recurUntilEffect = (f) => untilInputEffect(identity2(), f), recurUntilOption = (pf) => untilOutput(map14(identity2(), pf), isSome2), recurUpTo = (durationInput) => {
|
|
23828
23856
|
const duration2 = decode(durationInput);
|
|
23829
23857
|
return whileOutput(elapsed, (elapsed) => lessThan2(elapsed, duration2));
|
|
23830
23858
|
}, recurWhile = (f) => whileInput(identity2(), f), recurWhileEffect = (f) => whileInputEffect(identity2(), f), recurs = (n) => whileOutput(forever2, (out) => out < n), reduce10, reduceEffect2, repetitions = (self2) => reduce10(self2, 0, (n, _) => n + 1), resetAfter, resetWhen, run, runLoop = (self2, now, inputs, state, acc) => {
|
|
@@ -24160,7 +24188,7 @@ var init_schedule = __esm(() => {
|
|
|
24160
24188
|
})));
|
|
24161
24189
|
onDecision = /* @__PURE__ */ dual(2, (self2, f) => makeWithState(self2.initial, (now, input, state) => flatMap7(self2.step(now, input, state), ([state2, out, decision]) => as2(f(out, decision), [state2, out, decision]))));
|
|
24162
24190
|
provideContext3 = /* @__PURE__ */ dual(2, (self2, context3) => makeWithState(self2.initial, (now, input, state) => provideContext(self2.step(now, input, state), context3)));
|
|
24163
|
-
|
|
24191
|
+
provideService3 = /* @__PURE__ */ dual(3, (self2, tag, service2) => makeWithState(self2.initial, (now, input, state) => contextWithEffect((env) => provideContext(self2.step(now, input, state), add4(env, tag, service2)))));
|
|
24164
24192
|
reduce10 = /* @__PURE__ */ dual(3, (self2, zero2, f) => reduceEffect2(self2, zero2, (z, out) => sync(() => f(z, out))));
|
|
24165
24193
|
reduceEffect2 = /* @__PURE__ */ dual(3, (self2, zero2, f) => makeWithState([self2.initial, zero2], (now, input, [s, z]) => flatMap7(self2.step(now, input, s), ([s2, out, decision]) => isDone4(decision) ? succeed([[s2, z], z, decision]) : map9(f(z, out), (z2) => [[s2, z2], z, decision]))));
|
|
24166
24194
|
resetAfter = /* @__PURE__ */ dual(2, (self2, durationInput) => {
|
|
@@ -25051,7 +25079,7 @@ __export(exports_Effect, {
|
|
|
25051
25079
|
using: () => using2,
|
|
25052
25080
|
useSpan: () => useSpan2,
|
|
25053
25081
|
updateService: () => updateService2,
|
|
25054
|
-
updateFiberRefs: () =>
|
|
25082
|
+
updateFiberRefs: () => updateFiberRefs3,
|
|
25055
25083
|
unsandbox: () => unsandbox2,
|
|
25056
25084
|
unsafeMakeSemaphore: () => unsafeMakeSemaphore2,
|
|
25057
25085
|
unsafeMakeLatch: () => unsafeMakeLatch2,
|
|
@@ -25140,7 +25168,7 @@ __export(exports_Effect, {
|
|
|
25140
25168
|
raceAll: () => raceAll2,
|
|
25141
25169
|
race: () => race2,
|
|
25142
25170
|
provideServiceEffect: () => provideServiceEffect2,
|
|
25143
|
-
provideService: () =>
|
|
25171
|
+
provideService: () => provideService4,
|
|
25144
25172
|
provide: () => provide2,
|
|
25145
25173
|
promise: () => promise2,
|
|
25146
25174
|
patchRuntimeFlags: () => patchRuntimeFlags,
|
|
@@ -25391,7 +25419,7 @@ ${endStackCall}`;
|
|
|
25391
25419
|
};
|
|
25392
25420
|
return withSpan3(effect, options.spanName, opts);
|
|
25393
25421
|
}
|
|
25394
|
-
var EffectTypeId3, isEffect2, cachedWithTTL, cachedInvalidateWithTTL2, cached3, cachedFunction2, once3, all6, allWith2, allSuccesses2, dropUntil2, dropWhile2, takeUntil2, takeWhile2, every5, exists2, filter7, filterMap4, findFirst4, forEach5, head4, mergeAll5, partition4, reduce11, reduceWhile2, reduceRight3, reduceEffect3, replicate2, replicateEffect2, validateAll2, validateFirst2, async, asyncEffect2, custom2, withFiberRuntime2, fail9, failSync3, failCause8, failCauseSync3, die5, dieMessage2, dieSync3, gen2, never4, none9, promise2, succeed9, succeedNone2, succeedSome2, suspend3, sync4, _void, yieldNow4, _catch2, catchAll3, catchAllCause3, catchAllDefect2, catchIf2, catchSome2, catchSomeCause2, catchSomeDefect2, catchTag2, catchTags2, cause2, eventually2, ignore2, ignoreLogged2, parallelErrors2, sandbox2, retry2, withExecutionPlan2, retryOrElse, try_2, tryMap2, tryMapPromise2, tryPromise2, unsandbox2, allowInterrupt2, checkInterruptible2, disconnect2, interrupt7, interruptWith2, interruptible4, interruptibleMask2, onInterrupt2, uninterruptible2, uninterruptibleMask3, liftPredicate2, as5, asSome2, asSomeError2, asVoid3, flip2, flipWith2, map15, mapAccum3, mapBoth3, mapError3, mapErrorCause2, merge7, negate2, acquireRelease2, acquireReleaseInterruptible2, acquireUseRelease2, addFinalizer2, ensuring3, onError2, onExit3, parallelFinalizers2, sequentialFinalizers2, finalizersMask2, scope3, scopeWith2, scopedWith2, scoped3, using2, withEarlyRelease2, awaitAllChildren2, daemonChildren2, descriptor2, descriptorWith2, diffFiberRefs2, ensuringChild2, ensuringChildren2, fiberId2, fiberIdWith2, fork3, forkDaemon2, forkAll2, forkIn2, forkScoped2, forkWithErrorHandler2, fromFiber2, fromFiberEffect2, supervised2, transplant2, withConcurrency2, withScheduler2, withSchedulingPriority2, withMaxOpsBeforeYield2, clock2, clockWith4, withClockScoped2, withClock2, console3, consoleWith2, withConsoleScoped2, withConsole2, delay2, sleep4, timed2, timedWith2, timeout2, timeoutOption2, timeoutFail2, timeoutFailCause2, timeoutTo2, configProviderWith2, withConfigProvider2, withConfigProviderScoped2, context3, contextWith2, contextWithEffect2, mapInputContext3, provide2,
|
|
25422
|
+
var EffectTypeId3, isEffect2, cachedWithTTL, cachedInvalidateWithTTL2, cached3, cachedFunction2, once3, all6, allWith2, allSuccesses2, dropUntil2, dropWhile2, takeUntil2, takeWhile2, every5, exists2, filter7, filterMap4, findFirst4, forEach5, head4, mergeAll5, partition4, reduce11, reduceWhile2, reduceRight3, reduceEffect3, replicate2, replicateEffect2, validateAll2, validateFirst2, async, asyncEffect2, custom2, withFiberRuntime2, fail9, failSync3, failCause8, failCauseSync3, die5, dieMessage2, dieSync3, gen2, never4, none9, promise2, succeed9, succeedNone2, succeedSome2, suspend3, sync4, _void, yieldNow4, _catch2, catchAll3, catchAllCause3, catchAllDefect2, catchIf2, catchSome2, catchSomeCause2, catchSomeDefect2, catchTag2, catchTags2, cause2, eventually2, ignore2, ignoreLogged2, parallelErrors2, sandbox2, retry2, withExecutionPlan2, retryOrElse, try_2, tryMap2, tryMapPromise2, tryPromise2, unsandbox2, allowInterrupt2, checkInterruptible2, disconnect2, interrupt7, interruptWith2, interruptible4, interruptibleMask2, onInterrupt2, uninterruptible2, uninterruptibleMask3, liftPredicate2, as5, asSome2, asSomeError2, asVoid3, flip2, flipWith2, map15, mapAccum3, mapBoth3, mapError3, mapErrorCause2, merge7, negate2, acquireRelease2, acquireReleaseInterruptible2, acquireUseRelease2, addFinalizer2, ensuring3, onError2, onExit3, parallelFinalizers2, sequentialFinalizers2, finalizersMask2, scope3, scopeWith2, scopedWith2, scoped3, using2, withEarlyRelease2, awaitAllChildren2, daemonChildren2, descriptor2, descriptorWith2, diffFiberRefs2, ensuringChild2, ensuringChildren2, fiberId2, fiberIdWith2, fork3, forkDaemon2, forkAll2, forkIn2, forkScoped2, forkWithErrorHandler2, fromFiber2, fromFiberEffect2, supervised2, transplant2, withConcurrency2, withScheduler2, withSchedulingPriority2, withMaxOpsBeforeYield2, clock2, clockWith4, withClockScoped2, withClock2, console3, consoleWith2, withConsoleScoped2, withConsole2, delay2, sleep4, timed2, timedWith2, timeout2, timeoutOption2, timeoutFail2, timeoutFailCause2, timeoutTo2, configProviderWith2, withConfigProvider2, withConfigProviderScoped2, context3, contextWith2, contextWithEffect2, mapInputContext3, provide2, provideService4, provideServiceEffect2, serviceFunction2, serviceFunctionEffect2, serviceFunctions2, serviceConstants2, serviceMembers2, serviceOption2, serviceOptional2, updateService2, Do2, bind3, bindAll2, bindTo3, let_3, option2, either4, exit2, intoDeferred2, if_2, filterOrDie2, filterOrDieMessage2, filterOrElse2, filterOrFail2, filterEffectOrElse2, filterEffectOrFail2, unless2, unlessEffect2, when2, whenEffect2, whenFiberRef2, whenRef2, flatMap11, andThen6, flatten8, race2, raceAll2, raceFirst2, raceWith2, summarized2, tap3, tapBoth2, tapDefect2, tapError3, tapErrorTag2, tapErrorCause3, forever3, iterate2, loop2, repeat, repeatN2, repeatOrElse, schedule, scheduleForked2, scheduleFrom, whileLoop2, getFiberRefs, inheritFiberRefs2, locally, locallyWith, locallyScoped, locallyScopedWith, patchFiberRefs2, setFiberRefs2, updateFiberRefs3, isFailure4, isSuccess3, match15, matchCause3, matchCauseEffect3, matchEffect2, log3, logWithLevel2 = (level, ...message) => logWithLevel(level)(...message), logTrace2, logDebug2, logInfo2, logWarning2, logError2, logFatal2, withLogSpan2, annotateLogs3, annotateLogsScoped2, logAnnotations2, withUnhandledErrorLogLevel2, whenLogLevel2, orDie3, orDieWith2, orElse5, orElseFail2, orElseSucceed2, firstSuccessOf2, random3, randomWith2, withRandom2, withRandomFixed, withRandomScoped2, runtime3, getRuntimeFlags, patchRuntimeFlags, withRuntimeFlagsPatch, withRuntimeFlagsPatchScoped, tagMetrics2, labelMetrics2, tagMetricsScoped2, labelMetricsScoped2, metricLabels2, withMetric2, unsafeMakeSemaphore2, makeSemaphore2, unsafeMakeLatch2, makeLatch2, runFork2, runCallback, runPromise, runPromiseExit, runSync, runSyncExit, validate2, validateWith2, zip5, zipLeft4, zipRight4, zipWith7, ap, blocked2, runRequestBlock2, step3, request, cacheRequestResult, withRequestBatching2, withRequestCaching2, withRequestCache2, tracer2, tracerWith4, withTracer2, withTracerScoped2, withTracerEnabled2, withTracerTiming2, annotateSpans3, annotateCurrentSpan2, currentSpan2, currentPropagatedSpan2, currentParentSpan2, spanAnnotations2, spanLinks2, linkSpans2, linkSpanCurrent2, makeSpan2, makeSpanScoped2, useSpan2, withSpan3, functionWithSpan2, withSpanScoped2, withParentSpan3, fromNullable3, optionFromOptional2, transposeOption = (self2) => {
|
|
25395
25423
|
return isNone(self2) ? succeedNone2 : map15(self2.value, some);
|
|
25396
25424
|
}, transposeMapOption, makeTagProxy = (TagClass) => {
|
|
25397
25425
|
const cache = new Map;
|
|
@@ -25777,7 +25805,7 @@ var init_Effect = __esm(() => {
|
|
|
25777
25805
|
contextWithEffect2 = contextWithEffect;
|
|
25778
25806
|
mapInputContext3 = mapInputContext;
|
|
25779
25807
|
provide2 = effect_provide;
|
|
25780
|
-
|
|
25808
|
+
provideService4 = provideService;
|
|
25781
25809
|
provideServiceEffect2 = provideServiceEffect;
|
|
25782
25810
|
serviceFunction2 = serviceFunction;
|
|
25783
25811
|
serviceFunctionEffect2 = serviceFunctionEffect;
|
|
@@ -25841,7 +25869,7 @@ var init_Effect = __esm(() => {
|
|
|
25841
25869
|
locallyScopedWith = fiberRefLocallyScopedWith;
|
|
25842
25870
|
patchFiberRefs2 = patchFiberRefs;
|
|
25843
25871
|
setFiberRefs2 = setFiberRefs;
|
|
25844
|
-
|
|
25872
|
+
updateFiberRefs3 = updateFiberRefs;
|
|
25845
25873
|
isFailure4 = isFailure3;
|
|
25846
25874
|
isSuccess3 = isSuccess;
|
|
25847
25875
|
match15 = match9;
|
|
@@ -26133,6 +26161,160 @@ var init_Layer = __esm(() => {
|
|
|
26133
26161
|
updateService3 = /* @__PURE__ */ dual(3, (layer, tag, f) => provide3(layer, map16(context4(), (c) => add4(c, tag, f(unsafeGet4(c, tag))))));
|
|
26134
26162
|
});
|
|
26135
26163
|
|
|
26164
|
+
// ../../node_modules/.pnpm/effect@3.21.2/node_modules/effect/dist/esm/internal/managedRuntime.js
|
|
26165
|
+
function provide4(managed, effect2) {
|
|
26166
|
+
return flatMap7(managed.runtimeEffect, (rt) => withFiberRuntime((fiber) => {
|
|
26167
|
+
fiber.setFiberRefs(rt.fiberRefs);
|
|
26168
|
+
fiber.currentRuntimeFlags = rt.runtimeFlags;
|
|
26169
|
+
return provideContext(effect2, rt.context);
|
|
26170
|
+
}));
|
|
26171
|
+
}
|
|
26172
|
+
var isManagedRuntime = (u) => hasProperty(u, TypeId12), ManagedRuntimeProto, make39 = (layer, memoMap) => {
|
|
26173
|
+
memoMap = memoMap ?? unsafeMakeMemoMap();
|
|
26174
|
+
const scope5 = unsafeRunSyncEffect(scopeMake());
|
|
26175
|
+
let buildFiber;
|
|
26176
|
+
const runtimeEffect = suspend(() => {
|
|
26177
|
+
if (!buildFiber) {
|
|
26178
|
+
const scheduler = new SyncScheduler;
|
|
26179
|
+
buildFiber = unsafeForkEffect(tap(extend2(toRuntimeWithMemoMap(layer, memoMap), scope5), (rt) => {
|
|
26180
|
+
self2.cachedRuntime = rt;
|
|
26181
|
+
}), {
|
|
26182
|
+
scope: scope5,
|
|
26183
|
+
scheduler
|
|
26184
|
+
});
|
|
26185
|
+
scheduler.flush();
|
|
26186
|
+
}
|
|
26187
|
+
return flatten4(buildFiber.await);
|
|
26188
|
+
});
|
|
26189
|
+
const self2 = Object.assign(Object.create(ManagedRuntimeProto), {
|
|
26190
|
+
memoMap,
|
|
26191
|
+
scope: scope5,
|
|
26192
|
+
runtimeEffect,
|
|
26193
|
+
cachedRuntime: undefined,
|
|
26194
|
+
runtime() {
|
|
26195
|
+
return self2.cachedRuntime === undefined ? unsafeRunPromiseEffect(self2.runtimeEffect) : Promise.resolve(self2.cachedRuntime);
|
|
26196
|
+
},
|
|
26197
|
+
dispose() {
|
|
26198
|
+
return unsafeRunPromiseEffect(self2.disposeEffect);
|
|
26199
|
+
},
|
|
26200
|
+
disposeEffect: suspend(() => {
|
|
26201
|
+
self2.runtimeEffect = die2("ManagedRuntime disposed");
|
|
26202
|
+
self2.cachedRuntime = undefined;
|
|
26203
|
+
return close(self2.scope, exitVoid);
|
|
26204
|
+
}),
|
|
26205
|
+
runFork(effect2, options) {
|
|
26206
|
+
return self2.cachedRuntime === undefined ? unsafeForkEffect(provide4(self2, effect2), options) : unsafeFork2(self2.cachedRuntime)(effect2, options);
|
|
26207
|
+
},
|
|
26208
|
+
runSyncExit(effect2) {
|
|
26209
|
+
return self2.cachedRuntime === undefined ? unsafeRunSyncExitEffect(provide4(self2, effect2)) : unsafeRunSyncExit(self2.cachedRuntime)(effect2);
|
|
26210
|
+
},
|
|
26211
|
+
runSync(effect2) {
|
|
26212
|
+
return self2.cachedRuntime === undefined ? unsafeRunSyncEffect(provide4(self2, effect2)) : unsafeRunSync(self2.cachedRuntime)(effect2);
|
|
26213
|
+
},
|
|
26214
|
+
runPromiseExit(effect2, options) {
|
|
26215
|
+
return self2.cachedRuntime === undefined ? unsafeRunPromiseExitEffect(provide4(self2, effect2), options) : unsafeRunPromiseExit(self2.cachedRuntime)(effect2, options);
|
|
26216
|
+
},
|
|
26217
|
+
runCallback(effect2, options) {
|
|
26218
|
+
return self2.cachedRuntime === undefined ? unsafeRunCallback(defaultRuntime)(provide4(self2, effect2), options) : unsafeRunCallback(self2.cachedRuntime)(effect2, options);
|
|
26219
|
+
},
|
|
26220
|
+
runPromise(effect2, options) {
|
|
26221
|
+
return self2.cachedRuntime === undefined ? unsafeRunPromiseEffect(provide4(self2, effect2), options) : unsafeRunPromise(self2.cachedRuntime)(effect2, options);
|
|
26222
|
+
}
|
|
26223
|
+
});
|
|
26224
|
+
return self2;
|
|
26225
|
+
};
|
|
26226
|
+
var init_managedRuntime = __esm(() => {
|
|
26227
|
+
init_Effectable();
|
|
26228
|
+
init_Pipeable();
|
|
26229
|
+
init_Predicate();
|
|
26230
|
+
init_Scheduler();
|
|
26231
|
+
init_Scope();
|
|
26232
|
+
init_core();
|
|
26233
|
+
init_fiberRuntime();
|
|
26234
|
+
init_layer();
|
|
26235
|
+
init_circular2();
|
|
26236
|
+
init_runtime();
|
|
26237
|
+
ManagedRuntimeProto = {
|
|
26238
|
+
...CommitPrototype2,
|
|
26239
|
+
[TypeId12]: TypeId12,
|
|
26240
|
+
pipe() {
|
|
26241
|
+
return pipeArguments(this, arguments);
|
|
26242
|
+
},
|
|
26243
|
+
commit() {
|
|
26244
|
+
return this.runtimeEffect;
|
|
26245
|
+
}
|
|
26246
|
+
};
|
|
26247
|
+
});
|
|
26248
|
+
|
|
26249
|
+
// ../../node_modules/.pnpm/effect@3.21.2/node_modules/effect/dist/esm/ManagedRuntime.js
|
|
26250
|
+
var exports_ManagedRuntime = {};
|
|
26251
|
+
__export(exports_ManagedRuntime, {
|
|
26252
|
+
make: () => make40,
|
|
26253
|
+
isManagedRuntime: () => isManagedRuntime2,
|
|
26254
|
+
TypeId: () => TypeId17
|
|
26255
|
+
});
|
|
26256
|
+
var TypeId17, isManagedRuntime2, make40;
|
|
26257
|
+
var init_ManagedRuntime = __esm(() => {
|
|
26258
|
+
init_managedRuntime();
|
|
26259
|
+
init_circular2();
|
|
26260
|
+
TypeId17 = TypeId12;
|
|
26261
|
+
isManagedRuntime2 = isManagedRuntime;
|
|
26262
|
+
make40 = make39;
|
|
26263
|
+
});
|
|
26264
|
+
|
|
26265
|
+
// ../../node_modules/.pnpm/effect@3.21.2/node_modules/effect/dist/esm/Runtime.js
|
|
26266
|
+
var exports_Runtime = {};
|
|
26267
|
+
__export(exports_Runtime, {
|
|
26268
|
+
updateRuntimeFlags: () => updateRuntimeFlags3,
|
|
26269
|
+
updateFiberRefs: () => updateFiberRefs4,
|
|
26270
|
+
updateContext: () => updateContext3,
|
|
26271
|
+
setFiberRef: () => setFiberRef2,
|
|
26272
|
+
runSyncExit: () => runSyncExit2,
|
|
26273
|
+
runSync: () => runSync2,
|
|
26274
|
+
runPromiseExit: () => runPromiseExit2,
|
|
26275
|
+
runPromise: () => runPromise2,
|
|
26276
|
+
runFork: () => runFork3,
|
|
26277
|
+
runCallback: () => runCallback2,
|
|
26278
|
+
provideService: () => provideService5,
|
|
26279
|
+
makeFiberFailure: () => makeFiberFailure,
|
|
26280
|
+
make: () => make41,
|
|
26281
|
+
isFiberFailure: () => isFiberFailure2,
|
|
26282
|
+
isAsyncFiberException: () => isAsyncFiberException2,
|
|
26283
|
+
enableRuntimeFlag: () => enableRuntimeFlag2,
|
|
26284
|
+
disableRuntimeFlag: () => disableRuntimeFlag2,
|
|
26285
|
+
deleteFiberRef: () => deleteFiberRef2,
|
|
26286
|
+
defaultRuntimeFlags: () => defaultRuntimeFlags2,
|
|
26287
|
+
defaultRuntime: () => defaultRuntime2,
|
|
26288
|
+
FiberFailureId: () => FiberFailureId2,
|
|
26289
|
+
FiberFailureCauseId: () => FiberFailureCauseId2
|
|
26290
|
+
});
|
|
26291
|
+
var runFork3, runSyncExit2, runSync2, runCallback2, runPromise2, runPromiseExit2, defaultRuntime2, defaultRuntimeFlags2, make41, FiberFailureId2, FiberFailureCauseId2, isAsyncFiberException2, isFiberFailure2, makeFiberFailure, updateRuntimeFlags3, enableRuntimeFlag2, disableRuntimeFlag2, updateContext3, provideService5, updateFiberRefs4, setFiberRef2, deleteFiberRef2;
|
|
26292
|
+
var init_Runtime = __esm(() => {
|
|
26293
|
+
init_runtime();
|
|
26294
|
+
runFork3 = unsafeFork2;
|
|
26295
|
+
runSyncExit2 = unsafeRunSyncExit;
|
|
26296
|
+
runSync2 = unsafeRunSync;
|
|
26297
|
+
runCallback2 = unsafeRunCallback;
|
|
26298
|
+
runPromise2 = unsafeRunPromise;
|
|
26299
|
+
runPromiseExit2 = unsafeRunPromiseExit;
|
|
26300
|
+
defaultRuntime2 = defaultRuntime;
|
|
26301
|
+
defaultRuntimeFlags2 = defaultRuntimeFlags;
|
|
26302
|
+
make41 = make36;
|
|
26303
|
+
FiberFailureId2 = /* @__PURE__ */ Symbol.for("effect/Runtime/FiberFailure");
|
|
26304
|
+
FiberFailureCauseId2 = FiberFailureCauseId;
|
|
26305
|
+
isAsyncFiberException2 = isAsyncFiberException;
|
|
26306
|
+
isFiberFailure2 = isFiberFailure;
|
|
26307
|
+
makeFiberFailure = fiberFailure;
|
|
26308
|
+
updateRuntimeFlags3 = updateRuntimeFlags2;
|
|
26309
|
+
enableRuntimeFlag2 = enableRuntimeFlag;
|
|
26310
|
+
disableRuntimeFlag2 = disableRuntimeFlag;
|
|
26311
|
+
updateContext3 = updateContext2;
|
|
26312
|
+
provideService5 = provideService2;
|
|
26313
|
+
updateFiberRefs4 = updateFiberRefs2;
|
|
26314
|
+
setFiberRef2 = setFiberRef;
|
|
26315
|
+
deleteFiberRef2 = deleteFiberRef;
|
|
26316
|
+
});
|
|
26317
|
+
|
|
26136
26318
|
// ../../node_modules/.pnpm/effect@3.21.2/node_modules/effect/dist/esm/Schedule.js
|
|
26137
26319
|
var exports_Schedule = {};
|
|
26138
26320
|
__export(exports_Schedule, {
|
|
@@ -26173,7 +26355,7 @@ __export(exports_Schedule, {
|
|
|
26173
26355
|
recurUntilOption: () => recurUntilOption2,
|
|
26174
26356
|
recurUntilEffect: () => recurUntilEffect2,
|
|
26175
26357
|
recurUntil: () => recurUntil2,
|
|
26176
|
-
provideService: () =>
|
|
26358
|
+
provideService: () => provideService6,
|
|
26177
26359
|
provideContext: () => provideContext4,
|
|
26178
26360
|
passthrough: () => passthrough4,
|
|
26179
26361
|
once: () => once4,
|
|
@@ -26238,7 +26420,7 @@ __export(exports_Schedule, {
|
|
|
26238
26420
|
ScheduleDriverTypeId: () => ScheduleDriverTypeId2,
|
|
26239
26421
|
CurrentIterationMetadata: () => CurrentIterationMetadata2
|
|
26240
26422
|
});
|
|
26241
|
-
var ScheduleTypeId2, ScheduleDriverTypeId2, makeWithState2, isSchedule2, addDelay2, addDelayEffect2, andThen7, andThenEither2, as6, asVoid4, bothInOut2, check2, checkEffect2, collectAllInputs2, collectAllOutputs2, collectUntil2, collectUntilEffect2, collectWhile2, collectWhileEffect2, compose2, mapInput4, mapInputEffect2, mapInputContext4, count2, cron2, secondOfMinute2, minuteOfHour2, hourOfDay2, dayOfMonth2, dayOfWeek2, delayed2, delayedEffect2, delayedSchedule2, delays2, mapBoth4, mapBothEffect2, driver2, duration2, either5, eitherWith2, elapsed2, ensuring4, exponential3, fibonacci2, fixed4, forever4, fromDelay2, fromDelays2, fromFunction4, identity3, passthrough4, intersect6, intersectWith2, jittered2, jitteredWith2, linear2, map17, mapEffect4, modifyDelay2, modifyDelayEffect2, onDecision2, once4, provideContext4,
|
|
26423
|
+
var ScheduleTypeId2, ScheduleDriverTypeId2, makeWithState2, isSchedule2, addDelay2, addDelayEffect2, andThen7, andThenEither2, as6, asVoid4, bothInOut2, check2, checkEffect2, collectAllInputs2, collectAllOutputs2, collectUntil2, collectUntilEffect2, collectWhile2, collectWhileEffect2, compose2, mapInput4, mapInputEffect2, mapInputContext4, count2, cron2, secondOfMinute2, minuteOfHour2, hourOfDay2, dayOfMonth2, dayOfWeek2, delayed2, delayedEffect2, delayedSchedule2, delays2, mapBoth4, mapBothEffect2, driver2, duration2, either5, eitherWith2, elapsed2, ensuring4, exponential3, fibonacci2, fixed4, forever4, fromDelay2, fromDelays2, fromFunction4, identity3, passthrough4, intersect6, intersectWith2, jittered2, jitteredWith2, linear2, map17, mapEffect4, modifyDelay2, modifyDelayEffect2, onDecision2, once4, provideContext4, provideService6, recurUntil2, recurUntilEffect2, recurUntilOption2, recurUpTo2, recurWhile2, recurWhileEffect2, recurs2, reduce12, reduceEffect4, repeatForever, repetitions2, resetAfter2, resetWhen2, run2, spaced2, stop2, succeed11, sync6, tapInput2, tapOutput2, unfold3, union9, unionWith3, untilInput2, untilInputEffect2, untilOutput2, untilOutputEffect2, upTo2, whileInput2, whileInputEffect2, whileOutput2, whileOutputEffect2, windowed2, zipLeft5, zipRight5, zipWith9, CurrentIterationMetadata2;
|
|
26242
26424
|
var init_Schedule = __esm(() => {
|
|
26243
26425
|
init_schedule();
|
|
26244
26426
|
ScheduleTypeId2 = ScheduleTypeId;
|
|
@@ -26304,7 +26486,7 @@ var init_Schedule = __esm(() => {
|
|
|
26304
26486
|
onDecision2 = onDecision;
|
|
26305
26487
|
once4 = once2;
|
|
26306
26488
|
provideContext4 = provideContext3;
|
|
26307
|
-
|
|
26489
|
+
provideService6 = provideService3;
|
|
26308
26490
|
recurUntil2 = recurUntil;
|
|
26309
26491
|
recurUntilEffect2 = recurUntilEffect;
|
|
26310
26492
|
recurUntilOption2 = recurUntilOption;
|
|
@@ -26352,7 +26534,9 @@ var init_esm = __esm(() => {
|
|
|
26352
26534
|
init_Effect();
|
|
26353
26535
|
init_Fiber();
|
|
26354
26536
|
init_Layer();
|
|
26537
|
+
init_ManagedRuntime();
|
|
26355
26538
|
init_Ref();
|
|
26539
|
+
init_Runtime();
|
|
26356
26540
|
init_Schedule();
|
|
26357
26541
|
});
|
|
26358
26542
|
|
|
@@ -27281,21 +27465,30 @@ var init_pi_agent_service = __esm(() => {
|
|
|
27281
27465
|
async resumeFromDaemonMemory(options, stored) {
|
|
27282
27466
|
const { prompt, systemPrompt, model, context: context5 } = options;
|
|
27283
27467
|
const modelForSession = model ?? stored.model;
|
|
27284
|
-
|
|
27285
|
-
|
|
27286
|
-
|
|
27287
|
-
|
|
27288
|
-
|
|
27289
|
-
|
|
27290
|
-
|
|
27291
|
-
|
|
27292
|
-
|
|
27293
|
-
childProcess,
|
|
27294
|
-
|
|
27295
|
-
|
|
27296
|
-
|
|
27297
|
-
|
|
27298
|
-
|
|
27468
|
+
let childProcess;
|
|
27469
|
+
try {
|
|
27470
|
+
childProcess = this.spawnPiRpcProcess({
|
|
27471
|
+
workingDir: stored.workingDir,
|
|
27472
|
+
systemPrompt,
|
|
27473
|
+
model: modelForSession,
|
|
27474
|
+
sessionId: stored.harnessSessionId
|
|
27475
|
+
});
|
|
27476
|
+
await this.waitForSpawnReady(childProcess);
|
|
27477
|
+
await this.writePrompt(childProcess, prompt);
|
|
27478
|
+
return this.wireRpcProcess({
|
|
27479
|
+
childProcess,
|
|
27480
|
+
context: context5,
|
|
27481
|
+
workingDir: stored.workingDir,
|
|
27482
|
+
model: modelForSession,
|
|
27483
|
+
harnessSessionId: stored.harnessSessionId
|
|
27484
|
+
});
|
|
27485
|
+
} catch (err) {
|
|
27486
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
27487
|
+
process.stderr.write(`[${new Date().toISOString()}] role:${context5.role} daemon-resume-fallback] ${reason} — cold spawning
|
|
27488
|
+
`);
|
|
27489
|
+
childProcess?.kill();
|
|
27490
|
+
return this.spawn(options);
|
|
27491
|
+
}
|
|
27299
27492
|
}
|
|
27300
27493
|
async resumeTurn(pid, prompt) {
|
|
27301
27494
|
const child = this.childProcesses.get(pid);
|
|
@@ -28901,9 +29094,12 @@ ${options.prompt}`;
|
|
|
28901
29094
|
local: { cwd: stored.workingDir, settingSources: [] }
|
|
28902
29095
|
}), AGENT_CREATE_TIMEOUT_MS, "Agent.resume");
|
|
28903
29096
|
} catch (err) {
|
|
29097
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
29098
|
+
process.stderr.write(`[${new Date().toISOString()}] role:${context5.role} daemon-resume-fallback] ${reason} — cold spawning
|
|
29099
|
+
`);
|
|
28904
29100
|
keeper.kill();
|
|
28905
29101
|
this.deleteProcess(pid);
|
|
28906
|
-
|
|
29102
|
+
return this.spawn(options);
|
|
28907
29103
|
}
|
|
28908
29104
|
return this.startRunningSession({
|
|
28909
29105
|
pid,
|
|
@@ -31184,13 +31380,23 @@ function writeLogLine(target, options, kind, payload) {
|
|
|
31184
31380
|
`);
|
|
31185
31381
|
options.onLogLine?.(line);
|
|
31186
31382
|
}
|
|
31187
|
-
function
|
|
31188
|
-
if (!error || typeof error !== "object")
|
|
31383
|
+
function isTerminalProviderError(error) {
|
|
31384
|
+
if (!error || typeof error !== "object") {
|
|
31385
|
+
if (typeof error === "string") {
|
|
31386
|
+
return matchesTerminalProviderErrorText(error);
|
|
31387
|
+
}
|
|
31189
31388
|
return false;
|
|
31389
|
+
}
|
|
31190
31390
|
const e = error;
|
|
31191
31391
|
const name = String(e.name ?? e.type ?? "").toLowerCase();
|
|
31192
|
-
const message = String(e.data?.message ?? e.message ?? "").toLowerCase();
|
|
31193
|
-
|
|
31392
|
+
const message = String(e.data?.message ?? e.message ?? e.responseBody ?? "").toLowerCase();
|
|
31393
|
+
const blob = `${name}
|
|
31394
|
+
${message}`;
|
|
31395
|
+
return matchesTerminalProviderErrorText(blob);
|
|
31396
|
+
}
|
|
31397
|
+
function matchesTerminalProviderErrorText(blob) {
|
|
31398
|
+
const text = blob.toLowerCase();
|
|
31399
|
+
return text.includes("usagelimit") || text.includes("usage limit") || text.includes("enable usage from your available balance") || text.includes("rate limit") || text.includes("ratelimit") || text.includes("too many requests") || text.includes("x-ratelimit-exceeded") || text.includes("weekly rate limit") || text.includes("exceeded your weekly");
|
|
31194
31400
|
}
|
|
31195
31401
|
function eventSessionId(event) {
|
|
31196
31402
|
const p = event.properties;
|
|
@@ -31325,8 +31531,8 @@ function startSessionEventForwarder(client4, options) {
|
|
|
31325
31531
|
payload += ` [command: ${props.command}]`;
|
|
31326
31532
|
}
|
|
31327
31533
|
writeLogLine(errorTarget, options, "error", payload);
|
|
31328
|
-
if (
|
|
31329
|
-
writeLogLine(target, options, "agent_end", "reason:
|
|
31534
|
+
if (isTerminalProviderError(err)) {
|
|
31535
|
+
writeLogLine(target, options, "agent_end", "reason: provider_rate_limit");
|
|
31330
31536
|
for (const cb of agentEndCallbacks)
|
|
31331
31537
|
cb();
|
|
31332
31538
|
}
|
|
@@ -31339,6 +31545,11 @@ function startSessionEventForwarder(client4, options) {
|
|
|
31339
31545
|
} catch (err) {
|
|
31340
31546
|
const message = err instanceof Error ? err.message : String(err);
|
|
31341
31547
|
writeLogLine(errorTarget, options, "error", message);
|
|
31548
|
+
if (isTerminalProviderError(err)) {
|
|
31549
|
+
writeLogLine(target, options, "agent_end", "reason: provider_rate_limit");
|
|
31550
|
+
for (const cb of agentEndCallbacks)
|
|
31551
|
+
cb();
|
|
31552
|
+
}
|
|
31342
31553
|
} finally {
|
|
31343
31554
|
doneResolve();
|
|
31344
31555
|
}
|
|
@@ -31424,6 +31635,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31424
31635
|
init_parse_listening_url();
|
|
31425
31636
|
init_session_metadata_store();
|
|
31426
31637
|
OpenCodeSdkAgentService = class OpenCodeSdkAgentService extends BaseCLIAgentService {
|
|
31638
|
+
agentEndCallbacksByPid = new Map;
|
|
31427
31639
|
id = "opencode-sdk";
|
|
31428
31640
|
displayName = "OpenCode (SDK)";
|
|
31429
31641
|
command = OPENCODE_COMMAND2;
|
|
@@ -31462,8 +31674,8 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31462
31674
|
} catch (err) {
|
|
31463
31675
|
console.warn(`[opencode-sdk] session.abort for pid=${pid} sessionId=${meta.sessionId} failed (continuing with SIGTERM):`, err instanceof Error ? err.message : err);
|
|
31464
31676
|
}
|
|
31677
|
+
this.sessionStore.remove(meta.sessionId);
|
|
31465
31678
|
}
|
|
31466
|
-
this.sessionStore.remove(meta.sessionId);
|
|
31467
31679
|
}
|
|
31468
31680
|
await super.stop(pid);
|
|
31469
31681
|
}
|
|
@@ -31548,6 +31760,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31548
31760
|
this.forwarders.delete(pid);
|
|
31549
31761
|
}
|
|
31550
31762
|
this.sessionStore.remove(sessionId);
|
|
31763
|
+
this.agentEndCallbacksByPid.delete(pid);
|
|
31551
31764
|
this.deleteProcess(pid);
|
|
31552
31765
|
cb({ code: code2, signal, context: context5 });
|
|
31553
31766
|
});
|
|
@@ -31556,6 +31769,9 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31556
31769
|
outputCallbacks.push(cb);
|
|
31557
31770
|
},
|
|
31558
31771
|
onAgentEnd: (cb) => {
|
|
31772
|
+
const callbacks = this.agentEndCallbacksByPid.get(pid) ?? [];
|
|
31773
|
+
callbacks.push(cb);
|
|
31774
|
+
this.agentEndCallbacksByPid.set(pid, callbacks);
|
|
31559
31775
|
forwarder?.onAgentEnd(cb);
|
|
31560
31776
|
},
|
|
31561
31777
|
onLogLine: (cb) => {
|
|
@@ -31573,6 +31789,54 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31573
31789
|
}
|
|
31574
31790
|
};
|
|
31575
31791
|
}
|
|
31792
|
+
async startFreshSessionOnServe(args2) {
|
|
31793
|
+
const existingForwarder = this.forwarders.get(args2.pid);
|
|
31794
|
+
existingForwarder?.stop();
|
|
31795
|
+
this.forwarders.delete(args2.pid);
|
|
31796
|
+
const client4 = createOpencodeClient({ baseUrl: args2.baseUrl });
|
|
31797
|
+
const sessionCreateResult = await withTimeout2(client4.session.create({ body: {} }), SESSION_CREATE_TIMEOUT_MS, "session.create");
|
|
31798
|
+
if (!sessionCreateResult.data?.id) {
|
|
31799
|
+
throw new Error("Failed to create session during resume fallback");
|
|
31800
|
+
}
|
|
31801
|
+
const newSessionId2 = sessionCreateResult.data.id;
|
|
31802
|
+
const forwarder = startSessionEventForwarder(client4, {
|
|
31803
|
+
sessionId: newSessionId2,
|
|
31804
|
+
role: args2.context.role
|
|
31805
|
+
});
|
|
31806
|
+
const callbacks = this.agentEndCallbacksByPid.get(args2.pid) ?? [];
|
|
31807
|
+
for (const cb of callbacks) {
|
|
31808
|
+
forwarder.onAgentEnd(cb);
|
|
31809
|
+
}
|
|
31810
|
+
this.forwarders.set(args2.pid, forwarder);
|
|
31811
|
+
if (args2.oldSessionId) {
|
|
31812
|
+
this.sessionStore.remove(args2.oldSessionId);
|
|
31813
|
+
}
|
|
31814
|
+
this.sessionStore.upsert({
|
|
31815
|
+
sessionId: newSessionId2,
|
|
31816
|
+
machineId: args2.context.machineId,
|
|
31817
|
+
chatroomId: args2.context.chatroomId,
|
|
31818
|
+
role: args2.context.role,
|
|
31819
|
+
agentName: args2.agentName,
|
|
31820
|
+
...args2.model ? { model: args2.model } : {},
|
|
31821
|
+
pid: args2.pid,
|
|
31822
|
+
createdAt: new Date().toISOString(),
|
|
31823
|
+
baseUrl: args2.baseUrl
|
|
31824
|
+
});
|
|
31825
|
+
const modelParts = args2.model ? parseModelId(args2.model) : undefined;
|
|
31826
|
+
await withTimeout2(client4.session.promptAsync({
|
|
31827
|
+
path: { id: newSessionId2 },
|
|
31828
|
+
body: {
|
|
31829
|
+
agent: args2.agentName,
|
|
31830
|
+
parts: [{ type: "text", text: args2.prompt }],
|
|
31831
|
+
...modelParts ? { model: modelParts } : {},
|
|
31832
|
+
tools: {
|
|
31833
|
+
task: false,
|
|
31834
|
+
question: false,
|
|
31835
|
+
external_directory: false
|
|
31836
|
+
}
|
|
31837
|
+
}
|
|
31838
|
+
}), PROMPT_ASYNC_TIMEOUT_MS, "session.promptAsync");
|
|
31839
|
+
}
|
|
31576
31840
|
async resumeFromDaemonMemory(options, session2) {
|
|
31577
31841
|
const { prompt, systemPrompt, model, context: context5 } = options;
|
|
31578
31842
|
const sessionId = session2.harnessSessionId;
|
|
@@ -31624,11 +31888,11 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31624
31888
|
}), PROMPT_ASYNC_TIMEOUT_MS, "session.promptAsync");
|
|
31625
31889
|
} catch (err) {
|
|
31626
31890
|
const reason = err instanceof Error ? err.message : String(err);
|
|
31627
|
-
process.stderr.write(`[${new Date().toISOString()}] role:${context5.role} resume-
|
|
31891
|
+
process.stderr.write(`[${new Date().toISOString()}] role:${context5.role} daemon-resume-fallback] ${reason} — cold spawning
|
|
31628
31892
|
`);
|
|
31629
31893
|
forwarder?.stop();
|
|
31630
31894
|
childProcess.kill();
|
|
31631
|
-
|
|
31895
|
+
return this.spawn(options);
|
|
31632
31896
|
}
|
|
31633
31897
|
return this.registerRunningSession({
|
|
31634
31898
|
childProcess,
|
|
@@ -31733,23 +31997,45 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31733
31997
|
async resumeTurn(pid, prompt) {
|
|
31734
31998
|
const meta = this.sessionStore.findByPid(pid);
|
|
31735
31999
|
if (!meta) {
|
|
31736
|
-
|
|
32000
|
+
process.stderr.write(`[${new Date().toISOString()}] opencode-sdk resumeTurn: no metadata for pid=${pid}, skipping
|
|
32001
|
+
`);
|
|
32002
|
+
return;
|
|
31737
32003
|
}
|
|
31738
32004
|
const client4 = createOpencodeClient({ baseUrl: meta.baseUrl });
|
|
31739
32005
|
const modelParts = meta.model ? parseModelId(meta.model) : undefined;
|
|
31740
|
-
|
|
31741
|
-
|
|
31742
|
-
|
|
31743
|
-
|
|
31744
|
-
|
|
31745
|
-
|
|
31746
|
-
|
|
31747
|
-
|
|
31748
|
-
|
|
31749
|
-
|
|
32006
|
+
const context5 = {
|
|
32007
|
+
machineId: meta.machineId,
|
|
32008
|
+
chatroomId: meta.chatroomId,
|
|
32009
|
+
role: meta.role
|
|
32010
|
+
};
|
|
32011
|
+
try {
|
|
32012
|
+
await withTimeout2(client4.session.promptAsync({
|
|
32013
|
+
path: { id: meta.sessionId },
|
|
32014
|
+
body: {
|
|
32015
|
+
agent: meta.agentName,
|
|
32016
|
+
parts: [{ type: "text", text: prompt }],
|
|
32017
|
+
...modelParts ? { model: modelParts } : {},
|
|
32018
|
+
tools: {
|
|
32019
|
+
task: false,
|
|
32020
|
+
question: false,
|
|
32021
|
+
external_directory: false
|
|
32022
|
+
}
|
|
31750
32023
|
}
|
|
31751
|
-
}
|
|
31752
|
-
}
|
|
32024
|
+
}), PROMPT_ASYNC_TIMEOUT_MS, "session.promptAsync");
|
|
32025
|
+
} catch (err) {
|
|
32026
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
32027
|
+
process.stderr.write(`[${new Date().toISOString()}] role:${meta.role} resume-fallback] ${reason} — starting fresh session
|
|
32028
|
+
`);
|
|
32029
|
+
await this.startFreshSessionOnServe({
|
|
32030
|
+
pid,
|
|
32031
|
+
baseUrl: meta.baseUrl,
|
|
32032
|
+
context: context5,
|
|
32033
|
+
agentName: meta.agentName,
|
|
32034
|
+
model: meta.model,
|
|
32035
|
+
prompt,
|
|
32036
|
+
oldSessionId: meta.sessionId
|
|
32037
|
+
});
|
|
32038
|
+
}
|
|
31753
32039
|
}
|
|
31754
32040
|
};
|
|
31755
32041
|
});
|
|
@@ -41454,51 +41740,51 @@ var require_resize = __commonJS((exports, module) => {
|
|
|
41454
41740
|
}
|
|
41455
41741
|
return this;
|
|
41456
41742
|
}
|
|
41457
|
-
function
|
|
41458
|
-
if (is.integer(
|
|
41459
|
-
this.options.extendTop =
|
|
41460
|
-
this.options.extendBottom =
|
|
41461
|
-
this.options.extendLeft =
|
|
41462
|
-
this.options.extendRight =
|
|
41463
|
-
} else if (is.object(
|
|
41464
|
-
if (is.defined(
|
|
41465
|
-
if (is.integer(
|
|
41466
|
-
this.options.extendTop =
|
|
41743
|
+
function extend3(extend4) {
|
|
41744
|
+
if (is.integer(extend4) && extend4 > 0) {
|
|
41745
|
+
this.options.extendTop = extend4;
|
|
41746
|
+
this.options.extendBottom = extend4;
|
|
41747
|
+
this.options.extendLeft = extend4;
|
|
41748
|
+
this.options.extendRight = extend4;
|
|
41749
|
+
} else if (is.object(extend4)) {
|
|
41750
|
+
if (is.defined(extend4.top)) {
|
|
41751
|
+
if (is.integer(extend4.top) && extend4.top >= 0) {
|
|
41752
|
+
this.options.extendTop = extend4.top;
|
|
41467
41753
|
} else {
|
|
41468
|
-
throw is.invalidParameterError("top", "positive integer",
|
|
41754
|
+
throw is.invalidParameterError("top", "positive integer", extend4.top);
|
|
41469
41755
|
}
|
|
41470
41756
|
}
|
|
41471
|
-
if (is.defined(
|
|
41472
|
-
if (is.integer(
|
|
41473
|
-
this.options.extendBottom =
|
|
41757
|
+
if (is.defined(extend4.bottom)) {
|
|
41758
|
+
if (is.integer(extend4.bottom) && extend4.bottom >= 0) {
|
|
41759
|
+
this.options.extendBottom = extend4.bottom;
|
|
41474
41760
|
} else {
|
|
41475
|
-
throw is.invalidParameterError("bottom", "positive integer",
|
|
41761
|
+
throw is.invalidParameterError("bottom", "positive integer", extend4.bottom);
|
|
41476
41762
|
}
|
|
41477
41763
|
}
|
|
41478
|
-
if (is.defined(
|
|
41479
|
-
if (is.integer(
|
|
41480
|
-
this.options.extendLeft =
|
|
41764
|
+
if (is.defined(extend4.left)) {
|
|
41765
|
+
if (is.integer(extend4.left) && extend4.left >= 0) {
|
|
41766
|
+
this.options.extendLeft = extend4.left;
|
|
41481
41767
|
} else {
|
|
41482
|
-
throw is.invalidParameterError("left", "positive integer",
|
|
41768
|
+
throw is.invalidParameterError("left", "positive integer", extend4.left);
|
|
41483
41769
|
}
|
|
41484
41770
|
}
|
|
41485
|
-
if (is.defined(
|
|
41486
|
-
if (is.integer(
|
|
41487
|
-
this.options.extendRight =
|
|
41771
|
+
if (is.defined(extend4.right)) {
|
|
41772
|
+
if (is.integer(extend4.right) && extend4.right >= 0) {
|
|
41773
|
+
this.options.extendRight = extend4.right;
|
|
41488
41774
|
} else {
|
|
41489
|
-
throw is.invalidParameterError("right", "positive integer",
|
|
41775
|
+
throw is.invalidParameterError("right", "positive integer", extend4.right);
|
|
41490
41776
|
}
|
|
41491
41777
|
}
|
|
41492
|
-
this._setBackgroundColourOption("extendBackground",
|
|
41493
|
-
if (is.defined(
|
|
41494
|
-
if (is.string(extendWith[
|
|
41495
|
-
this.options.extendWith = extendWith[
|
|
41778
|
+
this._setBackgroundColourOption("extendBackground", extend4.background);
|
|
41779
|
+
if (is.defined(extend4.extendWith)) {
|
|
41780
|
+
if (is.string(extendWith[extend4.extendWith])) {
|
|
41781
|
+
this.options.extendWith = extendWith[extend4.extendWith];
|
|
41496
41782
|
} else {
|
|
41497
|
-
throw is.invalidParameterError("extendWith", "one of: background, copy, repeat, mirror",
|
|
41783
|
+
throw is.invalidParameterError("extendWith", "one of: background, copy, repeat, mirror", extend4.extendWith);
|
|
41498
41784
|
}
|
|
41499
41785
|
}
|
|
41500
41786
|
} else {
|
|
41501
|
-
throw is.invalidParameterError("extend", "integer or object",
|
|
41787
|
+
throw is.invalidParameterError("extend", "integer or object", extend4);
|
|
41502
41788
|
}
|
|
41503
41789
|
return this;
|
|
41504
41790
|
}
|
|
@@ -41554,7 +41840,7 @@ var require_resize = __commonJS((exports, module) => {
|
|
|
41554
41840
|
module.exports = (Sharp) => {
|
|
41555
41841
|
Object.assign(Sharp.prototype, {
|
|
41556
41842
|
resize,
|
|
41557
|
-
extend:
|
|
41843
|
+
extend: extend3,
|
|
41558
41844
|
extract,
|
|
41559
41845
|
trim
|
|
41560
41846
|
});
|
|
@@ -53499,7 +53785,7 @@ var toString, getPrototypeOf, iterator, toStringTag, kindOf, kindOfTest = (type)
|
|
|
53499
53785
|
return kind === "formdata" || kind === "object" && isFunction3(thing.toString) && thing.toString() === "[object FormData]";
|
|
53500
53786
|
}, isURLSearchParams, isReadableStream, isRequest3, isResponse, isHeaders, trim = (str) => {
|
|
53501
53787
|
return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
|
|
53502
|
-
}, _global, isContextDefined = (context5) => !isUndefined(context5) && context5 !== _global,
|
|
53788
|
+
}, _global, isContextDefined = (context5) => !isUndefined(context5) && context5 !== _global, extend3 = (a, b, thisArg, { allOwnKeys } = {}) => {
|
|
53503
53789
|
forEach6(b, (val, key) => {
|
|
53504
53790
|
if (thisArg && isFunction3(val)) {
|
|
53505
53791
|
Object.defineProperty(a, key, {
|
|
@@ -53753,7 +54039,7 @@ var init_utils = __esm(() => {
|
|
|
53753
54039
|
isFileList,
|
|
53754
54040
|
forEach: forEach6,
|
|
53755
54041
|
merge: merge9,
|
|
53756
|
-
extend:
|
|
54042
|
+
extend: extend3,
|
|
53757
54043
|
trim,
|
|
53758
54044
|
stripBOM,
|
|
53759
54045
|
inherits,
|
|
@@ -65184,7 +65470,7 @@ var require_common = __commonJS((exports, module) => {
|
|
|
65184
65470
|
debug.namespace = namespace;
|
|
65185
65471
|
debug.useColors = createDebug.useColors();
|
|
65186
65472
|
debug.color = createDebug.selectColor(namespace);
|
|
65187
|
-
debug.extend =
|
|
65473
|
+
debug.extend = extend4;
|
|
65188
65474
|
debug.destroy = createDebug.destroy;
|
|
65189
65475
|
Object.defineProperty(debug, "enabled", {
|
|
65190
65476
|
enumerable: true,
|
|
@@ -65208,7 +65494,7 @@ var require_common = __commonJS((exports, module) => {
|
|
|
65208
65494
|
}
|
|
65209
65495
|
return debug;
|
|
65210
65496
|
}
|
|
65211
|
-
function
|
|
65497
|
+
function extend4(namespace, delimiter) {
|
|
65212
65498
|
const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
|
|
65213
65499
|
newDebug.log = this.log;
|
|
65214
65500
|
return newDebug;
|
|
@@ -82834,15 +83120,10 @@ var init_on_daemon_shutdown = __esm(() => {
|
|
|
82834
83120
|
const activeAgents = agentPm.listActive();
|
|
82835
83121
|
if (activeAgents.length > 0) {
|
|
82836
83122
|
console.log(`[${formatTimestamp()}] Stopping ${activeAgents.length} agent(s)...`);
|
|
82837
|
-
yield* exports_Effect.
|
|
83123
|
+
yield* exports_Effect.all(activeAgents.map(({ chatroomId, role, slot }) => {
|
|
82838
83124
|
const pid = slot.pid;
|
|
82839
|
-
|
|
82840
|
-
|
|
82841
|
-
console.log(` Stopped ${role} (PID ${pid})`);
|
|
82842
|
-
} catch (e) {
|
|
82843
|
-
console.log(` ⚠️ Failed to stop ${role}: ${e.message}`);
|
|
82844
|
-
}
|
|
82845
|
-
})));
|
|
83125
|
+
return agentPm.stop({ chatroomId, role, reason: "daemon.shutdown" }).pipe(exports_Effect.tap(() => exports_Effect.sync(() => console.log(` Stopped ${role} (PID ${pid})`))), exports_Effect.catchAll((e) => exports_Effect.sync(() => console.log(` ⚠️ Failed to stop ${role}: ${e.message}`))));
|
|
83126
|
+
}), { concurrency: "unbounded" });
|
|
82846
83127
|
console.log(`[${formatTimestamp()}] All agents stopped`);
|
|
82847
83128
|
}
|
|
82848
83129
|
yield* exports_Effect.promise(() => session2.backend.mutation(api.machines.updateDaemonStatus, {
|
|
@@ -84924,36 +85205,45 @@ async function pushSingleWorkspaceGitStateImpl(ctx, workingDir) {
|
|
|
84924
85205
|
const stateKey = makeGitStateKey(ctx.machineId, workingDir);
|
|
84925
85206
|
const isRepo = await isGitRepo(workingDir);
|
|
84926
85207
|
if (!isRepo) {
|
|
84927
|
-
|
|
84928
|
-
if (ctx.lastPushedGitState.get(stateKey) === stateHash2)
|
|
84929
|
-
return;
|
|
84930
|
-
await ctx.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
84931
|
-
sessionId: ctx.sessionId,
|
|
84932
|
-
machineId: ctx.machineId,
|
|
84933
|
-
workingDir,
|
|
84934
|
-
status: "not_found"
|
|
84935
|
-
});
|
|
84936
|
-
ctx.lastPushedGitState.set(stateKey, stateHash2);
|
|
85208
|
+
await pushNotFoundGitState(ctx, workingDir, stateKey);
|
|
84937
85209
|
return;
|
|
84938
85210
|
}
|
|
84939
85211
|
const branchResult = await getBranch(workingDir);
|
|
84940
85212
|
if (branchResult.status === "error") {
|
|
84941
|
-
|
|
84942
|
-
if (ctx.lastPushedGitState.get(stateKey) === stateHash2)
|
|
84943
|
-
return;
|
|
84944
|
-
await ctx.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
84945
|
-
sessionId: ctx.sessionId,
|
|
84946
|
-
machineId: ctx.machineId,
|
|
84947
|
-
workingDir,
|
|
84948
|
-
status: "error",
|
|
84949
|
-
errorMessage: branchResult.message
|
|
84950
|
-
});
|
|
84951
|
-
ctx.lastPushedGitState.set(stateKey, stateHash2);
|
|
85213
|
+
await pushErrorGitState(ctx, workingDir, stateKey, branchResult.message);
|
|
84952
85214
|
return;
|
|
84953
85215
|
}
|
|
84954
85216
|
if (branchResult.status === "not_found") {
|
|
84955
85217
|
return;
|
|
84956
85218
|
}
|
|
85219
|
+
await pushAvailableGitState(ctx, workingDir, stateKey, branchResult);
|
|
85220
|
+
}
|
|
85221
|
+
async function pushNotFoundGitState(ctx, workingDir, stateKey) {
|
|
85222
|
+
const stateHash = "not_found";
|
|
85223
|
+
if (ctx.lastPushedGitState.get(stateKey) === stateHash)
|
|
85224
|
+
return;
|
|
85225
|
+
await ctx.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85226
|
+
sessionId: ctx.sessionId,
|
|
85227
|
+
machineId: ctx.machineId,
|
|
85228
|
+
workingDir,
|
|
85229
|
+
status: "not_found"
|
|
85230
|
+
});
|
|
85231
|
+
ctx.lastPushedGitState.set(stateKey, stateHash);
|
|
85232
|
+
}
|
|
85233
|
+
async function pushErrorGitState(ctx, workingDir, stateKey, message) {
|
|
85234
|
+
const stateHash = `error:${message}`;
|
|
85235
|
+
if (ctx.lastPushedGitState.get(stateKey) === stateHash)
|
|
85236
|
+
return;
|
|
85237
|
+
await ctx.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85238
|
+
sessionId: ctx.sessionId,
|
|
85239
|
+
machineId: ctx.machineId,
|
|
85240
|
+
workingDir,
|
|
85241
|
+
status: "error",
|
|
85242
|
+
errorMessage: message
|
|
85243
|
+
});
|
|
85244
|
+
ctx.lastPushedGitState.set(stateKey, stateHash);
|
|
85245
|
+
}
|
|
85246
|
+
async function pushAvailableGitState(ctx, workingDir, stateKey, branchResult) {
|
|
84957
85247
|
const branch = branchResult.branch;
|
|
84958
85248
|
const allFields = [branchField, ...GIT_STATE_FIELDS, ...makeBranchDependentFields(branch)];
|
|
84959
85249
|
const pipeline2 = new GitStatePipeline(allFields);
|
|
@@ -84990,16 +85280,12 @@ async function pushSingleWorkspaceGitStateImpl(ctx, workingDir) {
|
|
|
84990
85280
|
}
|
|
84991
85281
|
}
|
|
84992
85282
|
}
|
|
84993
|
-
|
|
84994
|
-
|
|
84995
|
-
const mutable = yield* DaemonMutableStateService;
|
|
84996
|
-
const lastPushedGitState = yield* exports_Ref.get(mutable.lastPushedGitState);
|
|
84997
|
-
const stateKey = makeGitStateKey(session2.machineId, workingDir);
|
|
84998
|
-
const isRepo = yield* exports_Effect.promise(() => isGitRepo(workingDir));
|
|
84999
|
-
if (!isRepo) {
|
|
85283
|
+
function pushObservedNotRepoEffect(session2, lastPushedGitState, stateKey, workingDir, reason) {
|
|
85284
|
+
return exports_Effect.gen(function* () {
|
|
85000
85285
|
const stateHash = "not_found";
|
|
85001
|
-
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === stateHash)
|
|
85286
|
+
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === stateHash) {
|
|
85002
85287
|
return;
|
|
85288
|
+
}
|
|
85003
85289
|
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85004
85290
|
sessionId: session2.sessionId,
|
|
85005
85291
|
machineId: session2.machineId,
|
|
@@ -85007,21 +85293,69 @@ var lastFullPushMs, branchField, GIT_STATE_FIELDS, pushSingleWorkspaceGitSummary
|
|
|
85007
85293
|
status: "not_found"
|
|
85008
85294
|
}));
|
|
85009
85295
|
lastPushedGitState.set(stateKey, stateHash);
|
|
85010
|
-
|
|
85011
|
-
|
|
85012
|
-
|
|
85013
|
-
|
|
85014
|
-
const stateHash = `error:${
|
|
85015
|
-
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === stateHash)
|
|
85296
|
+
});
|
|
85297
|
+
}
|
|
85298
|
+
function pushObservedBranchErrorEffect(session2, lastPushedGitState, stateKey, workingDir, reason, message) {
|
|
85299
|
+
return exports_Effect.gen(function* () {
|
|
85300
|
+
const stateHash = `error:${message}`;
|
|
85301
|
+
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === stateHash) {
|
|
85016
85302
|
return;
|
|
85303
|
+
}
|
|
85017
85304
|
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85018
85305
|
sessionId: session2.sessionId,
|
|
85019
85306
|
machineId: session2.machineId,
|
|
85020
85307
|
workingDir,
|
|
85021
85308
|
status: "error",
|
|
85022
|
-
errorMessage:
|
|
85309
|
+
errorMessage: message
|
|
85023
85310
|
}));
|
|
85024
85311
|
lastPushedGitState.set(stateKey, stateHash);
|
|
85312
|
+
});
|
|
85313
|
+
}
|
|
85314
|
+
function pushObservedFullGitStateEffect(session2, lastPushedGitState, stateKey, workingDir, branch, reason) {
|
|
85315
|
+
return exports_Effect.gen(function* () {
|
|
85316
|
+
yield* exports_Effect.promise(() => pushSingleWorkspaceGitStateImpl(buildGitStateDeps(session2, lastPushedGitState), workingDir));
|
|
85317
|
+
lastFullPushMs.set(stateKey, Date.now());
|
|
85318
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed full git state pushed: ${workingDir} (${branch})${reason === "refresh" ? " [refresh]" : ""}`);
|
|
85319
|
+
});
|
|
85320
|
+
}
|
|
85321
|
+
function pushObservedSlimGitSummaryEffect(session2, lastPushedGitState, stateKey, workingDir, branch, branchResult, reason) {
|
|
85322
|
+
return exports_Effect.gen(function* () {
|
|
85323
|
+
const slimFields = [
|
|
85324
|
+
branchField,
|
|
85325
|
+
...GIT_STATE_FIELDS.filter((f) => f.includeInSlim),
|
|
85326
|
+
...makeBranchDependentFields(branch)
|
|
85327
|
+
];
|
|
85328
|
+
const pipeline2 = new GitStatePipeline(slimFields);
|
|
85329
|
+
const preCollected = new Map([["branch", branchResult]]);
|
|
85330
|
+
const values3 = yield* exports_Effect.promise(() => pipeline2.collect(workingDir, preCollected));
|
|
85331
|
+
const hash2 = pipeline2.computeHash(values3, true);
|
|
85332
|
+
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === hash2) {
|
|
85333
|
+
return;
|
|
85334
|
+
}
|
|
85335
|
+
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85336
|
+
sessionId: session2.sessionId,
|
|
85337
|
+
machineId: session2.machineId,
|
|
85338
|
+
workingDir,
|
|
85339
|
+
status: "available",
|
|
85340
|
+
...pipeline2.toMutationArgs(values3, true)
|
|
85341
|
+
}));
|
|
85342
|
+
lastPushedGitState.set(stateKey, hash2);
|
|
85343
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed git summary pushed: ${workingDir} (${branch}${values3.get("isDirty") ? ", dirty" : ", clean"})${reason === "refresh" ? " [refresh]" : ""}`);
|
|
85344
|
+
});
|
|
85345
|
+
}
|
|
85346
|
+
var lastFullPushMs, branchField, GIT_STATE_FIELDS, pushSingleWorkspaceGitSummaryForObservedEffect = (workingDir, reason = "safety-poll") => exports_Effect.gen(function* pushObservedGitSummaryForObserved() {
|
|
85347
|
+
const session2 = yield* DaemonSessionService;
|
|
85348
|
+
const mutable = yield* DaemonMutableStateService;
|
|
85349
|
+
const lastPushedGitState = yield* exports_Ref.get(mutable.lastPushedGitState);
|
|
85350
|
+
const stateKey = makeGitStateKey(session2.machineId, workingDir);
|
|
85351
|
+
const isRepo = yield* exports_Effect.promise(() => isGitRepo(workingDir));
|
|
85352
|
+
if (!isRepo) {
|
|
85353
|
+
yield* pushObservedNotRepoEffect(session2, lastPushedGitState, stateKey, workingDir, reason);
|
|
85354
|
+
return;
|
|
85355
|
+
}
|
|
85356
|
+
const branchResult = yield* exports_Effect.promise(() => getBranch(workingDir));
|
|
85357
|
+
if (branchResult.status === "error") {
|
|
85358
|
+
yield* pushObservedBranchErrorEffect(session2, lastPushedGitState, stateKey, workingDir, reason, branchResult.message);
|
|
85025
85359
|
return;
|
|
85026
85360
|
}
|
|
85027
85361
|
if (branchResult.status === "not_found") {
|
|
@@ -85031,32 +85365,10 @@ var lastFullPushMs, branchField, GIT_STATE_FIELDS, pushSingleWorkspaceGitSummary
|
|
|
85031
85365
|
const now = Date.now();
|
|
85032
85366
|
const lastFull = lastFullPushMs.get(stateKey) ?? 0;
|
|
85033
85367
|
if (now - lastFull >= OBSERVED_FULL_PUSH_INTERVAL_MS) {
|
|
85034
|
-
yield*
|
|
85035
|
-
lastFullPushMs.set(stateKey, now);
|
|
85036
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed full git state pushed: ${workingDir} (${branch})${reason === "refresh" ? " [refresh]" : ""}`);
|
|
85037
|
-
return;
|
|
85038
|
-
}
|
|
85039
|
-
const slimFields = [
|
|
85040
|
-
branchField,
|
|
85041
|
-
...GIT_STATE_FIELDS.filter((f) => f.includeInSlim),
|
|
85042
|
-
...makeBranchDependentFields(branch)
|
|
85043
|
-
];
|
|
85044
|
-
const pipeline2 = new GitStatePipeline(slimFields);
|
|
85045
|
-
const preCollected = new Map([["branch", branchResult]]);
|
|
85046
|
-
const values3 = yield* exports_Effect.promise(() => pipeline2.collect(workingDir, preCollected));
|
|
85047
|
-
const hash2 = pipeline2.computeHash(values3, true);
|
|
85048
|
-
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === hash2) {
|
|
85368
|
+
yield* pushObservedFullGitStateEffect(session2, lastPushedGitState, stateKey, workingDir, branch, reason);
|
|
85049
85369
|
return;
|
|
85050
85370
|
}
|
|
85051
|
-
yield*
|
|
85052
|
-
sessionId: session2.sessionId,
|
|
85053
|
-
machineId: session2.machineId,
|
|
85054
|
-
workingDir,
|
|
85055
|
-
status: "available",
|
|
85056
|
-
...pipeline2.toMutationArgs(values3, true)
|
|
85057
|
-
}));
|
|
85058
|
-
lastPushedGitState.set(stateKey, hash2);
|
|
85059
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed git summary pushed: ${workingDir} (${branch}${values3.get("isDirty") ? ", dirty" : ", clean"})${reason === "refresh" ? " [refresh]" : ""}`);
|
|
85371
|
+
yield* pushObservedSlimGitSummaryEffect(session2, lastPushedGitState, stateKey, workingDir, branch, branchResult, reason);
|
|
85060
85372
|
}), pushGitStateEffect, pushSingleWorkspaceGitStateEffect = (workingDir) => exports_Effect.gen(function* () {
|
|
85061
85373
|
const session2 = yield* DaemonSessionService;
|
|
85062
85374
|
const mutable = yield* DaemonMutableStateService;
|
|
@@ -85272,14 +85584,12 @@ async function processPRAction(deps, req) {
|
|
|
85272
85584
|
timeout: EXEC_TIMEOUT_MS
|
|
85273
85585
|
});
|
|
85274
85586
|
console.log(`[${formatTimestamp()}] ✅ PR action: ${action} on #${prNumber}${result.stdout ? ` — ${result.stdout.trim()}` : ""}`);
|
|
85275
|
-
|
|
85587
|
+
exports_Runtime.runFork(deps.runtime)(pushGitStateEffect.pipe(exports_Effect.provide(exports_Layer.mergeAll(exports_Layer.succeed(DaemonSessionService, deps), DaemonMutableStateServiceLive({
|
|
85276
85588
|
lastPushedGitState: deps.lastPushedGitState,
|
|
85277
85589
|
lastPushedModels: null,
|
|
85278
85590
|
lastPushedHarnessFingerprint: null,
|
|
85279
85591
|
workspaceListStore: deps.workspaceListStore
|
|
85280
|
-
})))
|
|
85281
|
-
console.warn(`[${formatTimestamp()}] ⚠️ Failed to refresh git state after PR action: ${getErrorMessage(err)}`);
|
|
85282
|
-
});
|
|
85592
|
+
}))), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[${formatTimestamp()}] ⚠️ Failed to refresh git state after PR action: ${getErrorMessage(err)}`)))));
|
|
85283
85593
|
}
|
|
85284
85594
|
async function processPRCommits(deps, req) {
|
|
85285
85595
|
const prNumber = req.prNumber;
|
|
@@ -85304,32 +85614,35 @@ async function processCommitDetail(deps, req) {
|
|
|
85304
85614
|
getCommitDetail(req.workingDir, req.sha),
|
|
85305
85615
|
getCommitMetadata(req.workingDir, req.sha)
|
|
85306
85616
|
]);
|
|
85617
|
+
await upsertCommitDetailResult(deps, req, result, metadata);
|
|
85618
|
+
if (result.status === "available" || result.status === "truncated") {
|
|
85619
|
+
const compressed = gzipSync2(Buffer.from(result.content));
|
|
85620
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD0D Commit detail pushed: ${req.sha.slice(0, 7)} in ${req.workingDir} (${(Buffer.byteLength(result.content) / 1024).toFixed(1)}KB → ${(compressed.length / 1024).toFixed(1)}KB gzip)`);
|
|
85621
|
+
}
|
|
85622
|
+
}
|
|
85623
|
+
async function upsertCommitDetailResult(deps, req, result, metadata) {
|
|
85624
|
+
const baseArgs = {
|
|
85625
|
+
sessionId: deps.sessionId,
|
|
85626
|
+
machineId: deps.machineId,
|
|
85627
|
+
workingDir: req.workingDir,
|
|
85628
|
+
sha: req.sha,
|
|
85629
|
+
message: metadata?.message,
|
|
85630
|
+
body: metadata?.body,
|
|
85631
|
+
author: metadata?.author,
|
|
85632
|
+
date: metadata?.date
|
|
85633
|
+
};
|
|
85307
85634
|
if (result.status === "not_found") {
|
|
85308
85635
|
await deps.backend.mutation(api.workspaces.upsertCommitDetailV2, {
|
|
85309
|
-
|
|
85310
|
-
|
|
85311
|
-
workingDir: req.workingDir,
|
|
85312
|
-
sha: req.sha,
|
|
85313
|
-
status: "not_found",
|
|
85314
|
-
message: metadata?.message,
|
|
85315
|
-
body: metadata?.body,
|
|
85316
|
-
author: metadata?.author,
|
|
85317
|
-
date: metadata?.date
|
|
85636
|
+
...baseArgs,
|
|
85637
|
+
status: "not_found"
|
|
85318
85638
|
});
|
|
85319
85639
|
return;
|
|
85320
85640
|
}
|
|
85321
85641
|
if (result.status === "error") {
|
|
85322
85642
|
await deps.backend.mutation(api.workspaces.upsertCommitDetailV2, {
|
|
85323
|
-
|
|
85324
|
-
machineId: deps.machineId,
|
|
85325
|
-
workingDir: req.workingDir,
|
|
85326
|
-
sha: req.sha,
|
|
85643
|
+
...baseArgs,
|
|
85327
85644
|
status: "error",
|
|
85328
|
-
errorMessage: result.message
|
|
85329
|
-
message: metadata?.message,
|
|
85330
|
-
body: metadata?.body,
|
|
85331
|
-
author: metadata?.author,
|
|
85332
|
-
date: metadata?.date
|
|
85645
|
+
errorMessage: result.message
|
|
85333
85646
|
});
|
|
85334
85647
|
return;
|
|
85335
85648
|
}
|
|
@@ -85337,20 +85650,12 @@ async function processCommitDetail(deps, req) {
|
|
|
85337
85650
|
const compressed = gzipSync2(Buffer.from(result.content));
|
|
85338
85651
|
const diffContentCompressed = compressed.toString("base64");
|
|
85339
85652
|
await deps.backend.mutation(api.workspaces.upsertCommitDetailV2, {
|
|
85340
|
-
|
|
85341
|
-
machineId: deps.machineId,
|
|
85342
|
-
workingDir: req.workingDir,
|
|
85343
|
-
sha: req.sha,
|
|
85653
|
+
...baseArgs,
|
|
85344
85654
|
status: "available",
|
|
85345
85655
|
data: { compression: "gzip", content: diffContentCompressed },
|
|
85346
85656
|
truncated: result.truncated,
|
|
85347
|
-
message: metadata?.message,
|
|
85348
|
-
body: metadata?.body,
|
|
85349
|
-
author: metadata?.author,
|
|
85350
|
-
date: metadata?.date,
|
|
85351
85657
|
diffStat
|
|
85352
85658
|
});
|
|
85353
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDD0D Commit detail pushed: ${req.sha.slice(0, 7)} in ${req.workingDir} (${(Buffer.byteLength(result.content) / 1024).toFixed(1)}KB → ${(compressed.length / 1024).toFixed(1)}KB gzip)`);
|
|
85354
85659
|
}
|
|
85355
85660
|
async function processMoreCommits(deps, req) {
|
|
85356
85661
|
const offset = req.offset ?? 0;
|
|
@@ -85387,11 +85692,33 @@ async function processRecentCommits(deps, req) {
|
|
|
85387
85692
|
});
|
|
85388
85693
|
console.log(`[${formatTimestamp()}] \uD83D\uDCDC Recent commits pushed: ${req.workingDir} (${commits.length} commits)`);
|
|
85389
85694
|
}
|
|
85695
|
+
function dispatchGitRequest(deps, req) {
|
|
85696
|
+
switch (req.requestType) {
|
|
85697
|
+
case "full_diff":
|
|
85698
|
+
return exports_Effect.promise(() => processFullDiff(deps, req));
|
|
85699
|
+
case "commit_detail":
|
|
85700
|
+
return exports_Effect.promise(() => processCommitDetail(deps, req));
|
|
85701
|
+
case "more_commits":
|
|
85702
|
+
return exports_Effect.promise(() => processMoreCommits(deps, req));
|
|
85703
|
+
case "pr_diff":
|
|
85704
|
+
return exports_Effect.promise(() => processPRDiff(deps, req));
|
|
85705
|
+
case "pr_action":
|
|
85706
|
+
return exports_Effect.promise(() => processPRAction(deps, req));
|
|
85707
|
+
case "pr_commits":
|
|
85708
|
+
return exports_Effect.promise(() => processPRCommits(deps, req));
|
|
85709
|
+
case "all_pull_requests":
|
|
85710
|
+
return exports_Effect.promise(() => processAllPullRequests(deps, req));
|
|
85711
|
+
case "recent_commits":
|
|
85712
|
+
return exports_Effect.promise(() => processRecentCommits(deps, req));
|
|
85713
|
+
}
|
|
85714
|
+
}
|
|
85390
85715
|
var EXEC_TIMEOUT_MS = 60000, startGitRequestSubscriptionEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
85391
85716
|
const session2 = yield* DaemonSessionService;
|
|
85717
|
+
const runtime4 = yield* exports_Effect.runtime();
|
|
85392
85718
|
const processedRequestIds = new Map;
|
|
85393
85719
|
const DEDUP_TTL_MS = 5 * 60 * 1000;
|
|
85394
|
-
|
|
85720
|
+
const sessionWithRuntime = { ...session2, runtime: runtime4 };
|
|
85721
|
+
const processingState = { isProcessing: false };
|
|
85395
85722
|
session2.backend.mutation(api.workspaces.resetProcessingRequests, {
|
|
85396
85723
|
sessionId: session2.sessionId,
|
|
85397
85724
|
machineId: session2.machineId
|
|
@@ -85408,16 +85735,14 @@ var EXEC_TIMEOUT_MS = 60000, startGitRequestSubscriptionEffect = (wsClient2) =>
|
|
|
85408
85735
|
}, (requests) => {
|
|
85409
85736
|
if (!requests || requests.length === 0)
|
|
85410
85737
|
return;
|
|
85411
|
-
const logger =
|
|
85738
|
+
const logger = sessionWithRuntime.logger ?? console;
|
|
85412
85739
|
logger.log(`[${formatTimestamp()}] \uD83D\uDCEC Git subscription: received ${requests.length} pending request(s)`);
|
|
85413
|
-
if (
|
|
85740
|
+
if (processingState.isProcessing)
|
|
85414
85741
|
return;
|
|
85415
|
-
|
|
85416
|
-
|
|
85417
|
-
|
|
85418
|
-
})
|
|
85419
|
-
processing = false;
|
|
85420
|
-
});
|
|
85742
|
+
processingState.isProcessing = true;
|
|
85743
|
+
exports_Runtime.runFork(runtime4)(processRequestsEffect(requests, processedRequestIds, DEDUP_TTL_MS, runtime4).pipe(exports_Effect.provideService(DaemonSessionService, sessionWithRuntime), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[${formatTimestamp()}] ⚠️ Git request processing failed: ${getErrorMessage(err)}`))), exports_Effect.ensuring(exports_Effect.sync(() => {
|
|
85744
|
+
processingState.isProcessing = false;
|
|
85745
|
+
}))));
|
|
85421
85746
|
}, (err) => {
|
|
85422
85747
|
console.warn(`[${formatTimestamp()}] ⚠️ Git request subscription error: ${getErrorMessage(err)}`);
|
|
85423
85748
|
});
|
|
@@ -85428,7 +85753,7 @@ var EXEC_TIMEOUT_MS = 60000, startGitRequestSubscriptionEffect = (wsClient2) =>
|
|
|
85428
85753
|
console.log(`[${formatTimestamp()}] \uD83D\uDD00 Git request subscription stopped`);
|
|
85429
85754
|
}
|
|
85430
85755
|
};
|
|
85431
|
-
}), processRequestsEffect = (requests, processedRequestIds, dedupTtlMs) => exports_Effect.gen(function* () {
|
|
85756
|
+
}), processRequestsEffect = (requests, processedRequestIds, dedupTtlMs, runtime4) => exports_Effect.gen(function* () {
|
|
85432
85757
|
const session2 = yield* DaemonSessionService;
|
|
85433
85758
|
const evictBefore = Date.now() - dedupTtlMs;
|
|
85434
85759
|
for (const [id3, ts] of processedRequestIds) {
|
|
@@ -85448,32 +85773,8 @@ var EXEC_TIMEOUT_MS = 60000, startGitRequestSubscriptionEffect = (wsClient2) =>
|
|
|
85448
85773
|
}));
|
|
85449
85774
|
const logger = session2.logger ?? console;
|
|
85450
85775
|
logger.log(`[${formatTimestamp()}] ⚙️ Processing git request: type=${req.requestType}, id=${requestId}`);
|
|
85451
|
-
|
|
85452
|
-
|
|
85453
|
-
yield* exports_Effect.promise(() => processFullDiff(session2, req));
|
|
85454
|
-
break;
|
|
85455
|
-
case "commit_detail":
|
|
85456
|
-
yield* exports_Effect.promise(() => processCommitDetail(session2, req));
|
|
85457
|
-
break;
|
|
85458
|
-
case "more_commits":
|
|
85459
|
-
yield* exports_Effect.promise(() => processMoreCommits(session2, req));
|
|
85460
|
-
break;
|
|
85461
|
-
case "pr_diff":
|
|
85462
|
-
yield* exports_Effect.promise(() => processPRDiff(session2, req));
|
|
85463
|
-
break;
|
|
85464
|
-
case "pr_action":
|
|
85465
|
-
yield* exports_Effect.promise(() => processPRAction(session2, req));
|
|
85466
|
-
break;
|
|
85467
|
-
case "pr_commits":
|
|
85468
|
-
yield* exports_Effect.promise(() => processPRCommits(session2, req));
|
|
85469
|
-
break;
|
|
85470
|
-
case "all_pull_requests":
|
|
85471
|
-
yield* exports_Effect.promise(() => processAllPullRequests(session2, req));
|
|
85472
|
-
break;
|
|
85473
|
-
case "recent_commits":
|
|
85474
|
-
yield* exports_Effect.promise(() => processRecentCommits(session2, req));
|
|
85475
|
-
break;
|
|
85476
|
-
}
|
|
85776
|
+
const sessionWithRuntime = { ...session2, runtime: runtime4 };
|
|
85777
|
+
yield* dispatchGitRequest(sessionWithRuntime, req);
|
|
85477
85778
|
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.updateRequestStatus, {
|
|
85478
85779
|
sessionId: session2.sessionId,
|
|
85479
85780
|
requestId: req._id,
|
|
@@ -85653,6 +85954,26 @@ function startCommandSubscriber(session2, wsClient2, deps) {
|
|
|
85653
85954
|
});
|
|
85654
85955
|
return { stop: unsub };
|
|
85655
85956
|
}
|
|
85957
|
+
async function dispatchPendingCommand(session2, deps, cmd) {
|
|
85958
|
+
switch (cmd.type) {
|
|
85959
|
+
case "refreshCapabilities":
|
|
85960
|
+
await handleRefreshCapabilities(session2, deps, cmd);
|
|
85961
|
+
break;
|
|
85962
|
+
case "refreshSessionTitle":
|
|
85963
|
+
await handleRefreshSessionTitle(session2, deps, cmd);
|
|
85964
|
+
break;
|
|
85965
|
+
default:
|
|
85966
|
+
await markFailed(session2, cmd._id, `Unknown command type: ${cmd.type}`);
|
|
85967
|
+
}
|
|
85968
|
+
}
|
|
85969
|
+
async function processPendingCommand(session2, deps, cmd, now) {
|
|
85970
|
+
if (now - cmd.createdAt > DIRECT_HARNESS_COMMAND_TTL_MS) {
|
|
85971
|
+
console.log(`[direct-harness] Discarding stale command ${cmd._id} (type=${cmd.type}, age=${now - cmd.createdAt}ms)`);
|
|
85972
|
+
await markFailed(session2, cmd._id, "Command expired (TTL)");
|
|
85973
|
+
return;
|
|
85974
|
+
}
|
|
85975
|
+
await dispatchPendingCommand(session2, deps, cmd);
|
|
85976
|
+
}
|
|
85656
85977
|
async function drain(session2, deps, processed) {
|
|
85657
85978
|
const pending3 = await session2.backend.query(api.daemon.directHarness.commands.listPendingCommands, { sessionId: session2.sessionId, machineId: session2.machineId });
|
|
85658
85979
|
if (!pending3 || pending3.length === 0)
|
|
@@ -85663,21 +85984,7 @@ async function drain(session2, deps, processed) {
|
|
|
85663
85984
|
continue;
|
|
85664
85985
|
processed.add(cmd._id);
|
|
85665
85986
|
try {
|
|
85666
|
-
|
|
85667
|
-
console.log(`[direct-harness] Discarding stale command ${cmd._id} (type=${cmd.type}, age=${now - cmd.createdAt}ms)`);
|
|
85668
|
-
await markFailed(session2, cmd._id, "Command expired (TTL)");
|
|
85669
|
-
continue;
|
|
85670
|
-
}
|
|
85671
|
-
switch (cmd.type) {
|
|
85672
|
-
case "refreshCapabilities":
|
|
85673
|
-
await handleRefreshCapabilities(session2, deps, cmd);
|
|
85674
|
-
break;
|
|
85675
|
-
case "refreshSessionTitle":
|
|
85676
|
-
await handleRefreshSessionTitle(session2, deps, cmd);
|
|
85677
|
-
break;
|
|
85678
|
-
default:
|
|
85679
|
-
await markFailed(session2, cmd._id, `Unknown command type: ${cmd.type}`);
|
|
85680
|
-
}
|
|
85987
|
+
await processPendingCommand(session2, deps, cmd, now);
|
|
85681
85988
|
} catch (err) {
|
|
85682
85989
|
const message = err instanceof Error ? err.message : String(err);
|
|
85683
85990
|
console.warn(`[direct-harness] Command ${cmd._id} failed: ${message}`);
|
|
@@ -86500,74 +86807,73 @@ async function drain2(session2, deps) {
|
|
|
86500
86807
|
}
|
|
86501
86808
|
}
|
|
86502
86809
|
}
|
|
86503
|
-
async function
|
|
86504
|
-
|
|
86505
|
-
if (!
|
|
86506
|
-
|
|
86507
|
-
|
|
86508
|
-
|
|
86509
|
-
|
|
86510
|
-
|
|
86511
|
-
|
|
86512
|
-
|
|
86513
|
-
|
|
86514
|
-
|
|
86515
|
-
|
|
86516
|
-
|
|
86517
|
-
|
|
86518
|
-
|
|
86519
|
-
|
|
86520
|
-
|
|
86810
|
+
async function resumeSessionHandle(session2, deps, rowId, info) {
|
|
86811
|
+
const opencodeSessionId = info.opencodeSessionId;
|
|
86812
|
+
if (!opencodeSessionId) {
|
|
86813
|
+
console.warn(`[direct-harness] Session ${rowId} not yet open — waiting for session-subscriber`);
|
|
86814
|
+
return null;
|
|
86815
|
+
}
|
|
86816
|
+
const workspaceId = info.workspaceId;
|
|
86817
|
+
if (!workspaceId) {
|
|
86818
|
+
console.warn(`[direct-harness] Cannot resume session ${rowId}: no workspace info`);
|
|
86819
|
+
return null;
|
|
86820
|
+
}
|
|
86821
|
+
let harness = deps.harnesses.get(workspaceId);
|
|
86822
|
+
if (harness && !harness.isAlive()) {
|
|
86823
|
+
harness.close().catch(() => {});
|
|
86824
|
+
deps.harnesses.delete(workspaceId);
|
|
86825
|
+
harness = undefined;
|
|
86826
|
+
}
|
|
86827
|
+
if (!harness) {
|
|
86828
|
+
const workspace = await session2.backend.query(api.workspaces.getWorkspaceById, {
|
|
86829
|
+
sessionId: session2.sessionId,
|
|
86830
|
+
workspaceId
|
|
86831
|
+
});
|
|
86832
|
+
if (!workspace) {
|
|
86833
|
+
console.warn(`[direct-harness] Cannot resume session ${rowId}: workspace not found`);
|
|
86834
|
+
return null;
|
|
86521
86835
|
}
|
|
86522
|
-
|
|
86523
|
-
|
|
86524
|
-
|
|
86525
|
-
|
|
86526
|
-
|
|
86527
|
-
|
|
86528
|
-
|
|
86529
|
-
|
|
86836
|
+
harness = await startOpencodeSdkHarness({
|
|
86837
|
+
type: "opencode",
|
|
86838
|
+
workingDir: workspace.workingDir,
|
|
86839
|
+
workspaceId
|
|
86840
|
+
});
|
|
86841
|
+
deps.harnesses.set(workspaceId, harness);
|
|
86842
|
+
}
|
|
86843
|
+
try {
|
|
86844
|
+
return await resumeSession({
|
|
86845
|
+
harness,
|
|
86846
|
+
journalFactory: deps.journalFactory,
|
|
86847
|
+
chunkExtractor: createOpencodeSdkChunkExtractor()
|
|
86848
|
+
}, { harnessSessionId: rowId, opencodeSessionId, workspaceId });
|
|
86849
|
+
} catch (err) {
|
|
86850
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
86851
|
+
console.warn(`[direct-harness] Cannot resume session ${rowId}: ${message}`);
|
|
86852
|
+
await deps.sessionRepository.markFailed(rowId).catch(() => {});
|
|
86853
|
+
return null;
|
|
86854
|
+
}
|
|
86855
|
+
}
|
|
86856
|
+
function wireResumedSessionEvents(handle, deps, info) {
|
|
86857
|
+
const idleConfig = {
|
|
86858
|
+
agent: info.lastUsedConfig.agent ?? "build",
|
|
86859
|
+
model: info.lastUsedConfig.model
|
|
86860
|
+
};
|
|
86861
|
+
let lastBoundKey = null;
|
|
86862
|
+
handle.session.onEvent((event) => {
|
|
86863
|
+
const turn = handle.currentTurn;
|
|
86864
|
+
if (turn?.messageId !== null && turn?.messageId !== undefined) {
|
|
86865
|
+
const key = `${turn.turnId}:${turn.messageId}`;
|
|
86866
|
+
if (key !== lastBoundKey) {
|
|
86867
|
+
lastBoundKey = key;
|
|
86868
|
+
deps.sessionRepository.bindTurnMessageId(turn.turnId, turn.messageId).catch((err) => console.warn("[direct-harness] bindTurnMessageId error (resume):", err));
|
|
86530
86869
|
}
|
|
86531
|
-
harness = await startOpencodeSdkHarness({
|
|
86532
|
-
type: "opencode",
|
|
86533
|
-
workingDir: workspace.workingDir,
|
|
86534
|
-
workspaceId
|
|
86535
|
-
});
|
|
86536
|
-
deps.harnesses.set(workspaceId, harness);
|
|
86537
86870
|
}
|
|
86538
|
-
|
|
86539
|
-
handle
|
|
86540
|
-
harness,
|
|
86541
|
-
journalFactory: deps.journalFactory,
|
|
86542
|
-
chunkExtractor: createOpencodeSdkChunkExtractor()
|
|
86543
|
-
}, { harnessSessionId: rowId, opencodeSessionId, workspaceId });
|
|
86544
|
-
} catch (err) {
|
|
86545
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
86546
|
-
console.warn(`[direct-harness] Cannot resume session ${rowId}: ${message}`);
|
|
86547
|
-
await deps.sessionRepository.markFailed(rowId).catch(() => {});
|
|
86548
|
-
return;
|
|
86871
|
+
if (event.type === "session.idle") {
|
|
86872
|
+
handleSessionIdle(handle, handle.journal, idleConfig, deps.sessionRepository).catch((err) => console.warn("[direct-harness] idle handler error (resume):", err));
|
|
86549
86873
|
}
|
|
86550
|
-
|
|
86551
|
-
|
|
86552
|
-
|
|
86553
|
-
agent: info?.lastUsedConfig.agent ?? "build",
|
|
86554
|
-
model: info?.lastUsedConfig.model
|
|
86555
|
-
};
|
|
86556
|
-
let lastBoundKey = null;
|
|
86557
|
-
handle.session.onEvent((event) => {
|
|
86558
|
-
const turn = handle.currentTurn;
|
|
86559
|
-
if (turn?.messageId !== null && turn?.messageId !== undefined) {
|
|
86560
|
-
const key = `${turn.turnId}:${turn.messageId}`;
|
|
86561
|
-
if (key !== lastBoundKey) {
|
|
86562
|
-
lastBoundKey = key;
|
|
86563
|
-
deps.sessionRepository.bindTurnMessageId(turn.turnId, turn.messageId).catch((err) => console.warn("[direct-harness] bindTurnMessageId error (resume):", err));
|
|
86564
|
-
}
|
|
86565
|
-
}
|
|
86566
|
-
if (event.type === "session.idle") {
|
|
86567
|
-
handleSessionIdle(handle, handle.journal, idleConfig, deps.sessionRepository).catch((err) => console.warn("[direct-harness] idle handler error (resume):", err));
|
|
86568
|
-
}
|
|
86569
|
-
});
|
|
86570
|
-
}
|
|
86874
|
+
});
|
|
86875
|
+
}
|
|
86876
|
+
async function deliverPendingMessages(handle, deps, rowId, messages, info) {
|
|
86571
86877
|
for (const msg of messages) {
|
|
86572
86878
|
const override = info?.lastUsedConfig ?? { agent: "build" };
|
|
86573
86879
|
try {
|
|
@@ -86591,6 +86897,24 @@ async function processSessionMessages(session2, deps, rowId, messages, info) {
|
|
|
86591
86897
|
}
|
|
86592
86898
|
}
|
|
86593
86899
|
}
|
|
86900
|
+
async function processSessionMessages(session2, deps, rowId, messages, info) {
|
|
86901
|
+
let handle = deps.activeSessions.get(rowId);
|
|
86902
|
+
if (!handle) {
|
|
86903
|
+
if (!info) {
|
|
86904
|
+
console.warn(`[direct-harness] Session ${rowId} not yet open — waiting for session-subscriber`);
|
|
86905
|
+
return;
|
|
86906
|
+
}
|
|
86907
|
+
const resumed = await resumeSessionHandle(session2, deps, rowId, info);
|
|
86908
|
+
if (!resumed) {
|
|
86909
|
+
return;
|
|
86910
|
+
}
|
|
86911
|
+
handle = resumed;
|
|
86912
|
+
deps.activeSessions.set(rowId, handle);
|
|
86913
|
+
await deps.sessionRepository.markActive(rowId).catch(() => {});
|
|
86914
|
+
wireResumedSessionEvents(handle, deps, info);
|
|
86915
|
+
}
|
|
86916
|
+
await deliverPendingMessages(handle, deps, rowId, messages, info);
|
|
86917
|
+
}
|
|
86594
86918
|
var init_prompt_subscriber = __esm(() => {
|
|
86595
86919
|
init_idle_handler();
|
|
86596
86920
|
init_api3();
|
|
@@ -86619,6 +86943,60 @@ function startSessionSubscriber(daemonSession, wsClient2, deps) {
|
|
|
86619
86943
|
});
|
|
86620
86944
|
return { stop: unsub };
|
|
86621
86945
|
}
|
|
86946
|
+
async function getOrCreateHarness(daemonSession, deps, session2, workspace) {
|
|
86947
|
+
let harness = deps.harnesses.get(session2.workspaceId);
|
|
86948
|
+
if (harness && !harness.isAlive()) {
|
|
86949
|
+
console.warn(`[direct-harness] Harness for workspace ${session2.workspaceId} is no longer alive — restarting`);
|
|
86950
|
+
harness.close().catch(() => {});
|
|
86951
|
+
deps.harnesses.delete(session2.workspaceId);
|
|
86952
|
+
harness = undefined;
|
|
86953
|
+
}
|
|
86954
|
+
if (!harness) {
|
|
86955
|
+
harness = await startOpencodeSdkHarness({
|
|
86956
|
+
type: "opencode",
|
|
86957
|
+
workingDir: workspace.workingDir,
|
|
86958
|
+
workspaceId: session2.workspaceId
|
|
86959
|
+
});
|
|
86960
|
+
deps.harnesses.set(session2.workspaceId, harness);
|
|
86961
|
+
}
|
|
86962
|
+
return harness;
|
|
86963
|
+
}
|
|
86964
|
+
function recordLiveSessionChunk(event, handle, journal, extractChunk, deps) {
|
|
86965
|
+
const chunk2 = extractChunk(event);
|
|
86966
|
+
if (chunk2 === null) {
|
|
86967
|
+
return;
|
|
86968
|
+
}
|
|
86969
|
+
journal.record({
|
|
86970
|
+
content: chunk2.content,
|
|
86971
|
+
timestamp: Date.now(),
|
|
86972
|
+
messageId: chunk2.messageId,
|
|
86973
|
+
partType: chunk2.partType
|
|
86974
|
+
});
|
|
86975
|
+
if (handle.currentTurn && handle.currentTurn.messageId === null) {
|
|
86976
|
+
handle.currentTurn.messageId = chunk2.messageId;
|
|
86977
|
+
deps.sessionRepository.bindTurnMessageId(handle.currentTurn.turnId, chunk2.messageId).catch((err) => console.warn("[direct-harness] bindTurnMessageId error:", err));
|
|
86978
|
+
}
|
|
86979
|
+
}
|
|
86980
|
+
function handleLiveSessionTitleUpdate(event, deps, rowId, liveSession) {
|
|
86981
|
+
if (event.type !== "session.updated") {
|
|
86982
|
+
return;
|
|
86983
|
+
}
|
|
86984
|
+
const info = event.payload.info;
|
|
86985
|
+
const newTitle = info?.title;
|
|
86986
|
+
if (!newTitle || newTitle === liveSession.sessionTitle) {
|
|
86987
|
+
return;
|
|
86988
|
+
}
|
|
86989
|
+
liveSession.setTitle?.(newTitle);
|
|
86990
|
+
deps.sessionRepository.updateSessionTitle(rowId, newTitle).catch((err) => console.warn("[direct-harness] updateSessionTitle error:", err));
|
|
86991
|
+
}
|
|
86992
|
+
function handleLiveSessionEvent(event, ctx) {
|
|
86993
|
+
const { handle, journal, extractChunk, idleConfig, deps, rowId, liveSession } = ctx;
|
|
86994
|
+
recordLiveSessionChunk(event, handle, journal, extractChunk, deps);
|
|
86995
|
+
if (event.type === "session.idle") {
|
|
86996
|
+
handleSessionIdle(handle, journal, idleConfig, deps.sessionRepository).catch((err) => console.warn("[direct-harness] idle handler error:", err));
|
|
86997
|
+
}
|
|
86998
|
+
handleLiveSessionTitleUpdate(event, deps, rowId, liveSession);
|
|
86999
|
+
}
|
|
86622
87000
|
async function processOne(daemonSession, deps, session2) {
|
|
86623
87001
|
const rowId = session2._id;
|
|
86624
87002
|
try {
|
|
@@ -86631,21 +87009,7 @@ async function processOne(daemonSession, deps, session2) {
|
|
|
86631
87009
|
await deps.sessionRepository.markFailed(rowId);
|
|
86632
87010
|
return;
|
|
86633
87011
|
}
|
|
86634
|
-
|
|
86635
|
-
if (harness && !harness.isAlive()) {
|
|
86636
|
-
console.warn(`[direct-harness] Harness for workspace ${session2.workspaceId} is no longer alive — restarting`);
|
|
86637
|
-
harness.close().catch(() => {});
|
|
86638
|
-
deps.harnesses.delete(session2.workspaceId);
|
|
86639
|
-
harness = undefined;
|
|
86640
|
-
}
|
|
86641
|
-
if (!harness) {
|
|
86642
|
-
harness = await startOpencodeSdkHarness({
|
|
86643
|
-
type: "opencode",
|
|
86644
|
-
workingDir: workspace.workingDir,
|
|
86645
|
-
workspaceId: session2.workspaceId
|
|
86646
|
-
});
|
|
86647
|
-
deps.harnesses.set(session2.workspaceId, harness);
|
|
86648
|
-
}
|
|
87012
|
+
const harness = await getOrCreateHarness(daemonSession, deps, session2, workspace);
|
|
86649
87013
|
const liveSession = await harness.newSession({
|
|
86650
87014
|
agent: session2.opencode?.lastUsedConfig.agent ?? "build",
|
|
86651
87015
|
harnessSessionId: rowId
|
|
@@ -86677,30 +87041,15 @@ async function processOne(daemonSession, deps, session2) {
|
|
|
86677
87041
|
close: close2
|
|
86678
87042
|
};
|
|
86679
87043
|
unsubscribeEvents = liveSession.onEvent((event) => {
|
|
86680
|
-
|
|
86681
|
-
|
|
86682
|
-
journal
|
|
86683
|
-
|
|
86684
|
-
|
|
86685
|
-
|
|
86686
|
-
|
|
86687
|
-
|
|
86688
|
-
|
|
86689
|
-
handle.currentTurn.messageId = chunk2.messageId;
|
|
86690
|
-
deps.sessionRepository.bindTurnMessageId(handle.currentTurn.turnId, chunk2.messageId).catch((err) => console.warn("[direct-harness] bindTurnMessageId error:", err));
|
|
86691
|
-
}
|
|
86692
|
-
}
|
|
86693
|
-
if (event.type === "session.idle") {
|
|
86694
|
-
handleSessionIdle(handle, journal, idleConfig, deps.sessionRepository).catch((err) => console.warn("[direct-harness] idle handler error:", err));
|
|
86695
|
-
}
|
|
86696
|
-
if (event.type === "session.updated") {
|
|
86697
|
-
const info = event.payload.info;
|
|
86698
|
-
const newTitle = info?.title;
|
|
86699
|
-
if (newTitle && newTitle !== liveSession.sessionTitle) {
|
|
86700
|
-
liveSession.setTitle?.(newTitle);
|
|
86701
|
-
deps.sessionRepository.updateSessionTitle(rowId, newTitle).catch((err) => console.warn("[direct-harness] updateSessionTitle error:", err));
|
|
86702
|
-
}
|
|
86703
|
-
}
|
|
87044
|
+
handleLiveSessionEvent(event, {
|
|
87045
|
+
handle,
|
|
87046
|
+
journal,
|
|
87047
|
+
extractChunk,
|
|
87048
|
+
idleConfig,
|
|
87049
|
+
deps,
|
|
87050
|
+
rowId,
|
|
87051
|
+
liveSession
|
|
87052
|
+
});
|
|
86704
87053
|
});
|
|
86705
87054
|
deps.activeSessions.set(rowId, handle);
|
|
86706
87055
|
try {
|
|
@@ -87528,16 +87877,14 @@ var init_state_recovery = __esm(() => {
|
|
|
87528
87877
|
for (const config3 of configsResult.configs) {
|
|
87529
87878
|
if (config3.machineId === session2.machineId && config3.workingDir) {
|
|
87530
87879
|
registeredCount++;
|
|
87531
|
-
exports_Effect.
|
|
87880
|
+
yield* exports_Effect.forkDaemon(exports_Effect.tryPromise(() => session2.backend.mutation(api.workspaces.registerWorkspace, {
|
|
87532
87881
|
sessionId: session2.sessionId,
|
|
87533
87882
|
chatroomId,
|
|
87534
87883
|
machineId: session2.machineId,
|
|
87535
87884
|
workingDir: config3.workingDir,
|
|
87536
87885
|
hostname: session2.config?.hostname ?? "unknown",
|
|
87537
87886
|
registeredBy: config3.role
|
|
87538
|
-
}))
|
|
87539
|
-
console.warn(`[daemon] ⚠️ Failed to register workspace on recovery: ${err.message}`);
|
|
87540
|
-
});
|
|
87887
|
+
})).pipe(exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[daemon] ⚠️ Failed to register workspace on recovery: ${err.message}`)))));
|
|
87541
87888
|
}
|
|
87542
87889
|
}
|
|
87543
87890
|
}), () => exports_Effect.void);
|
|
@@ -87608,16 +87955,18 @@ class DaemonEventBus {
|
|
|
87608
87955
|
}
|
|
87609
87956
|
|
|
87610
87957
|
// src/events/daemon/agent/on-agent-exited.ts
|
|
87611
|
-
|
|
87612
|
-
|
|
87958
|
+
var onAgentExitedEffect = (payload) => exports_Effect.gen(function* () {
|
|
87959
|
+
const apm = yield* DaemonAgentProcessManagerService;
|
|
87960
|
+
yield* apm.handleExit({
|
|
87613
87961
|
chatroomId: payload.chatroomId,
|
|
87614
87962
|
role: payload.role,
|
|
87615
87963
|
pid: payload.pid,
|
|
87616
87964
|
code: payload.code,
|
|
87617
87965
|
signal: payload.signal
|
|
87618
87966
|
});
|
|
87619
|
-
}
|
|
87967
|
+
});
|
|
87620
87968
|
var init_on_agent_exited = __esm(() => {
|
|
87969
|
+
init_esm();
|
|
87621
87970
|
init_daemon_services();
|
|
87622
87971
|
});
|
|
87623
87972
|
|
|
@@ -87638,9 +87987,11 @@ var init_on_agent_stopped = () => {};
|
|
|
87638
87987
|
// src/events/daemon/register-listeners.ts
|
|
87639
87988
|
var registerEventListenersEffect = () => exports_Effect.gen(function* () {
|
|
87640
87989
|
const session2 = yield* DaemonSessionService;
|
|
87641
|
-
const
|
|
87990
|
+
const runtime4 = yield* exports_Effect.runtime();
|
|
87642
87991
|
const unsubs = [];
|
|
87643
|
-
unsubs.push(session2.events.on("agent:exited", (payload) =>
|
|
87992
|
+
unsubs.push(session2.events.on("agent:exited", (payload) => {
|
|
87993
|
+
exports_Runtime.runFork(runtime4)(onAgentExitedEffect(payload));
|
|
87994
|
+
}));
|
|
87644
87995
|
unsubs.push(session2.events.on("agent:started", (payload) => logAgentStarted(payload)));
|
|
87645
87996
|
unsubs.push(session2.events.on("agent:stopped", (payload) => logAgentStopped(payload)));
|
|
87646
87997
|
return () => {
|
|
@@ -87960,9 +88311,131 @@ var init_decide_resume_path = __esm(() => {
|
|
|
87960
88311
|
]);
|
|
87961
88312
|
});
|
|
87962
88313
|
|
|
88314
|
+
// src/domain/agent-lifecycle/entities/agent-slot.ts
|
|
88315
|
+
function agentKey2(chatroomId, role) {
|
|
88316
|
+
return `${chatroomId}:${role.toLowerCase()}`;
|
|
88317
|
+
}
|
|
88318
|
+
var idleSlot = () => ({ state: "idle" });
|
|
88319
|
+
// src/domain/agent-lifecycle/policies/slot-transitions.ts
|
|
88320
|
+
function makeError(tag, from, event) {
|
|
88321
|
+
return {
|
|
88322
|
+
ok: false,
|
|
88323
|
+
error: { _tag: tag, from, event }
|
|
88324
|
+
};
|
|
88325
|
+
}
|
|
88326
|
+
function makeResult(slot) {
|
|
88327
|
+
return { ok: true, slot };
|
|
88328
|
+
}
|
|
88329
|
+
function transitionFromIdle(slot, event) {
|
|
88330
|
+
if (event.type === "ensure_running_requested") {
|
|
88331
|
+
return makeResult(slot);
|
|
88332
|
+
}
|
|
88333
|
+
if (event.type === "spawn_started") {
|
|
88334
|
+
return makeResult({ ...slot, state: "spawning", pendingOperationKey: event.operationKey });
|
|
88335
|
+
}
|
|
88336
|
+
if (event.type === "process_exited") {
|
|
88337
|
+
return makeResult(slot);
|
|
88338
|
+
}
|
|
88339
|
+
return makeError("InvalidTransition", slot.state, event.type);
|
|
88340
|
+
}
|
|
88341
|
+
function transitionFromSpawning(slot, event) {
|
|
88342
|
+
if (event.type === "spawn_started") {
|
|
88343
|
+
return makeResult({ ...slot, pendingOperationKey: event.operationKey });
|
|
88344
|
+
}
|
|
88345
|
+
if (event.type === "spawn_succeeded") {
|
|
88346
|
+
return makeResult({ ...slot, state: "running", pid: event.pid });
|
|
88347
|
+
}
|
|
88348
|
+
if (event.type === "spawn_failed" || event.type === "process_exited") {
|
|
88349
|
+
return makeResult({ state: "idle" });
|
|
88350
|
+
}
|
|
88351
|
+
return makeError("InvalidTransition", slot.state, event.type);
|
|
88352
|
+
}
|
|
88353
|
+
function transitionFromRunning(slot, event) {
|
|
88354
|
+
if (event.type === "stop_requested") {
|
|
88355
|
+
return makeResult({ ...slot, state: "stopping", pendingOperationKey: event.operationKey });
|
|
88356
|
+
}
|
|
88357
|
+
if (event.type === "process_exited") {
|
|
88358
|
+
if (slot.pid !== undefined && slot.pid !== event.pid) {
|
|
88359
|
+
return { ok: false, error: { _tag: "StalePid", expected: slot.pid, got: event.pid } };
|
|
88360
|
+
}
|
|
88361
|
+
return makeResult({ state: "idle" });
|
|
88362
|
+
}
|
|
88363
|
+
if (event.type === "stale_process_detected") {
|
|
88364
|
+
return makeResult({ state: "idle" });
|
|
88365
|
+
}
|
|
88366
|
+
return makeError("InvalidTransition", slot.state, event.type);
|
|
88367
|
+
}
|
|
88368
|
+
function transitionFromStopping(slot, event) {
|
|
88369
|
+
if (event.type === "stop_completed") {
|
|
88370
|
+
return makeResult({ state: "idle" });
|
|
88371
|
+
}
|
|
88372
|
+
if (event.type === "process_exited") {
|
|
88373
|
+
return { ok: false, error: { _tag: "IgnoredDuplicateExit" } };
|
|
88374
|
+
}
|
|
88375
|
+
return makeError("InvalidTransition", slot.state, event.type);
|
|
88376
|
+
}
|
|
88377
|
+
function transitionSlot(slot, event) {
|
|
88378
|
+
switch (slot.state) {
|
|
88379
|
+
case "idle":
|
|
88380
|
+
return transitionFromIdle(slot, event);
|
|
88381
|
+
case "spawning":
|
|
88382
|
+
return transitionFromSpawning(slot, event);
|
|
88383
|
+
case "running":
|
|
88384
|
+
return transitionFromRunning(slot, event);
|
|
88385
|
+
case "stopping":
|
|
88386
|
+
return transitionFromStopping(slot, event);
|
|
88387
|
+
}
|
|
88388
|
+
}
|
|
88389
|
+
function shouldIgnoreProcessExit(slot, exitPid) {
|
|
88390
|
+
if (slot.state === "stopping")
|
|
88391
|
+
return true;
|
|
88392
|
+
if (slot.pid !== undefined && slot.pid !== exitPid)
|
|
88393
|
+
return true;
|
|
88394
|
+
return false;
|
|
88395
|
+
}
|
|
88396
|
+
|
|
88397
|
+
// src/domain/agent-lifecycle/policies/restart-decision.ts
|
|
88398
|
+
function decideRestartAfterExit(input) {
|
|
88399
|
+
if (!shouldAutoRestartAfterProcessExit(input.stopReason)) {
|
|
88400
|
+
return { _tag: "NoRestart", reason: `Intentional stop: ${input.stopReason}` };
|
|
88401
|
+
}
|
|
88402
|
+
if (!input.harness || !input.workingDir) {
|
|
88403
|
+
return { _tag: "NoRestart", reason: "Missing harness or workingDir" };
|
|
88404
|
+
}
|
|
88405
|
+
if (input.isPermanentFailure) {
|
|
88406
|
+
return {
|
|
88407
|
+
_tag: "NoRestart",
|
|
88408
|
+
reason: input.permanentFailureMessage ?? "Permanent failure"
|
|
88409
|
+
};
|
|
88410
|
+
}
|
|
88411
|
+
if (input.backoffWaitMs && input.backoffWaitMs > 0) {
|
|
88412
|
+
return {
|
|
88413
|
+
_tag: "ScheduleRetry",
|
|
88414
|
+
waitMs: input.backoffWaitMs,
|
|
88415
|
+
spawnReason: "platform.crash_recovery",
|
|
88416
|
+
wantResume: input.wantResume
|
|
88417
|
+
};
|
|
88418
|
+
}
|
|
88419
|
+
return {
|
|
88420
|
+
_tag: "RestartNow",
|
|
88421
|
+
spawnReason: "platform.crash_recovery",
|
|
88422
|
+
wantResume: input.wantResume,
|
|
88423
|
+
bypassConcurrentLimit: true
|
|
88424
|
+
};
|
|
88425
|
+
}
|
|
88426
|
+
var init_restart_decision = __esm(() => {
|
|
88427
|
+
init_decide_resume_path();
|
|
88428
|
+
});
|
|
88429
|
+
|
|
88430
|
+
// src/domain/agent-lifecycle/policies/spawn-gate.ts
|
|
88431
|
+
function shouldBypassConcurrentLimit(spawnReason) {
|
|
88432
|
+
return spawnReason.startsWith("user.") || spawnReason === "platform.crash_recovery";
|
|
88433
|
+
}
|
|
88434
|
+
|
|
87963
88435
|
// src/domain/agent-lifecycle/index.ts
|
|
87964
88436
|
var init_agent_lifecycle = __esm(() => {
|
|
87965
88437
|
init_decide_resume_path();
|
|
88438
|
+
init_restart_decision();
|
|
87966
88439
|
});
|
|
87967
88440
|
|
|
87968
88441
|
// src/domain/agent-lifecycle/policies/append-recent-log-line.ts
|
|
@@ -88158,6 +88631,90 @@ class RapidResumeTracker {
|
|
|
88158
88631
|
}
|
|
88159
88632
|
var RAPID_RESUME_WINDOW_MS = 30000, RAPID_RESUME_THRESHOLD = 5;
|
|
88160
88633
|
|
|
88634
|
+
// src/infrastructure/services/agent-lifecycle/agent-lifecycle-port-adapters.ts
|
|
88635
|
+
function createSpawnPort(spawning) {
|
|
88636
|
+
return {
|
|
88637
|
+
shouldAllowSpawn: (chatroomId, reason, options) => spawning.shouldAllowSpawn(chatroomId, reason, options),
|
|
88638
|
+
recordSpawn: (chatroomId) => exports_Effect.sync(() => {
|
|
88639
|
+
spawning.recordSpawn(chatroomId);
|
|
88640
|
+
}),
|
|
88641
|
+
recordExit: (chatroomId) => exports_Effect.sync(() => {
|
|
88642
|
+
spawning.recordExit(chatroomId);
|
|
88643
|
+
})
|
|
88644
|
+
};
|
|
88645
|
+
}
|
|
88646
|
+
function createHarnessSpawnPort(deps) {
|
|
88647
|
+
return {
|
|
88648
|
+
spawn: (args2) => exports_Effect.tryPromise({
|
|
88649
|
+
try: async () => {
|
|
88650
|
+
const service3 = deps.agentServices.get(args2.harness);
|
|
88651
|
+
if (!service3) {
|
|
88652
|
+
throw new Error(`Unknown agent harness: ${args2.harness}`);
|
|
88653
|
+
}
|
|
88654
|
+
const result = await service3.spawn({
|
|
88655
|
+
workingDir: args2.workingDir,
|
|
88656
|
+
prompt: args2.prompt,
|
|
88657
|
+
systemPrompt: args2.systemPrompt ?? "",
|
|
88658
|
+
model: args2.model,
|
|
88659
|
+
context: {
|
|
88660
|
+
machineId: deps.machineId,
|
|
88661
|
+
chatroomId: args2.chatroomId,
|
|
88662
|
+
role: args2.role
|
|
88663
|
+
}
|
|
88664
|
+
});
|
|
88665
|
+
return {
|
|
88666
|
+
pid: result.pid,
|
|
88667
|
+
harnessSessionId: result.harnessSessionId,
|
|
88668
|
+
onAgentEnd: (cb) => {
|
|
88669
|
+
result.onAgentEnd?.(cb);
|
|
88670
|
+
},
|
|
88671
|
+
onLogLine: result.onLogLine ? (lineCb) => {
|
|
88672
|
+
result.onLogLine?.((line) => {
|
|
88673
|
+
lineCb(line);
|
|
88674
|
+
});
|
|
88675
|
+
} : undefined
|
|
88676
|
+
};
|
|
88677
|
+
},
|
|
88678
|
+
catch: (e) => e instanceof Error ? e : new Error(String(e))
|
|
88679
|
+
}),
|
|
88680
|
+
stop: (pid, opts) => exports_Effect.tryPromise({
|
|
88681
|
+
try: async () => {
|
|
88682
|
+
for (const service3 of deps.agentServices.values()) {
|
|
88683
|
+
try {
|
|
88684
|
+
await service3.stop(pid, opts);
|
|
88685
|
+
return;
|
|
88686
|
+
} catch {}
|
|
88687
|
+
}
|
|
88688
|
+
},
|
|
88689
|
+
catch: (e) => e instanceof Error ? e : new Error(String(e))
|
|
88690
|
+
}),
|
|
88691
|
+
isAlive: (pid) => exports_Effect.sync(() => {
|
|
88692
|
+
return isProcessAlive((p) => process.kill(p, 0), pid);
|
|
88693
|
+
})
|
|
88694
|
+
};
|
|
88695
|
+
}
|
|
88696
|
+
function createAgentLifecyclePorts(deps) {
|
|
88697
|
+
return {
|
|
88698
|
+
spawn: createSpawnPort(deps.spawning),
|
|
88699
|
+
harness: createHarnessSpawnPort(deps),
|
|
88700
|
+
sessionId: deps.sessionId,
|
|
88701
|
+
machineId: deps.machineId
|
|
88702
|
+
};
|
|
88703
|
+
}
|
|
88704
|
+
var init_agent_lifecycle_port_adapters = __esm(() => {
|
|
88705
|
+
init_esm();
|
|
88706
|
+
});
|
|
88707
|
+
|
|
88708
|
+
// src/infrastructure/services/agent-lifecycle/agent-lifecycle-types.ts
|
|
88709
|
+
var AgentLifecyclePorts, AgentLifecycleService;
|
|
88710
|
+
var init_agent_lifecycle_types = __esm(() => {
|
|
88711
|
+
init_esm();
|
|
88712
|
+
AgentLifecyclePorts = class AgentLifecyclePorts extends exports_Context.Tag("AgentLifecyclePorts")() {
|
|
88713
|
+
};
|
|
88714
|
+
AgentLifecycleService = class AgentLifecycleService extends exports_Context.Tag("AgentLifecycleService")() {
|
|
88715
|
+
};
|
|
88716
|
+
});
|
|
88717
|
+
|
|
88161
88718
|
// src/infrastructure/services/remote-agents/spawn-prompt.ts
|
|
88162
88719
|
function createSpawnPrompt(raw) {
|
|
88163
88720
|
const trimmed = raw?.trim();
|
|
@@ -88165,8 +88722,264 @@ function createSpawnPrompt(raw) {
|
|
|
88165
88722
|
}
|
|
88166
88723
|
var DEFAULT_TRIGGER_PROMPT = "Please read your system prompt carefully and follow the Getting Started instructions.";
|
|
88167
88724
|
|
|
88725
|
+
// src/infrastructure/services/agent-lifecycle/agent-lifecycle-service.ts
|
|
88726
|
+
var AgentLifecycleServiceLive;
|
|
88727
|
+
var init_agent_lifecycle_service = __esm(() => {
|
|
88728
|
+
init_esm();
|
|
88729
|
+
init_agent_lifecycle_types();
|
|
88730
|
+
init_agent_lifecycle();
|
|
88731
|
+
AgentLifecycleServiceLive = exports_Layer.effect(AgentLifecycleService, exports_Effect.gen(function* () {
|
|
88732
|
+
const ports = yield* AgentLifecyclePorts;
|
|
88733
|
+
const slotsRef = yield* exports_Ref.make(new Map);
|
|
88734
|
+
const getSlotFromRef = (key) => exports_Ref.get(slotsRef).pipe(exports_Effect.map((map18) => map18.get(key)));
|
|
88735
|
+
const setSlotInRef = (key, slot) => exports_Ref.update(slotsRef, (map18) => map18.set(key, slot));
|
|
88736
|
+
const removeSlotFromRef = (key) => exports_Ref.update(slotsRef, (map18) => {
|
|
88737
|
+
const next4 = new Map(map18);
|
|
88738
|
+
next4.delete(key);
|
|
88739
|
+
return next4;
|
|
88740
|
+
});
|
|
88741
|
+
const spawnAndRegister = (key, opts) => exports_Effect.gen(function* () {
|
|
88742
|
+
let slot = {
|
|
88743
|
+
...idleSlot(),
|
|
88744
|
+
harness: opts.agentHarness,
|
|
88745
|
+
model: opts.model,
|
|
88746
|
+
workingDir: opts.workingDir,
|
|
88747
|
+
wantResume: opts.wantResume,
|
|
88748
|
+
_initPrompt: opts.initPrompt ?? "",
|
|
88749
|
+
_systemPrompt: opts.systemPrompt
|
|
88750
|
+
};
|
|
88751
|
+
const startedResult = transitionSlot(slot, {
|
|
88752
|
+
type: "spawn_started",
|
|
88753
|
+
operationKey: opts.reason
|
|
88754
|
+
});
|
|
88755
|
+
if (!startedResult.ok) {
|
|
88756
|
+
return { success: false, error: "spawn_failed" };
|
|
88757
|
+
}
|
|
88758
|
+
slot = startedResult.slot;
|
|
88759
|
+
const spawnHandle = yield* ports.harness.spawn({
|
|
88760
|
+
harness: opts.agentHarness,
|
|
88761
|
+
chatroomId: opts.chatroomId,
|
|
88762
|
+
role: opts.role,
|
|
88763
|
+
workingDir: opts.workingDir,
|
|
88764
|
+
model: opts.model,
|
|
88765
|
+
prompt: createSpawnPrompt(opts.initPrompt),
|
|
88766
|
+
systemPrompt: opts.systemPrompt
|
|
88767
|
+
}).pipe(exports_Effect.catchAll(() => exports_Effect.succeed(null)));
|
|
88768
|
+
if (!spawnHandle) {
|
|
88769
|
+
return { success: false, error: "spawn_failed" };
|
|
88770
|
+
}
|
|
88771
|
+
const succeededResult = transitionSlot(slot, {
|
|
88772
|
+
type: "spawn_succeeded",
|
|
88773
|
+
pid: spawnHandle.pid
|
|
88774
|
+
});
|
|
88775
|
+
if (!succeededResult.ok) {
|
|
88776
|
+
return { success: false, error: "spawn_failed" };
|
|
88777
|
+
}
|
|
88778
|
+
slot = succeededResult.slot;
|
|
88779
|
+
yield* ports.spawn.recordSpawn(opts.chatroomId);
|
|
88780
|
+
yield* setSlotInRef(key, slot);
|
|
88781
|
+
if (spawnHandle) {
|
|
88782
|
+
spawnHandle.onAgentEnd(() => {});
|
|
88783
|
+
}
|
|
88784
|
+
if (spawnHandle && spawnHandle.harnessSessionId) {
|
|
88785
|
+
const updatedSlot = { ...slot, harnessSessionId: spawnHandle.harnessSessionId };
|
|
88786
|
+
yield* setSlotInRef(key, updatedSlot);
|
|
88787
|
+
}
|
|
88788
|
+
return { success: true, pid: slot.pid };
|
|
88789
|
+
});
|
|
88790
|
+
const ensureRunning = (opts) => exports_Effect.gen(function* () {
|
|
88791
|
+
const key = agentKey2(opts.chatroomId, opts.role);
|
|
88792
|
+
const currentSlot = yield* getSlotFromRef(key);
|
|
88793
|
+
if (currentSlot && currentSlot.state !== "idle") {
|
|
88794
|
+
return {
|
|
88795
|
+
success: true,
|
|
88796
|
+
pid: currentSlot.pid
|
|
88797
|
+
};
|
|
88798
|
+
}
|
|
88799
|
+
const bypass = shouldBypassConcurrentLimit(opts.reason);
|
|
88800
|
+
const allowResult = ports.spawn.shouldAllowSpawn(opts.chatroomId, opts.reason, bypass ? { bypassConcurrentLimit: true } : undefined);
|
|
88801
|
+
if (!allowResult.allowed) {
|
|
88802
|
+
const error = allowResult.retryAfterMs ? "rate_limited" : "backoff";
|
|
88803
|
+
return { success: false, error };
|
|
88804
|
+
}
|
|
88805
|
+
const result = yield* spawnAndRegister(key, opts);
|
|
88806
|
+
if (!result.success && result.error) {
|
|
88807
|
+
yield* exports_Effect.logError(`Agent spawn failed for ${key}: ${result.error}`);
|
|
88808
|
+
}
|
|
88809
|
+
return result;
|
|
88810
|
+
});
|
|
88811
|
+
const stop4 = (opts) => exports_Effect.gen(function* () {
|
|
88812
|
+
const key = agentKey2(opts.chatroomId, opts.role);
|
|
88813
|
+
const slot = yield* getSlotFromRef(key);
|
|
88814
|
+
if (!slot) {
|
|
88815
|
+
return { success: false };
|
|
88816
|
+
}
|
|
88817
|
+
const stoppingResult = transitionSlot(slot, {
|
|
88818
|
+
type: "stop_requested",
|
|
88819
|
+
operationKey: opts.reason
|
|
88820
|
+
});
|
|
88821
|
+
if (!stoppingResult.ok) {
|
|
88822
|
+
return { success: false };
|
|
88823
|
+
}
|
|
88824
|
+
const stoppingSlot = stoppingResult.slot;
|
|
88825
|
+
yield* setSlotInRef(key, stoppingSlot);
|
|
88826
|
+
if (stoppingSlot.pid) {
|
|
88827
|
+
yield* ports.harness.stop(stoppingSlot.pid, { preserveForResume: false }).pipe(exports_Effect.ignore);
|
|
88828
|
+
}
|
|
88829
|
+
yield* ports.spawn.recordExit(opts.chatroomId);
|
|
88830
|
+
const completedResult = transitionSlot(stoppingSlot, {
|
|
88831
|
+
type: "stop_completed"
|
|
88832
|
+
});
|
|
88833
|
+
if (completedResult.ok) {
|
|
88834
|
+
yield* setSlotInRef(key, completedResult.slot);
|
|
88835
|
+
}
|
|
88836
|
+
return { success: true };
|
|
88837
|
+
});
|
|
88838
|
+
const executeRestart = (slot, chatroomId, role) => exports_Effect.gen(function* () {
|
|
88839
|
+
const restartOutcome = decideRestartAfterExit({
|
|
88840
|
+
stopReason: resolveStopReason(slot._stopReasonCode ?? 0, slot._stopReasonSignal ?? null),
|
|
88841
|
+
harness: slot.harness,
|
|
88842
|
+
workingDir: slot.workingDir,
|
|
88843
|
+
wantResume: slot.wantResume ?? false,
|
|
88844
|
+
isPermanentFailure: false,
|
|
88845
|
+
restartAllowed: true
|
|
88846
|
+
});
|
|
88847
|
+
yield* dispatchRestartOutcome(restartOutcome, slot, chatroomId, role);
|
|
88848
|
+
});
|
|
88849
|
+
const dispatchRestartOutcome = (outcome, slot, chatroomId, role) => exports_Effect.gen(function* () {
|
|
88850
|
+
switch (outcome._tag) {
|
|
88851
|
+
case "RestartNow": {
|
|
88852
|
+
yield* handleRestartNow(slot, chatroomId, role, outcome);
|
|
88853
|
+
break;
|
|
88854
|
+
}
|
|
88855
|
+
case "ScheduleRetry": {
|
|
88856
|
+
yield* handleScheduleRetry(slot, chatroomId, role, outcome);
|
|
88857
|
+
break;
|
|
88858
|
+
}
|
|
88859
|
+
case "NoRestart": {
|
|
88860
|
+
break;
|
|
88861
|
+
}
|
|
88862
|
+
}
|
|
88863
|
+
});
|
|
88864
|
+
const handleRestartNow = (slot, chatroomId, role, outcome) => exports_Effect.gen(function* () {
|
|
88865
|
+
if (!slot.harness) {
|
|
88866
|
+
yield* exports_Effect.logError(`Agent restart failed for ${chatroomId}:${role}: missing harness`);
|
|
88867
|
+
return;
|
|
88868
|
+
}
|
|
88869
|
+
const restartResult = yield* ensureRunning({
|
|
88870
|
+
chatroomId,
|
|
88871
|
+
role,
|
|
88872
|
+
agentHarness: slot.harness,
|
|
88873
|
+
workingDir: slot.workingDir ?? "",
|
|
88874
|
+
reason: outcome.spawnReason,
|
|
88875
|
+
wantResume: outcome.wantResume,
|
|
88876
|
+
initPrompt: slot._initPrompt,
|
|
88877
|
+
systemPrompt: slot._systemPrompt
|
|
88878
|
+
});
|
|
88879
|
+
if (!restartResult.success && restartResult.error) {
|
|
88880
|
+
yield* exports_Effect.logError(`Agent restart failed for ${chatroomId}:${role}: ${restartResult.error}`);
|
|
88881
|
+
}
|
|
88882
|
+
});
|
|
88883
|
+
const handleScheduleRetry = (slot, chatroomId, role, outcome) => exports_Effect.gen(function* () {
|
|
88884
|
+
if (!slot.harness) {
|
|
88885
|
+
yield* exports_Effect.logError(`Agent restart failed for ${chatroomId}:${role}: missing harness`);
|
|
88886
|
+
return;
|
|
88887
|
+
}
|
|
88888
|
+
yield* exports_Effect.forkDaemon(exports_Effect.sleep(exports_Duration.millis(outcome.waitMs)).pipe(exports_Effect.as(ensureRunning({
|
|
88889
|
+
chatroomId,
|
|
88890
|
+
role,
|
|
88891
|
+
agentHarness: slot.harness,
|
|
88892
|
+
workingDir: slot.workingDir ?? "",
|
|
88893
|
+
reason: outcome.spawnReason,
|
|
88894
|
+
wantResume: outcome.wantResume,
|
|
88895
|
+
initPrompt: slot._initPrompt,
|
|
88896
|
+
systemPrompt: slot._systemPrompt
|
|
88897
|
+
}))));
|
|
88898
|
+
});
|
|
88899
|
+
const handleExit = (opts) => exports_Effect.gen(function* () {
|
|
88900
|
+
const key = agentKey2(opts.chatroomId, opts.role);
|
|
88901
|
+
const slot = yield* getSlotFromRef(key);
|
|
88902
|
+
if (!slot) {
|
|
88903
|
+
return;
|
|
88904
|
+
}
|
|
88905
|
+
if (shouldIgnoreProcessExit(slot, opts.pid)) {
|
|
88906
|
+
return;
|
|
88907
|
+
}
|
|
88908
|
+
const stopReason = resolveStopReason(opts.code, opts.signal);
|
|
88909
|
+
const transitionResult = transitionSlot(slot, {
|
|
88910
|
+
type: "process_exited",
|
|
88911
|
+
pid: opts.pid
|
|
88912
|
+
});
|
|
88913
|
+
if (!transitionResult.ok) {
|
|
88914
|
+
return;
|
|
88915
|
+
}
|
|
88916
|
+
const exitedSlot = {
|
|
88917
|
+
...transitionResult.slot,
|
|
88918
|
+
_stopReasonCode: opts.code,
|
|
88919
|
+
_stopReasonSignal: opts.signal,
|
|
88920
|
+
harness: slot.harness,
|
|
88921
|
+
workingDir: slot.workingDir,
|
|
88922
|
+
wantResume: slot.wantResume,
|
|
88923
|
+
_initPrompt: slot._initPrompt,
|
|
88924
|
+
_systemPrompt: slot._systemPrompt
|
|
88925
|
+
};
|
|
88926
|
+
yield* setSlotInRef(key, exitedSlot);
|
|
88927
|
+
yield* executeRestart(exitedSlot, opts.chatroomId, opts.role);
|
|
88928
|
+
const restartOutcome = decideRestartAfterExit({
|
|
88929
|
+
stopReason,
|
|
88930
|
+
harness: slot.harness,
|
|
88931
|
+
workingDir: slot.workingDir,
|
|
88932
|
+
wantResume: slot.wantResume ?? false,
|
|
88933
|
+
isPermanentFailure: false,
|
|
88934
|
+
restartAllowed: true
|
|
88935
|
+
});
|
|
88936
|
+
if (restartOutcome._tag === "NoRestart") {
|
|
88937
|
+
yield* removeSlotFromRef(key);
|
|
88938
|
+
}
|
|
88939
|
+
yield* ports.spawn.recordExit(opts.chatroomId);
|
|
88940
|
+
});
|
|
88941
|
+
const getSlot = (chatroomId, role) => getSlotFromRef(agentKey2(chatroomId, role));
|
|
88942
|
+
const listActive = () => exports_Ref.get(slotsRef).pipe(exports_Effect.map((map18) => {
|
|
88943
|
+
const results = [];
|
|
88944
|
+
for (const [key, slot] of map18) {
|
|
88945
|
+
if (slot.state !== "idle") {
|
|
88946
|
+
const [chatroomId, role] = key.split(":");
|
|
88947
|
+
results.push({ chatroomId, role, slot });
|
|
88948
|
+
}
|
|
88949
|
+
}
|
|
88950
|
+
return results;
|
|
88951
|
+
}));
|
|
88952
|
+
return {
|
|
88953
|
+
ensureRunning,
|
|
88954
|
+
stop: stop4,
|
|
88955
|
+
handleExit,
|
|
88956
|
+
getSlot,
|
|
88957
|
+
listActive
|
|
88958
|
+
};
|
|
88959
|
+
}));
|
|
88960
|
+
});
|
|
88961
|
+
|
|
88962
|
+
// src/infrastructure/services/agent-lifecycle/agent-lifecycle-runtime.ts
|
|
88963
|
+
function createAgentLifecycleRuntime(deps) {
|
|
88964
|
+
const layer = exports_Layer.provide(AgentLifecycleServiceLive, exports_Layer.succeed(AgentLifecyclePorts, createAgentLifecyclePorts(deps)));
|
|
88965
|
+
const runtime4 = exports_ManagedRuntime.make(layer);
|
|
88966
|
+
return {
|
|
88967
|
+
runtime: runtime4,
|
|
88968
|
+
runPromise(effect2) {
|
|
88969
|
+
return runtime4.runPromise(effect2);
|
|
88970
|
+
},
|
|
88971
|
+
dispose: () => runtime4.dispose()
|
|
88972
|
+
};
|
|
88973
|
+
}
|
|
88974
|
+
var init_agent_lifecycle_runtime = __esm(() => {
|
|
88975
|
+
init_esm();
|
|
88976
|
+
init_agent_lifecycle_port_adapters();
|
|
88977
|
+
init_agent_lifecycle_service();
|
|
88978
|
+
init_agent_lifecycle_types();
|
|
88979
|
+
});
|
|
88980
|
+
|
|
88168
88981
|
// src/infrastructure/services/agent-process-manager/agent-process-manager.ts
|
|
88169
|
-
function
|
|
88982
|
+
function agentKey3(chatroomId, role) {
|
|
88170
88983
|
return `${chatroomId}:${role.toLowerCase()}`;
|
|
88171
88984
|
}
|
|
88172
88985
|
|
|
@@ -88177,17 +88990,47 @@ class AgentProcessManager {
|
|
|
88177
88990
|
exitRetryQueue = [];
|
|
88178
88991
|
exitRetryTimer = null;
|
|
88179
88992
|
turnEndQueue = new TurnEndQueue;
|
|
88993
|
+
lifecycle;
|
|
88180
88994
|
constructor(deps) {
|
|
88181
88995
|
this.deps = {
|
|
88182
88996
|
...deps,
|
|
88183
88997
|
resumeStormTracker: deps.resumeStormTracker ?? new RapidResumeTracker
|
|
88184
88998
|
};
|
|
88999
|
+
const portAdapterDeps = {
|
|
89000
|
+
spawning: this.deps.spawning,
|
|
89001
|
+
agentServices: this.deps.agentServices,
|
|
89002
|
+
sessionId: this.deps.sessionId,
|
|
89003
|
+
machineId: this.deps.machineId,
|
|
89004
|
+
onAgentEnd: (args2) => void this.runHandleAgentEnd(args2)
|
|
89005
|
+
};
|
|
89006
|
+
this.lifecycle = createAgentLifecycleRuntime(portAdapterDeps);
|
|
89007
|
+
}
|
|
89008
|
+
updateSlotsMirror(chatroomId, role, slot) {
|
|
89009
|
+
const key = agentKey3(chatroomId, role);
|
|
89010
|
+
const existing = this.slots.get(key);
|
|
89011
|
+
if (!existing || existing.state !== slot.state || existing.pid !== slot.pid) {
|
|
89012
|
+
this.slots.set(key, {
|
|
89013
|
+
state: slot.state,
|
|
89014
|
+
pid: slot.pid,
|
|
89015
|
+
harness: slot.harness,
|
|
89016
|
+
harnessSessionId: slot.harnessSessionId,
|
|
89017
|
+
model: slot.model,
|
|
89018
|
+
workingDir: slot.workingDir,
|
|
89019
|
+
startedAt: slot.startedAt,
|
|
89020
|
+
resumeInFlight: slot.resumeInFlight,
|
|
89021
|
+
recentLogLines: slot.recentLogLines,
|
|
89022
|
+
wantResume: slot.wantResume
|
|
89023
|
+
});
|
|
89024
|
+
}
|
|
89025
|
+
}
|
|
89026
|
+
getSlotFromMirror(chatroomId, role) {
|
|
89027
|
+
return this.slots.get(agentKey3(chatroomId, role));
|
|
88185
89028
|
}
|
|
88186
|
-
|
|
88187
|
-
|
|
89029
|
+
whenTurnEndsIdle() {
|
|
89030
|
+
return this.turnEndQueue.whenIdle();
|
|
88188
89031
|
}
|
|
88189
89032
|
async ensureRunning(opts) {
|
|
88190
|
-
const key =
|
|
89033
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
88191
89034
|
const slot = this.getOrCreateSlot(key);
|
|
88192
89035
|
if (slot.state === "running" && slot.pid && !isProcessAlive(this.deps.processes.kill, slot.pid)) {
|
|
88193
89036
|
slot.state = "idle";
|
|
@@ -88211,30 +89054,21 @@ class AgentProcessManager {
|
|
|
88211
89054
|
return operation;
|
|
88212
89055
|
}
|
|
88213
89056
|
async stop(opts) {
|
|
88214
|
-
const key =
|
|
89057
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
88215
89058
|
const slot = this.slots.get(key);
|
|
89059
|
+
const earlyResult = await this.handleStopEarlyReturns(slot, opts, key);
|
|
89060
|
+
if (earlyResult) {
|
|
89061
|
+
return earlyResult;
|
|
89062
|
+
}
|
|
89063
|
+
const actualSlot = slot;
|
|
89064
|
+
if (actualSlot.pendingOperation) {
|
|
89065
|
+
await actualSlot.pendingOperation;
|
|
89066
|
+
}
|
|
89067
|
+
return { success: true };
|
|
89068
|
+
}
|
|
89069
|
+
async handleStopEarlyReturns(slot, opts, key) {
|
|
88216
89070
|
if (!slot || slot.state === "idle") {
|
|
88217
|
-
|
|
88218
|
-
if (eventPid && eventPid > 0) {
|
|
88219
|
-
try {
|
|
88220
|
-
this.deps.processes.kill(eventPid, "SIGTERM");
|
|
88221
|
-
} catch {}
|
|
88222
|
-
}
|
|
88223
|
-
const exitArgs1 = {
|
|
88224
|
-
sessionId: this.deps.sessionId,
|
|
88225
|
-
machineId: this.deps.machineId,
|
|
88226
|
-
chatroomId: opts.chatroomId,
|
|
88227
|
-
role: opts.role,
|
|
88228
|
-
pid: eventPid ?? 0,
|
|
88229
|
-
stopReason: opts.reason,
|
|
88230
|
-
exitCode: undefined,
|
|
88231
|
-
signal: undefined,
|
|
88232
|
-
agentHarness: undefined
|
|
88233
|
-
};
|
|
88234
|
-
this.deps.backend.mutation(api.machines.recordAgentExited, exitArgs1).catch((err) => {
|
|
88235
|
-
console.log(` ⚠️ Failed to record agent exit (idle cleanup): ${err.message}`);
|
|
88236
|
-
this.queueExitRetry({ role: opts.role, args: exitArgs1 });
|
|
88237
|
-
});
|
|
89071
|
+
await this.killAndRecordForIdleSlot(slot, opts);
|
|
88238
89072
|
return { success: true };
|
|
88239
89073
|
}
|
|
88240
89074
|
if (slot.state === "stopping" && slot.pendingOperation) {
|
|
@@ -88250,14 +89084,48 @@ class AgentProcessManager {
|
|
|
88250
89084
|
slot.state = "stopping";
|
|
88251
89085
|
const operation = this.doStop(key, slot, pid, opts);
|
|
88252
89086
|
slot.pendingOperation = operation;
|
|
88253
|
-
|
|
88254
|
-
|
|
89087
|
+
return null;
|
|
89088
|
+
}
|
|
89089
|
+
async killAndRecordForIdleSlot(slot, opts) {
|
|
89090
|
+
const eventPid = opts.pid;
|
|
89091
|
+
if (eventPid && eventPid > 0) {
|
|
89092
|
+
try {
|
|
89093
|
+
this.deps.processes.kill(eventPid, "SIGTERM");
|
|
89094
|
+
} catch {}
|
|
89095
|
+
}
|
|
89096
|
+
const exitArgs1 = {
|
|
89097
|
+
sessionId: this.deps.sessionId,
|
|
89098
|
+
machineId: this.deps.machineId,
|
|
89099
|
+
chatroomId: opts.chatroomId,
|
|
89100
|
+
role: opts.role,
|
|
89101
|
+
pid: eventPid ?? 0,
|
|
89102
|
+
stopReason: opts.reason,
|
|
89103
|
+
exitCode: undefined,
|
|
89104
|
+
signal: undefined,
|
|
89105
|
+
agentHarness: undefined
|
|
89106
|
+
};
|
|
89107
|
+
this.deps.backend.mutation(api.machines.recordAgentExited, exitArgs1).catch((err) => {
|
|
89108
|
+
console.log(` ⚠️ Failed to record agent exit (idle cleanup): ${err.message}`);
|
|
89109
|
+
this.queueExitRetry({ role: opts.role, args: exitArgs1 });
|
|
89110
|
+
});
|
|
88255
89111
|
}
|
|
88256
89112
|
async runHandleAgentEnd(opts) {
|
|
88257
|
-
const slot = this.slots.get(
|
|
89113
|
+
const slot = this.slots.get(agentKey3(opts.chatroomId, opts.role));
|
|
88258
89114
|
const service3 = this.deps.agentServices.get(opts.harness);
|
|
88259
89115
|
const capabilities = getHarnessCapabilities(opts.harness);
|
|
88260
89116
|
const supportsSessionResume = capabilities.supportsSessionResume && typeof service3?.resumeTurn === "function";
|
|
89117
|
+
this.updateSlotsMirror(opts.chatroomId, opts.role, {
|
|
89118
|
+
state: slot?.state ?? "idle",
|
|
89119
|
+
pid: slot?.pid,
|
|
89120
|
+
harness: slot?.harness,
|
|
89121
|
+
harnessSessionId: slot?.harnessSessionId,
|
|
89122
|
+
model: slot?.model,
|
|
89123
|
+
workingDir: slot?.workingDir,
|
|
89124
|
+
startedAt: slot?.startedAt,
|
|
89125
|
+
resumeInFlight: slot?.resumeInFlight,
|
|
89126
|
+
recentLogLines: slot?.recentLogLines,
|
|
89127
|
+
wantResume: slot?.wantResume
|
|
89128
|
+
});
|
|
88261
89129
|
console.log(`[AgentProcessManager] lifecycle.turn.completed: role=${opts.role} pid=${opts.pid} harness=${opts.harness} supportsResume=${supportsSessionResume}`);
|
|
88262
89130
|
const result = await handleTurnCompleted({
|
|
88263
89131
|
resumeStormTracker: this.deps.resumeStormTracker,
|
|
@@ -88296,37 +89164,76 @@ class AgentProcessManager {
|
|
|
88296
89164
|
}
|
|
88297
89165
|
}
|
|
88298
89166
|
async handleExit(opts) {
|
|
88299
|
-
const key =
|
|
89167
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
88300
89168
|
const slot = this.slots.get(key);
|
|
88301
|
-
if (!slot || slot.pid !== opts.pid) {
|
|
88302
|
-
return;
|
|
88303
|
-
}
|
|
88304
|
-
if (slot.state === "stopping") {
|
|
89169
|
+
if (!slot || slot.pid !== opts.pid || slot.state === "stopping") {
|
|
88305
89170
|
return;
|
|
88306
89171
|
}
|
|
88307
89172
|
const stopReason = resolveStopReason(opts.code, opts.signal);
|
|
88308
89173
|
this.deps.spawning.recordExit(opts.chatroomId);
|
|
88309
|
-
const
|
|
88310
|
-
|
|
88311
|
-
const
|
|
88312
|
-
|
|
88313
|
-
|
|
88314
|
-
|
|
88315
|
-
|
|
88316
|
-
|
|
88317
|
-
|
|
88318
|
-
|
|
88319
|
-
harnessSessionId,
|
|
88320
|
-
harness,
|
|
88321
|
-
agentName: harnessMeta?.agentName ?? "",
|
|
88322
|
-
workingDir: workingDir ?? "",
|
|
88323
|
-
model: model ?? harnessMeta?.model
|
|
89174
|
+
const ctx = this.captureExitContext(slot, opts, stopReason);
|
|
89175
|
+
await this.preserveHarnessSessionOnExit(key, slot, ctx);
|
|
89176
|
+
const lifecyclePromise = this.lifecycle.runPromise(exports_Effect.gen(function* () {
|
|
89177
|
+
const svc = yield* AgentLifecycleService;
|
|
89178
|
+
yield* svc.handleExit({
|
|
89179
|
+
chatroomId: opts.chatroomId,
|
|
89180
|
+
role: opts.role,
|
|
89181
|
+
pid: opts.pid,
|
|
89182
|
+
code: opts.code,
|
|
89183
|
+
signal: opts.signal
|
|
88324
89184
|
});
|
|
89185
|
+
}));
|
|
89186
|
+
this.resetSlotAfterExit(slot);
|
|
89187
|
+
await this.emitExitEvent(slot, opts, ctx);
|
|
89188
|
+
try {
|
|
89189
|
+
await this.deps.persistence.clearAgentPid(this.deps.machineId, opts.chatroomId, opts.role);
|
|
89190
|
+
} catch {}
|
|
89191
|
+
this.untrackAllServices(opts.pid);
|
|
89192
|
+
lifecyclePromise.then(() => this.dispatchRestartAfterExit(opts, ctx, key)).catch(() => {});
|
|
89193
|
+
}
|
|
89194
|
+
captureExitContext(slot, opts, stopReason) {
|
|
89195
|
+
return {
|
|
89196
|
+
harness: slot.harness,
|
|
89197
|
+
model: slot.model,
|
|
89198
|
+
workingDir: slot.workingDir,
|
|
89199
|
+
harnessSessionId: slot.harnessSessionId,
|
|
89200
|
+
wantResume: slot.wantResume,
|
|
89201
|
+
recentLogLines: slot.recentLogLines,
|
|
89202
|
+
stopReason
|
|
89203
|
+
};
|
|
89204
|
+
}
|
|
89205
|
+
recordExitHarnessSession(key, slot, harness, harnessSessionId, ctx) {
|
|
89206
|
+
const service3 = this.deps.agentServices.get(harness);
|
|
89207
|
+
const harnessMeta = service3 && slot.pid ? this.readHarnessReconnectMetadata(service3, slot.pid) : undefined;
|
|
89208
|
+
this.recordLastHarnessSession(key, {
|
|
89209
|
+
harnessSessionId,
|
|
89210
|
+
harness,
|
|
89211
|
+
agentName: harnessMeta?.agentName ?? "",
|
|
89212
|
+
workingDir: ctx.workingDir ?? "",
|
|
89213
|
+
model: ctx.model ?? harnessMeta?.model
|
|
89214
|
+
});
|
|
89215
|
+
}
|
|
89216
|
+
async preserveHarnessSessionOnExit(key, slot, ctx) {
|
|
89217
|
+
const { harness, harnessSessionId, stopReason } = ctx;
|
|
89218
|
+
if (!harness || !harnessSessionId) {
|
|
89219
|
+
return;
|
|
88325
89220
|
}
|
|
89221
|
+
if (!getHarnessCapabilities(harness).supportsSessionResume) {
|
|
89222
|
+
return;
|
|
89223
|
+
}
|
|
89224
|
+
if (!shouldRetainHarnessSessionForReconnect(stopReason)) {
|
|
89225
|
+
return;
|
|
89226
|
+
}
|
|
89227
|
+
this.recordExitHarnessSession(key, slot, harness, harnessSessionId, ctx);
|
|
89228
|
+
}
|
|
89229
|
+
resetSlotAfterExit(slot) {
|
|
88326
89230
|
slot.state = "idle";
|
|
88327
89231
|
slot.pid = undefined;
|
|
88328
89232
|
slot.startedAt = undefined;
|
|
88329
89233
|
slot.pendingOperation = undefined;
|
|
89234
|
+
}
|
|
89235
|
+
async emitExitEvent(slot, opts, ctx) {
|
|
89236
|
+
const stopReason = ctx.stopReason;
|
|
88330
89237
|
const exitArgs2 = {
|
|
88331
89238
|
sessionId: this.deps.sessionId,
|
|
88332
89239
|
machineId: this.deps.machineId,
|
|
@@ -88337,42 +89244,36 @@ class AgentProcessManager {
|
|
|
88337
89244
|
stopSignal: stopReason === "agent_process.signal" ? opts.signal ?? undefined : undefined,
|
|
88338
89245
|
exitCode: opts.code ?? undefined,
|
|
88339
89246
|
signal: opts.signal ?? undefined,
|
|
88340
|
-
agentHarness: harness
|
|
89247
|
+
agentHarness: ctx.harness
|
|
88341
89248
|
};
|
|
88342
89249
|
this.deps.backend.mutation(api.machines.recordAgentExited, exitArgs2).catch((err) => {
|
|
88343
89250
|
console.log(` ⚠️ Failed to record agent exit event: ${err.message}`);
|
|
88344
89251
|
this.queueExitRetry({ role: opts.role, args: exitArgs2 });
|
|
88345
89252
|
});
|
|
88346
|
-
|
|
88347
|
-
|
|
88348
|
-
} catch {}
|
|
89253
|
+
}
|
|
89254
|
+
untrackAllServices(pid) {
|
|
88349
89255
|
for (const service3 of this.deps.agentServices.values()) {
|
|
88350
|
-
service3.untrack(
|
|
89256
|
+
service3.untrack(pid);
|
|
88351
89257
|
}
|
|
88352
|
-
|
|
88353
|
-
|
|
89258
|
+
}
|
|
89259
|
+
dispatchRestartAfterExit(opts, ctx, _key) {
|
|
89260
|
+
const stopReasonForRestart = resolveStopReason(opts.code, opts.signal);
|
|
89261
|
+
if (!shouldAutoRestartAfterProcessExit(stopReasonForRestart)) {
|
|
89262
|
+
if (stopReasonForRestart === "user.stop" || stopReasonForRestart === "platform.team_switch" || stopReasonForRestart === "daemon.shutdown") {
|
|
88354
89263
|
this.deps.crashLoop.clear(opts.chatroomId, opts.role);
|
|
88355
89264
|
}
|
|
88356
89265
|
return;
|
|
88357
89266
|
}
|
|
89267
|
+
this.maybeRestartAgent(opts, ctx);
|
|
89268
|
+
}
|
|
89269
|
+
maybeRestartAgent(opts, ctx) {
|
|
89270
|
+
const { harness, model, workingDir, recentLogLines } = ctx;
|
|
88358
89271
|
if (!harness || !workingDir) {
|
|
88359
89272
|
console.log(`[AgentProcessManager] ⚠️ Cannot restart — missing harness or workingDir ` + `(role: ${opts.role}, harness: ${harness ?? "none"}, workingDir: ${workingDir ?? "none"})`);
|
|
88360
89273
|
return;
|
|
88361
89274
|
}
|
|
88362
89275
|
if (isPermanentHarnessFailure(recentLogLines ?? [])) {
|
|
88363
|
-
|
|
88364
|
-
console.log(`[AgentProcessManager] ⛔ Skipping restart — ${error}`);
|
|
88365
|
-
this.deps.crashLoop.clear(opts.chatroomId, opts.role);
|
|
88366
|
-
this.clearLastHarnessSession(key);
|
|
88367
|
-
this.deps.backend.mutation(api.machines.emitAgentStartFailed, {
|
|
88368
|
-
sessionId: this.deps.sessionId,
|
|
88369
|
-
machineId: this.deps.machineId,
|
|
88370
|
-
chatroomId: opts.chatroomId,
|
|
88371
|
-
role: opts.role,
|
|
88372
|
-
error
|
|
88373
|
-
}).catch((emitErr) => {
|
|
88374
|
-
console.log(` ⚠️ Failed to emit startFailed event: ${emitErr.message}`);
|
|
88375
|
-
});
|
|
89276
|
+
this.handlePermanentFailureForRestart(opts, recentLogLines);
|
|
88376
89277
|
return;
|
|
88377
89278
|
}
|
|
88378
89279
|
this.ensureRunning({
|
|
@@ -88382,22 +89283,39 @@ class AgentProcessManager {
|
|
|
88382
89283
|
model,
|
|
88383
89284
|
workingDir,
|
|
88384
89285
|
reason: "platform.crash_recovery",
|
|
88385
|
-
wantResume: wantResume ?? true
|
|
89286
|
+
wantResume: ctx.wantResume ?? true
|
|
88386
89287
|
}).catch((err) => {
|
|
88387
89288
|
console.log(` ⚠️ Failed to restart agent: ${err.message}`);
|
|
88388
|
-
this.
|
|
88389
|
-
sessionId: this.deps.sessionId,
|
|
88390
|
-
machineId: this.deps.machineId,
|
|
88391
|
-
chatroomId: opts.chatroomId,
|
|
88392
|
-
role: opts.role,
|
|
88393
|
-
error: err.message
|
|
88394
|
-
}).catch((emitErr) => {
|
|
88395
|
-
console.log(` ⚠️ Failed to emit startFailed event: ${emitErr.message}`);
|
|
88396
|
-
});
|
|
89289
|
+
this.emitStartFailedEvent(opts.role, opts.chatroomId, err.message);
|
|
88397
89290
|
});
|
|
88398
89291
|
}
|
|
89292
|
+
handlePermanentFailureForRestart(opts, recentLogLines) {
|
|
89293
|
+
const error = formatPermanentHarnessFailureMessage(recentLogLines ?? []);
|
|
89294
|
+
console.log(`[AgentProcessManager] ⛔ Skipping restart — ${error}`);
|
|
89295
|
+
this.deps.crashLoop.clear(opts.chatroomId, opts.role);
|
|
89296
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
89297
|
+
this.clearLastHarnessSession(key);
|
|
89298
|
+
this.deps.backend.mutation(api.machines.emitAgentStartFailed, {
|
|
89299
|
+
sessionId: this.deps.sessionId,
|
|
89300
|
+
machineId: this.deps.machineId,
|
|
89301
|
+
chatroomId: opts.chatroomId,
|
|
89302
|
+
role: opts.role,
|
|
89303
|
+
error
|
|
89304
|
+
}).catch((emitErr) => {
|
|
89305
|
+
console.log(` ⚠️ Failed to emit startFailed event: ${emitErr.message}`);
|
|
89306
|
+
});
|
|
89307
|
+
}
|
|
89308
|
+
emitStartFailedEvent(role, chatroomId, error) {
|
|
89309
|
+
this.deps.backend.mutation(api.machines.emitAgentStartFailed, {
|
|
89310
|
+
sessionId: this.deps.sessionId,
|
|
89311
|
+
machineId: this.deps.machineId,
|
|
89312
|
+
chatroomId,
|
|
89313
|
+
role,
|
|
89314
|
+
error
|
|
89315
|
+
}).catch(() => {});
|
|
89316
|
+
}
|
|
88399
89317
|
getSlot(chatroomId, role) {
|
|
88400
|
-
return this.
|
|
89318
|
+
return this.getSlotFromMirror(chatroomId, role);
|
|
88401
89319
|
}
|
|
88402
89320
|
listActive() {
|
|
88403
89321
|
const result = [];
|
|
@@ -88468,13 +89386,19 @@ class AgentProcessManager {
|
|
|
88468
89386
|
untrackChildPid(pid);
|
|
88469
89387
|
}
|
|
88470
89388
|
async killExistingBeforeSpawn(chatroomId, role) {
|
|
88471
|
-
const key =
|
|
89389
|
+
const key = agentKey3(chatroomId, role);
|
|
89390
|
+
await this.killInMemorySlotIfAlive(key, chatroomId, role);
|
|
89391
|
+
await this.killPersistedProcessIfAlive(chatroomId, role);
|
|
89392
|
+
}
|
|
89393
|
+
async killInMemorySlotIfAlive(key, chatroomId, role) {
|
|
88472
89394
|
const slot = this.slots.get(key);
|
|
88473
89395
|
if (slot?.pid && isProcessAlive(this.deps.processes.kill, slot.pid) && (slot.state === "running" || slot.state === "spawning")) {
|
|
88474
|
-
const
|
|
89396
|
+
const pid = slot.pid;
|
|
88475
89397
|
slot.state = "stopping";
|
|
88476
|
-
await this.doStop(key, slot,
|
|
89398
|
+
await this.doStop(key, slot, pid, { chatroomId, role, reason: "daemon.respawn" });
|
|
88477
89399
|
}
|
|
89400
|
+
}
|
|
89401
|
+
async killPersistedProcessIfAlive(chatroomId, role) {
|
|
88478
89402
|
let entries2 = [];
|
|
88479
89403
|
try {
|
|
88480
89404
|
entries2 = await this.deps.persistence.listAgentEntries(this.deps.machineId);
|
|
@@ -88487,11 +89411,10 @@ class AgentProcessManager {
|
|
|
88487
89411
|
}
|
|
88488
89412
|
const { pid, harness } = persisted.entry;
|
|
88489
89413
|
if (!isProcessAlive(this.deps.processes.kill, pid)) {
|
|
88490
|
-
|
|
88491
|
-
await this.deps.persistence.clearAgentPid(this.deps.machineId, chatroomId, role);
|
|
88492
|
-
} catch {}
|
|
89414
|
+
await this.deps.persistence.clearAgentPid(this.deps.machineId, chatroomId, role).catch(() => {});
|
|
88493
89415
|
return;
|
|
88494
89416
|
}
|
|
89417
|
+
const key = agentKey3(chatroomId, role);
|
|
88495
89418
|
const currentSlot = this.slots.get(key);
|
|
88496
89419
|
if (currentSlot?.pid === pid && currentSlot.state !== "idle") {
|
|
88497
89420
|
return;
|
|
@@ -88574,30 +89497,20 @@ class AgentProcessManager {
|
|
|
88574
89497
|
}
|
|
88575
89498
|
}
|
|
88576
89499
|
async tryDaemonMemoryResume(opts) {
|
|
88577
|
-
const
|
|
88578
|
-
if (
|
|
89500
|
+
const validationResult = this.validateDaemonMemoryResumePreconditions(opts);
|
|
89501
|
+
if (validationResult) {
|
|
88579
89502
|
return null;
|
|
88580
89503
|
}
|
|
88581
89504
|
const stored = this.lastHarnessSessions.get(opts.key);
|
|
88582
89505
|
if (!stored) {
|
|
88583
89506
|
return null;
|
|
88584
89507
|
}
|
|
88585
|
-
|
|
88586
|
-
|
|
88587
|
-
await this.emitSessionResumeFailed(opts.chatroomId, opts.role, "working directory changed", stored.harnessSessionId);
|
|
88588
|
-
return null;
|
|
88589
|
-
}
|
|
88590
|
-
if (stored.harness !== opts.agentHarness || !stored.agentName) {
|
|
88591
|
-
this.clearLastHarnessSession(opts.key);
|
|
88592
|
-
await this.emitSessionResumeFailed(opts.chatroomId, opts.role, stored.harness !== opts.agentHarness ? "harness changed" : "incomplete session in daemon memory", stored.harnessSessionId);
|
|
88593
|
-
return null;
|
|
88594
|
-
}
|
|
88595
|
-
if (!opts.service.resumeFromDaemonMemory) {
|
|
88596
|
-
await this.emitSessionResumeFailed(opts.chatroomId, opts.role, "daemon-memory session resume not yet supported", stored.harnessSessionId);
|
|
89508
|
+
const resumeFromDaemonMemory = opts.service.resumeFromDaemonMemory;
|
|
89509
|
+
if (!resumeFromDaemonMemory) {
|
|
88597
89510
|
return null;
|
|
88598
89511
|
}
|
|
88599
89512
|
try {
|
|
88600
|
-
const spawnResult = await
|
|
89513
|
+
const spawnResult = await resumeFromDaemonMemory({
|
|
88601
89514
|
workingDir: stored.workingDir,
|
|
88602
89515
|
prompt: createSpawnPrompt(opts.initPrompt),
|
|
88603
89516
|
systemPrompt: opts.systemPrompt,
|
|
@@ -88621,6 +89534,31 @@ class AgentProcessManager {
|
|
|
88621
89534
|
return null;
|
|
88622
89535
|
}
|
|
88623
89536
|
}
|
|
89537
|
+
validateDaemonMemoryResumePreconditions(opts) {
|
|
89538
|
+
const capabilities = getHarnessCapabilities(opts.agentHarness);
|
|
89539
|
+
if (!capabilities.supportsSessionResume) {
|
|
89540
|
+
return null;
|
|
89541
|
+
}
|
|
89542
|
+
const stored = this.lastHarnessSessions.get(opts.key);
|
|
89543
|
+
if (!stored) {
|
|
89544
|
+
return null;
|
|
89545
|
+
}
|
|
89546
|
+
if (stored.workingDir !== opts.workingDir) {
|
|
89547
|
+
this.clearLastHarnessSession(opts.key);
|
|
89548
|
+
this.emitSessionResumeFailed(opts.chatroomId, opts.role, "working directory changed", stored.harnessSessionId);
|
|
89549
|
+
return "working directory changed";
|
|
89550
|
+
}
|
|
89551
|
+
if (stored.harness !== opts.agentHarness || !stored.agentName) {
|
|
89552
|
+
this.clearLastHarnessSession(opts.key);
|
|
89553
|
+
this.emitSessionResumeFailed(opts.chatroomId, opts.role, stored.harness !== opts.agentHarness ? "harness changed" : "incomplete session in daemon memory", stored.harnessSessionId);
|
|
89554
|
+
return "validation failed";
|
|
89555
|
+
}
|
|
89556
|
+
if (!opts.service.resumeFromDaemonMemory) {
|
|
89557
|
+
this.emitSessionResumeFailed(opts.chatroomId, opts.role, "daemon-memory session resume not yet supported", stored.harnessSessionId);
|
|
89558
|
+
return "not supported";
|
|
89559
|
+
}
|
|
89560
|
+
return null;
|
|
89561
|
+
}
|
|
88624
89562
|
async emitSessionResumed(chatroomId, role, harnessSessionId) {
|
|
88625
89563
|
try {
|
|
88626
89564
|
await this.deps.backend.mutation(api.machines.emitSessionResumed, {
|
|
@@ -88650,195 +89588,248 @@ class AgentProcessManager {
|
|
|
88650
89588
|
console.log(` ⚠️ Failed to emit sessionResumeFailed event: ${err.message}`);
|
|
88651
89589
|
}
|
|
88652
89590
|
}
|
|
88653
|
-
|
|
88654
|
-
slot.state = "
|
|
88655
|
-
|
|
88656
|
-
|
|
89591
|
+
resetSlotIdle(slot) {
|
|
89592
|
+
slot.state = "idle";
|
|
89593
|
+
slot.pendingOperation = undefined;
|
|
89594
|
+
}
|
|
89595
|
+
checkRateLimitGate(opts, slot) {
|
|
89596
|
+
const spawnCheck = this.deps.spawning.shouldAllowSpawn(opts.chatroomId, opts.reason, {
|
|
89597
|
+
bypassConcurrentLimit: opts.reason.startsWith("user.")
|
|
89598
|
+
});
|
|
89599
|
+
if (!spawnCheck.allowed) {
|
|
89600
|
+
this.resetSlotIdle(slot);
|
|
89601
|
+
return { success: false, error: "rate_limited" };
|
|
89602
|
+
}
|
|
89603
|
+
return null;
|
|
89604
|
+
}
|
|
89605
|
+
checkCrashLoopGate(opts, slot) {
|
|
89606
|
+
if (opts.reason !== "platform.crash_recovery") {
|
|
89607
|
+
return null;
|
|
89608
|
+
}
|
|
89609
|
+
const loopCheck = this.deps.crashLoop.record(opts.chatroomId, opts.role, this.deps.clock.now());
|
|
89610
|
+
if (loopCheck.allowed) {
|
|
89611
|
+
return null;
|
|
89612
|
+
}
|
|
89613
|
+
if (loopCheck.waitMs !== undefined && loopCheck.waitMs > 0) {
|
|
89614
|
+
console.log(` ⏳ Agent restart backoff: waiting ${loopCheck.waitMs}ms before retry`);
|
|
89615
|
+
this.resetSlotIdle(slot);
|
|
89616
|
+
return { success: false, error: "backoff" };
|
|
89617
|
+
}
|
|
89618
|
+
this.deps.backend.mutation(api.machines.emitRestartLimitReached, {
|
|
89619
|
+
sessionId: this.deps.sessionId,
|
|
89620
|
+
machineId: this.deps.machineId,
|
|
89621
|
+
chatroomId: opts.chatroomId,
|
|
89622
|
+
role: opts.role,
|
|
89623
|
+
restartCount: loopCheck.restartCount,
|
|
89624
|
+
windowMs: loopCheck.windowMs
|
|
89625
|
+
}).catch((err) => {
|
|
89626
|
+
console.log(` ⚠️ Failed to emit restartLimitReached event: ${err.message}`);
|
|
89627
|
+
});
|
|
89628
|
+
this.resetSlotIdle(slot);
|
|
89629
|
+
return { success: false, error: "crash_loop" };
|
|
89630
|
+
}
|
|
89631
|
+
async validateWorkingDirGate(opts, slot) {
|
|
89632
|
+
try {
|
|
89633
|
+
const dirStat = await this.deps.fs.stat(opts.workingDir);
|
|
89634
|
+
if (!dirStat.isDirectory()) {
|
|
89635
|
+
this.resetSlotIdle(slot);
|
|
89636
|
+
return {
|
|
89637
|
+
success: false,
|
|
89638
|
+
error: `Working directory is not a directory: ${opts.workingDir}`
|
|
89639
|
+
};
|
|
89640
|
+
}
|
|
89641
|
+
} catch {
|
|
89642
|
+
this.resetSlotIdle(slot);
|
|
89643
|
+
return { success: false, error: `Working directory does not exist: ${opts.workingDir}` };
|
|
89644
|
+
}
|
|
89645
|
+
return null;
|
|
89646
|
+
}
|
|
89647
|
+
async fetchInitPromptResult(opts, slot) {
|
|
89648
|
+
let initPromptResult;
|
|
88657
89649
|
try {
|
|
88658
|
-
|
|
88659
|
-
|
|
89650
|
+
initPromptResult = await this.deps.backend.query(api.messages.getInitPrompt, {
|
|
89651
|
+
sessionId: this.deps.sessionId,
|
|
89652
|
+
chatroomId: opts.chatroomId,
|
|
89653
|
+
role: opts.role,
|
|
89654
|
+
convexUrl: this.deps.convexUrl
|
|
88660
89655
|
});
|
|
88661
|
-
|
|
88662
|
-
|
|
88663
|
-
|
|
88664
|
-
|
|
88665
|
-
|
|
88666
|
-
|
|
88667
|
-
|
|
88668
|
-
|
|
88669
|
-
|
|
88670
|
-
|
|
88671
|
-
|
|
88672
|
-
|
|
88673
|
-
|
|
88674
|
-
|
|
88675
|
-
|
|
88676
|
-
|
|
89656
|
+
} catch (e) {
|
|
89657
|
+
this.resetSlotIdle(slot);
|
|
89658
|
+
return {
|
|
89659
|
+
ok: false,
|
|
89660
|
+
result: { success: false, error: `Failed to fetch init prompt: ${e.message}` }
|
|
89661
|
+
};
|
|
89662
|
+
}
|
|
89663
|
+
if (!initPromptResult?.prompt) {
|
|
89664
|
+
this.resetSlotIdle(slot);
|
|
89665
|
+
return {
|
|
89666
|
+
ok: false,
|
|
89667
|
+
result: { success: false, error: "Failed to fetch init prompt from backend" }
|
|
89668
|
+
};
|
|
89669
|
+
}
|
|
89670
|
+
return {
|
|
89671
|
+
ok: true,
|
|
89672
|
+
initialMessage: initPromptResult.initialMessage,
|
|
89673
|
+
rolePrompt: initPromptResult.rolePrompt
|
|
89674
|
+
};
|
|
89675
|
+
}
|
|
89676
|
+
async spawnAgentForEnsureRunning(key, slot, opts, initPrompt, wantResume) {
|
|
89677
|
+
const service3 = this.deps.agentServices.get(opts.agentHarness);
|
|
89678
|
+
if (!service3) {
|
|
89679
|
+
this.resetSlotIdle(slot);
|
|
89680
|
+
return {
|
|
89681
|
+
ok: false,
|
|
89682
|
+
result: { success: false, error: `Unknown agent harness: ${opts.agentHarness}` }
|
|
89683
|
+
};
|
|
89684
|
+
}
|
|
89685
|
+
let spawnResult;
|
|
89686
|
+
const resumePath = decideResumePathOnRestart({
|
|
89687
|
+
supportsSessionResume: getHarnessCapabilities(opts.agentHarness).supportsSessionResume,
|
|
89688
|
+
wantResume,
|
|
89689
|
+
hasStoredSnapshot: this.lastHarnessSessions.has(key)
|
|
89690
|
+
});
|
|
89691
|
+
if (resumePath === "daemon_memory") {
|
|
89692
|
+
spawnResult = await this.tryDaemonMemoryResume({
|
|
89693
|
+
key,
|
|
89694
|
+
chatroomId: opts.chatroomId,
|
|
89695
|
+
role: opts.role,
|
|
89696
|
+
agentHarness: opts.agentHarness,
|
|
89697
|
+
workingDir: opts.workingDir,
|
|
89698
|
+
model: opts.model,
|
|
89699
|
+
initPrompt: initPrompt.initialMessage,
|
|
89700
|
+
systemPrompt: initPrompt.rolePrompt,
|
|
89701
|
+
service: service3
|
|
89702
|
+
}) ?? undefined;
|
|
89703
|
+
}
|
|
89704
|
+
if (!spawnResult) {
|
|
89705
|
+
try {
|
|
89706
|
+
spawnResult = await service3.spawn({
|
|
89707
|
+
workingDir: opts.workingDir,
|
|
89708
|
+
prompt: createSpawnPrompt(initPrompt.initialMessage),
|
|
89709
|
+
systemPrompt: initPrompt.rolePrompt,
|
|
89710
|
+
model: opts.model,
|
|
89711
|
+
context: {
|
|
88677
89712
|
machineId: this.deps.machineId,
|
|
88678
89713
|
chatroomId: opts.chatroomId,
|
|
88679
|
-
role: opts.role
|
|
88680
|
-
|
|
88681
|
-
windowMs: loopCheck.windowMs
|
|
88682
|
-
}).catch((err) => {
|
|
88683
|
-
console.log(` ⚠️ Failed to emit restartLimitReached event: ${err.message}`);
|
|
88684
|
-
});
|
|
88685
|
-
slot.state = "idle";
|
|
88686
|
-
slot.pendingOperation = undefined;
|
|
88687
|
-
return { success: false, error: "crash_loop" };
|
|
88688
|
-
}
|
|
88689
|
-
}
|
|
88690
|
-
try {
|
|
88691
|
-
const dirStat = await this.deps.fs.stat(opts.workingDir);
|
|
88692
|
-
if (!dirStat.isDirectory()) {
|
|
88693
|
-
slot.state = "idle";
|
|
88694
|
-
slot.pendingOperation = undefined;
|
|
88695
|
-
return {
|
|
88696
|
-
success: false,
|
|
88697
|
-
error: `Working directory is not a directory: ${opts.workingDir}`
|
|
88698
|
-
};
|
|
88699
|
-
}
|
|
88700
|
-
} catch {
|
|
88701
|
-
slot.state = "idle";
|
|
88702
|
-
slot.pendingOperation = undefined;
|
|
88703
|
-
return { success: false, error: `Working directory does not exist: ${opts.workingDir}` };
|
|
88704
|
-
}
|
|
88705
|
-
let initPromptResult;
|
|
88706
|
-
try {
|
|
88707
|
-
initPromptResult = await this.deps.backend.query(api.messages.getInitPrompt, {
|
|
88708
|
-
sessionId: this.deps.sessionId,
|
|
88709
|
-
chatroomId: opts.chatroomId,
|
|
88710
|
-
role: opts.role,
|
|
88711
|
-
convexUrl: this.deps.convexUrl
|
|
89714
|
+
role: opts.role
|
|
89715
|
+
}
|
|
88712
89716
|
});
|
|
88713
89717
|
} catch (e) {
|
|
88714
|
-
slot
|
|
88715
|
-
|
|
88716
|
-
|
|
88717
|
-
|
|
88718
|
-
|
|
88719
|
-
slot.state = "idle";
|
|
88720
|
-
slot.pendingOperation = undefined;
|
|
88721
|
-
return { success: false, error: "Failed to fetch init prompt from backend" };
|
|
88722
|
-
}
|
|
88723
|
-
const service3 = this.deps.agentServices.get(opts.agentHarness);
|
|
88724
|
-
if (!service3) {
|
|
88725
|
-
slot.state = "idle";
|
|
88726
|
-
slot.pendingOperation = undefined;
|
|
88727
|
-
return { success: false, error: `Unknown agent harness: ${opts.agentHarness}` };
|
|
89718
|
+
this.resetSlotIdle(slot);
|
|
89719
|
+
return {
|
|
89720
|
+
ok: false,
|
|
89721
|
+
result: { success: false, error: `Failed to spawn agent: ${e.message}` }
|
|
89722
|
+
};
|
|
88728
89723
|
}
|
|
88729
|
-
|
|
88730
|
-
|
|
88731
|
-
|
|
88732
|
-
|
|
88733
|
-
|
|
89724
|
+
}
|
|
89725
|
+
return { ok: true, spawnResult };
|
|
89726
|
+
}
|
|
89727
|
+
assignRunningSlotState(key, slot, opts, spawnResult, wantResume, pid) {
|
|
89728
|
+
slot.state = "running";
|
|
89729
|
+
slot.pid = pid;
|
|
89730
|
+
slot.harness = opts.agentHarness;
|
|
89731
|
+
slot.harnessSessionId = spawnResult.harnessSessionId;
|
|
89732
|
+
if (spawnResult.harnessSessionId) {
|
|
89733
|
+
this.recordLastHarnessSession(key, {
|
|
89734
|
+
harnessSessionId: spawnResult.harnessSessionId,
|
|
89735
|
+
harness: opts.agentHarness,
|
|
89736
|
+
agentName: spawnResult.harnessReconnect?.agentName ?? "",
|
|
89737
|
+
workingDir: opts.workingDir,
|
|
89738
|
+
model: opts.model ?? spawnResult.harnessReconnect?.model
|
|
88734
89739
|
});
|
|
88735
|
-
|
|
88736
|
-
|
|
88737
|
-
|
|
88738
|
-
|
|
88739
|
-
|
|
88740
|
-
|
|
88741
|
-
|
|
88742
|
-
|
|
88743
|
-
|
|
88744
|
-
|
|
88745
|
-
|
|
88746
|
-
|
|
88747
|
-
|
|
88748
|
-
|
|
88749
|
-
|
|
88750
|
-
|
|
88751
|
-
|
|
88752
|
-
|
|
88753
|
-
|
|
88754
|
-
|
|
88755
|
-
|
|
88756
|
-
|
|
88757
|
-
|
|
88758
|
-
|
|
88759
|
-
|
|
88760
|
-
|
|
88761
|
-
|
|
88762
|
-
|
|
88763
|
-
|
|
88764
|
-
return { success: false, error: `Failed to spawn agent: ${e.message}` };
|
|
88765
|
-
}
|
|
88766
|
-
}
|
|
88767
|
-
const { pid } = spawnResult;
|
|
88768
|
-
this.deps.spawning.recordSpawn(opts.chatroomId);
|
|
88769
|
-
slot.state = "running";
|
|
88770
|
-
slot.pid = pid;
|
|
88771
|
-
slot.harness = opts.agentHarness;
|
|
88772
|
-
slot.harnessSessionId = spawnResult.harnessSessionId;
|
|
88773
|
-
if (spawnResult.harnessSessionId) {
|
|
88774
|
-
this.recordLastHarnessSession(key, {
|
|
88775
|
-
harnessSessionId: spawnResult.harnessSessionId,
|
|
88776
|
-
harness: opts.agentHarness,
|
|
88777
|
-
agentName: spawnResult.harnessReconnect?.agentName ?? "",
|
|
88778
|
-
workingDir: opts.workingDir,
|
|
88779
|
-
model: opts.model ?? spawnResult.harnessReconnect?.model
|
|
88780
|
-
});
|
|
88781
|
-
}
|
|
88782
|
-
slot.model = opts.model;
|
|
88783
|
-
slot.wantResume = wantResume;
|
|
88784
|
-
slot.workingDir = opts.workingDir;
|
|
88785
|
-
slot.startedAt = this.deps.clock.now();
|
|
88786
|
-
slot.pendingOperation = undefined;
|
|
88787
|
-
slot.recentLogLines = [];
|
|
88788
|
-
this.deps.resumeStormTracker.reset(opts.chatroomId, opts.role);
|
|
88789
|
-
if (spawnResult.onLogLine) {
|
|
88790
|
-
spawnResult.onLogLine((line) => appendRecentLogLine(slot, line));
|
|
88791
|
-
}
|
|
88792
|
-
this.deps.backend.mutation(api.machines.updateSpawnedAgent, {
|
|
88793
|
-
sessionId: this.deps.sessionId,
|
|
88794
|
-
machineId: this.deps.machineId,
|
|
89740
|
+
}
|
|
89741
|
+
slot.model = opts.model;
|
|
89742
|
+
slot.wantResume = wantResume;
|
|
89743
|
+
slot.workingDir = opts.workingDir;
|
|
89744
|
+
slot.startedAt = this.deps.clock.now();
|
|
89745
|
+
slot.pendingOperation = undefined;
|
|
89746
|
+
slot.recentLogLines = [];
|
|
89747
|
+
this.deps.resumeStormTracker.reset(opts.chatroomId, opts.role);
|
|
89748
|
+
}
|
|
89749
|
+
emitSpawnedAgentUpdate(opts, spawnResult, pid) {
|
|
89750
|
+
this.deps.backend.mutation(api.machines.updateSpawnedAgent, {
|
|
89751
|
+
sessionId: this.deps.sessionId,
|
|
89752
|
+
machineId: this.deps.machineId,
|
|
89753
|
+
chatroomId: opts.chatroomId,
|
|
89754
|
+
role: opts.role,
|
|
89755
|
+
pid,
|
|
89756
|
+
model: opts.model,
|
|
89757
|
+
reason: opts.reason,
|
|
89758
|
+
...spawnResult.harnessSessionId ? { harnessSessionId: spawnResult.harnessSessionId } : {}
|
|
89759
|
+
}).catch((err) => {
|
|
89760
|
+
console.log(` ⚠️ Failed to update PID in backend: ${err.message}`);
|
|
89761
|
+
});
|
|
89762
|
+
}
|
|
89763
|
+
registerSpawnCallbacks(slot, opts, spawnResult, pid) {
|
|
89764
|
+
if (spawnResult.onLogLine) {
|
|
89765
|
+
spawnResult.onLogLine((line) => appendRecentLogLine(slot, line));
|
|
89766
|
+
}
|
|
89767
|
+
spawnResult.onExit(({ code: code2, signal }) => {
|
|
89768
|
+
this.handleExit({
|
|
88795
89769
|
chatroomId: opts.chatroomId,
|
|
88796
89770
|
role: opts.role,
|
|
88797
89771
|
pid,
|
|
88798
|
-
|
|
88799
|
-
|
|
88800
|
-
...spawnResult.harnessSessionId ? { harnessSessionId: spawnResult.harnessSessionId } : {}
|
|
88801
|
-
}).catch((err) => {
|
|
88802
|
-
console.log(` ⚠️ Failed to update PID in backend: ${err.message}`);
|
|
89772
|
+
code: code2,
|
|
89773
|
+
signal
|
|
88803
89774
|
});
|
|
88804
|
-
|
|
88805
|
-
|
|
88806
|
-
|
|
88807
|
-
|
|
88808
|
-
this.handleExit({
|
|
89775
|
+
});
|
|
89776
|
+
if (spawnResult.onAgentEnd) {
|
|
89777
|
+
spawnResult.onAgentEnd(() => {
|
|
89778
|
+
this.turnEndQueue.enqueue(() => this.runHandleAgentEnd({
|
|
88809
89779
|
chatroomId: opts.chatroomId,
|
|
88810
89780
|
role: opts.role,
|
|
88811
89781
|
pid,
|
|
88812
|
-
|
|
88813
|
-
|
|
88814
|
-
});
|
|
89782
|
+
harness: opts.agentHarness
|
|
89783
|
+
}));
|
|
88815
89784
|
});
|
|
88816
|
-
|
|
88817
|
-
|
|
88818
|
-
|
|
88819
|
-
|
|
88820
|
-
|
|
88821
|
-
|
|
88822
|
-
|
|
88823
|
-
|
|
88824
|
-
|
|
89785
|
+
}
|
|
89786
|
+
let lastReportedTokenAt = 0;
|
|
89787
|
+
spawnResult.onOutput(() => {
|
|
89788
|
+
const now = this.deps.clock.now();
|
|
89789
|
+
if (now - lastReportedTokenAt >= 30000) {
|
|
89790
|
+
lastReportedTokenAt = now;
|
|
89791
|
+
this.deps.backend.mutation(api.participants.updateTokenActivity, {
|
|
89792
|
+
sessionId: this.deps.sessionId,
|
|
89793
|
+
chatroomId: opts.chatroomId,
|
|
89794
|
+
role: opts.role
|
|
89795
|
+
}).catch(() => {});
|
|
88825
89796
|
}
|
|
88826
|
-
|
|
88827
|
-
|
|
88828
|
-
|
|
88829
|
-
|
|
88830
|
-
|
|
88831
|
-
|
|
88832
|
-
|
|
88833
|
-
|
|
88834
|
-
|
|
88835
|
-
|
|
88836
|
-
|
|
88837
|
-
|
|
88838
|
-
|
|
89797
|
+
});
|
|
89798
|
+
}
|
|
89799
|
+
async finalizeRunningSlot(key, slot, opts, spawnResult, wantResume) {
|
|
89800
|
+
const { pid } = spawnResult;
|
|
89801
|
+
this.deps.spawning.recordSpawn(opts.chatroomId);
|
|
89802
|
+
this.assignRunningSlotState(key, slot, opts, spawnResult, wantResume, pid);
|
|
89803
|
+
this.emitSpawnedAgentUpdate(opts, spawnResult, pid);
|
|
89804
|
+
try {
|
|
89805
|
+
await this.deps.persistence.persistAgentPid(this.deps.machineId, opts.chatroomId, opts.role, pid, opts.agentHarness);
|
|
89806
|
+
} catch {}
|
|
89807
|
+
this.registerSpawnCallbacks(slot, opts, spawnResult, pid);
|
|
89808
|
+
}
|
|
89809
|
+
async doEnsureRunning(key, slot, opts) {
|
|
89810
|
+
slot.state = "spawning";
|
|
89811
|
+
const wantResume = opts.wantResume;
|
|
89812
|
+
console.log(`[AgentProcessManager] harness start: role=${opts.role} harness=${opts.agentHarness} wantResume=${wantResume} reason=${opts.reason}`);
|
|
89813
|
+
try {
|
|
89814
|
+
const rateLimit = this.checkRateLimitGate(opts, slot);
|
|
89815
|
+
if (rateLimit)
|
|
89816
|
+
return rateLimit;
|
|
89817
|
+
const crashLoop = this.checkCrashLoopGate(opts, slot);
|
|
89818
|
+
if (crashLoop)
|
|
89819
|
+
return crashLoop;
|
|
89820
|
+
const workingDir = await this.validateWorkingDirGate(opts, slot);
|
|
89821
|
+
if (workingDir)
|
|
89822
|
+
return workingDir;
|
|
89823
|
+
const initPrompt = await this.fetchInitPromptResult(opts, slot);
|
|
89824
|
+
if (!initPrompt.ok)
|
|
89825
|
+
return initPrompt.result;
|
|
89826
|
+
const spawn5 = await this.spawnAgentForEnsureRunning(key, slot, opts, initPrompt, wantResume);
|
|
89827
|
+
if (!spawn5.ok)
|
|
89828
|
+
return spawn5.result;
|
|
89829
|
+
await this.finalizeRunningSlot(key, slot, opts, spawn5.spawnResult, wantResume);
|
|
89830
|
+
return { success: true, pid: spawn5.spawnResult.pid };
|
|
88839
89831
|
} catch (e) {
|
|
88840
|
-
slot
|
|
88841
|
-
slot.pendingOperation = undefined;
|
|
89832
|
+
this.resetSlotIdle(slot);
|
|
88842
89833
|
return { success: false, error: `Unexpected error: ${e.message}` };
|
|
88843
89834
|
}
|
|
88844
89835
|
}
|
|
@@ -88851,64 +89842,75 @@ class AgentProcessManager {
|
|
|
88851
89842
|
readHarnessReconnectMetadata(service3, pid) {
|
|
88852
89843
|
return service3.getHarnessReconnectContext?.(pid);
|
|
88853
89844
|
}
|
|
88854
|
-
|
|
88855
|
-
|
|
88856
|
-
|
|
88857
|
-
|
|
88858
|
-
|
|
88859
|
-
|
|
88860
|
-
|
|
88861
|
-
|
|
88862
|
-
|
|
88863
|
-
|
|
88864
|
-
|
|
88865
|
-
|
|
88866
|
-
|
|
88867
|
-
|
|
88868
|
-
|
|
88869
|
-
|
|
88870
|
-
|
|
88871
|
-
|
|
88872
|
-
|
|
88873
|
-
|
|
89845
|
+
shouldPreserveHarnessOnStop(slot, opts) {
|
|
89846
|
+
const harness = slot.harness;
|
|
89847
|
+
const supportsResume = harness ? getHarnessCapabilities(harness).supportsSessionResume : false;
|
|
89848
|
+
return shouldPreserveHarnessTeardown(opts.reason, supportsResume, Boolean(slot.harnessSessionId));
|
|
89849
|
+
}
|
|
89850
|
+
recordHarnessSessionOnStop(key, slot, pid, service3) {
|
|
89851
|
+
const harness = slot.harness;
|
|
89852
|
+
const harnessMeta = service3 ? this.readHarnessReconnectMetadata(service3, pid) : undefined;
|
|
89853
|
+
this.recordLastHarnessSession(key, {
|
|
89854
|
+
harnessSessionId: slot.harnessSessionId,
|
|
89855
|
+
harness,
|
|
89856
|
+
agentName: harnessMeta?.agentName ?? "",
|
|
89857
|
+
workingDir: slot.workingDir ?? "",
|
|
89858
|
+
model: slot.model ?? harnessMeta?.model
|
|
89859
|
+
});
|
|
89860
|
+
}
|
|
89861
|
+
updateHarnessSessionOnStop(key, slot, pid, service3, preserveForResume) {
|
|
89862
|
+
const harness = slot.harness;
|
|
89863
|
+
if (harness && slot.harnessSessionId) {
|
|
89864
|
+
if (preserveForResume) {
|
|
89865
|
+
this.recordHarnessSessionOnStop(key, slot, pid, service3);
|
|
89866
|
+
} else {
|
|
88874
89867
|
this.clearLastHarnessSession(key);
|
|
88875
89868
|
}
|
|
88876
|
-
|
|
88877
|
-
|
|
88878
|
-
|
|
88879
|
-
|
|
88880
|
-
|
|
88881
|
-
|
|
88882
|
-
|
|
88883
|
-
|
|
88884
|
-
|
|
88885
|
-
|
|
88886
|
-
|
|
88887
|
-
|
|
88888
|
-
|
|
88889
|
-
|
|
88890
|
-
|
|
88891
|
-
|
|
88892
|
-
|
|
88893
|
-
|
|
88894
|
-
|
|
88895
|
-
|
|
88896
|
-
|
|
88897
|
-
|
|
88898
|
-
|
|
88899
|
-
|
|
88900
|
-
|
|
88901
|
-
|
|
88902
|
-
|
|
88903
|
-
|
|
88904
|
-
|
|
89869
|
+
return;
|
|
89870
|
+
}
|
|
89871
|
+
if (!preserveForResume) {
|
|
89872
|
+
this.clearLastHarnessSession(key);
|
|
89873
|
+
}
|
|
89874
|
+
}
|
|
89875
|
+
preserveOrClearHarnessSessionOnStop(key, slot, pid, opts, service3) {
|
|
89876
|
+
const preserveForResume = this.shouldPreserveHarnessOnStop(slot, opts);
|
|
89877
|
+
this.updateHarnessSessionOnStop(key, slot, pid, service3, preserveForResume);
|
|
89878
|
+
return preserveForResume;
|
|
89879
|
+
}
|
|
89880
|
+
async killProcessWithFallback(pid) {
|
|
89881
|
+
try {
|
|
89882
|
+
this.deps.processes.kill(-pid, "SIGTERM");
|
|
89883
|
+
} catch {}
|
|
89884
|
+
let dead = false;
|
|
89885
|
+
for (let i2 = 0;i2 < 20; i2++) {
|
|
89886
|
+
await this.deps.clock.delay(500);
|
|
89887
|
+
if (!isProcessAlive(this.deps.processes.kill, pid)) {
|
|
89888
|
+
dead = true;
|
|
89889
|
+
break;
|
|
89890
|
+
}
|
|
89891
|
+
}
|
|
89892
|
+
if (!dead) {
|
|
89893
|
+
try {
|
|
89894
|
+
this.deps.processes.kill(-pid, "SIGKILL");
|
|
89895
|
+
} catch {}
|
|
89896
|
+
for (let i2 = 0;i2 < 10; i2++) {
|
|
89897
|
+
await this.deps.clock.delay(500);
|
|
89898
|
+
if (!isProcessAlive(this.deps.processes.kill, pid)) {
|
|
89899
|
+
break;
|
|
88905
89900
|
}
|
|
88906
89901
|
}
|
|
88907
|
-
}
|
|
89902
|
+
}
|
|
89903
|
+
for (const svc of this.deps.agentServices.values()) {
|
|
89904
|
+
svc.untrack(pid);
|
|
89905
|
+
}
|
|
89906
|
+
}
|
|
89907
|
+
resetSlotAfterStop(slot) {
|
|
88908
89908
|
slot.state = "idle";
|
|
88909
89909
|
slot.pid = undefined;
|
|
88910
89910
|
slot.startedAt = undefined;
|
|
88911
89911
|
slot.pendingOperation = undefined;
|
|
89912
|
+
}
|
|
89913
|
+
recordStopExit(slot, pid, opts) {
|
|
88912
89914
|
const exitArgs3 = {
|
|
88913
89915
|
sessionId: this.deps.sessionId,
|
|
88914
89916
|
machineId: this.deps.machineId,
|
|
@@ -88924,6 +89926,21 @@ class AgentProcessManager {
|
|
|
88924
89926
|
console.log(` ⚠️ Failed to record agent exit event: ${err.message}`);
|
|
88925
89927
|
this.queueExitRetry({ role: opts.role, args: exitArgs3 });
|
|
88926
89928
|
});
|
|
89929
|
+
}
|
|
89930
|
+
async doStop(key, slot, pid, opts) {
|
|
89931
|
+
try {
|
|
89932
|
+
const harness = slot.harness;
|
|
89933
|
+
const service3 = harness ? this.deps.agentServices.get(harness) : undefined;
|
|
89934
|
+
const preserveForResume = this.preserveOrClearHarnessSessionOnStop(key, slot, pid, opts, service3);
|
|
89935
|
+
if (service3) {
|
|
89936
|
+
await service3.stop(pid, { preserveForResume });
|
|
89937
|
+
service3.untrack(pid);
|
|
89938
|
+
} else {
|
|
89939
|
+
await this.killProcessWithFallback(pid);
|
|
89940
|
+
}
|
|
89941
|
+
} catch {}
|
|
89942
|
+
this.resetSlotAfterStop(slot);
|
|
89943
|
+
this.recordStopExit(slot, pid, opts);
|
|
88927
89944
|
try {
|
|
88928
89945
|
await this.deps.persistence.clearAgentPid(this.deps.machineId, opts.chatroomId, opts.role);
|
|
88929
89946
|
} catch {}
|
|
@@ -88934,12 +89951,15 @@ var AGENT_EXIT_RETRY_INTERVAL_MS = 1e4;
|
|
|
88934
89951
|
var init_agent_process_manager = __esm(() => {
|
|
88935
89952
|
init_generator();
|
|
88936
89953
|
init_types();
|
|
89954
|
+
init_esm();
|
|
88937
89955
|
init_turn_completed_backend();
|
|
88938
89956
|
init_api3();
|
|
88939
89957
|
init_orphan_tracker();
|
|
88940
89958
|
init_agent_lifecycle();
|
|
88941
89959
|
init_classify_resume_storm_reason();
|
|
88942
89960
|
init_handle_turn_completed();
|
|
89961
|
+
init_agent_lifecycle_runtime();
|
|
89962
|
+
init_agent_lifecycle_types();
|
|
88943
89963
|
});
|
|
88944
89964
|
|
|
88945
89965
|
// src/infrastructure/services/harness-spawning/rate-limiter.ts
|
|
@@ -89505,6 +90525,7 @@ var init_models_refresh = __esm(() => {
|
|
|
89505
90525
|
var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
89506
90526
|
const session2 = yield* DaemonSessionService;
|
|
89507
90527
|
const effectContext2 = yield* exports_Effect.context();
|
|
90528
|
+
const runtime4 = yield* exports_Effect.runtime();
|
|
89508
90529
|
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Starting observed-sync subscription (reactive)`);
|
|
89509
90530
|
const observedWorkingDirs = new Map;
|
|
89510
90531
|
const chatroomRefreshState = new Map;
|
|
@@ -89560,7 +90581,7 @@ var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(func
|
|
|
89560
90581
|
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed-sync subscription stopped`);
|
|
89561
90582
|
}
|
|
89562
90583
|
};
|
|
89563
|
-
function
|
|
90584
|
+
function collectWorkingDirChanges(observed) {
|
|
89564
90585
|
const newWorkingDirs = new Set;
|
|
89565
90586
|
const refreshedWorkingDirs = new Set;
|
|
89566
90587
|
for (const chatroom of observed) {
|
|
@@ -89578,55 +90599,77 @@ var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(func
|
|
|
89578
90599
|
newWorkingDirs.add(wd);
|
|
89579
90600
|
}
|
|
89580
90601
|
}
|
|
90602
|
+
return { newWorkingDirs, refreshedWorkingDirs };
|
|
90603
|
+
}
|
|
90604
|
+
function pruneStaleChatroomRefreshState(observed) {
|
|
89581
90605
|
for (const [chatroomId] of chatroomRefreshState) {
|
|
89582
90606
|
const stillObserved = observed.some((c) => c.chatroomId === chatroomId);
|
|
89583
90607
|
if (!stillObserved) {
|
|
89584
90608
|
chatroomRefreshState.delete(chatroomId);
|
|
89585
90609
|
}
|
|
89586
90610
|
}
|
|
90611
|
+
}
|
|
90612
|
+
function removeUnobservedWorkingDirs(newWorkingDirs) {
|
|
89587
90613
|
const currentWorkingDirs = new Set(observedWorkingDirs.keys());
|
|
89588
|
-
let addedCount = 0;
|
|
89589
90614
|
let removedCount = 0;
|
|
89590
90615
|
for (const wd of currentWorkingDirs) {
|
|
89591
|
-
if (
|
|
89592
|
-
|
|
89593
|
-
|
|
89594
|
-
|
|
89595
|
-
|
|
89596
|
-
|
|
89597
|
-
|
|
89598
|
-
|
|
89599
|
-
|
|
89600
|
-
|
|
89601
|
-
|
|
89602
|
-
|
|
89603
|
-
|
|
89604
|
-
|
|
89605
|
-
}
|
|
90616
|
+
if (newWorkingDirs.has(wd)) {
|
|
90617
|
+
continue;
|
|
90618
|
+
}
|
|
90619
|
+
const state = observedWorkingDirs.get(wd);
|
|
90620
|
+
if (!state) {
|
|
90621
|
+
continue;
|
|
90622
|
+
}
|
|
90623
|
+
clearInterval(state.intervalHandle);
|
|
90624
|
+
observedWorkingDirs.delete(wd);
|
|
90625
|
+
const skips = skippedPushCount.get(wd) ?? 0;
|
|
90626
|
+
if (skips > 0) {
|
|
90627
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Stopped observing ${wd} (skipped ${skips} overlapping pushes)`);
|
|
90628
|
+
} else {
|
|
90629
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Stopped observing ${wd}`);
|
|
89606
90630
|
}
|
|
90631
|
+
skippedPushCount.delete(wd);
|
|
90632
|
+
pendingRefresh.delete(wd);
|
|
90633
|
+
removedCount++;
|
|
89607
90634
|
}
|
|
90635
|
+
return removedCount;
|
|
90636
|
+
}
|
|
90637
|
+
function addNewlyObservedWorkingDirs(newWorkingDirs) {
|
|
90638
|
+
let addedCount = 0;
|
|
89608
90639
|
for (const wd of newWorkingDirs) {
|
|
90640
|
+
if (observedWorkingDirs.has(wd)) {
|
|
90641
|
+
continue;
|
|
90642
|
+
}
|
|
90643
|
+
observedWorkingDirs.set(wd, {
|
|
90644
|
+
intervalHandle: setInterval(() => {
|
|
90645
|
+
schedulePushForWorkingDir(wd, "safety-poll");
|
|
90646
|
+
}, OBSERVED_SAFETY_POLL_MS),
|
|
90647
|
+
pushInFlight: false
|
|
90648
|
+
});
|
|
90649
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Started observing ${wd}`);
|
|
90650
|
+
schedulePushForWorkingDir(wd, "safety-poll");
|
|
90651
|
+
addedCount++;
|
|
90652
|
+
}
|
|
90653
|
+
return addedCount;
|
|
90654
|
+
}
|
|
90655
|
+
function triggerRefreshedWorkingDirs(refreshedWorkingDirs) {
|
|
90656
|
+
for (const wd of refreshedWorkingDirs) {
|
|
89609
90657
|
if (!observedWorkingDirs.has(wd)) {
|
|
89610
|
-
|
|
89611
|
-
intervalHandle: setInterval(() => {
|
|
89612
|
-
schedulePushForWorkingDir(wd, "safety-poll");
|
|
89613
|
-
}, OBSERVED_SAFETY_POLL_MS),
|
|
89614
|
-
pushInFlight: false
|
|
89615
|
-
});
|
|
89616
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Started observing ${wd}`);
|
|
89617
|
-
schedulePushForWorkingDir(wd, "safety-poll");
|
|
89618
|
-
addedCount++;
|
|
90658
|
+
continue;
|
|
89619
90659
|
}
|
|
90660
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD04 Refresh triggered for ${wd}`);
|
|
90661
|
+
schedulePushForWorkingDir(wd, "refresh");
|
|
89620
90662
|
}
|
|
90663
|
+
}
|
|
90664
|
+
function handleObservedChange(observed) {
|
|
90665
|
+
const { newWorkingDirs, refreshedWorkingDirs } = collectWorkingDirChanges(observed);
|
|
90666
|
+
pruneStaleChatroomRefreshState(observed);
|
|
90667
|
+
const removedCount = removeUnobservedWorkingDirs(newWorkingDirs);
|
|
90668
|
+
const addedCount = addNewlyObservedWorkingDirs(newWorkingDirs);
|
|
89621
90669
|
if (addedCount > 0 || removedCount > 0) {
|
|
89622
90670
|
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observing ${observedWorkingDirs.size} working dir(s)`);
|
|
89623
90671
|
}
|
|
89624
|
-
|
|
89625
|
-
if (observedWorkingDirs.has(wd)) {
|
|
89626
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDD04 Refresh triggered for ${wd}`);
|
|
89627
|
-
schedulePushForWorkingDir(wd, "refresh");
|
|
89628
|
-
}
|
|
89629
|
-
}
|
|
90672
|
+
triggerRefreshedWorkingDirs(refreshedWorkingDirs);
|
|
89630
90673
|
}
|
|
89631
90674
|
function schedulePushForWorkingDir(workingDir, reason = "safety-poll") {
|
|
89632
90675
|
if (stopped)
|
|
@@ -89644,9 +90687,13 @@ var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(func
|
|
|
89644
90687
|
return;
|
|
89645
90688
|
}
|
|
89646
90689
|
state.pushInFlight = true;
|
|
89647
|
-
pushForWorkingDir(workingDir, reason)
|
|
89648
|
-
|
|
89649
|
-
|
|
90690
|
+
pushForWorkingDir(workingDir, reason);
|
|
90691
|
+
}
|
|
90692
|
+
function pushForWorkingDir(workingDir, reason = "safety-poll") {
|
|
90693
|
+
exports_Runtime.runFork(runtime4)(exports_Effect.all([
|
|
90694
|
+
pushSingleWorkspaceGitSummaryForObservedEffect(workingDir, reason),
|
|
90695
|
+
pushSingleWorkspaceCommandsEffect(workingDir)
|
|
90696
|
+
], { concurrency: "unbounded" }).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[${formatTimestamp()}] ⚠️ Observed sync failed for ${workingDir}: ${getErrorMessage(err)}`))), exports_Effect.ensuring(exports_Effect.sync(() => {
|
|
89650
90697
|
const s = observedWorkingDirs.get(workingDir);
|
|
89651
90698
|
if (s) {
|
|
89652
90699
|
s.pushInFlight = false;
|
|
@@ -89655,15 +90702,7 @@ var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(func
|
|
|
89655
90702
|
schedulePushForWorkingDir(workingDir, "refresh");
|
|
89656
90703
|
}
|
|
89657
90704
|
}
|
|
89658
|
-
});
|
|
89659
|
-
}
|
|
89660
|
-
async function pushForWorkingDir(workingDir, reason = "safety-poll") {
|
|
89661
|
-
await exports_Effect.runPromise(pushSingleWorkspaceGitSummaryForObservedEffect(workingDir, reason).pipe(exports_Effect.provide(effectContext2))).catch((err) => {
|
|
89662
|
-
console.warn(`[${formatTimestamp()}] ⚠️ Observed git summary push failed for ${workingDir}: ${getErrorMessage(err)}`);
|
|
89663
|
-
});
|
|
89664
|
-
await exports_Effect.runPromise(pushSingleWorkspaceCommandsEffect(workingDir).pipe(exports_Effect.provide(effectContext2))).catch((err) => {
|
|
89665
|
-
console.warn(`[${formatTimestamp()}] ⚠️ Command sync failed for ${workingDir}: ${getErrorMessage(err)}`);
|
|
89666
|
-
});
|
|
90705
|
+
}))));
|
|
89667
90706
|
}
|
|
89668
90707
|
});
|
|
89669
90708
|
var init_observed_sync = __esm(() => {
|
|
@@ -89736,36 +90775,21 @@ var init_workspace_list_subscription = __esm(() => {
|
|
|
89736
90775
|
});
|
|
89737
90776
|
|
|
89738
90777
|
// src/commands/machine/daemon-start/command-loop.ts
|
|
89739
|
-
function
|
|
89740
|
-
const
|
|
89741
|
-
for (const [id3, ts] of tracker.commandIds) {
|
|
89742
|
-
if (ts < evictBefore)
|
|
89743
|
-
tracker.commandIds.delete(id3);
|
|
89744
|
-
}
|
|
89745
|
-
for (const [id3, ts] of tracker.pingIds) {
|
|
89746
|
-
if (ts < evictBefore)
|
|
89747
|
-
tracker.pingIds.delete(id3);
|
|
89748
|
-
}
|
|
89749
|
-
for (const [id3, ts] of tracker.gitRefreshIds) {
|
|
89750
|
-
if (ts < evictBefore)
|
|
89751
|
-
tracker.gitRefreshIds.delete(id3);
|
|
89752
|
-
}
|
|
89753
|
-
for (const [id3, ts] of tracker.capabilitiesRefreshIds) {
|
|
90778
|
+
function evictStaleEntries(entries2, evictBefore) {
|
|
90779
|
+
for (const [id3, ts] of entries2) {
|
|
89754
90780
|
if (ts < evictBefore)
|
|
89755
|
-
|
|
89756
|
-
}
|
|
89757
|
-
for (const [id3, ts] of tracker.localActionIds) {
|
|
89758
|
-
if (ts < evictBefore)
|
|
89759
|
-
tracker.localActionIds.delete(id3);
|
|
89760
|
-
}
|
|
89761
|
-
for (const [id3, ts] of tracker.commandRunIds) {
|
|
89762
|
-
if (ts < evictBefore)
|
|
89763
|
-
tracker.commandRunIds.delete(id3);
|
|
89764
|
-
}
|
|
89765
|
-
for (const [id3, ts] of tracker.commandStopIds) {
|
|
89766
|
-
if (ts < evictBefore)
|
|
89767
|
-
tracker.commandStopIds.delete(id3);
|
|
90781
|
+
entries2.delete(id3);
|
|
89768
90782
|
}
|
|
90783
|
+
}
|
|
90784
|
+
function evictStaleDedupEntries(tracker) {
|
|
90785
|
+
const evictBefore = Date.now() - AGENT_REQUEST_DEADLINE_MS;
|
|
90786
|
+
evictStaleEntries(tracker.commandIds, evictBefore);
|
|
90787
|
+
evictStaleEntries(tracker.pingIds, evictBefore);
|
|
90788
|
+
evictStaleEntries(tracker.gitRefreshIds, evictBefore);
|
|
90789
|
+
evictStaleEntries(tracker.capabilitiesRefreshIds, evictBefore);
|
|
90790
|
+
evictStaleEntries(tracker.localActionIds, evictBefore);
|
|
90791
|
+
evictStaleEntries(tracker.commandRunIds, evictBefore);
|
|
90792
|
+
evictStaleEntries(tracker.commandStopIds, evictBefore);
|
|
89769
90793
|
processManager.evictStalePendingStops();
|
|
89770
90794
|
}
|
|
89771
90795
|
function handleRequestStartEffect(event, tracker) {
|
|
@@ -89936,6 +90960,7 @@ var init_command_loop = __esm(() => {
|
|
|
89936
90960
|
startCommandLoopEffect = exports_Effect.gen(function* () {
|
|
89937
90961
|
const session2 = yield* DaemonSessionService;
|
|
89938
90962
|
const effectContext2 = yield* exports_Effect.context();
|
|
90963
|
+
const runtime4 = yield* exports_Effect.runtime();
|
|
89939
90964
|
const observedSyncEnabled = featureFlags.observedSyncEnabled ?? false;
|
|
89940
90965
|
let heartbeatCount = 0;
|
|
89941
90966
|
const heartbeatTimer = setInterval(() => {
|
|
@@ -89946,15 +90971,9 @@ var init_command_loop = __esm(() => {
|
|
|
89946
90971
|
heartbeatCount++;
|
|
89947
90972
|
console.log(`[${formatTimestamp()}] \uD83D\uDC93 Daemon heartbeat #${heartbeatCount} OK`);
|
|
89948
90973
|
if (!observedSyncEnabled) {
|
|
89949
|
-
|
|
89950
|
-
|
|
89951
|
-
});
|
|
89952
|
-
exports_Effect.runPromise(pushCommandsEffect.pipe(exports_Effect.provide(effectContext2))).catch((err) => {
|
|
89953
|
-
console.warn(`[${formatTimestamp()}] ⚠️ Command sync failed: ${getErrorMessage(err)}`);
|
|
89954
|
-
});
|
|
89955
|
-
exports_Effect.runPromise(syncCommitDetailsEffect().pipe(exports_Effect.provide(effectContext2))).catch((err) => {
|
|
89956
|
-
console.warn(`[${formatTimestamp()}] ⚠️ Commit detail sync failed: ${getErrorMessage(err)}`);
|
|
89957
|
-
});
|
|
90974
|
+
exports_Runtime.runFork(runtime4)(exports_Effect.all([pushGitStateEffect, pushCommandsEffect, syncCommitDetailsEffect()], {
|
|
90975
|
+
concurrency: "unbounded"
|
|
90976
|
+
}).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[${formatTimestamp()}] ⚠️ Heartbeat sync failed: ${getErrorMessage(err)}`)))));
|
|
89958
90977
|
}
|
|
89959
90978
|
}).catch((err) => {
|
|
89960
90979
|
console.warn(`[${formatTimestamp()}] ⚠️ Daemon heartbeat failed: ${getErrorMessage(err)}`);
|
|
@@ -89976,9 +90995,9 @@ var init_command_loop = __esm(() => {
|
|
|
89976
90995
|
if (observedSyncEnabled) {
|
|
89977
90996
|
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed-sync enabled, skipping immediate push`);
|
|
89978
90997
|
} else {
|
|
89979
|
-
|
|
89980
|
-
|
|
89981
|
-
|
|
90998
|
+
exports_Runtime.runFork(runtime4)(exports_Effect.all([pushGitStateEffect, pushCommandsEffect, syncCommitDetailsEffect()], {
|
|
90999
|
+
concurrency: "unbounded"
|
|
91000
|
+
}).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[${formatTimestamp()}] ⚠️ Startup sync failed: ${getErrorMessage(err)}`)))));
|
|
89982
91001
|
}
|
|
89983
91002
|
const PROCESS_KILL_TIMEOUT_MS = 6000;
|
|
89984
91003
|
const CLOSE_TIMEOUT_MS = 3000;
|
|
@@ -90011,43 +91030,46 @@ var init_command_loop = __esm(() => {
|
|
|
90011
91030
|
return;
|
|
90012
91031
|
isShuttingDown = true;
|
|
90013
91032
|
console.log(`
|
|
90014
|
-
[${formatTimestamp()}] Shutting down... (press Ctrl+
|
|
91033
|
+
[${formatTimestamp()}] Shutting down... (press Ctrl+B again to force)`);
|
|
91034
|
+
const watchdog = setupShutdownWatchdog();
|
|
91035
|
+
clearInterval(heartbeatTimer);
|
|
91036
|
+
stopSubscriptions();
|
|
91037
|
+
await runDaemonShutdownEffect();
|
|
91038
|
+
await closeAllSessionsAndHarnesses();
|
|
91039
|
+
clearTimeout(watchdog);
|
|
91040
|
+
releaseLock();
|
|
91041
|
+
process.exit(0);
|
|
91042
|
+
};
|
|
91043
|
+
const setupShutdownWatchdog = () => {
|
|
90015
91044
|
const watchdog = setTimeout(() => {
|
|
90016
91045
|
console.error(`[${formatTimestamp()}] Shutdown timed out — forcing exit.`);
|
|
90017
91046
|
forceExit(1);
|
|
90018
91047
|
}, SHUTDOWN_WATCHDOG_MS);
|
|
90019
91048
|
watchdog.unref?.();
|
|
90020
|
-
|
|
90021
|
-
|
|
90022
|
-
|
|
90023
|
-
|
|
90024
|
-
|
|
90025
|
-
|
|
90026
|
-
|
|
90027
|
-
|
|
90028
|
-
|
|
90029
|
-
|
|
90030
|
-
|
|
90031
|
-
|
|
90032
|
-
|
|
90033
|
-
|
|
90034
|
-
|
|
90035
|
-
if (pendingHarnessSessionSubscriptionHandle)
|
|
90036
|
-
pendingHarnessSessionSubscriptionHandle.stop();
|
|
90037
|
-
if (commandSubscriptionHandle)
|
|
90038
|
-
commandSubscriptionHandle.stop();
|
|
90039
|
-
if (lifecycleManager)
|
|
90040
|
-
lifecycleManager.stopMonitoring();
|
|
91049
|
+
return watchdog;
|
|
91050
|
+
};
|
|
91051
|
+
const stopSubscriptions = () => {
|
|
91052
|
+
gitSubscriptionHandle?.stop();
|
|
91053
|
+
fileContentSubscriptionHandle?.stop();
|
|
91054
|
+
fileTreeSubscriptionHandle?.stop();
|
|
91055
|
+
workspaceListSubscriptionHandle?.stop();
|
|
91056
|
+
observedSyncSubscriptionHandle?.stop();
|
|
91057
|
+
logObserverSubscriptionHandle?.stop();
|
|
91058
|
+
pendingPromptSubscriptionHandle?.stop();
|
|
91059
|
+
pendingHarnessSessionSubscriptionHandle?.stop();
|
|
91060
|
+
commandSubscriptionHandle?.stop();
|
|
91061
|
+
lifecycleManager?.stopMonitoring();
|
|
91062
|
+
};
|
|
91063
|
+
const runDaemonShutdownEffect = async () => {
|
|
90041
91064
|
await withTimeout3(exports_Effect.runPromise(onDaemonShutdownEffect.pipe(exports_Effect.provide(effectContext2))), PROCESS_KILL_TIMEOUT_MS);
|
|
91065
|
+
};
|
|
91066
|
+
const closeAllSessionsAndHarnesses = async () => {
|
|
90042
91067
|
for (const handle of activeSessions.values()) {
|
|
90043
91068
|
await withTimeout3(handle.close(), CLOSE_TIMEOUT_MS);
|
|
90044
91069
|
}
|
|
90045
91070
|
for (const harness of harnesses.values()) {
|
|
90046
91071
|
await withTimeout3(harness.close(), CLOSE_TIMEOUT_MS);
|
|
90047
91072
|
}
|
|
90048
|
-
clearTimeout(watchdog);
|
|
90049
|
-
releaseLock();
|
|
90050
|
-
process.exit(0);
|
|
90051
91073
|
};
|
|
90052
91074
|
const handleSignal = (signal) => {
|
|
90053
91075
|
signalCount += 1;
|
|
@@ -91316,4 +92338,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
91316
92338
|
});
|
|
91317
92339
|
program2.parse();
|
|
91318
92340
|
|
|
91319
|
-
//# debugId=
|
|
92341
|
+
//# debugId=D908929E6EC55FCC64756E2164756E21
|