chatroom-cli 1.55.5 → 1.55.7
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 +1952 -844
- package/dist/index.js.map +38 -26
- 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
|
|
|
@@ -27143,6 +27327,96 @@ var init_opencode = __esm(() => {
|
|
|
27143
27327
|
init_opencode_agent_service();
|
|
27144
27328
|
});
|
|
27145
27329
|
|
|
27330
|
+
// src/infrastructure/services/remote-agents/agent-log-format.ts
|
|
27331
|
+
function buildAgentLogPrefix(agent, context5) {
|
|
27332
|
+
const roleTag = context5.role ?? "unknown";
|
|
27333
|
+
const chatroomSuffix = context5.chatroomId ? `@${context5.chatroomId.slice(-6)}` : "";
|
|
27334
|
+
return `[${agent}:${roleTag}${chatroomSuffix}`;
|
|
27335
|
+
}
|
|
27336
|
+
function formatAgentLogLine(prefix, kind, payload) {
|
|
27337
|
+
return payload !== undefined && payload !== "" ? `${prefix} ${kind}] ${payload}` : `${prefix} ${kind}]`;
|
|
27338
|
+
}
|
|
27339
|
+
function formatTimestampedLogLine(role, kind, payload, now) {
|
|
27340
|
+
const ts = now ? now() : new Date().toISOString();
|
|
27341
|
+
return `[${ts}] role:${role} ${kind}]${payload ? ` ${payload}` : ""}`;
|
|
27342
|
+
}
|
|
27343
|
+
function formatBashRunningPayload(command) {
|
|
27344
|
+
return `${BASH_RUNNING_PREFIX} ${command}`;
|
|
27345
|
+
}
|
|
27346
|
+
function isBashLikeToolName(name) {
|
|
27347
|
+
return /bash|shell|terminal|command/i.test(name);
|
|
27348
|
+
}
|
|
27349
|
+
function extractBashCommandFromToolInput(name, input) {
|
|
27350
|
+
if (!isBashLikeToolName(name))
|
|
27351
|
+
return null;
|
|
27352
|
+
if (input && typeof input === "object" && "command" in input) {
|
|
27353
|
+
return String(input.command);
|
|
27354
|
+
}
|
|
27355
|
+
if (typeof input === "string")
|
|
27356
|
+
return input;
|
|
27357
|
+
return null;
|
|
27358
|
+
}
|
|
27359
|
+
function resolveBashCommandForLog(name, input) {
|
|
27360
|
+
if (!isBashLikeToolName(name))
|
|
27361
|
+
return null;
|
|
27362
|
+
const extracted = extractBashCommandFromToolInput(name, input);
|
|
27363
|
+
if (extracted !== null)
|
|
27364
|
+
return extracted;
|
|
27365
|
+
if (input != null)
|
|
27366
|
+
return JSON.stringify(input);
|
|
27367
|
+
return "";
|
|
27368
|
+
}
|
|
27369
|
+
function extractBashCommandFromCursorToolCall(toolCall) {
|
|
27370
|
+
if (!toolCall || typeof toolCall !== "object")
|
|
27371
|
+
return null;
|
|
27372
|
+
for (const [key, value] of Object.entries(toolCall)) {
|
|
27373
|
+
if (!isBashLikeToolName(key) || !value || typeof value !== "object")
|
|
27374
|
+
continue;
|
|
27375
|
+
const args2 = value.args;
|
|
27376
|
+
if (args2 && typeof args2 === "object" && "command" in args2) {
|
|
27377
|
+
return String(args2.command);
|
|
27378
|
+
}
|
|
27379
|
+
}
|
|
27380
|
+
return null;
|
|
27381
|
+
}
|
|
27382
|
+
function appendToolInputToPayload(base, input, toolName) {
|
|
27383
|
+
if (!input || typeof input === "object" && Object.keys(input).length === 0) {
|
|
27384
|
+
return base;
|
|
27385
|
+
}
|
|
27386
|
+
const inp = input;
|
|
27387
|
+
if (toolName === "bash" && typeof inp.command === "string") {
|
|
27388
|
+
return `${base}: ${inp.command}`;
|
|
27389
|
+
}
|
|
27390
|
+
const inputStr = typeof inp === "string" ? inp : JSON.stringify(inp);
|
|
27391
|
+
return `${base}: ${inputStr}`;
|
|
27392
|
+
}
|
|
27393
|
+
function createAgentLogWriter(prefix, options) {
|
|
27394
|
+
const target = options?.target ?? process.stdout;
|
|
27395
|
+
const emitLogLine = options?.emitLogLine;
|
|
27396
|
+
const writeLine = (formatted) => {
|
|
27397
|
+
target.write(`${formatted}
|
|
27398
|
+
`);
|
|
27399
|
+
emitLogLine?.(formatted);
|
|
27400
|
+
};
|
|
27401
|
+
return {
|
|
27402
|
+
write(kind, payload) {
|
|
27403
|
+
writeLine(formatAgentLogLine(prefix, kind, payload));
|
|
27404
|
+
},
|
|
27405
|
+
writeLine,
|
|
27406
|
+
flushBufferedLines(buffer, kind) {
|
|
27407
|
+
if (!buffer)
|
|
27408
|
+
return buffer;
|
|
27409
|
+
for (const line of buffer.split(`
|
|
27410
|
+
`)) {
|
|
27411
|
+
if (line)
|
|
27412
|
+
writeLine(formatAgentLogLine(prefix, kind, line));
|
|
27413
|
+
}
|
|
27414
|
+
return "";
|
|
27415
|
+
}
|
|
27416
|
+
};
|
|
27417
|
+
}
|
|
27418
|
+
var BASH_TOOL_KIND = "tool: bash", BASH_RUNNING_PREFIX = "running:";
|
|
27419
|
+
|
|
27146
27420
|
// src/infrastructure/services/remote-agents/pi/pi-rpc-reader.ts
|
|
27147
27421
|
import { createInterface } from "node:readline";
|
|
27148
27422
|
|
|
@@ -27281,21 +27555,30 @@ var init_pi_agent_service = __esm(() => {
|
|
|
27281
27555
|
async resumeFromDaemonMemory(options, stored) {
|
|
27282
27556
|
const { prompt, systemPrompt, model, context: context5 } = options;
|
|
27283
27557
|
const modelForSession = model ?? stored.model;
|
|
27284
|
-
|
|
27285
|
-
|
|
27286
|
-
|
|
27287
|
-
|
|
27288
|
-
|
|
27289
|
-
|
|
27290
|
-
|
|
27291
|
-
|
|
27292
|
-
|
|
27293
|
-
childProcess,
|
|
27294
|
-
|
|
27295
|
-
|
|
27296
|
-
|
|
27297
|
-
|
|
27298
|
-
|
|
27558
|
+
let childProcess;
|
|
27559
|
+
try {
|
|
27560
|
+
childProcess = this.spawnPiRpcProcess({
|
|
27561
|
+
workingDir: stored.workingDir,
|
|
27562
|
+
systemPrompt,
|
|
27563
|
+
model: modelForSession,
|
|
27564
|
+
sessionId: stored.harnessSessionId
|
|
27565
|
+
});
|
|
27566
|
+
await this.waitForSpawnReady(childProcess);
|
|
27567
|
+
await this.writePrompt(childProcess, prompt);
|
|
27568
|
+
return this.wireRpcProcess({
|
|
27569
|
+
childProcess,
|
|
27570
|
+
context: context5,
|
|
27571
|
+
workingDir: stored.workingDir,
|
|
27572
|
+
model: modelForSession,
|
|
27573
|
+
harnessSessionId: stored.harnessSessionId
|
|
27574
|
+
});
|
|
27575
|
+
} catch (err) {
|
|
27576
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
27577
|
+
process.stderr.write(`[${new Date().toISOString()}] role:${context5.role} daemon-resume-fallback] ${reason} — cold spawning
|
|
27578
|
+
`);
|
|
27579
|
+
childProcess?.kill();
|
|
27580
|
+
return this.spawn(options);
|
|
27581
|
+
}
|
|
27299
27582
|
}
|
|
27300
27583
|
async resumeTurn(pid, prompt) {
|
|
27301
27584
|
const child = this.childProcesses.get(pid);
|
|
@@ -27423,9 +27706,7 @@ var init_pi_agent_service = __esm(() => {
|
|
|
27423
27706
|
this.childProcesses.set(pid, childProcess);
|
|
27424
27707
|
this.trackedSessions.set(pid, { harnessSessionId, workingDir, model });
|
|
27425
27708
|
const entry = this.registerProcess(pid, context5);
|
|
27426
|
-
const
|
|
27427
|
-
const chatroomSuffix = context5.chatroomId ? `@${context5.chatroomId.slice(-6)}` : "";
|
|
27428
|
-
const logPrefix = `[pi:${roleTag}${chatroomSuffix}`;
|
|
27709
|
+
const logPrefix = buildAgentLogPrefix("pi", context5);
|
|
27429
27710
|
const outputCallbacks = [];
|
|
27430
27711
|
const logLineCallbacks = [];
|
|
27431
27712
|
const agentEndCallbacks = [];
|
|
@@ -27461,11 +27742,7 @@ var init_pi_agent_service = __esm(() => {
|
|
|
27461
27742
|
onOutput,
|
|
27462
27743
|
onLogLine
|
|
27463
27744
|
};
|
|
27464
|
-
const
|
|
27465
|
-
process.stdout.write(`${formatted}
|
|
27466
|
-
`);
|
|
27467
|
-
emitLogLine(formatted);
|
|
27468
|
-
};
|
|
27745
|
+
const log4 = createAgentLogWriter(logPrefix, { emitLogLine });
|
|
27469
27746
|
const onStderrData = (chunk2) => {
|
|
27470
27747
|
entry.lastOutputAt = Date.now();
|
|
27471
27748
|
for (const cb of outputCallbacks)
|
|
@@ -27486,15 +27763,9 @@ var init_pi_agent_service = __esm(() => {
|
|
|
27486
27763
|
let textBuffer = "";
|
|
27487
27764
|
let thinkingBuffer = "";
|
|
27488
27765
|
const flushBufferedLines = (buffer, kind, clear) => {
|
|
27489
|
-
|
|
27490
|
-
return;
|
|
27491
|
-
for (const line of buffer.split(`
|
|
27492
|
-
`)) {
|
|
27493
|
-
if (line) {
|
|
27494
|
-
writeFormattedLogLine(`${logPrefix} ${kind}] ${line}`);
|
|
27495
|
-
}
|
|
27496
|
-
}
|
|
27766
|
+
const remaining = log4.flushBufferedLines(buffer, kind);
|
|
27497
27767
|
clear();
|
|
27768
|
+
return remaining;
|
|
27498
27769
|
};
|
|
27499
27770
|
const flushText = () => flushBufferedLines(textBuffer, "text", () => {
|
|
27500
27771
|
textBuffer = "";
|
|
@@ -27529,20 +27800,24 @@ var init_pi_agent_service = __esm(() => {
|
|
|
27529
27800
|
reader.onAgentEnd(() => {
|
|
27530
27801
|
flushText();
|
|
27531
27802
|
flushThinking();
|
|
27532
|
-
|
|
27533
|
-
`);
|
|
27803
|
+
log4.write("agent_end");
|
|
27534
27804
|
for (const cb of agentEndCallbacks)
|
|
27535
27805
|
cb();
|
|
27536
27806
|
});
|
|
27537
27807
|
reader.onToolCall((name, toolArgs) => {
|
|
27538
27808
|
flushText();
|
|
27539
27809
|
flushThinking();
|
|
27810
|
+
const bashCmd = resolveBashCommandForLog(name, toolArgs);
|
|
27811
|
+
if (bashCmd !== null) {
|
|
27812
|
+
log4.write(BASH_TOOL_KIND, formatBashRunningPayload(bashCmd));
|
|
27813
|
+
return;
|
|
27814
|
+
}
|
|
27540
27815
|
const argsStr = toolArgs != null ? ` args: ${JSON.stringify(toolArgs)}` : "";
|
|
27541
|
-
|
|
27816
|
+
log4.write("tool", `${name}${argsStr}`);
|
|
27542
27817
|
});
|
|
27543
27818
|
reader.onToolResult((name, result) => {
|
|
27544
27819
|
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
27545
|
-
|
|
27820
|
+
log4.write("tool_result", `${name} result: ${resultStr}`);
|
|
27546
27821
|
});
|
|
27547
27822
|
attachStderr(childProcess.stderr);
|
|
27548
27823
|
return {
|
|
@@ -27748,9 +28023,7 @@ ${options.prompt}`;
|
|
|
27748
28023
|
const pid = childProcess.pid;
|
|
27749
28024
|
const context5 = options.context;
|
|
27750
28025
|
const entry = this.registerProcess(pid, context5);
|
|
27751
|
-
const
|
|
27752
|
-
const chatroomSuffix = context5.chatroomId ? `@${context5.chatroomId.slice(-6)}` : "";
|
|
27753
|
-
const logPrefix = `[cursor:${roleTag}${chatroomSuffix}`;
|
|
28026
|
+
const logPrefix = buildAgentLogPrefix("cursor", context5);
|
|
27754
28027
|
const outputCallbacks = [];
|
|
27755
28028
|
if (childProcess.stdout) {
|
|
27756
28029
|
const reader = new CursorStreamReader(childProcess.stdout);
|
|
@@ -27761,7 +28034,7 @@ ${options.prompt}`;
|
|
|
27761
28034
|
for (const line of textBuffer.split(`
|
|
27762
28035
|
`)) {
|
|
27763
28036
|
if (line)
|
|
27764
|
-
process.stdout.write(`${logPrefix
|
|
28037
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, "text", line)}
|
|
27765
28038
|
`);
|
|
27766
28039
|
}
|
|
27767
28040
|
textBuffer = "";
|
|
@@ -27782,17 +28055,23 @@ ${options.prompt}`;
|
|
|
27782
28055
|
});
|
|
27783
28056
|
reader.onAgentEnd(() => {
|
|
27784
28057
|
flushText();
|
|
27785
|
-
process.stdout.write(`${logPrefix
|
|
28058
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, "agent_end")}
|
|
27786
28059
|
`);
|
|
27787
28060
|
});
|
|
27788
28061
|
reader.onToolCall((callId, toolCall) => {
|
|
27789
28062
|
flushText();
|
|
27790
|
-
|
|
28063
|
+
const bashCmd = extractBashCommandFromCursorToolCall(toolCall);
|
|
28064
|
+
if (bashCmd !== null) {
|
|
28065
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, BASH_TOOL_KIND, formatBashRunningPayload(bashCmd))}
|
|
28066
|
+
`);
|
|
28067
|
+
return;
|
|
28068
|
+
}
|
|
28069
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, "tool", `${callId} ${JSON.stringify(toolCall)}`)}
|
|
27791
28070
|
`);
|
|
27792
28071
|
});
|
|
27793
28072
|
reader.onToolResult((callId) => {
|
|
27794
28073
|
flushText();
|
|
27795
|
-
process.stdout.write(`${logPrefix
|
|
28074
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, "tool_result", callId)}
|
|
27796
28075
|
`);
|
|
27797
28076
|
});
|
|
27798
28077
|
if (childProcess.stderr) {
|
|
@@ -28183,9 +28462,7 @@ var init_claude_code_agent_service = __esm(() => {
|
|
|
28183
28462
|
const pid = childProcess.pid;
|
|
28184
28463
|
const context5 = options.context;
|
|
28185
28464
|
const entry = this.registerProcess(pid, context5);
|
|
28186
|
-
const
|
|
28187
|
-
const chatroomSuffix = context5.chatroomId ? `@${context5.chatroomId.slice(-6)}` : "";
|
|
28188
|
-
const logPrefix = `[claude:${roleTag}${chatroomSuffix}]`;
|
|
28465
|
+
const logPrefix = buildAgentLogPrefix("claude", context5);
|
|
28189
28466
|
const outputCallbacks = [];
|
|
28190
28467
|
if (childProcess.stdout) {
|
|
28191
28468
|
const reader = new ClaudeStreamReader(childProcess.stdout);
|
|
@@ -28197,7 +28474,7 @@ var init_claude_code_agent_service = __esm(() => {
|
|
|
28197
28474
|
for (const line of textBuffer.split(`
|
|
28198
28475
|
`)) {
|
|
28199
28476
|
if (line)
|
|
28200
|
-
process.stdout.write(`${logPrefix
|
|
28477
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, "text", line)}
|
|
28201
28478
|
`);
|
|
28202
28479
|
}
|
|
28203
28480
|
textBuffer = "";
|
|
@@ -28208,7 +28485,7 @@ var init_claude_code_agent_service = __esm(() => {
|
|
|
28208
28485
|
for (const line of thinkingBuffer.split(`
|
|
28209
28486
|
`)) {
|
|
28210
28487
|
if (line)
|
|
28211
|
-
process.stdout.write(`${logPrefix
|
|
28488
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, "thinking", line)}
|
|
28212
28489
|
`);
|
|
28213
28490
|
}
|
|
28214
28491
|
thinkingBuffer = "";
|
|
@@ -28239,8 +28516,16 @@ var init_claude_code_agent_service = __esm(() => {
|
|
|
28239
28516
|
});
|
|
28240
28517
|
reader.onToolUse((name, input) => {
|
|
28241
28518
|
entry.lastOutputAt = Date.now();
|
|
28519
|
+
const bashCmd = extractBashCommandFromToolInput(name, input);
|
|
28520
|
+
if (bashCmd !== null) {
|
|
28521
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, BASH_TOOL_KIND, formatBashRunningPayload(bashCmd))}
|
|
28522
|
+
`);
|
|
28523
|
+
for (const cb of outputCallbacks)
|
|
28524
|
+
cb();
|
|
28525
|
+
return;
|
|
28526
|
+
}
|
|
28242
28527
|
const inputStr = JSON.stringify(input);
|
|
28243
|
-
process.stdout.write(`${logPrefix
|
|
28528
|
+
process.stdout.write(`${formatAgentLogLine(logPrefix, "tool", `${name}(${inputStr.slice(0, 100)}${inputStr.length > 100 ? "..." : ""})`)}
|
|
28244
28529
|
`);
|
|
28245
28530
|
for (const cb of outputCallbacks)
|
|
28246
28531
|
cb();
|
|
@@ -28633,19 +28918,25 @@ class CursorSdkStreamAdapter {
|
|
|
28633
28918
|
case "assistant":
|
|
28634
28919
|
this.handleAssistant(message);
|
|
28635
28920
|
break;
|
|
28636
|
-
case "tool_call":
|
|
28921
|
+
case "tool_call": {
|
|
28637
28922
|
this.flushText();
|
|
28638
|
-
|
|
28923
|
+
const bashCmd = extractBashCommandFromToolInput(message.name, message.args);
|
|
28924
|
+
if (bashCmd !== null) {
|
|
28925
|
+
this.writeLine(formatAgentLogLine(this.logPrefix, BASH_TOOL_KIND, formatBashRunningPayload(bashCmd)));
|
|
28926
|
+
break;
|
|
28927
|
+
}
|
|
28928
|
+
this.writeLine(formatAgentLogLine(this.logPrefix, `tool: ${message.call_id} ${message.name} ${JSON.stringify({ status: message.status, args: message.args })}`));
|
|
28639
28929
|
break;
|
|
28930
|
+
}
|
|
28640
28931
|
case "status":
|
|
28641
|
-
this.writeLine(
|
|
28932
|
+
this.writeLine(formatAgentLogLine(this.logPrefix, `status: ${message.status}`));
|
|
28642
28933
|
break;
|
|
28643
28934
|
case "thinking":
|
|
28644
|
-
this.writeLine(
|
|
28935
|
+
this.writeLine(formatAgentLogLine(this.logPrefix, "thinking", message.text));
|
|
28645
28936
|
break;
|
|
28646
28937
|
case "system":
|
|
28647
28938
|
if (message.subtype === "init") {
|
|
28648
|
-
this.writeLine(
|
|
28939
|
+
this.writeLine(formatAgentLogLine(this.logPrefix, "system: init"));
|
|
28649
28940
|
}
|
|
28650
28941
|
break;
|
|
28651
28942
|
default:
|
|
@@ -28676,7 +28967,7 @@ class CursorSdkStreamAdapter {
|
|
|
28676
28967
|
for (const line of this.textBuffer.split(`
|
|
28677
28968
|
`)) {
|
|
28678
28969
|
if (line)
|
|
28679
|
-
this.writeLine(
|
|
28970
|
+
this.writeLine(formatAgentLogLine(this.logPrefix, "text", line));
|
|
28680
28971
|
}
|
|
28681
28972
|
this.textBuffer = "";
|
|
28682
28973
|
}
|
|
@@ -28685,7 +28976,7 @@ class CursorSdkStreamAdapter {
|
|
|
28685
28976
|
return;
|
|
28686
28977
|
this.agentEndEmitted = true;
|
|
28687
28978
|
this.flushText();
|
|
28688
|
-
this.writeLine(
|
|
28979
|
+
this.writeLine(formatAgentLogLine(this.logPrefix, "agent_end"));
|
|
28689
28980
|
for (const cb of this.agentEndCallbacks)
|
|
28690
28981
|
cb();
|
|
28691
28982
|
}
|
|
@@ -28699,6 +28990,7 @@ class CursorSdkStreamAdapter {
|
|
|
28699
28990
|
cb();
|
|
28700
28991
|
}
|
|
28701
28992
|
}
|
|
28993
|
+
var init_cursor_sdk_stream_adapter = () => {};
|
|
28702
28994
|
|
|
28703
28995
|
// src/infrastructure/services/remote-agents/cursor-sdk/cursor-sdk-agent-service.ts
|
|
28704
28996
|
import { randomUUID } from "node:crypto";
|
|
@@ -28758,16 +29050,11 @@ function waitForResumeOrAbort(session2) {
|
|
|
28758
29050
|
})
|
|
28759
29051
|
]);
|
|
28760
29052
|
}
|
|
28761
|
-
function buildLogPrefix(context5) {
|
|
28762
|
-
const roleTag = context5.role ?? "unknown";
|
|
28763
|
-
const chatroomSuffix = context5.chatroomId ? `@${context5.chatroomId.slice(-6)}` : "";
|
|
28764
|
-
return `[cursor-sdk:${roleTag}${chatroomSuffix}`;
|
|
28765
|
-
}
|
|
28766
29053
|
function resolveModelId(model) {
|
|
28767
29054
|
return model ? resolveCursorSdkModel(model) : DEFAULT_MODEL;
|
|
28768
29055
|
}
|
|
28769
29056
|
function writeSpawnError(logPrefix, err, emitLogLine) {
|
|
28770
|
-
const line =
|
|
29057
|
+
const line = formatAgentLogLine(logPrefix, "spawn-error", formatCursorSdkLoadError(err));
|
|
28771
29058
|
process.stderr.write(`${line}
|
|
28772
29059
|
`);
|
|
28773
29060
|
emitLogLine?.(line);
|
|
@@ -28779,6 +29066,7 @@ var init_cursor_sdk_agent_service = __esm(() => {
|
|
|
28779
29066
|
init_base_cli_agent_service();
|
|
28780
29067
|
init_detection_result();
|
|
28781
29068
|
init_cursor_sdk_package();
|
|
29069
|
+
init_cursor_sdk_stream_adapter();
|
|
28782
29070
|
CursorSdkAgentService = class CursorSdkAgentService extends BaseCLIAgentService {
|
|
28783
29071
|
id = "cursor-sdk";
|
|
28784
29072
|
displayName = "Cursor (SDK)";
|
|
@@ -28901,9 +29189,12 @@ ${options.prompt}`;
|
|
|
28901
29189
|
local: { cwd: stored.workingDir, settingSources: [] }
|
|
28902
29190
|
}), AGENT_CREATE_TIMEOUT_MS, "Agent.resume");
|
|
28903
29191
|
} catch (err) {
|
|
29192
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
29193
|
+
process.stderr.write(`[${new Date().toISOString()}] role:${context5.role} daemon-resume-fallback] ${reason} — cold spawning
|
|
29194
|
+
`);
|
|
28904
29195
|
keeper.kill();
|
|
28905
29196
|
this.deleteProcess(pid);
|
|
28906
|
-
|
|
29197
|
+
return this.spawn(options);
|
|
28907
29198
|
}
|
|
28908
29199
|
return this.startRunningSession({
|
|
28909
29200
|
pid,
|
|
@@ -28943,7 +29234,7 @@ ${options.prompt}`;
|
|
|
28943
29234
|
forceFirstTurn
|
|
28944
29235
|
} = args2;
|
|
28945
29236
|
const entry = this.registerProcess(pid, context5);
|
|
28946
|
-
const logPrefix =
|
|
29237
|
+
const logPrefix = buildAgentLogPrefix("cursor-sdk", context5);
|
|
28947
29238
|
const session2 = {
|
|
28948
29239
|
agent,
|
|
28949
29240
|
keeper,
|
|
@@ -29070,7 +29361,7 @@ ${options.prompt}`;
|
|
|
29070
29361
|
adapter.flushPendingOutput();
|
|
29071
29362
|
if (result.status === "error") {
|
|
29072
29363
|
exitCode = 2;
|
|
29073
|
-
const runErrorLine =
|
|
29364
|
+
const runErrorLine = formatAgentLogLine(logPrefix, "run-error", `run ${result.id} failed`);
|
|
29074
29365
|
process.stderr.write(`${runErrorLine}
|
|
29075
29366
|
`);
|
|
29076
29367
|
emitLogLine(runErrorLine);
|
|
@@ -29166,6 +29457,7 @@ ${options.prompt}`;
|
|
|
29166
29457
|
// src/infrastructure/services/remote-agents/cursor-sdk/index.ts
|
|
29167
29458
|
var init_cursor_sdk = __esm(() => {
|
|
29168
29459
|
init_cursor_sdk_agent_service();
|
|
29460
|
+
init_cursor_sdk_stream_adapter();
|
|
29169
29461
|
});
|
|
29170
29462
|
|
|
29171
29463
|
// ../../node_modules/.pnpm/@opencode-ai+sdk@1.15.11/node_modules/@opencode-ai/sdk/dist/gen/types.gen.js
|
|
@@ -31175,8 +31467,7 @@ function selectAgent(agents) {
|
|
|
31175
31467
|
|
|
31176
31468
|
// src/infrastructure/services/remote-agents/opencode-sdk/session-event-forwarder.ts
|
|
31177
31469
|
function formatLogLine(options, kind, payload) {
|
|
31178
|
-
|
|
31179
|
-
return `[${ts}] role:${options.role} ${kind}]${payload ? ` ${payload}` : ""}`;
|
|
31470
|
+
return formatTimestampedLogLine(options.role, kind, payload, options.now);
|
|
31180
31471
|
}
|
|
31181
31472
|
function writeLogLine(target, options, kind, payload) {
|
|
31182
31473
|
const line = formatLogLine(options, kind, payload);
|
|
@@ -31184,13 +31475,23 @@ function writeLogLine(target, options, kind, payload) {
|
|
|
31184
31475
|
`);
|
|
31185
31476
|
options.onLogLine?.(line);
|
|
31186
31477
|
}
|
|
31187
|
-
function
|
|
31188
|
-
if (!error || typeof error !== "object")
|
|
31478
|
+
function isTerminalProviderError(error) {
|
|
31479
|
+
if (!error || typeof error !== "object") {
|
|
31480
|
+
if (typeof error === "string") {
|
|
31481
|
+
return matchesTerminalProviderErrorText(error);
|
|
31482
|
+
}
|
|
31189
31483
|
return false;
|
|
31484
|
+
}
|
|
31190
31485
|
const e = error;
|
|
31191
31486
|
const name = String(e.name ?? e.type ?? "").toLowerCase();
|
|
31192
|
-
const message = String(e.data?.message ?? e.message ?? "").toLowerCase();
|
|
31193
|
-
|
|
31487
|
+
const message = String(e.data?.message ?? e.message ?? e.responseBody ?? "").toLowerCase();
|
|
31488
|
+
const blob = `${name}
|
|
31489
|
+
${message}`;
|
|
31490
|
+
return matchesTerminalProviderErrorText(blob);
|
|
31491
|
+
}
|
|
31492
|
+
function matchesTerminalProviderErrorText(blob) {
|
|
31493
|
+
const text = blob.toLowerCase();
|
|
31494
|
+
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
31495
|
}
|
|
31195
31496
|
function eventSessionId(event) {
|
|
31196
31497
|
const p = event.properties;
|
|
@@ -31256,25 +31557,14 @@ function startSessionEventForwarder(client4, options) {
|
|
|
31256
31557
|
writeLogLine(target, options, "thinking", chunk2);
|
|
31257
31558
|
}
|
|
31258
31559
|
} else if (part?.type === "tool" && part.tool) {
|
|
31259
|
-
let appendInput = function(base, input, tool) {
|
|
31260
|
-
if (!input || typeof input === "object" && Object.keys(input).length === 0) {
|
|
31261
|
-
return base;
|
|
31262
|
-
}
|
|
31263
|
-
const inp = input;
|
|
31264
|
-
if (tool === "bash" && typeof inp.command === "string") {
|
|
31265
|
-
return `${base}: ${inp.command}`;
|
|
31266
|
-
}
|
|
31267
|
-
const inputStr = typeof inp === "string" ? inp : JSON.stringify(inp);
|
|
31268
|
-
return `${base}: ${inputStr}`;
|
|
31269
|
-
};
|
|
31270
31560
|
const state = typeof props?.state === "string" ? props.state : typeof part.state?.status === "string" ? part.state.status : "started";
|
|
31271
31561
|
let payload = state;
|
|
31272
31562
|
if (part.state?.input) {
|
|
31273
|
-
payload =
|
|
31563
|
+
payload = appendToolInputToPayload(payload, part.state.input, part.tool);
|
|
31274
31564
|
}
|
|
31275
31565
|
if (state === "completed" && part.state?.time?.start !== undefined && part.state?.time?.end !== undefined) {
|
|
31276
31566
|
const duration3 = ((part.state.time.end - part.state.time.start) / 1000).toFixed(1);
|
|
31277
|
-
payload =
|
|
31567
|
+
payload = appendToolInputToPayload(`${state} (${duration3}s)`, part.state.input, part.tool);
|
|
31278
31568
|
}
|
|
31279
31569
|
const callID = part.callID ?? "unknown";
|
|
31280
31570
|
const seenKey = `${callID}:${state}`;
|
|
@@ -31325,8 +31615,8 @@ function startSessionEventForwarder(client4, options) {
|
|
|
31325
31615
|
payload += ` [command: ${props.command}]`;
|
|
31326
31616
|
}
|
|
31327
31617
|
writeLogLine(errorTarget, options, "error", payload);
|
|
31328
|
-
if (
|
|
31329
|
-
writeLogLine(target, options, "agent_end", "reason:
|
|
31618
|
+
if (isTerminalProviderError(err)) {
|
|
31619
|
+
writeLogLine(target, options, "agent_end", "reason: provider_rate_limit");
|
|
31330
31620
|
for (const cb of agentEndCallbacks)
|
|
31331
31621
|
cb();
|
|
31332
31622
|
}
|
|
@@ -31339,6 +31629,11 @@ function startSessionEventForwarder(client4, options) {
|
|
|
31339
31629
|
} catch (err) {
|
|
31340
31630
|
const message = err instanceof Error ? err.message : String(err);
|
|
31341
31631
|
writeLogLine(errorTarget, options, "error", message);
|
|
31632
|
+
if (isTerminalProviderError(err)) {
|
|
31633
|
+
writeLogLine(target, options, "agent_end", "reason: provider_rate_limit");
|
|
31634
|
+
for (const cb of agentEndCallbacks)
|
|
31635
|
+
cb();
|
|
31636
|
+
}
|
|
31342
31637
|
} finally {
|
|
31343
31638
|
doneResolve();
|
|
31344
31639
|
}
|
|
@@ -31354,6 +31649,7 @@ function startSessionEventForwarder(client4, options) {
|
|
|
31354
31649
|
}
|
|
31355
31650
|
};
|
|
31356
31651
|
}
|
|
31652
|
+
var init_session_event_forwarder = () => {};
|
|
31357
31653
|
|
|
31358
31654
|
// src/infrastructure/services/remote-agents/opencode-sdk/session-metadata-store.ts
|
|
31359
31655
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "node:fs";
|
|
@@ -31422,8 +31718,10 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31422
31718
|
init_dist();
|
|
31423
31719
|
init_base_cli_agent_service();
|
|
31424
31720
|
init_parse_listening_url();
|
|
31721
|
+
init_session_event_forwarder();
|
|
31425
31722
|
init_session_metadata_store();
|
|
31426
31723
|
OpenCodeSdkAgentService = class OpenCodeSdkAgentService extends BaseCLIAgentService {
|
|
31724
|
+
agentEndCallbacksByPid = new Map;
|
|
31427
31725
|
id = "opencode-sdk";
|
|
31428
31726
|
displayName = "OpenCode (SDK)";
|
|
31429
31727
|
command = OPENCODE_COMMAND2;
|
|
@@ -31462,8 +31760,8 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31462
31760
|
} catch (err) {
|
|
31463
31761
|
console.warn(`[opencode-sdk] session.abort for pid=${pid} sessionId=${meta.sessionId} failed (continuing with SIGTERM):`, err instanceof Error ? err.message : err);
|
|
31464
31762
|
}
|
|
31763
|
+
this.sessionStore.remove(meta.sessionId);
|
|
31465
31764
|
}
|
|
31466
|
-
this.sessionStore.remove(meta.sessionId);
|
|
31467
31765
|
}
|
|
31468
31766
|
await super.stop(pid);
|
|
31469
31767
|
}
|
|
@@ -31548,6 +31846,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31548
31846
|
this.forwarders.delete(pid);
|
|
31549
31847
|
}
|
|
31550
31848
|
this.sessionStore.remove(sessionId);
|
|
31849
|
+
this.agentEndCallbacksByPid.delete(pid);
|
|
31551
31850
|
this.deleteProcess(pid);
|
|
31552
31851
|
cb({ code: code2, signal, context: context5 });
|
|
31553
31852
|
});
|
|
@@ -31556,6 +31855,9 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31556
31855
|
outputCallbacks.push(cb);
|
|
31557
31856
|
},
|
|
31558
31857
|
onAgentEnd: (cb) => {
|
|
31858
|
+
const callbacks = this.agentEndCallbacksByPid.get(pid) ?? [];
|
|
31859
|
+
callbacks.push(cb);
|
|
31860
|
+
this.agentEndCallbacksByPid.set(pid, callbacks);
|
|
31559
31861
|
forwarder?.onAgentEnd(cb);
|
|
31560
31862
|
},
|
|
31561
31863
|
onLogLine: (cb) => {
|
|
@@ -31573,6 +31875,54 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31573
31875
|
}
|
|
31574
31876
|
};
|
|
31575
31877
|
}
|
|
31878
|
+
async startFreshSessionOnServe(args2) {
|
|
31879
|
+
const existingForwarder = this.forwarders.get(args2.pid);
|
|
31880
|
+
existingForwarder?.stop();
|
|
31881
|
+
this.forwarders.delete(args2.pid);
|
|
31882
|
+
const client4 = createOpencodeClient({ baseUrl: args2.baseUrl });
|
|
31883
|
+
const sessionCreateResult = await withTimeout2(client4.session.create({ body: {} }), SESSION_CREATE_TIMEOUT_MS, "session.create");
|
|
31884
|
+
if (!sessionCreateResult.data?.id) {
|
|
31885
|
+
throw new Error("Failed to create session during resume fallback");
|
|
31886
|
+
}
|
|
31887
|
+
const newSessionId2 = sessionCreateResult.data.id;
|
|
31888
|
+
const forwarder = startSessionEventForwarder(client4, {
|
|
31889
|
+
sessionId: newSessionId2,
|
|
31890
|
+
role: args2.context.role
|
|
31891
|
+
});
|
|
31892
|
+
const callbacks = this.agentEndCallbacksByPid.get(args2.pid) ?? [];
|
|
31893
|
+
for (const cb of callbacks) {
|
|
31894
|
+
forwarder.onAgentEnd(cb);
|
|
31895
|
+
}
|
|
31896
|
+
this.forwarders.set(args2.pid, forwarder);
|
|
31897
|
+
if (args2.oldSessionId) {
|
|
31898
|
+
this.sessionStore.remove(args2.oldSessionId);
|
|
31899
|
+
}
|
|
31900
|
+
this.sessionStore.upsert({
|
|
31901
|
+
sessionId: newSessionId2,
|
|
31902
|
+
machineId: args2.context.machineId,
|
|
31903
|
+
chatroomId: args2.context.chatroomId,
|
|
31904
|
+
role: args2.context.role,
|
|
31905
|
+
agentName: args2.agentName,
|
|
31906
|
+
...args2.model ? { model: args2.model } : {},
|
|
31907
|
+
pid: args2.pid,
|
|
31908
|
+
createdAt: new Date().toISOString(),
|
|
31909
|
+
baseUrl: args2.baseUrl
|
|
31910
|
+
});
|
|
31911
|
+
const modelParts = args2.model ? parseModelId(args2.model) : undefined;
|
|
31912
|
+
await withTimeout2(client4.session.promptAsync({
|
|
31913
|
+
path: { id: newSessionId2 },
|
|
31914
|
+
body: {
|
|
31915
|
+
agent: args2.agentName,
|
|
31916
|
+
parts: [{ type: "text", text: args2.prompt }],
|
|
31917
|
+
...modelParts ? { model: modelParts } : {},
|
|
31918
|
+
tools: {
|
|
31919
|
+
task: false,
|
|
31920
|
+
question: false,
|
|
31921
|
+
external_directory: false
|
|
31922
|
+
}
|
|
31923
|
+
}
|
|
31924
|
+
}), PROMPT_ASYNC_TIMEOUT_MS, "session.promptAsync");
|
|
31925
|
+
}
|
|
31576
31926
|
async resumeFromDaemonMemory(options, session2) {
|
|
31577
31927
|
const { prompt, systemPrompt, model, context: context5 } = options;
|
|
31578
31928
|
const sessionId = session2.harnessSessionId;
|
|
@@ -31624,11 +31974,11 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31624
31974
|
}), PROMPT_ASYNC_TIMEOUT_MS, "session.promptAsync");
|
|
31625
31975
|
} catch (err) {
|
|
31626
31976
|
const reason = err instanceof Error ? err.message : String(err);
|
|
31627
|
-
process.stderr.write(`[${new Date().toISOString()}] role:${context5.role} resume-
|
|
31977
|
+
process.stderr.write(`[${new Date().toISOString()}] role:${context5.role} daemon-resume-fallback] ${reason} — cold spawning
|
|
31628
31978
|
`);
|
|
31629
31979
|
forwarder?.stop();
|
|
31630
31980
|
childProcess.kill();
|
|
31631
|
-
|
|
31981
|
+
return this.spawn(options);
|
|
31632
31982
|
}
|
|
31633
31983
|
return this.registerRunningSession({
|
|
31634
31984
|
childProcess,
|
|
@@ -31733,23 +32083,45 @@ var init_opencode_sdk_agent_service = __esm(() => {
|
|
|
31733
32083
|
async resumeTurn(pid, prompt) {
|
|
31734
32084
|
const meta = this.sessionStore.findByPid(pid);
|
|
31735
32085
|
if (!meta) {
|
|
31736
|
-
|
|
32086
|
+
process.stderr.write(`[${new Date().toISOString()}] opencode-sdk resumeTurn: no metadata for pid=${pid}, skipping
|
|
32087
|
+
`);
|
|
32088
|
+
return;
|
|
31737
32089
|
}
|
|
31738
32090
|
const client4 = createOpencodeClient({ baseUrl: meta.baseUrl });
|
|
31739
32091
|
const modelParts = meta.model ? parseModelId(meta.model) : undefined;
|
|
31740
|
-
|
|
31741
|
-
|
|
31742
|
-
|
|
31743
|
-
|
|
31744
|
-
|
|
31745
|
-
|
|
31746
|
-
|
|
31747
|
-
|
|
31748
|
-
|
|
31749
|
-
|
|
32092
|
+
const context5 = {
|
|
32093
|
+
machineId: meta.machineId,
|
|
32094
|
+
chatroomId: meta.chatroomId,
|
|
32095
|
+
role: meta.role
|
|
32096
|
+
};
|
|
32097
|
+
try {
|
|
32098
|
+
await withTimeout2(client4.session.promptAsync({
|
|
32099
|
+
path: { id: meta.sessionId },
|
|
32100
|
+
body: {
|
|
32101
|
+
agent: meta.agentName,
|
|
32102
|
+
parts: [{ type: "text", text: prompt }],
|
|
32103
|
+
...modelParts ? { model: modelParts } : {},
|
|
32104
|
+
tools: {
|
|
32105
|
+
task: false,
|
|
32106
|
+
question: false,
|
|
32107
|
+
external_directory: false
|
|
32108
|
+
}
|
|
31750
32109
|
}
|
|
31751
|
-
}
|
|
31752
|
-
}
|
|
32110
|
+
}), PROMPT_ASYNC_TIMEOUT_MS, "session.promptAsync");
|
|
32111
|
+
} catch (err) {
|
|
32112
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
32113
|
+
process.stderr.write(`[${new Date().toISOString()}] role:${meta.role} resume-fallback] ${reason} — starting fresh session
|
|
32114
|
+
`);
|
|
32115
|
+
await this.startFreshSessionOnServe({
|
|
32116
|
+
pid,
|
|
32117
|
+
baseUrl: meta.baseUrl,
|
|
32118
|
+
context: context5,
|
|
32119
|
+
agentName: meta.agentName,
|
|
32120
|
+
model: meta.model,
|
|
32121
|
+
prompt,
|
|
32122
|
+
oldSessionId: meta.sessionId
|
|
32123
|
+
});
|
|
32124
|
+
}
|
|
31753
32125
|
}
|
|
31754
32126
|
};
|
|
31755
32127
|
});
|
|
@@ -41454,51 +41826,51 @@ var require_resize = __commonJS((exports, module) => {
|
|
|
41454
41826
|
}
|
|
41455
41827
|
return this;
|
|
41456
41828
|
}
|
|
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 =
|
|
41829
|
+
function extend3(extend4) {
|
|
41830
|
+
if (is.integer(extend4) && extend4 > 0) {
|
|
41831
|
+
this.options.extendTop = extend4;
|
|
41832
|
+
this.options.extendBottom = extend4;
|
|
41833
|
+
this.options.extendLeft = extend4;
|
|
41834
|
+
this.options.extendRight = extend4;
|
|
41835
|
+
} else if (is.object(extend4)) {
|
|
41836
|
+
if (is.defined(extend4.top)) {
|
|
41837
|
+
if (is.integer(extend4.top) && extend4.top >= 0) {
|
|
41838
|
+
this.options.extendTop = extend4.top;
|
|
41467
41839
|
} else {
|
|
41468
|
-
throw is.invalidParameterError("top", "positive integer",
|
|
41840
|
+
throw is.invalidParameterError("top", "positive integer", extend4.top);
|
|
41469
41841
|
}
|
|
41470
41842
|
}
|
|
41471
|
-
if (is.defined(
|
|
41472
|
-
if (is.integer(
|
|
41473
|
-
this.options.extendBottom =
|
|
41843
|
+
if (is.defined(extend4.bottom)) {
|
|
41844
|
+
if (is.integer(extend4.bottom) && extend4.bottom >= 0) {
|
|
41845
|
+
this.options.extendBottom = extend4.bottom;
|
|
41474
41846
|
} else {
|
|
41475
|
-
throw is.invalidParameterError("bottom", "positive integer",
|
|
41847
|
+
throw is.invalidParameterError("bottom", "positive integer", extend4.bottom);
|
|
41476
41848
|
}
|
|
41477
41849
|
}
|
|
41478
|
-
if (is.defined(
|
|
41479
|
-
if (is.integer(
|
|
41480
|
-
this.options.extendLeft =
|
|
41850
|
+
if (is.defined(extend4.left)) {
|
|
41851
|
+
if (is.integer(extend4.left) && extend4.left >= 0) {
|
|
41852
|
+
this.options.extendLeft = extend4.left;
|
|
41481
41853
|
} else {
|
|
41482
|
-
throw is.invalidParameterError("left", "positive integer",
|
|
41854
|
+
throw is.invalidParameterError("left", "positive integer", extend4.left);
|
|
41483
41855
|
}
|
|
41484
41856
|
}
|
|
41485
|
-
if (is.defined(
|
|
41486
|
-
if (is.integer(
|
|
41487
|
-
this.options.extendRight =
|
|
41857
|
+
if (is.defined(extend4.right)) {
|
|
41858
|
+
if (is.integer(extend4.right) && extend4.right >= 0) {
|
|
41859
|
+
this.options.extendRight = extend4.right;
|
|
41488
41860
|
} else {
|
|
41489
|
-
throw is.invalidParameterError("right", "positive integer",
|
|
41861
|
+
throw is.invalidParameterError("right", "positive integer", extend4.right);
|
|
41490
41862
|
}
|
|
41491
41863
|
}
|
|
41492
|
-
this._setBackgroundColourOption("extendBackground",
|
|
41493
|
-
if (is.defined(
|
|
41494
|
-
if (is.string(extendWith[
|
|
41495
|
-
this.options.extendWith = extendWith[
|
|
41864
|
+
this._setBackgroundColourOption("extendBackground", extend4.background);
|
|
41865
|
+
if (is.defined(extend4.extendWith)) {
|
|
41866
|
+
if (is.string(extendWith[extend4.extendWith])) {
|
|
41867
|
+
this.options.extendWith = extendWith[extend4.extendWith];
|
|
41496
41868
|
} else {
|
|
41497
|
-
throw is.invalidParameterError("extendWith", "one of: background, copy, repeat, mirror",
|
|
41869
|
+
throw is.invalidParameterError("extendWith", "one of: background, copy, repeat, mirror", extend4.extendWith);
|
|
41498
41870
|
}
|
|
41499
41871
|
}
|
|
41500
41872
|
} else {
|
|
41501
|
-
throw is.invalidParameterError("extend", "integer or object",
|
|
41873
|
+
throw is.invalidParameterError("extend", "integer or object", extend4);
|
|
41502
41874
|
}
|
|
41503
41875
|
return this;
|
|
41504
41876
|
}
|
|
@@ -41554,7 +41926,7 @@ var require_resize = __commonJS((exports, module) => {
|
|
|
41554
41926
|
module.exports = (Sharp) => {
|
|
41555
41927
|
Object.assign(Sharp.prototype, {
|
|
41556
41928
|
resize,
|
|
41557
|
-
extend:
|
|
41929
|
+
extend: extend3,
|
|
41558
41930
|
extract,
|
|
41559
41931
|
trim
|
|
41560
41932
|
});
|
|
@@ -53499,7 +53871,7 @@ var toString, getPrototypeOf, iterator, toStringTag, kindOf, kindOfTest = (type)
|
|
|
53499
53871
|
return kind === "formdata" || kind === "object" && isFunction3(thing.toString) && thing.toString() === "[object FormData]";
|
|
53500
53872
|
}, isURLSearchParams, isReadableStream, isRequest3, isResponse, isHeaders, trim = (str) => {
|
|
53501
53873
|
return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
|
|
53502
|
-
}, _global, isContextDefined = (context5) => !isUndefined(context5) && context5 !== _global,
|
|
53874
|
+
}, _global, isContextDefined = (context5) => !isUndefined(context5) && context5 !== _global, extend3 = (a, b, thisArg, { allOwnKeys } = {}) => {
|
|
53503
53875
|
forEach6(b, (val, key) => {
|
|
53504
53876
|
if (thisArg && isFunction3(val)) {
|
|
53505
53877
|
Object.defineProperty(a, key, {
|
|
@@ -53753,7 +54125,7 @@ var init_utils = __esm(() => {
|
|
|
53753
54125
|
isFileList,
|
|
53754
54126
|
forEach: forEach6,
|
|
53755
54127
|
merge: merge9,
|
|
53756
|
-
extend:
|
|
54128
|
+
extend: extend3,
|
|
53757
54129
|
trim,
|
|
53758
54130
|
stripBOM,
|
|
53759
54131
|
inherits,
|
|
@@ -65184,7 +65556,7 @@ var require_common = __commonJS((exports, module) => {
|
|
|
65184
65556
|
debug.namespace = namespace;
|
|
65185
65557
|
debug.useColors = createDebug.useColors();
|
|
65186
65558
|
debug.color = createDebug.selectColor(namespace);
|
|
65187
|
-
debug.extend =
|
|
65559
|
+
debug.extend = extend4;
|
|
65188
65560
|
debug.destroy = createDebug.destroy;
|
|
65189
65561
|
Object.defineProperty(debug, "enabled", {
|
|
65190
65562
|
enumerable: true,
|
|
@@ -65208,7 +65580,7 @@ var require_common = __commonJS((exports, module) => {
|
|
|
65208
65580
|
}
|
|
65209
65581
|
return debug;
|
|
65210
65582
|
}
|
|
65211
|
-
function
|
|
65583
|
+
function extend4(namespace, delimiter) {
|
|
65212
65584
|
const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
|
|
65213
65585
|
newDebug.log = this.log;
|
|
65214
65586
|
return newDebug;
|
|
@@ -82834,15 +83206,10 @@ var init_on_daemon_shutdown = __esm(() => {
|
|
|
82834
83206
|
const activeAgents = agentPm.listActive();
|
|
82835
83207
|
if (activeAgents.length > 0) {
|
|
82836
83208
|
console.log(`[${formatTimestamp()}] Stopping ${activeAgents.length} agent(s)...`);
|
|
82837
|
-
yield* exports_Effect.
|
|
83209
|
+
yield* exports_Effect.all(activeAgents.map(({ chatroomId, role, slot }) => {
|
|
82838
83210
|
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
|
-
})));
|
|
83211
|
+
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}`))));
|
|
83212
|
+
}), { concurrency: "unbounded" });
|
|
82846
83213
|
console.log(`[${formatTimestamp()}] All agents stopped`);
|
|
82847
83214
|
}
|
|
82848
83215
|
yield* exports_Effect.promise(() => session2.backend.mutation(api.machines.updateDaemonStatus, {
|
|
@@ -84924,36 +85291,45 @@ async function pushSingleWorkspaceGitStateImpl(ctx, workingDir) {
|
|
|
84924
85291
|
const stateKey = makeGitStateKey(ctx.machineId, workingDir);
|
|
84925
85292
|
const isRepo = await isGitRepo(workingDir);
|
|
84926
85293
|
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);
|
|
85294
|
+
await pushNotFoundGitState(ctx, workingDir, stateKey);
|
|
84937
85295
|
return;
|
|
84938
85296
|
}
|
|
84939
85297
|
const branchResult = await getBranch(workingDir);
|
|
84940
85298
|
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);
|
|
85299
|
+
await pushErrorGitState(ctx, workingDir, stateKey, branchResult.message);
|
|
84952
85300
|
return;
|
|
84953
85301
|
}
|
|
84954
85302
|
if (branchResult.status === "not_found") {
|
|
84955
85303
|
return;
|
|
84956
85304
|
}
|
|
85305
|
+
await pushAvailableGitState(ctx, workingDir, stateKey, branchResult);
|
|
85306
|
+
}
|
|
85307
|
+
async function pushNotFoundGitState(ctx, workingDir, stateKey) {
|
|
85308
|
+
const stateHash = "not_found";
|
|
85309
|
+
if (ctx.lastPushedGitState.get(stateKey) === stateHash)
|
|
85310
|
+
return;
|
|
85311
|
+
await ctx.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85312
|
+
sessionId: ctx.sessionId,
|
|
85313
|
+
machineId: ctx.machineId,
|
|
85314
|
+
workingDir,
|
|
85315
|
+
status: "not_found"
|
|
85316
|
+
});
|
|
85317
|
+
ctx.lastPushedGitState.set(stateKey, stateHash);
|
|
85318
|
+
}
|
|
85319
|
+
async function pushErrorGitState(ctx, workingDir, stateKey, message) {
|
|
85320
|
+
const stateHash = `error:${message}`;
|
|
85321
|
+
if (ctx.lastPushedGitState.get(stateKey) === stateHash)
|
|
85322
|
+
return;
|
|
85323
|
+
await ctx.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85324
|
+
sessionId: ctx.sessionId,
|
|
85325
|
+
machineId: ctx.machineId,
|
|
85326
|
+
workingDir,
|
|
85327
|
+
status: "error",
|
|
85328
|
+
errorMessage: message
|
|
85329
|
+
});
|
|
85330
|
+
ctx.lastPushedGitState.set(stateKey, stateHash);
|
|
85331
|
+
}
|
|
85332
|
+
async function pushAvailableGitState(ctx, workingDir, stateKey, branchResult) {
|
|
84957
85333
|
const branch = branchResult.branch;
|
|
84958
85334
|
const allFields = [branchField, ...GIT_STATE_FIELDS, ...makeBranchDependentFields(branch)];
|
|
84959
85335
|
const pipeline2 = new GitStatePipeline(allFields);
|
|
@@ -84990,16 +85366,12 @@ async function pushSingleWorkspaceGitStateImpl(ctx, workingDir) {
|
|
|
84990
85366
|
}
|
|
84991
85367
|
}
|
|
84992
85368
|
}
|
|
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) {
|
|
85369
|
+
function pushObservedNotRepoEffect(session2, lastPushedGitState, stateKey, workingDir, reason) {
|
|
85370
|
+
return exports_Effect.gen(function* () {
|
|
85000
85371
|
const stateHash = "not_found";
|
|
85001
|
-
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === stateHash)
|
|
85372
|
+
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === stateHash) {
|
|
85002
85373
|
return;
|
|
85374
|
+
}
|
|
85003
85375
|
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85004
85376
|
sessionId: session2.sessionId,
|
|
85005
85377
|
machineId: session2.machineId,
|
|
@@ -85007,21 +85379,69 @@ var lastFullPushMs, branchField, GIT_STATE_FIELDS, pushSingleWorkspaceGitSummary
|
|
|
85007
85379
|
status: "not_found"
|
|
85008
85380
|
}));
|
|
85009
85381
|
lastPushedGitState.set(stateKey, stateHash);
|
|
85010
|
-
|
|
85011
|
-
|
|
85012
|
-
|
|
85013
|
-
|
|
85014
|
-
const stateHash = `error:${
|
|
85015
|
-
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === stateHash)
|
|
85382
|
+
});
|
|
85383
|
+
}
|
|
85384
|
+
function pushObservedBranchErrorEffect(session2, lastPushedGitState, stateKey, workingDir, reason, message) {
|
|
85385
|
+
return exports_Effect.gen(function* () {
|
|
85386
|
+
const stateHash = `error:${message}`;
|
|
85387
|
+
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === stateHash) {
|
|
85016
85388
|
return;
|
|
85389
|
+
}
|
|
85017
85390
|
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85018
85391
|
sessionId: session2.sessionId,
|
|
85019
85392
|
machineId: session2.machineId,
|
|
85020
85393
|
workingDir,
|
|
85021
85394
|
status: "error",
|
|
85022
|
-
errorMessage:
|
|
85395
|
+
errorMessage: message
|
|
85023
85396
|
}));
|
|
85024
85397
|
lastPushedGitState.set(stateKey, stateHash);
|
|
85398
|
+
});
|
|
85399
|
+
}
|
|
85400
|
+
function pushObservedFullGitStateEffect(session2, lastPushedGitState, stateKey, workingDir, branch, reason) {
|
|
85401
|
+
return exports_Effect.gen(function* () {
|
|
85402
|
+
yield* exports_Effect.promise(() => pushSingleWorkspaceGitStateImpl(buildGitStateDeps(session2, lastPushedGitState), workingDir));
|
|
85403
|
+
lastFullPushMs.set(stateKey, Date.now());
|
|
85404
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed full git state pushed: ${workingDir} (${branch})${reason === "refresh" ? " [refresh]" : ""}`);
|
|
85405
|
+
});
|
|
85406
|
+
}
|
|
85407
|
+
function pushObservedSlimGitSummaryEffect(session2, lastPushedGitState, stateKey, workingDir, branch, branchResult, reason) {
|
|
85408
|
+
return exports_Effect.gen(function* () {
|
|
85409
|
+
const slimFields = [
|
|
85410
|
+
branchField,
|
|
85411
|
+
...GIT_STATE_FIELDS.filter((f) => f.includeInSlim),
|
|
85412
|
+
...makeBranchDependentFields(branch)
|
|
85413
|
+
];
|
|
85414
|
+
const pipeline2 = new GitStatePipeline(slimFields);
|
|
85415
|
+
const preCollected = new Map([["branch", branchResult]]);
|
|
85416
|
+
const values3 = yield* exports_Effect.promise(() => pipeline2.collect(workingDir, preCollected));
|
|
85417
|
+
const hash2 = pipeline2.computeHash(values3, true);
|
|
85418
|
+
if (reason !== "refresh" && lastPushedGitState.get(stateKey) === hash2) {
|
|
85419
|
+
return;
|
|
85420
|
+
}
|
|
85421
|
+
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
85422
|
+
sessionId: session2.sessionId,
|
|
85423
|
+
machineId: session2.machineId,
|
|
85424
|
+
workingDir,
|
|
85425
|
+
status: "available",
|
|
85426
|
+
...pipeline2.toMutationArgs(values3, true)
|
|
85427
|
+
}));
|
|
85428
|
+
lastPushedGitState.set(stateKey, hash2);
|
|
85429
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed git summary pushed: ${workingDir} (${branch}${values3.get("isDirty") ? ", dirty" : ", clean"})${reason === "refresh" ? " [refresh]" : ""}`);
|
|
85430
|
+
});
|
|
85431
|
+
}
|
|
85432
|
+
var lastFullPushMs, branchField, GIT_STATE_FIELDS, pushSingleWorkspaceGitSummaryForObservedEffect = (workingDir, reason = "safety-poll") => exports_Effect.gen(function* pushObservedGitSummaryForObserved() {
|
|
85433
|
+
const session2 = yield* DaemonSessionService;
|
|
85434
|
+
const mutable = yield* DaemonMutableStateService;
|
|
85435
|
+
const lastPushedGitState = yield* exports_Ref.get(mutable.lastPushedGitState);
|
|
85436
|
+
const stateKey = makeGitStateKey(session2.machineId, workingDir);
|
|
85437
|
+
const isRepo = yield* exports_Effect.promise(() => isGitRepo(workingDir));
|
|
85438
|
+
if (!isRepo) {
|
|
85439
|
+
yield* pushObservedNotRepoEffect(session2, lastPushedGitState, stateKey, workingDir, reason);
|
|
85440
|
+
return;
|
|
85441
|
+
}
|
|
85442
|
+
const branchResult = yield* exports_Effect.promise(() => getBranch(workingDir));
|
|
85443
|
+
if (branchResult.status === "error") {
|
|
85444
|
+
yield* pushObservedBranchErrorEffect(session2, lastPushedGitState, stateKey, workingDir, reason, branchResult.message);
|
|
85025
85445
|
return;
|
|
85026
85446
|
}
|
|
85027
85447
|
if (branchResult.status === "not_found") {
|
|
@@ -85031,32 +85451,10 @@ var lastFullPushMs, branchField, GIT_STATE_FIELDS, pushSingleWorkspaceGitSummary
|
|
|
85031
85451
|
const now = Date.now();
|
|
85032
85452
|
const lastFull = lastFullPushMs.get(stateKey) ?? 0;
|
|
85033
85453
|
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]" : ""}`);
|
|
85454
|
+
yield* pushObservedFullGitStateEffect(session2, lastPushedGitState, stateKey, workingDir, branch, reason);
|
|
85037
85455
|
return;
|
|
85038
85456
|
}
|
|
85039
|
-
|
|
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) {
|
|
85049
|
-
return;
|
|
85050
|
-
}
|
|
85051
|
-
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.upsertWorkspaceGitState, {
|
|
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]" : ""}`);
|
|
85457
|
+
yield* pushObservedSlimGitSummaryEffect(session2, lastPushedGitState, stateKey, workingDir, branch, branchResult, reason);
|
|
85060
85458
|
}), pushGitStateEffect, pushSingleWorkspaceGitStateEffect = (workingDir) => exports_Effect.gen(function* () {
|
|
85061
85459
|
const session2 = yield* DaemonSessionService;
|
|
85062
85460
|
const mutable = yield* DaemonMutableStateService;
|
|
@@ -85272,14 +85670,12 @@ async function processPRAction(deps, req) {
|
|
|
85272
85670
|
timeout: EXEC_TIMEOUT_MS
|
|
85273
85671
|
});
|
|
85274
85672
|
console.log(`[${formatTimestamp()}] ✅ PR action: ${action} on #${prNumber}${result.stdout ? ` — ${result.stdout.trim()}` : ""}`);
|
|
85275
|
-
|
|
85673
|
+
exports_Runtime.runFork(deps.runtime)(pushGitStateEffect.pipe(exports_Effect.provide(exports_Layer.mergeAll(exports_Layer.succeed(DaemonSessionService, deps), DaemonMutableStateServiceLive({
|
|
85276
85674
|
lastPushedGitState: deps.lastPushedGitState,
|
|
85277
85675
|
lastPushedModels: null,
|
|
85278
85676
|
lastPushedHarnessFingerprint: null,
|
|
85279
85677
|
workspaceListStore: deps.workspaceListStore
|
|
85280
|
-
})))
|
|
85281
|
-
console.warn(`[${formatTimestamp()}] ⚠️ Failed to refresh git state after PR action: ${getErrorMessage(err)}`);
|
|
85282
|
-
});
|
|
85678
|
+
}))), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[${formatTimestamp()}] ⚠️ Failed to refresh git state after PR action: ${getErrorMessage(err)}`)))));
|
|
85283
85679
|
}
|
|
85284
85680
|
async function processPRCommits(deps, req) {
|
|
85285
85681
|
const prNumber = req.prNumber;
|
|
@@ -85304,32 +85700,35 @@ async function processCommitDetail(deps, req) {
|
|
|
85304
85700
|
getCommitDetail(req.workingDir, req.sha),
|
|
85305
85701
|
getCommitMetadata(req.workingDir, req.sha)
|
|
85306
85702
|
]);
|
|
85703
|
+
await upsertCommitDetailResult(deps, req, result, metadata);
|
|
85704
|
+
if (result.status === "available" || result.status === "truncated") {
|
|
85705
|
+
const compressed = gzipSync2(Buffer.from(result.content));
|
|
85706
|
+
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)`);
|
|
85707
|
+
}
|
|
85708
|
+
}
|
|
85709
|
+
async function upsertCommitDetailResult(deps, req, result, metadata) {
|
|
85710
|
+
const baseArgs = {
|
|
85711
|
+
sessionId: deps.sessionId,
|
|
85712
|
+
machineId: deps.machineId,
|
|
85713
|
+
workingDir: req.workingDir,
|
|
85714
|
+
sha: req.sha,
|
|
85715
|
+
message: metadata?.message,
|
|
85716
|
+
body: metadata?.body,
|
|
85717
|
+
author: metadata?.author,
|
|
85718
|
+
date: metadata?.date
|
|
85719
|
+
};
|
|
85307
85720
|
if (result.status === "not_found") {
|
|
85308
85721
|
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
|
|
85722
|
+
...baseArgs,
|
|
85723
|
+
status: "not_found"
|
|
85318
85724
|
});
|
|
85319
85725
|
return;
|
|
85320
85726
|
}
|
|
85321
85727
|
if (result.status === "error") {
|
|
85322
85728
|
await deps.backend.mutation(api.workspaces.upsertCommitDetailV2, {
|
|
85323
|
-
|
|
85324
|
-
machineId: deps.machineId,
|
|
85325
|
-
workingDir: req.workingDir,
|
|
85326
|
-
sha: req.sha,
|
|
85729
|
+
...baseArgs,
|
|
85327
85730
|
status: "error",
|
|
85328
|
-
errorMessage: result.message
|
|
85329
|
-
message: metadata?.message,
|
|
85330
|
-
body: metadata?.body,
|
|
85331
|
-
author: metadata?.author,
|
|
85332
|
-
date: metadata?.date
|
|
85731
|
+
errorMessage: result.message
|
|
85333
85732
|
});
|
|
85334
85733
|
return;
|
|
85335
85734
|
}
|
|
@@ -85337,20 +85736,12 @@ async function processCommitDetail(deps, req) {
|
|
|
85337
85736
|
const compressed = gzipSync2(Buffer.from(result.content));
|
|
85338
85737
|
const diffContentCompressed = compressed.toString("base64");
|
|
85339
85738
|
await deps.backend.mutation(api.workspaces.upsertCommitDetailV2, {
|
|
85340
|
-
|
|
85341
|
-
machineId: deps.machineId,
|
|
85342
|
-
workingDir: req.workingDir,
|
|
85343
|
-
sha: req.sha,
|
|
85739
|
+
...baseArgs,
|
|
85344
85740
|
status: "available",
|
|
85345
85741
|
data: { compression: "gzip", content: diffContentCompressed },
|
|
85346
85742
|
truncated: result.truncated,
|
|
85347
|
-
message: metadata?.message,
|
|
85348
|
-
body: metadata?.body,
|
|
85349
|
-
author: metadata?.author,
|
|
85350
|
-
date: metadata?.date,
|
|
85351
85743
|
diffStat
|
|
85352
85744
|
});
|
|
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
85745
|
}
|
|
85355
85746
|
async function processMoreCommits(deps, req) {
|
|
85356
85747
|
const offset = req.offset ?? 0;
|
|
@@ -85387,11 +85778,33 @@ async function processRecentCommits(deps, req) {
|
|
|
85387
85778
|
});
|
|
85388
85779
|
console.log(`[${formatTimestamp()}] \uD83D\uDCDC Recent commits pushed: ${req.workingDir} (${commits.length} commits)`);
|
|
85389
85780
|
}
|
|
85781
|
+
function dispatchGitRequest(deps, req) {
|
|
85782
|
+
switch (req.requestType) {
|
|
85783
|
+
case "full_diff":
|
|
85784
|
+
return exports_Effect.promise(() => processFullDiff(deps, req));
|
|
85785
|
+
case "commit_detail":
|
|
85786
|
+
return exports_Effect.promise(() => processCommitDetail(deps, req));
|
|
85787
|
+
case "more_commits":
|
|
85788
|
+
return exports_Effect.promise(() => processMoreCommits(deps, req));
|
|
85789
|
+
case "pr_diff":
|
|
85790
|
+
return exports_Effect.promise(() => processPRDiff(deps, req));
|
|
85791
|
+
case "pr_action":
|
|
85792
|
+
return exports_Effect.promise(() => processPRAction(deps, req));
|
|
85793
|
+
case "pr_commits":
|
|
85794
|
+
return exports_Effect.promise(() => processPRCommits(deps, req));
|
|
85795
|
+
case "all_pull_requests":
|
|
85796
|
+
return exports_Effect.promise(() => processAllPullRequests(deps, req));
|
|
85797
|
+
case "recent_commits":
|
|
85798
|
+
return exports_Effect.promise(() => processRecentCommits(deps, req));
|
|
85799
|
+
}
|
|
85800
|
+
}
|
|
85390
85801
|
var EXEC_TIMEOUT_MS = 60000, startGitRequestSubscriptionEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
85391
85802
|
const session2 = yield* DaemonSessionService;
|
|
85803
|
+
const runtime4 = yield* exports_Effect.runtime();
|
|
85392
85804
|
const processedRequestIds = new Map;
|
|
85393
85805
|
const DEDUP_TTL_MS = 5 * 60 * 1000;
|
|
85394
|
-
|
|
85806
|
+
const sessionWithRuntime = { ...session2, runtime: runtime4 };
|
|
85807
|
+
const processingState = { isProcessing: false };
|
|
85395
85808
|
session2.backend.mutation(api.workspaces.resetProcessingRequests, {
|
|
85396
85809
|
sessionId: session2.sessionId,
|
|
85397
85810
|
machineId: session2.machineId
|
|
@@ -85408,16 +85821,14 @@ var EXEC_TIMEOUT_MS = 60000, startGitRequestSubscriptionEffect = (wsClient2) =>
|
|
|
85408
85821
|
}, (requests) => {
|
|
85409
85822
|
if (!requests || requests.length === 0)
|
|
85410
85823
|
return;
|
|
85411
|
-
const logger =
|
|
85824
|
+
const logger = sessionWithRuntime.logger ?? console;
|
|
85412
85825
|
logger.log(`[${formatTimestamp()}] \uD83D\uDCEC Git subscription: received ${requests.length} pending request(s)`);
|
|
85413
|
-
if (
|
|
85826
|
+
if (processingState.isProcessing)
|
|
85414
85827
|
return;
|
|
85415
|
-
|
|
85416
|
-
|
|
85417
|
-
|
|
85418
|
-
})
|
|
85419
|
-
processing = false;
|
|
85420
|
-
});
|
|
85828
|
+
processingState.isProcessing = true;
|
|
85829
|
+
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(() => {
|
|
85830
|
+
processingState.isProcessing = false;
|
|
85831
|
+
}))));
|
|
85421
85832
|
}, (err) => {
|
|
85422
85833
|
console.warn(`[${formatTimestamp()}] ⚠️ Git request subscription error: ${getErrorMessage(err)}`);
|
|
85423
85834
|
});
|
|
@@ -85428,7 +85839,7 @@ var EXEC_TIMEOUT_MS = 60000, startGitRequestSubscriptionEffect = (wsClient2) =>
|
|
|
85428
85839
|
console.log(`[${formatTimestamp()}] \uD83D\uDD00 Git request subscription stopped`);
|
|
85429
85840
|
}
|
|
85430
85841
|
};
|
|
85431
|
-
}), processRequestsEffect = (requests, processedRequestIds, dedupTtlMs) => exports_Effect.gen(function* () {
|
|
85842
|
+
}), processRequestsEffect = (requests, processedRequestIds, dedupTtlMs, runtime4) => exports_Effect.gen(function* () {
|
|
85432
85843
|
const session2 = yield* DaemonSessionService;
|
|
85433
85844
|
const evictBefore = Date.now() - dedupTtlMs;
|
|
85434
85845
|
for (const [id3, ts] of processedRequestIds) {
|
|
@@ -85448,32 +85859,8 @@ var EXEC_TIMEOUT_MS = 60000, startGitRequestSubscriptionEffect = (wsClient2) =>
|
|
|
85448
85859
|
}));
|
|
85449
85860
|
const logger = session2.logger ?? console;
|
|
85450
85861
|
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
|
-
}
|
|
85862
|
+
const sessionWithRuntime = { ...session2, runtime: runtime4 };
|
|
85863
|
+
yield* dispatchGitRequest(sessionWithRuntime, req);
|
|
85477
85864
|
yield* exports_Effect.promise(() => session2.backend.mutation(api.workspaces.updateRequestStatus, {
|
|
85478
85865
|
sessionId: session2.sessionId,
|
|
85479
85866
|
requestId: req._id,
|
|
@@ -85653,6 +86040,26 @@ function startCommandSubscriber(session2, wsClient2, deps) {
|
|
|
85653
86040
|
});
|
|
85654
86041
|
return { stop: unsub };
|
|
85655
86042
|
}
|
|
86043
|
+
async function dispatchPendingCommand(session2, deps, cmd) {
|
|
86044
|
+
switch (cmd.type) {
|
|
86045
|
+
case "refreshCapabilities":
|
|
86046
|
+
await handleRefreshCapabilities(session2, deps, cmd);
|
|
86047
|
+
break;
|
|
86048
|
+
case "refreshSessionTitle":
|
|
86049
|
+
await handleRefreshSessionTitle(session2, deps, cmd);
|
|
86050
|
+
break;
|
|
86051
|
+
default:
|
|
86052
|
+
await markFailed(session2, cmd._id, `Unknown command type: ${cmd.type}`);
|
|
86053
|
+
}
|
|
86054
|
+
}
|
|
86055
|
+
async function processPendingCommand(session2, deps, cmd, now) {
|
|
86056
|
+
if (now - cmd.createdAt > DIRECT_HARNESS_COMMAND_TTL_MS) {
|
|
86057
|
+
console.log(`[direct-harness] Discarding stale command ${cmd._id} (type=${cmd.type}, age=${now - cmd.createdAt}ms)`);
|
|
86058
|
+
await markFailed(session2, cmd._id, "Command expired (TTL)");
|
|
86059
|
+
return;
|
|
86060
|
+
}
|
|
86061
|
+
await dispatchPendingCommand(session2, deps, cmd);
|
|
86062
|
+
}
|
|
85656
86063
|
async function drain(session2, deps, processed) {
|
|
85657
86064
|
const pending3 = await session2.backend.query(api.daemon.directHarness.commands.listPendingCommands, { sessionId: session2.sessionId, machineId: session2.machineId });
|
|
85658
86065
|
if (!pending3 || pending3.length === 0)
|
|
@@ -85663,21 +86070,7 @@ async function drain(session2, deps, processed) {
|
|
|
85663
86070
|
continue;
|
|
85664
86071
|
processed.add(cmd._id);
|
|
85665
86072
|
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
|
-
}
|
|
86073
|
+
await processPendingCommand(session2, deps, cmd, now);
|
|
85681
86074
|
} catch (err) {
|
|
85682
86075
|
const message = err instanceof Error ? err.message : String(err);
|
|
85683
86076
|
console.warn(`[direct-harness] Command ${cmd._id} failed: ${message}`);
|
|
@@ -86500,74 +86893,73 @@ async function drain2(session2, deps) {
|
|
|
86500
86893
|
}
|
|
86501
86894
|
}
|
|
86502
86895
|
}
|
|
86503
|
-
async function
|
|
86504
|
-
|
|
86505
|
-
if (!
|
|
86506
|
-
|
|
86507
|
-
|
|
86508
|
-
|
|
86509
|
-
|
|
86510
|
-
|
|
86511
|
-
|
|
86512
|
-
|
|
86513
|
-
|
|
86514
|
-
|
|
86515
|
-
|
|
86516
|
-
|
|
86517
|
-
|
|
86518
|
-
|
|
86519
|
-
|
|
86520
|
-
|
|
86896
|
+
async function resumeSessionHandle(session2, deps, rowId, info) {
|
|
86897
|
+
const opencodeSessionId = info.opencodeSessionId;
|
|
86898
|
+
if (!opencodeSessionId) {
|
|
86899
|
+
console.warn(`[direct-harness] Session ${rowId} not yet open — waiting for session-subscriber`);
|
|
86900
|
+
return null;
|
|
86901
|
+
}
|
|
86902
|
+
const workspaceId = info.workspaceId;
|
|
86903
|
+
if (!workspaceId) {
|
|
86904
|
+
console.warn(`[direct-harness] Cannot resume session ${rowId}: no workspace info`);
|
|
86905
|
+
return null;
|
|
86906
|
+
}
|
|
86907
|
+
let harness = deps.harnesses.get(workspaceId);
|
|
86908
|
+
if (harness && !harness.isAlive()) {
|
|
86909
|
+
harness.close().catch(() => {});
|
|
86910
|
+
deps.harnesses.delete(workspaceId);
|
|
86911
|
+
harness = undefined;
|
|
86912
|
+
}
|
|
86913
|
+
if (!harness) {
|
|
86914
|
+
const workspace = await session2.backend.query(api.workspaces.getWorkspaceById, {
|
|
86915
|
+
sessionId: session2.sessionId,
|
|
86916
|
+
workspaceId
|
|
86917
|
+
});
|
|
86918
|
+
if (!workspace) {
|
|
86919
|
+
console.warn(`[direct-harness] Cannot resume session ${rowId}: workspace not found`);
|
|
86920
|
+
return null;
|
|
86521
86921
|
}
|
|
86522
|
-
|
|
86523
|
-
|
|
86524
|
-
|
|
86525
|
-
|
|
86526
|
-
|
|
86527
|
-
|
|
86528
|
-
|
|
86529
|
-
|
|
86922
|
+
harness = await startOpencodeSdkHarness({
|
|
86923
|
+
type: "opencode",
|
|
86924
|
+
workingDir: workspace.workingDir,
|
|
86925
|
+
workspaceId
|
|
86926
|
+
});
|
|
86927
|
+
deps.harnesses.set(workspaceId, harness);
|
|
86928
|
+
}
|
|
86929
|
+
try {
|
|
86930
|
+
return await resumeSession({
|
|
86931
|
+
harness,
|
|
86932
|
+
journalFactory: deps.journalFactory,
|
|
86933
|
+
chunkExtractor: createOpencodeSdkChunkExtractor()
|
|
86934
|
+
}, { harnessSessionId: rowId, opencodeSessionId, workspaceId });
|
|
86935
|
+
} catch (err) {
|
|
86936
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
86937
|
+
console.warn(`[direct-harness] Cannot resume session ${rowId}: ${message}`);
|
|
86938
|
+
await deps.sessionRepository.markFailed(rowId).catch(() => {});
|
|
86939
|
+
return null;
|
|
86940
|
+
}
|
|
86941
|
+
}
|
|
86942
|
+
function wireResumedSessionEvents(handle, deps, info) {
|
|
86943
|
+
const idleConfig = {
|
|
86944
|
+
agent: info.lastUsedConfig.agent ?? "build",
|
|
86945
|
+
model: info.lastUsedConfig.model
|
|
86946
|
+
};
|
|
86947
|
+
let lastBoundKey = null;
|
|
86948
|
+
handle.session.onEvent((event) => {
|
|
86949
|
+
const turn = handle.currentTurn;
|
|
86950
|
+
if (turn?.messageId !== null && turn?.messageId !== undefined) {
|
|
86951
|
+
const key = `${turn.turnId}:${turn.messageId}`;
|
|
86952
|
+
if (key !== lastBoundKey) {
|
|
86953
|
+
lastBoundKey = key;
|
|
86954
|
+
deps.sessionRepository.bindTurnMessageId(turn.turnId, turn.messageId).catch((err) => console.warn("[direct-harness] bindTurnMessageId error (resume):", err));
|
|
86530
86955
|
}
|
|
86531
|
-
harness = await startOpencodeSdkHarness({
|
|
86532
|
-
type: "opencode",
|
|
86533
|
-
workingDir: workspace.workingDir,
|
|
86534
|
-
workspaceId
|
|
86535
|
-
});
|
|
86536
|
-
deps.harnesses.set(workspaceId, harness);
|
|
86537
86956
|
}
|
|
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;
|
|
86957
|
+
if (event.type === "session.idle") {
|
|
86958
|
+
handleSessionIdle(handle, handle.journal, idleConfig, deps.sessionRepository).catch((err) => console.warn("[direct-harness] idle handler error (resume):", err));
|
|
86549
86959
|
}
|
|
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
|
-
}
|
|
86960
|
+
});
|
|
86961
|
+
}
|
|
86962
|
+
async function deliverPendingMessages(handle, deps, rowId, messages, info) {
|
|
86571
86963
|
for (const msg of messages) {
|
|
86572
86964
|
const override = info?.lastUsedConfig ?? { agent: "build" };
|
|
86573
86965
|
try {
|
|
@@ -86591,6 +86983,24 @@ async function processSessionMessages(session2, deps, rowId, messages, info) {
|
|
|
86591
86983
|
}
|
|
86592
86984
|
}
|
|
86593
86985
|
}
|
|
86986
|
+
async function processSessionMessages(session2, deps, rowId, messages, info) {
|
|
86987
|
+
let handle = deps.activeSessions.get(rowId);
|
|
86988
|
+
if (!handle) {
|
|
86989
|
+
if (!info) {
|
|
86990
|
+
console.warn(`[direct-harness] Session ${rowId} not yet open — waiting for session-subscriber`);
|
|
86991
|
+
return;
|
|
86992
|
+
}
|
|
86993
|
+
const resumed = await resumeSessionHandle(session2, deps, rowId, info);
|
|
86994
|
+
if (!resumed) {
|
|
86995
|
+
return;
|
|
86996
|
+
}
|
|
86997
|
+
handle = resumed;
|
|
86998
|
+
deps.activeSessions.set(rowId, handle);
|
|
86999
|
+
await deps.sessionRepository.markActive(rowId).catch(() => {});
|
|
87000
|
+
wireResumedSessionEvents(handle, deps, info);
|
|
87001
|
+
}
|
|
87002
|
+
await deliverPendingMessages(handle, deps, rowId, messages, info);
|
|
87003
|
+
}
|
|
86594
87004
|
var init_prompt_subscriber = __esm(() => {
|
|
86595
87005
|
init_idle_handler();
|
|
86596
87006
|
init_api3();
|
|
@@ -86619,6 +87029,60 @@ function startSessionSubscriber(daemonSession, wsClient2, deps) {
|
|
|
86619
87029
|
});
|
|
86620
87030
|
return { stop: unsub };
|
|
86621
87031
|
}
|
|
87032
|
+
async function getOrCreateHarness(daemonSession, deps, session2, workspace) {
|
|
87033
|
+
let harness = deps.harnesses.get(session2.workspaceId);
|
|
87034
|
+
if (harness && !harness.isAlive()) {
|
|
87035
|
+
console.warn(`[direct-harness] Harness for workspace ${session2.workspaceId} is no longer alive — restarting`);
|
|
87036
|
+
harness.close().catch(() => {});
|
|
87037
|
+
deps.harnesses.delete(session2.workspaceId);
|
|
87038
|
+
harness = undefined;
|
|
87039
|
+
}
|
|
87040
|
+
if (!harness) {
|
|
87041
|
+
harness = await startOpencodeSdkHarness({
|
|
87042
|
+
type: "opencode",
|
|
87043
|
+
workingDir: workspace.workingDir,
|
|
87044
|
+
workspaceId: session2.workspaceId
|
|
87045
|
+
});
|
|
87046
|
+
deps.harnesses.set(session2.workspaceId, harness);
|
|
87047
|
+
}
|
|
87048
|
+
return harness;
|
|
87049
|
+
}
|
|
87050
|
+
function recordLiveSessionChunk(event, handle, journal, extractChunk, deps) {
|
|
87051
|
+
const chunk2 = extractChunk(event);
|
|
87052
|
+
if (chunk2 === null) {
|
|
87053
|
+
return;
|
|
87054
|
+
}
|
|
87055
|
+
journal.record({
|
|
87056
|
+
content: chunk2.content,
|
|
87057
|
+
timestamp: Date.now(),
|
|
87058
|
+
messageId: chunk2.messageId,
|
|
87059
|
+
partType: chunk2.partType
|
|
87060
|
+
});
|
|
87061
|
+
if (handle.currentTurn && handle.currentTurn.messageId === null) {
|
|
87062
|
+
handle.currentTurn.messageId = chunk2.messageId;
|
|
87063
|
+
deps.sessionRepository.bindTurnMessageId(handle.currentTurn.turnId, chunk2.messageId).catch((err) => console.warn("[direct-harness] bindTurnMessageId error:", err));
|
|
87064
|
+
}
|
|
87065
|
+
}
|
|
87066
|
+
function handleLiveSessionTitleUpdate(event, deps, rowId, liveSession) {
|
|
87067
|
+
if (event.type !== "session.updated") {
|
|
87068
|
+
return;
|
|
87069
|
+
}
|
|
87070
|
+
const info = event.payload.info;
|
|
87071
|
+
const newTitle = info?.title;
|
|
87072
|
+
if (!newTitle || newTitle === liveSession.sessionTitle) {
|
|
87073
|
+
return;
|
|
87074
|
+
}
|
|
87075
|
+
liveSession.setTitle?.(newTitle);
|
|
87076
|
+
deps.sessionRepository.updateSessionTitle(rowId, newTitle).catch((err) => console.warn("[direct-harness] updateSessionTitle error:", err));
|
|
87077
|
+
}
|
|
87078
|
+
function handleLiveSessionEvent(event, ctx) {
|
|
87079
|
+
const { handle, journal, extractChunk, idleConfig, deps, rowId, liveSession } = ctx;
|
|
87080
|
+
recordLiveSessionChunk(event, handle, journal, extractChunk, deps);
|
|
87081
|
+
if (event.type === "session.idle") {
|
|
87082
|
+
handleSessionIdle(handle, journal, idleConfig, deps.sessionRepository).catch((err) => console.warn("[direct-harness] idle handler error:", err));
|
|
87083
|
+
}
|
|
87084
|
+
handleLiveSessionTitleUpdate(event, deps, rowId, liveSession);
|
|
87085
|
+
}
|
|
86622
87086
|
async function processOne(daemonSession, deps, session2) {
|
|
86623
87087
|
const rowId = session2._id;
|
|
86624
87088
|
try {
|
|
@@ -86631,21 +87095,7 @@ async function processOne(daemonSession, deps, session2) {
|
|
|
86631
87095
|
await deps.sessionRepository.markFailed(rowId);
|
|
86632
87096
|
return;
|
|
86633
87097
|
}
|
|
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
|
-
}
|
|
87098
|
+
const harness = await getOrCreateHarness(daemonSession, deps, session2, workspace);
|
|
86649
87099
|
const liveSession = await harness.newSession({
|
|
86650
87100
|
agent: session2.opencode?.lastUsedConfig.agent ?? "build",
|
|
86651
87101
|
harnessSessionId: rowId
|
|
@@ -86677,30 +87127,15 @@ async function processOne(daemonSession, deps, session2) {
|
|
|
86677
87127
|
close: close2
|
|
86678
87128
|
};
|
|
86679
87129
|
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
|
-
}
|
|
87130
|
+
handleLiveSessionEvent(event, {
|
|
87131
|
+
handle,
|
|
87132
|
+
journal,
|
|
87133
|
+
extractChunk,
|
|
87134
|
+
idleConfig,
|
|
87135
|
+
deps,
|
|
87136
|
+
rowId,
|
|
87137
|
+
liveSession
|
|
87138
|
+
});
|
|
86704
87139
|
});
|
|
86705
87140
|
deps.activeSessions.set(rowId, handle);
|
|
86706
87141
|
try {
|
|
@@ -87528,16 +87963,14 @@ var init_state_recovery = __esm(() => {
|
|
|
87528
87963
|
for (const config3 of configsResult.configs) {
|
|
87529
87964
|
if (config3.machineId === session2.machineId && config3.workingDir) {
|
|
87530
87965
|
registeredCount++;
|
|
87531
|
-
exports_Effect.
|
|
87966
|
+
yield* exports_Effect.forkDaemon(exports_Effect.tryPromise(() => session2.backend.mutation(api.workspaces.registerWorkspace, {
|
|
87532
87967
|
sessionId: session2.sessionId,
|
|
87533
87968
|
chatroomId,
|
|
87534
87969
|
machineId: session2.machineId,
|
|
87535
87970
|
workingDir: config3.workingDir,
|
|
87536
87971
|
hostname: session2.config?.hostname ?? "unknown",
|
|
87537
87972
|
registeredBy: config3.role
|
|
87538
|
-
}))
|
|
87539
|
-
console.warn(`[daemon] ⚠️ Failed to register workspace on recovery: ${err.message}`);
|
|
87540
|
-
});
|
|
87973
|
+
})).pipe(exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[daemon] ⚠️ Failed to register workspace on recovery: ${err.message}`)))));
|
|
87541
87974
|
}
|
|
87542
87975
|
}
|
|
87543
87976
|
}), () => exports_Effect.void);
|
|
@@ -87608,16 +88041,18 @@ class DaemonEventBus {
|
|
|
87608
88041
|
}
|
|
87609
88042
|
|
|
87610
88043
|
// src/events/daemon/agent/on-agent-exited.ts
|
|
87611
|
-
|
|
87612
|
-
|
|
88044
|
+
var onAgentExitedEffect = (payload) => exports_Effect.gen(function* () {
|
|
88045
|
+
const apm = yield* DaemonAgentProcessManagerService;
|
|
88046
|
+
yield* apm.handleExit({
|
|
87613
88047
|
chatroomId: payload.chatroomId,
|
|
87614
88048
|
role: payload.role,
|
|
87615
88049
|
pid: payload.pid,
|
|
87616
88050
|
code: payload.code,
|
|
87617
88051
|
signal: payload.signal
|
|
87618
88052
|
});
|
|
87619
|
-
}
|
|
88053
|
+
});
|
|
87620
88054
|
var init_on_agent_exited = __esm(() => {
|
|
88055
|
+
init_esm();
|
|
87621
88056
|
init_daemon_services();
|
|
87622
88057
|
});
|
|
87623
88058
|
|
|
@@ -87638,9 +88073,11 @@ var init_on_agent_stopped = () => {};
|
|
|
87638
88073
|
// src/events/daemon/register-listeners.ts
|
|
87639
88074
|
var registerEventListenersEffect = () => exports_Effect.gen(function* () {
|
|
87640
88075
|
const session2 = yield* DaemonSessionService;
|
|
87641
|
-
const
|
|
88076
|
+
const runtime4 = yield* exports_Effect.runtime();
|
|
87642
88077
|
const unsubs = [];
|
|
87643
|
-
unsubs.push(session2.events.on("agent:exited", (payload) =>
|
|
88078
|
+
unsubs.push(session2.events.on("agent:exited", (payload) => {
|
|
88079
|
+
exports_Runtime.runFork(runtime4)(onAgentExitedEffect(payload));
|
|
88080
|
+
}));
|
|
87644
88081
|
unsubs.push(session2.events.on("agent:started", (payload) => logAgentStarted(payload)));
|
|
87645
88082
|
unsubs.push(session2.events.on("agent:stopped", (payload) => logAgentStopped(payload)));
|
|
87646
88083
|
return () => {
|
|
@@ -87960,9 +88397,131 @@ var init_decide_resume_path = __esm(() => {
|
|
|
87960
88397
|
]);
|
|
87961
88398
|
});
|
|
87962
88399
|
|
|
88400
|
+
// src/domain/agent-lifecycle/entities/agent-slot.ts
|
|
88401
|
+
function agentKey2(chatroomId, role) {
|
|
88402
|
+
return `${chatroomId}:${role.toLowerCase()}`;
|
|
88403
|
+
}
|
|
88404
|
+
var idleSlot = () => ({ state: "idle" });
|
|
88405
|
+
// src/domain/agent-lifecycle/policies/slot-transitions.ts
|
|
88406
|
+
function makeError(tag, from, event) {
|
|
88407
|
+
return {
|
|
88408
|
+
ok: false,
|
|
88409
|
+
error: { _tag: tag, from, event }
|
|
88410
|
+
};
|
|
88411
|
+
}
|
|
88412
|
+
function makeResult(slot) {
|
|
88413
|
+
return { ok: true, slot };
|
|
88414
|
+
}
|
|
88415
|
+
function transitionFromIdle(slot, event) {
|
|
88416
|
+
if (event.type === "ensure_running_requested") {
|
|
88417
|
+
return makeResult(slot);
|
|
88418
|
+
}
|
|
88419
|
+
if (event.type === "spawn_started") {
|
|
88420
|
+
return makeResult({ ...slot, state: "spawning", pendingOperationKey: event.operationKey });
|
|
88421
|
+
}
|
|
88422
|
+
if (event.type === "process_exited") {
|
|
88423
|
+
return makeResult(slot);
|
|
88424
|
+
}
|
|
88425
|
+
return makeError("InvalidTransition", slot.state, event.type);
|
|
88426
|
+
}
|
|
88427
|
+
function transitionFromSpawning(slot, event) {
|
|
88428
|
+
if (event.type === "spawn_started") {
|
|
88429
|
+
return makeResult({ ...slot, pendingOperationKey: event.operationKey });
|
|
88430
|
+
}
|
|
88431
|
+
if (event.type === "spawn_succeeded") {
|
|
88432
|
+
return makeResult({ ...slot, state: "running", pid: event.pid });
|
|
88433
|
+
}
|
|
88434
|
+
if (event.type === "spawn_failed" || event.type === "process_exited") {
|
|
88435
|
+
return makeResult({ state: "idle" });
|
|
88436
|
+
}
|
|
88437
|
+
return makeError("InvalidTransition", slot.state, event.type);
|
|
88438
|
+
}
|
|
88439
|
+
function transitionFromRunning(slot, event) {
|
|
88440
|
+
if (event.type === "stop_requested") {
|
|
88441
|
+
return makeResult({ ...slot, state: "stopping", pendingOperationKey: event.operationKey });
|
|
88442
|
+
}
|
|
88443
|
+
if (event.type === "process_exited") {
|
|
88444
|
+
if (slot.pid !== undefined && slot.pid !== event.pid) {
|
|
88445
|
+
return { ok: false, error: { _tag: "StalePid", expected: slot.pid, got: event.pid } };
|
|
88446
|
+
}
|
|
88447
|
+
return makeResult({ state: "idle" });
|
|
88448
|
+
}
|
|
88449
|
+
if (event.type === "stale_process_detected") {
|
|
88450
|
+
return makeResult({ state: "idle" });
|
|
88451
|
+
}
|
|
88452
|
+
return makeError("InvalidTransition", slot.state, event.type);
|
|
88453
|
+
}
|
|
88454
|
+
function transitionFromStopping(slot, event) {
|
|
88455
|
+
if (event.type === "stop_completed") {
|
|
88456
|
+
return makeResult({ state: "idle" });
|
|
88457
|
+
}
|
|
88458
|
+
if (event.type === "process_exited") {
|
|
88459
|
+
return { ok: false, error: { _tag: "IgnoredDuplicateExit" } };
|
|
88460
|
+
}
|
|
88461
|
+
return makeError("InvalidTransition", slot.state, event.type);
|
|
88462
|
+
}
|
|
88463
|
+
function transitionSlot(slot, event) {
|
|
88464
|
+
switch (slot.state) {
|
|
88465
|
+
case "idle":
|
|
88466
|
+
return transitionFromIdle(slot, event);
|
|
88467
|
+
case "spawning":
|
|
88468
|
+
return transitionFromSpawning(slot, event);
|
|
88469
|
+
case "running":
|
|
88470
|
+
return transitionFromRunning(slot, event);
|
|
88471
|
+
case "stopping":
|
|
88472
|
+
return transitionFromStopping(slot, event);
|
|
88473
|
+
}
|
|
88474
|
+
}
|
|
88475
|
+
function shouldIgnoreProcessExit(slot, exitPid) {
|
|
88476
|
+
if (slot.state === "stopping")
|
|
88477
|
+
return true;
|
|
88478
|
+
if (slot.pid !== undefined && slot.pid !== exitPid)
|
|
88479
|
+
return true;
|
|
88480
|
+
return false;
|
|
88481
|
+
}
|
|
88482
|
+
|
|
88483
|
+
// src/domain/agent-lifecycle/policies/restart-decision.ts
|
|
88484
|
+
function decideRestartAfterExit(input) {
|
|
88485
|
+
if (!shouldAutoRestartAfterProcessExit(input.stopReason)) {
|
|
88486
|
+
return { _tag: "NoRestart", reason: `Intentional stop: ${input.stopReason}` };
|
|
88487
|
+
}
|
|
88488
|
+
if (!input.harness || !input.workingDir) {
|
|
88489
|
+
return { _tag: "NoRestart", reason: "Missing harness or workingDir" };
|
|
88490
|
+
}
|
|
88491
|
+
if (input.isPermanentFailure) {
|
|
88492
|
+
return {
|
|
88493
|
+
_tag: "NoRestart",
|
|
88494
|
+
reason: input.permanentFailureMessage ?? "Permanent failure"
|
|
88495
|
+
};
|
|
88496
|
+
}
|
|
88497
|
+
if (input.backoffWaitMs && input.backoffWaitMs > 0) {
|
|
88498
|
+
return {
|
|
88499
|
+
_tag: "ScheduleRetry",
|
|
88500
|
+
waitMs: input.backoffWaitMs,
|
|
88501
|
+
spawnReason: "platform.crash_recovery",
|
|
88502
|
+
wantResume: input.wantResume
|
|
88503
|
+
};
|
|
88504
|
+
}
|
|
88505
|
+
return {
|
|
88506
|
+
_tag: "RestartNow",
|
|
88507
|
+
spawnReason: "platform.crash_recovery",
|
|
88508
|
+
wantResume: input.wantResume,
|
|
88509
|
+
bypassConcurrentLimit: true
|
|
88510
|
+
};
|
|
88511
|
+
}
|
|
88512
|
+
var init_restart_decision = __esm(() => {
|
|
88513
|
+
init_decide_resume_path();
|
|
88514
|
+
});
|
|
88515
|
+
|
|
88516
|
+
// src/domain/agent-lifecycle/policies/spawn-gate.ts
|
|
88517
|
+
function shouldBypassConcurrentLimit(spawnReason) {
|
|
88518
|
+
return spawnReason.startsWith("user.") || spawnReason === "platform.crash_recovery";
|
|
88519
|
+
}
|
|
88520
|
+
|
|
87963
88521
|
// src/domain/agent-lifecycle/index.ts
|
|
87964
88522
|
var init_agent_lifecycle = __esm(() => {
|
|
87965
88523
|
init_decide_resume_path();
|
|
88524
|
+
init_restart_decision();
|
|
87966
88525
|
});
|
|
87967
88526
|
|
|
87968
88527
|
// src/domain/agent-lifecycle/policies/append-recent-log-line.ts
|
|
@@ -88158,6 +88717,90 @@ class RapidResumeTracker {
|
|
|
88158
88717
|
}
|
|
88159
88718
|
var RAPID_RESUME_WINDOW_MS = 30000, RAPID_RESUME_THRESHOLD = 5;
|
|
88160
88719
|
|
|
88720
|
+
// src/infrastructure/services/agent-lifecycle/agent-lifecycle-port-adapters.ts
|
|
88721
|
+
function createSpawnPort(spawning) {
|
|
88722
|
+
return {
|
|
88723
|
+
shouldAllowSpawn: (chatroomId, reason, options) => spawning.shouldAllowSpawn(chatroomId, reason, options),
|
|
88724
|
+
recordSpawn: (chatroomId) => exports_Effect.sync(() => {
|
|
88725
|
+
spawning.recordSpawn(chatroomId);
|
|
88726
|
+
}),
|
|
88727
|
+
recordExit: (chatroomId) => exports_Effect.sync(() => {
|
|
88728
|
+
spawning.recordExit(chatroomId);
|
|
88729
|
+
})
|
|
88730
|
+
};
|
|
88731
|
+
}
|
|
88732
|
+
function createHarnessSpawnPort(deps) {
|
|
88733
|
+
return {
|
|
88734
|
+
spawn: (args2) => exports_Effect.tryPromise({
|
|
88735
|
+
try: async () => {
|
|
88736
|
+
const service3 = deps.agentServices.get(args2.harness);
|
|
88737
|
+
if (!service3) {
|
|
88738
|
+
throw new Error(`Unknown agent harness: ${args2.harness}`);
|
|
88739
|
+
}
|
|
88740
|
+
const result = await service3.spawn({
|
|
88741
|
+
workingDir: args2.workingDir,
|
|
88742
|
+
prompt: args2.prompt,
|
|
88743
|
+
systemPrompt: args2.systemPrompt ?? "",
|
|
88744
|
+
model: args2.model,
|
|
88745
|
+
context: {
|
|
88746
|
+
machineId: deps.machineId,
|
|
88747
|
+
chatroomId: args2.chatroomId,
|
|
88748
|
+
role: args2.role
|
|
88749
|
+
}
|
|
88750
|
+
});
|
|
88751
|
+
return {
|
|
88752
|
+
pid: result.pid,
|
|
88753
|
+
harnessSessionId: result.harnessSessionId,
|
|
88754
|
+
onAgentEnd: (cb) => {
|
|
88755
|
+
result.onAgentEnd?.(cb);
|
|
88756
|
+
},
|
|
88757
|
+
onLogLine: result.onLogLine ? (lineCb) => {
|
|
88758
|
+
result.onLogLine?.((line) => {
|
|
88759
|
+
lineCb(line);
|
|
88760
|
+
});
|
|
88761
|
+
} : undefined
|
|
88762
|
+
};
|
|
88763
|
+
},
|
|
88764
|
+
catch: (e) => e instanceof Error ? e : new Error(String(e))
|
|
88765
|
+
}),
|
|
88766
|
+
stop: (pid, opts) => exports_Effect.tryPromise({
|
|
88767
|
+
try: async () => {
|
|
88768
|
+
for (const service3 of deps.agentServices.values()) {
|
|
88769
|
+
try {
|
|
88770
|
+
await service3.stop(pid, opts);
|
|
88771
|
+
return;
|
|
88772
|
+
} catch {}
|
|
88773
|
+
}
|
|
88774
|
+
},
|
|
88775
|
+
catch: (e) => e instanceof Error ? e : new Error(String(e))
|
|
88776
|
+
}),
|
|
88777
|
+
isAlive: (pid) => exports_Effect.sync(() => {
|
|
88778
|
+
return isProcessAlive((p) => process.kill(p, 0), pid);
|
|
88779
|
+
})
|
|
88780
|
+
};
|
|
88781
|
+
}
|
|
88782
|
+
function createAgentLifecyclePorts(deps) {
|
|
88783
|
+
return {
|
|
88784
|
+
spawn: createSpawnPort(deps.spawning),
|
|
88785
|
+
harness: createHarnessSpawnPort(deps),
|
|
88786
|
+
sessionId: deps.sessionId,
|
|
88787
|
+
machineId: deps.machineId
|
|
88788
|
+
};
|
|
88789
|
+
}
|
|
88790
|
+
var init_agent_lifecycle_port_adapters = __esm(() => {
|
|
88791
|
+
init_esm();
|
|
88792
|
+
});
|
|
88793
|
+
|
|
88794
|
+
// src/infrastructure/services/agent-lifecycle/agent-lifecycle-types.ts
|
|
88795
|
+
var AgentLifecyclePorts, AgentLifecycleService;
|
|
88796
|
+
var init_agent_lifecycle_types = __esm(() => {
|
|
88797
|
+
init_esm();
|
|
88798
|
+
AgentLifecyclePorts = class AgentLifecyclePorts extends exports_Context.Tag("AgentLifecyclePorts")() {
|
|
88799
|
+
};
|
|
88800
|
+
AgentLifecycleService = class AgentLifecycleService extends exports_Context.Tag("AgentLifecycleService")() {
|
|
88801
|
+
};
|
|
88802
|
+
});
|
|
88803
|
+
|
|
88161
88804
|
// src/infrastructure/services/remote-agents/spawn-prompt.ts
|
|
88162
88805
|
function createSpawnPrompt(raw) {
|
|
88163
88806
|
const trimmed = raw?.trim();
|
|
@@ -88165,8 +88808,264 @@ function createSpawnPrompt(raw) {
|
|
|
88165
88808
|
}
|
|
88166
88809
|
var DEFAULT_TRIGGER_PROMPT = "Please read your system prompt carefully and follow the Getting Started instructions.";
|
|
88167
88810
|
|
|
88811
|
+
// src/infrastructure/services/agent-lifecycle/agent-lifecycle-service.ts
|
|
88812
|
+
var AgentLifecycleServiceLive;
|
|
88813
|
+
var init_agent_lifecycle_service = __esm(() => {
|
|
88814
|
+
init_esm();
|
|
88815
|
+
init_agent_lifecycle_types();
|
|
88816
|
+
init_agent_lifecycle();
|
|
88817
|
+
AgentLifecycleServiceLive = exports_Layer.effect(AgentLifecycleService, exports_Effect.gen(function* () {
|
|
88818
|
+
const ports = yield* AgentLifecyclePorts;
|
|
88819
|
+
const slotsRef = yield* exports_Ref.make(new Map);
|
|
88820
|
+
const getSlotFromRef = (key) => exports_Ref.get(slotsRef).pipe(exports_Effect.map((map18) => map18.get(key)));
|
|
88821
|
+
const setSlotInRef = (key, slot) => exports_Ref.update(slotsRef, (map18) => map18.set(key, slot));
|
|
88822
|
+
const removeSlotFromRef = (key) => exports_Ref.update(slotsRef, (map18) => {
|
|
88823
|
+
const next4 = new Map(map18);
|
|
88824
|
+
next4.delete(key);
|
|
88825
|
+
return next4;
|
|
88826
|
+
});
|
|
88827
|
+
const spawnAndRegister = (key, opts) => exports_Effect.gen(function* () {
|
|
88828
|
+
let slot = {
|
|
88829
|
+
...idleSlot(),
|
|
88830
|
+
harness: opts.agentHarness,
|
|
88831
|
+
model: opts.model,
|
|
88832
|
+
workingDir: opts.workingDir,
|
|
88833
|
+
wantResume: opts.wantResume,
|
|
88834
|
+
_initPrompt: opts.initPrompt ?? "",
|
|
88835
|
+
_systemPrompt: opts.systemPrompt
|
|
88836
|
+
};
|
|
88837
|
+
const startedResult = transitionSlot(slot, {
|
|
88838
|
+
type: "spawn_started",
|
|
88839
|
+
operationKey: opts.reason
|
|
88840
|
+
});
|
|
88841
|
+
if (!startedResult.ok) {
|
|
88842
|
+
return { success: false, error: "spawn_failed" };
|
|
88843
|
+
}
|
|
88844
|
+
slot = startedResult.slot;
|
|
88845
|
+
const spawnHandle = yield* ports.harness.spawn({
|
|
88846
|
+
harness: opts.agentHarness,
|
|
88847
|
+
chatroomId: opts.chatroomId,
|
|
88848
|
+
role: opts.role,
|
|
88849
|
+
workingDir: opts.workingDir,
|
|
88850
|
+
model: opts.model,
|
|
88851
|
+
prompt: createSpawnPrompt(opts.initPrompt),
|
|
88852
|
+
systemPrompt: opts.systemPrompt
|
|
88853
|
+
}).pipe(exports_Effect.catchAll(() => exports_Effect.succeed(null)));
|
|
88854
|
+
if (!spawnHandle) {
|
|
88855
|
+
return { success: false, error: "spawn_failed" };
|
|
88856
|
+
}
|
|
88857
|
+
const succeededResult = transitionSlot(slot, {
|
|
88858
|
+
type: "spawn_succeeded",
|
|
88859
|
+
pid: spawnHandle.pid
|
|
88860
|
+
});
|
|
88861
|
+
if (!succeededResult.ok) {
|
|
88862
|
+
return { success: false, error: "spawn_failed" };
|
|
88863
|
+
}
|
|
88864
|
+
slot = succeededResult.slot;
|
|
88865
|
+
yield* ports.spawn.recordSpawn(opts.chatroomId);
|
|
88866
|
+
yield* setSlotInRef(key, slot);
|
|
88867
|
+
if (spawnHandle) {
|
|
88868
|
+
spawnHandle.onAgentEnd(() => {});
|
|
88869
|
+
}
|
|
88870
|
+
if (spawnHandle && spawnHandle.harnessSessionId) {
|
|
88871
|
+
const updatedSlot = { ...slot, harnessSessionId: spawnHandle.harnessSessionId };
|
|
88872
|
+
yield* setSlotInRef(key, updatedSlot);
|
|
88873
|
+
}
|
|
88874
|
+
return { success: true, pid: slot.pid };
|
|
88875
|
+
});
|
|
88876
|
+
const ensureRunning = (opts) => exports_Effect.gen(function* () {
|
|
88877
|
+
const key = agentKey2(opts.chatroomId, opts.role);
|
|
88878
|
+
const currentSlot = yield* getSlotFromRef(key);
|
|
88879
|
+
if (currentSlot && currentSlot.state !== "idle") {
|
|
88880
|
+
return {
|
|
88881
|
+
success: true,
|
|
88882
|
+
pid: currentSlot.pid
|
|
88883
|
+
};
|
|
88884
|
+
}
|
|
88885
|
+
const bypass = shouldBypassConcurrentLimit(opts.reason);
|
|
88886
|
+
const allowResult = ports.spawn.shouldAllowSpawn(opts.chatroomId, opts.reason, bypass ? { bypassConcurrentLimit: true } : undefined);
|
|
88887
|
+
if (!allowResult.allowed) {
|
|
88888
|
+
const error = allowResult.retryAfterMs ? "rate_limited" : "backoff";
|
|
88889
|
+
return { success: false, error };
|
|
88890
|
+
}
|
|
88891
|
+
const result = yield* spawnAndRegister(key, opts);
|
|
88892
|
+
if (!result.success && result.error) {
|
|
88893
|
+
yield* exports_Effect.logError(`Agent spawn failed for ${key}: ${result.error}`);
|
|
88894
|
+
}
|
|
88895
|
+
return result;
|
|
88896
|
+
});
|
|
88897
|
+
const stop4 = (opts) => exports_Effect.gen(function* () {
|
|
88898
|
+
const key = agentKey2(opts.chatroomId, opts.role);
|
|
88899
|
+
const slot = yield* getSlotFromRef(key);
|
|
88900
|
+
if (!slot) {
|
|
88901
|
+
return { success: false };
|
|
88902
|
+
}
|
|
88903
|
+
const stoppingResult = transitionSlot(slot, {
|
|
88904
|
+
type: "stop_requested",
|
|
88905
|
+
operationKey: opts.reason
|
|
88906
|
+
});
|
|
88907
|
+
if (!stoppingResult.ok) {
|
|
88908
|
+
return { success: false };
|
|
88909
|
+
}
|
|
88910
|
+
const stoppingSlot = stoppingResult.slot;
|
|
88911
|
+
yield* setSlotInRef(key, stoppingSlot);
|
|
88912
|
+
if (stoppingSlot.pid) {
|
|
88913
|
+
yield* ports.harness.stop(stoppingSlot.pid, { preserveForResume: false }).pipe(exports_Effect.ignore);
|
|
88914
|
+
}
|
|
88915
|
+
yield* ports.spawn.recordExit(opts.chatroomId);
|
|
88916
|
+
const completedResult = transitionSlot(stoppingSlot, {
|
|
88917
|
+
type: "stop_completed"
|
|
88918
|
+
});
|
|
88919
|
+
if (completedResult.ok) {
|
|
88920
|
+
yield* setSlotInRef(key, completedResult.slot);
|
|
88921
|
+
}
|
|
88922
|
+
return { success: true };
|
|
88923
|
+
});
|
|
88924
|
+
const executeRestart = (slot, chatroomId, role) => exports_Effect.gen(function* () {
|
|
88925
|
+
const restartOutcome = decideRestartAfterExit({
|
|
88926
|
+
stopReason: resolveStopReason(slot._stopReasonCode ?? 0, slot._stopReasonSignal ?? null),
|
|
88927
|
+
harness: slot.harness,
|
|
88928
|
+
workingDir: slot.workingDir,
|
|
88929
|
+
wantResume: slot.wantResume ?? false,
|
|
88930
|
+
isPermanentFailure: false,
|
|
88931
|
+
restartAllowed: true
|
|
88932
|
+
});
|
|
88933
|
+
yield* dispatchRestartOutcome(restartOutcome, slot, chatroomId, role);
|
|
88934
|
+
});
|
|
88935
|
+
const dispatchRestartOutcome = (outcome, slot, chatroomId, role) => exports_Effect.gen(function* () {
|
|
88936
|
+
switch (outcome._tag) {
|
|
88937
|
+
case "RestartNow": {
|
|
88938
|
+
yield* handleRestartNow(slot, chatroomId, role, outcome);
|
|
88939
|
+
break;
|
|
88940
|
+
}
|
|
88941
|
+
case "ScheduleRetry": {
|
|
88942
|
+
yield* handleScheduleRetry(slot, chatroomId, role, outcome);
|
|
88943
|
+
break;
|
|
88944
|
+
}
|
|
88945
|
+
case "NoRestart": {
|
|
88946
|
+
break;
|
|
88947
|
+
}
|
|
88948
|
+
}
|
|
88949
|
+
});
|
|
88950
|
+
const handleRestartNow = (slot, chatroomId, role, outcome) => exports_Effect.gen(function* () {
|
|
88951
|
+
if (!slot.harness) {
|
|
88952
|
+
yield* exports_Effect.logError(`Agent restart failed for ${chatroomId}:${role}: missing harness`);
|
|
88953
|
+
return;
|
|
88954
|
+
}
|
|
88955
|
+
const restartResult = yield* ensureRunning({
|
|
88956
|
+
chatroomId,
|
|
88957
|
+
role,
|
|
88958
|
+
agentHarness: slot.harness,
|
|
88959
|
+
workingDir: slot.workingDir ?? "",
|
|
88960
|
+
reason: outcome.spawnReason,
|
|
88961
|
+
wantResume: outcome.wantResume,
|
|
88962
|
+
initPrompt: slot._initPrompt,
|
|
88963
|
+
systemPrompt: slot._systemPrompt
|
|
88964
|
+
});
|
|
88965
|
+
if (!restartResult.success && restartResult.error) {
|
|
88966
|
+
yield* exports_Effect.logError(`Agent restart failed for ${chatroomId}:${role}: ${restartResult.error}`);
|
|
88967
|
+
}
|
|
88968
|
+
});
|
|
88969
|
+
const handleScheduleRetry = (slot, chatroomId, role, outcome) => exports_Effect.gen(function* () {
|
|
88970
|
+
if (!slot.harness) {
|
|
88971
|
+
yield* exports_Effect.logError(`Agent restart failed for ${chatroomId}:${role}: missing harness`);
|
|
88972
|
+
return;
|
|
88973
|
+
}
|
|
88974
|
+
yield* exports_Effect.forkDaemon(exports_Effect.sleep(exports_Duration.millis(outcome.waitMs)).pipe(exports_Effect.as(ensureRunning({
|
|
88975
|
+
chatroomId,
|
|
88976
|
+
role,
|
|
88977
|
+
agentHarness: slot.harness,
|
|
88978
|
+
workingDir: slot.workingDir ?? "",
|
|
88979
|
+
reason: outcome.spawnReason,
|
|
88980
|
+
wantResume: outcome.wantResume,
|
|
88981
|
+
initPrompt: slot._initPrompt,
|
|
88982
|
+
systemPrompt: slot._systemPrompt
|
|
88983
|
+
}))));
|
|
88984
|
+
});
|
|
88985
|
+
const handleExit = (opts) => exports_Effect.gen(function* () {
|
|
88986
|
+
const key = agentKey2(opts.chatroomId, opts.role);
|
|
88987
|
+
const slot = yield* getSlotFromRef(key);
|
|
88988
|
+
if (!slot) {
|
|
88989
|
+
return;
|
|
88990
|
+
}
|
|
88991
|
+
if (shouldIgnoreProcessExit(slot, opts.pid)) {
|
|
88992
|
+
return;
|
|
88993
|
+
}
|
|
88994
|
+
const stopReason = resolveStopReason(opts.code, opts.signal);
|
|
88995
|
+
const transitionResult = transitionSlot(slot, {
|
|
88996
|
+
type: "process_exited",
|
|
88997
|
+
pid: opts.pid
|
|
88998
|
+
});
|
|
88999
|
+
if (!transitionResult.ok) {
|
|
89000
|
+
return;
|
|
89001
|
+
}
|
|
89002
|
+
const exitedSlot = {
|
|
89003
|
+
...transitionResult.slot,
|
|
89004
|
+
_stopReasonCode: opts.code,
|
|
89005
|
+
_stopReasonSignal: opts.signal,
|
|
89006
|
+
harness: slot.harness,
|
|
89007
|
+
workingDir: slot.workingDir,
|
|
89008
|
+
wantResume: slot.wantResume,
|
|
89009
|
+
_initPrompt: slot._initPrompt,
|
|
89010
|
+
_systemPrompt: slot._systemPrompt
|
|
89011
|
+
};
|
|
89012
|
+
yield* setSlotInRef(key, exitedSlot);
|
|
89013
|
+
yield* executeRestart(exitedSlot, opts.chatroomId, opts.role);
|
|
89014
|
+
const restartOutcome = decideRestartAfterExit({
|
|
89015
|
+
stopReason,
|
|
89016
|
+
harness: slot.harness,
|
|
89017
|
+
workingDir: slot.workingDir,
|
|
89018
|
+
wantResume: slot.wantResume ?? false,
|
|
89019
|
+
isPermanentFailure: false,
|
|
89020
|
+
restartAllowed: true
|
|
89021
|
+
});
|
|
89022
|
+
if (restartOutcome._tag === "NoRestart") {
|
|
89023
|
+
yield* removeSlotFromRef(key);
|
|
89024
|
+
}
|
|
89025
|
+
yield* ports.spawn.recordExit(opts.chatroomId);
|
|
89026
|
+
});
|
|
89027
|
+
const getSlot = (chatroomId, role) => getSlotFromRef(agentKey2(chatroomId, role));
|
|
89028
|
+
const listActive = () => exports_Ref.get(slotsRef).pipe(exports_Effect.map((map18) => {
|
|
89029
|
+
const results = [];
|
|
89030
|
+
for (const [key, slot] of map18) {
|
|
89031
|
+
if (slot.state !== "idle") {
|
|
89032
|
+
const [chatroomId, role] = key.split(":");
|
|
89033
|
+
results.push({ chatroomId, role, slot });
|
|
89034
|
+
}
|
|
89035
|
+
}
|
|
89036
|
+
return results;
|
|
89037
|
+
}));
|
|
89038
|
+
return {
|
|
89039
|
+
ensureRunning,
|
|
89040
|
+
stop: stop4,
|
|
89041
|
+
handleExit,
|
|
89042
|
+
getSlot,
|
|
89043
|
+
listActive
|
|
89044
|
+
};
|
|
89045
|
+
}));
|
|
89046
|
+
});
|
|
89047
|
+
|
|
89048
|
+
// src/infrastructure/services/agent-lifecycle/agent-lifecycle-runtime.ts
|
|
89049
|
+
function createAgentLifecycleRuntime(deps) {
|
|
89050
|
+
const layer = exports_Layer.provide(AgentLifecycleServiceLive, exports_Layer.succeed(AgentLifecyclePorts, createAgentLifecyclePorts(deps)));
|
|
89051
|
+
const runtime4 = exports_ManagedRuntime.make(layer);
|
|
89052
|
+
return {
|
|
89053
|
+
runtime: runtime4,
|
|
89054
|
+
runPromise(effect2) {
|
|
89055
|
+
return runtime4.runPromise(effect2);
|
|
89056
|
+
},
|
|
89057
|
+
dispose: () => runtime4.dispose()
|
|
89058
|
+
};
|
|
89059
|
+
}
|
|
89060
|
+
var init_agent_lifecycle_runtime = __esm(() => {
|
|
89061
|
+
init_esm();
|
|
89062
|
+
init_agent_lifecycle_port_adapters();
|
|
89063
|
+
init_agent_lifecycle_service();
|
|
89064
|
+
init_agent_lifecycle_types();
|
|
89065
|
+
});
|
|
89066
|
+
|
|
88168
89067
|
// src/infrastructure/services/agent-process-manager/agent-process-manager.ts
|
|
88169
|
-
function
|
|
89068
|
+
function agentKey3(chatroomId, role) {
|
|
88170
89069
|
return `${chatroomId}:${role.toLowerCase()}`;
|
|
88171
89070
|
}
|
|
88172
89071
|
|
|
@@ -88177,17 +89076,47 @@ class AgentProcessManager {
|
|
|
88177
89076
|
exitRetryQueue = [];
|
|
88178
89077
|
exitRetryTimer = null;
|
|
88179
89078
|
turnEndQueue = new TurnEndQueue;
|
|
89079
|
+
lifecycle;
|
|
88180
89080
|
constructor(deps) {
|
|
88181
89081
|
this.deps = {
|
|
88182
89082
|
...deps,
|
|
88183
89083
|
resumeStormTracker: deps.resumeStormTracker ?? new RapidResumeTracker
|
|
88184
89084
|
};
|
|
89085
|
+
const portAdapterDeps = {
|
|
89086
|
+
spawning: this.deps.spawning,
|
|
89087
|
+
agentServices: this.deps.agentServices,
|
|
89088
|
+
sessionId: this.deps.sessionId,
|
|
89089
|
+
machineId: this.deps.machineId,
|
|
89090
|
+
onAgentEnd: (args2) => void this.runHandleAgentEnd(args2)
|
|
89091
|
+
};
|
|
89092
|
+
this.lifecycle = createAgentLifecycleRuntime(portAdapterDeps);
|
|
89093
|
+
}
|
|
89094
|
+
updateSlotsMirror(chatroomId, role, slot) {
|
|
89095
|
+
const key = agentKey3(chatroomId, role);
|
|
89096
|
+
const existing = this.slots.get(key);
|
|
89097
|
+
if (!existing || existing.state !== slot.state || existing.pid !== slot.pid) {
|
|
89098
|
+
this.slots.set(key, {
|
|
89099
|
+
state: slot.state,
|
|
89100
|
+
pid: slot.pid,
|
|
89101
|
+
harness: slot.harness,
|
|
89102
|
+
harnessSessionId: slot.harnessSessionId,
|
|
89103
|
+
model: slot.model,
|
|
89104
|
+
workingDir: slot.workingDir,
|
|
89105
|
+
startedAt: slot.startedAt,
|
|
89106
|
+
resumeInFlight: slot.resumeInFlight,
|
|
89107
|
+
recentLogLines: slot.recentLogLines,
|
|
89108
|
+
wantResume: slot.wantResume
|
|
89109
|
+
});
|
|
89110
|
+
}
|
|
89111
|
+
}
|
|
89112
|
+
getSlotFromMirror(chatroomId, role) {
|
|
89113
|
+
return this.slots.get(agentKey3(chatroomId, role));
|
|
88185
89114
|
}
|
|
88186
|
-
|
|
88187
|
-
|
|
89115
|
+
whenTurnEndsIdle() {
|
|
89116
|
+
return this.turnEndQueue.whenIdle();
|
|
88188
89117
|
}
|
|
88189
89118
|
async ensureRunning(opts) {
|
|
88190
|
-
const key =
|
|
89119
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
88191
89120
|
const slot = this.getOrCreateSlot(key);
|
|
88192
89121
|
if (slot.state === "running" && slot.pid && !isProcessAlive(this.deps.processes.kill, slot.pid)) {
|
|
88193
89122
|
slot.state = "idle";
|
|
@@ -88211,30 +89140,21 @@ class AgentProcessManager {
|
|
|
88211
89140
|
return operation;
|
|
88212
89141
|
}
|
|
88213
89142
|
async stop(opts) {
|
|
88214
|
-
const key =
|
|
89143
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
88215
89144
|
const slot = this.slots.get(key);
|
|
89145
|
+
const earlyResult = await this.handleStopEarlyReturns(slot, opts, key);
|
|
89146
|
+
if (earlyResult) {
|
|
89147
|
+
return earlyResult;
|
|
89148
|
+
}
|
|
89149
|
+
const actualSlot = slot;
|
|
89150
|
+
if (actualSlot.pendingOperation) {
|
|
89151
|
+
await actualSlot.pendingOperation;
|
|
89152
|
+
}
|
|
89153
|
+
return { success: true };
|
|
89154
|
+
}
|
|
89155
|
+
async handleStopEarlyReturns(slot, opts, key) {
|
|
88216
89156
|
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
|
-
});
|
|
89157
|
+
await this.killAndRecordForIdleSlot(slot, opts);
|
|
88238
89158
|
return { success: true };
|
|
88239
89159
|
}
|
|
88240
89160
|
if (slot.state === "stopping" && slot.pendingOperation) {
|
|
@@ -88250,14 +89170,48 @@ class AgentProcessManager {
|
|
|
88250
89170
|
slot.state = "stopping";
|
|
88251
89171
|
const operation = this.doStop(key, slot, pid, opts);
|
|
88252
89172
|
slot.pendingOperation = operation;
|
|
88253
|
-
|
|
88254
|
-
|
|
89173
|
+
return null;
|
|
89174
|
+
}
|
|
89175
|
+
async killAndRecordForIdleSlot(slot, opts) {
|
|
89176
|
+
const eventPid = opts.pid;
|
|
89177
|
+
if (eventPid && eventPid > 0) {
|
|
89178
|
+
try {
|
|
89179
|
+
this.deps.processes.kill(eventPid, "SIGTERM");
|
|
89180
|
+
} catch {}
|
|
89181
|
+
}
|
|
89182
|
+
const exitArgs1 = {
|
|
89183
|
+
sessionId: this.deps.sessionId,
|
|
89184
|
+
machineId: this.deps.machineId,
|
|
89185
|
+
chatroomId: opts.chatroomId,
|
|
89186
|
+
role: opts.role,
|
|
89187
|
+
pid: eventPid ?? 0,
|
|
89188
|
+
stopReason: opts.reason,
|
|
89189
|
+
exitCode: undefined,
|
|
89190
|
+
signal: undefined,
|
|
89191
|
+
agentHarness: undefined
|
|
89192
|
+
};
|
|
89193
|
+
this.deps.backend.mutation(api.machines.recordAgentExited, exitArgs1).catch((err) => {
|
|
89194
|
+
console.log(` ⚠️ Failed to record agent exit (idle cleanup): ${err.message}`);
|
|
89195
|
+
this.queueExitRetry({ role: opts.role, args: exitArgs1 });
|
|
89196
|
+
});
|
|
88255
89197
|
}
|
|
88256
89198
|
async runHandleAgentEnd(opts) {
|
|
88257
|
-
const slot = this.slots.get(
|
|
89199
|
+
const slot = this.slots.get(agentKey3(opts.chatroomId, opts.role));
|
|
88258
89200
|
const service3 = this.deps.agentServices.get(opts.harness);
|
|
88259
89201
|
const capabilities = getHarnessCapabilities(opts.harness);
|
|
88260
89202
|
const supportsSessionResume = capabilities.supportsSessionResume && typeof service3?.resumeTurn === "function";
|
|
89203
|
+
this.updateSlotsMirror(opts.chatroomId, opts.role, {
|
|
89204
|
+
state: slot?.state ?? "idle",
|
|
89205
|
+
pid: slot?.pid,
|
|
89206
|
+
harness: slot?.harness,
|
|
89207
|
+
harnessSessionId: slot?.harnessSessionId,
|
|
89208
|
+
model: slot?.model,
|
|
89209
|
+
workingDir: slot?.workingDir,
|
|
89210
|
+
startedAt: slot?.startedAt,
|
|
89211
|
+
resumeInFlight: slot?.resumeInFlight,
|
|
89212
|
+
recentLogLines: slot?.recentLogLines,
|
|
89213
|
+
wantResume: slot?.wantResume
|
|
89214
|
+
});
|
|
88261
89215
|
console.log(`[AgentProcessManager] lifecycle.turn.completed: role=${opts.role} pid=${opts.pid} harness=${opts.harness} supportsResume=${supportsSessionResume}`);
|
|
88262
89216
|
const result = await handleTurnCompleted({
|
|
88263
89217
|
resumeStormTracker: this.deps.resumeStormTracker,
|
|
@@ -88296,37 +89250,76 @@ class AgentProcessManager {
|
|
|
88296
89250
|
}
|
|
88297
89251
|
}
|
|
88298
89252
|
async handleExit(opts) {
|
|
88299
|
-
const key =
|
|
89253
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
88300
89254
|
const slot = this.slots.get(key);
|
|
88301
|
-
if (!slot || slot.pid !== opts.pid) {
|
|
88302
|
-
return;
|
|
88303
|
-
}
|
|
88304
|
-
if (slot.state === "stopping") {
|
|
89255
|
+
if (!slot || slot.pid !== opts.pid || slot.state === "stopping") {
|
|
88305
89256
|
return;
|
|
88306
89257
|
}
|
|
88307
89258
|
const stopReason = resolveStopReason(opts.code, opts.signal);
|
|
88308
89259
|
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
|
|
89260
|
+
const ctx = this.captureExitContext(slot, opts, stopReason);
|
|
89261
|
+
await this.preserveHarnessSessionOnExit(key, slot, ctx);
|
|
89262
|
+
const lifecyclePromise = this.lifecycle.runPromise(exports_Effect.gen(function* () {
|
|
89263
|
+
const svc = yield* AgentLifecycleService;
|
|
89264
|
+
yield* svc.handleExit({
|
|
89265
|
+
chatroomId: opts.chatroomId,
|
|
89266
|
+
role: opts.role,
|
|
89267
|
+
pid: opts.pid,
|
|
89268
|
+
code: opts.code,
|
|
89269
|
+
signal: opts.signal
|
|
88324
89270
|
});
|
|
89271
|
+
}));
|
|
89272
|
+
this.resetSlotAfterExit(slot);
|
|
89273
|
+
await this.emitExitEvent(slot, opts, ctx);
|
|
89274
|
+
try {
|
|
89275
|
+
await this.deps.persistence.clearAgentPid(this.deps.machineId, opts.chatroomId, opts.role);
|
|
89276
|
+
} catch {}
|
|
89277
|
+
this.untrackAllServices(opts.pid);
|
|
89278
|
+
lifecyclePromise.then(() => this.dispatchRestartAfterExit(opts, ctx, key)).catch(() => {});
|
|
89279
|
+
}
|
|
89280
|
+
captureExitContext(slot, opts, stopReason) {
|
|
89281
|
+
return {
|
|
89282
|
+
harness: slot.harness,
|
|
89283
|
+
model: slot.model,
|
|
89284
|
+
workingDir: slot.workingDir,
|
|
89285
|
+
harnessSessionId: slot.harnessSessionId,
|
|
89286
|
+
wantResume: slot.wantResume,
|
|
89287
|
+
recentLogLines: slot.recentLogLines,
|
|
89288
|
+
stopReason
|
|
89289
|
+
};
|
|
89290
|
+
}
|
|
89291
|
+
recordExitHarnessSession(key, slot, harness, harnessSessionId, ctx) {
|
|
89292
|
+
const service3 = this.deps.agentServices.get(harness);
|
|
89293
|
+
const harnessMeta = service3 && slot.pid ? this.readHarnessReconnectMetadata(service3, slot.pid) : undefined;
|
|
89294
|
+
this.recordLastHarnessSession(key, {
|
|
89295
|
+
harnessSessionId,
|
|
89296
|
+
harness,
|
|
89297
|
+
agentName: harnessMeta?.agentName ?? "",
|
|
89298
|
+
workingDir: ctx.workingDir ?? "",
|
|
89299
|
+
model: ctx.model ?? harnessMeta?.model
|
|
89300
|
+
});
|
|
89301
|
+
}
|
|
89302
|
+
async preserveHarnessSessionOnExit(key, slot, ctx) {
|
|
89303
|
+
const { harness, harnessSessionId, stopReason } = ctx;
|
|
89304
|
+
if (!harness || !harnessSessionId) {
|
|
89305
|
+
return;
|
|
88325
89306
|
}
|
|
89307
|
+
if (!getHarnessCapabilities(harness).supportsSessionResume) {
|
|
89308
|
+
return;
|
|
89309
|
+
}
|
|
89310
|
+
if (!shouldRetainHarnessSessionForReconnect(stopReason)) {
|
|
89311
|
+
return;
|
|
89312
|
+
}
|
|
89313
|
+
this.recordExitHarnessSession(key, slot, harness, harnessSessionId, ctx);
|
|
89314
|
+
}
|
|
89315
|
+
resetSlotAfterExit(slot) {
|
|
88326
89316
|
slot.state = "idle";
|
|
88327
89317
|
slot.pid = undefined;
|
|
88328
89318
|
slot.startedAt = undefined;
|
|
88329
89319
|
slot.pendingOperation = undefined;
|
|
89320
|
+
}
|
|
89321
|
+
async emitExitEvent(slot, opts, ctx) {
|
|
89322
|
+
const stopReason = ctx.stopReason;
|
|
88330
89323
|
const exitArgs2 = {
|
|
88331
89324
|
sessionId: this.deps.sessionId,
|
|
88332
89325
|
machineId: this.deps.machineId,
|
|
@@ -88337,42 +89330,36 @@ class AgentProcessManager {
|
|
|
88337
89330
|
stopSignal: stopReason === "agent_process.signal" ? opts.signal ?? undefined : undefined,
|
|
88338
89331
|
exitCode: opts.code ?? undefined,
|
|
88339
89332
|
signal: opts.signal ?? undefined,
|
|
88340
|
-
agentHarness: harness
|
|
89333
|
+
agentHarness: ctx.harness
|
|
88341
89334
|
};
|
|
88342
89335
|
this.deps.backend.mutation(api.machines.recordAgentExited, exitArgs2).catch((err) => {
|
|
88343
89336
|
console.log(` ⚠️ Failed to record agent exit event: ${err.message}`);
|
|
88344
89337
|
this.queueExitRetry({ role: opts.role, args: exitArgs2 });
|
|
88345
89338
|
});
|
|
88346
|
-
|
|
88347
|
-
|
|
88348
|
-
} catch {}
|
|
89339
|
+
}
|
|
89340
|
+
untrackAllServices(pid) {
|
|
88349
89341
|
for (const service3 of this.deps.agentServices.values()) {
|
|
88350
|
-
service3.untrack(
|
|
89342
|
+
service3.untrack(pid);
|
|
88351
89343
|
}
|
|
88352
|
-
|
|
88353
|
-
|
|
89344
|
+
}
|
|
89345
|
+
dispatchRestartAfterExit(opts, ctx, _key) {
|
|
89346
|
+
const stopReasonForRestart = resolveStopReason(opts.code, opts.signal);
|
|
89347
|
+
if (!shouldAutoRestartAfterProcessExit(stopReasonForRestart)) {
|
|
89348
|
+
if (stopReasonForRestart === "user.stop" || stopReasonForRestart === "platform.team_switch" || stopReasonForRestart === "daemon.shutdown") {
|
|
88354
89349
|
this.deps.crashLoop.clear(opts.chatroomId, opts.role);
|
|
88355
89350
|
}
|
|
88356
89351
|
return;
|
|
88357
89352
|
}
|
|
89353
|
+
this.maybeRestartAgent(opts, ctx);
|
|
89354
|
+
}
|
|
89355
|
+
maybeRestartAgent(opts, ctx) {
|
|
89356
|
+
const { harness, model, workingDir, recentLogLines } = ctx;
|
|
88358
89357
|
if (!harness || !workingDir) {
|
|
88359
89358
|
console.log(`[AgentProcessManager] ⚠️ Cannot restart — missing harness or workingDir ` + `(role: ${opts.role}, harness: ${harness ?? "none"}, workingDir: ${workingDir ?? "none"})`);
|
|
88360
89359
|
return;
|
|
88361
89360
|
}
|
|
88362
89361
|
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
|
-
});
|
|
89362
|
+
this.handlePermanentFailureForRestart(opts, recentLogLines);
|
|
88376
89363
|
return;
|
|
88377
89364
|
}
|
|
88378
89365
|
this.ensureRunning({
|
|
@@ -88382,22 +89369,39 @@ class AgentProcessManager {
|
|
|
88382
89369
|
model,
|
|
88383
89370
|
workingDir,
|
|
88384
89371
|
reason: "platform.crash_recovery",
|
|
88385
|
-
wantResume: wantResume ?? true
|
|
89372
|
+
wantResume: ctx.wantResume ?? true
|
|
88386
89373
|
}).catch((err) => {
|
|
88387
89374
|
console.log(` ⚠️ Failed to restart agent: ${err.message}`);
|
|
88388
|
-
this.
|
|
88389
|
-
|
|
88390
|
-
|
|
88391
|
-
|
|
88392
|
-
|
|
88393
|
-
|
|
88394
|
-
|
|
88395
|
-
|
|
88396
|
-
|
|
89375
|
+
this.emitStartFailedEvent(opts.role, opts.chatroomId, err.message);
|
|
89376
|
+
});
|
|
89377
|
+
}
|
|
89378
|
+
handlePermanentFailureForRestart(opts, recentLogLines) {
|
|
89379
|
+
const error = formatPermanentHarnessFailureMessage(recentLogLines ?? []);
|
|
89380
|
+
console.log(`[AgentProcessManager] ⛔ Skipping restart — ${error}`);
|
|
89381
|
+
this.deps.crashLoop.clear(opts.chatroomId, opts.role);
|
|
89382
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
89383
|
+
this.clearLastHarnessSession(key);
|
|
89384
|
+
this.deps.backend.mutation(api.machines.emitAgentStartFailed, {
|
|
89385
|
+
sessionId: this.deps.sessionId,
|
|
89386
|
+
machineId: this.deps.machineId,
|
|
89387
|
+
chatroomId: opts.chatroomId,
|
|
89388
|
+
role: opts.role,
|
|
89389
|
+
error
|
|
89390
|
+
}).catch((emitErr) => {
|
|
89391
|
+
console.log(` ⚠️ Failed to emit startFailed event: ${emitErr.message}`);
|
|
88397
89392
|
});
|
|
88398
89393
|
}
|
|
89394
|
+
emitStartFailedEvent(role, chatroomId, error) {
|
|
89395
|
+
this.deps.backend.mutation(api.machines.emitAgentStartFailed, {
|
|
89396
|
+
sessionId: this.deps.sessionId,
|
|
89397
|
+
machineId: this.deps.machineId,
|
|
89398
|
+
chatroomId,
|
|
89399
|
+
role,
|
|
89400
|
+
error
|
|
89401
|
+
}).catch(() => {});
|
|
89402
|
+
}
|
|
88399
89403
|
getSlot(chatroomId, role) {
|
|
88400
|
-
return this.
|
|
89404
|
+
return this.getSlotFromMirror(chatroomId, role);
|
|
88401
89405
|
}
|
|
88402
89406
|
listActive() {
|
|
88403
89407
|
const result = [];
|
|
@@ -88468,13 +89472,19 @@ class AgentProcessManager {
|
|
|
88468
89472
|
untrackChildPid(pid);
|
|
88469
89473
|
}
|
|
88470
89474
|
async killExistingBeforeSpawn(chatroomId, role) {
|
|
88471
|
-
const key =
|
|
89475
|
+
const key = agentKey3(chatroomId, role);
|
|
89476
|
+
await this.killInMemorySlotIfAlive(key, chatroomId, role);
|
|
89477
|
+
await this.killPersistedProcessIfAlive(chatroomId, role);
|
|
89478
|
+
}
|
|
89479
|
+
async killInMemorySlotIfAlive(key, chatroomId, role) {
|
|
88472
89480
|
const slot = this.slots.get(key);
|
|
88473
89481
|
if (slot?.pid && isProcessAlive(this.deps.processes.kill, slot.pid) && (slot.state === "running" || slot.state === "spawning")) {
|
|
88474
|
-
const
|
|
89482
|
+
const pid = slot.pid;
|
|
88475
89483
|
slot.state = "stopping";
|
|
88476
|
-
await this.doStop(key, slot,
|
|
89484
|
+
await this.doStop(key, slot, pid, { chatroomId, role, reason: "daemon.respawn" });
|
|
88477
89485
|
}
|
|
89486
|
+
}
|
|
89487
|
+
async killPersistedProcessIfAlive(chatroomId, role) {
|
|
88478
89488
|
let entries2 = [];
|
|
88479
89489
|
try {
|
|
88480
89490
|
entries2 = await this.deps.persistence.listAgentEntries(this.deps.machineId);
|
|
@@ -88487,11 +89497,10 @@ class AgentProcessManager {
|
|
|
88487
89497
|
}
|
|
88488
89498
|
const { pid, harness } = persisted.entry;
|
|
88489
89499
|
if (!isProcessAlive(this.deps.processes.kill, pid)) {
|
|
88490
|
-
|
|
88491
|
-
await this.deps.persistence.clearAgentPid(this.deps.machineId, chatroomId, role);
|
|
88492
|
-
} catch {}
|
|
89500
|
+
await this.deps.persistence.clearAgentPid(this.deps.machineId, chatroomId, role).catch(() => {});
|
|
88493
89501
|
return;
|
|
88494
89502
|
}
|
|
89503
|
+
const key = agentKey3(chatroomId, role);
|
|
88495
89504
|
const currentSlot = this.slots.get(key);
|
|
88496
89505
|
if (currentSlot?.pid === pid && currentSlot.state !== "idle") {
|
|
88497
89506
|
return;
|
|
@@ -88574,30 +89583,20 @@ class AgentProcessManager {
|
|
|
88574
89583
|
}
|
|
88575
89584
|
}
|
|
88576
89585
|
async tryDaemonMemoryResume(opts) {
|
|
88577
|
-
const
|
|
88578
|
-
if (
|
|
89586
|
+
const validationResult = this.validateDaemonMemoryResumePreconditions(opts);
|
|
89587
|
+
if (validationResult) {
|
|
88579
89588
|
return null;
|
|
88580
89589
|
}
|
|
88581
89590
|
const stored = this.lastHarnessSessions.get(opts.key);
|
|
88582
89591
|
if (!stored) {
|
|
88583
89592
|
return null;
|
|
88584
89593
|
}
|
|
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);
|
|
89594
|
+
const resumeFromDaemonMemory = opts.service.resumeFromDaemonMemory;
|
|
89595
|
+
if (!resumeFromDaemonMemory) {
|
|
88597
89596
|
return null;
|
|
88598
89597
|
}
|
|
88599
89598
|
try {
|
|
88600
|
-
const spawnResult = await
|
|
89599
|
+
const spawnResult = await resumeFromDaemonMemory({
|
|
88601
89600
|
workingDir: stored.workingDir,
|
|
88602
89601
|
prompt: createSpawnPrompt(opts.initPrompt),
|
|
88603
89602
|
systemPrompt: opts.systemPrompt,
|
|
@@ -88621,6 +89620,31 @@ class AgentProcessManager {
|
|
|
88621
89620
|
return null;
|
|
88622
89621
|
}
|
|
88623
89622
|
}
|
|
89623
|
+
validateDaemonMemoryResumePreconditions(opts) {
|
|
89624
|
+
const capabilities = getHarnessCapabilities(opts.agentHarness);
|
|
89625
|
+
if (!capabilities.supportsSessionResume) {
|
|
89626
|
+
return null;
|
|
89627
|
+
}
|
|
89628
|
+
const stored = this.lastHarnessSessions.get(opts.key);
|
|
89629
|
+
if (!stored) {
|
|
89630
|
+
return null;
|
|
89631
|
+
}
|
|
89632
|
+
if (stored.workingDir !== opts.workingDir) {
|
|
89633
|
+
this.clearLastHarnessSession(opts.key);
|
|
89634
|
+
this.emitSessionResumeFailed(opts.chatroomId, opts.role, "working directory changed", stored.harnessSessionId);
|
|
89635
|
+
return "working directory changed";
|
|
89636
|
+
}
|
|
89637
|
+
if (stored.harness !== opts.agentHarness || !stored.agentName) {
|
|
89638
|
+
this.clearLastHarnessSession(opts.key);
|
|
89639
|
+
this.emitSessionResumeFailed(opts.chatroomId, opts.role, stored.harness !== opts.agentHarness ? "harness changed" : "incomplete session in daemon memory", stored.harnessSessionId);
|
|
89640
|
+
return "validation failed";
|
|
89641
|
+
}
|
|
89642
|
+
if (!opts.service.resumeFromDaemonMemory) {
|
|
89643
|
+
this.emitSessionResumeFailed(opts.chatroomId, opts.role, "daemon-memory session resume not yet supported", stored.harnessSessionId);
|
|
89644
|
+
return "not supported";
|
|
89645
|
+
}
|
|
89646
|
+
return null;
|
|
89647
|
+
}
|
|
88624
89648
|
async emitSessionResumed(chatroomId, role, harnessSessionId) {
|
|
88625
89649
|
try {
|
|
88626
89650
|
await this.deps.backend.mutation(api.machines.emitSessionResumed, {
|
|
@@ -88650,195 +89674,248 @@ class AgentProcessManager {
|
|
|
88650
89674
|
console.log(` ⚠️ Failed to emit sessionResumeFailed event: ${err.message}`);
|
|
88651
89675
|
}
|
|
88652
89676
|
}
|
|
88653
|
-
|
|
88654
|
-
slot.state = "
|
|
88655
|
-
|
|
88656
|
-
|
|
89677
|
+
resetSlotIdle(slot) {
|
|
89678
|
+
slot.state = "idle";
|
|
89679
|
+
slot.pendingOperation = undefined;
|
|
89680
|
+
}
|
|
89681
|
+
checkRateLimitGate(opts, slot) {
|
|
89682
|
+
const spawnCheck = this.deps.spawning.shouldAllowSpawn(opts.chatroomId, opts.reason, {
|
|
89683
|
+
bypassConcurrentLimit: opts.reason.startsWith("user.")
|
|
89684
|
+
});
|
|
89685
|
+
if (!spawnCheck.allowed) {
|
|
89686
|
+
this.resetSlotIdle(slot);
|
|
89687
|
+
return { success: false, error: "rate_limited" };
|
|
89688
|
+
}
|
|
89689
|
+
return null;
|
|
89690
|
+
}
|
|
89691
|
+
checkCrashLoopGate(opts, slot) {
|
|
89692
|
+
if (opts.reason !== "platform.crash_recovery") {
|
|
89693
|
+
return null;
|
|
89694
|
+
}
|
|
89695
|
+
const loopCheck = this.deps.crashLoop.record(opts.chatroomId, opts.role, this.deps.clock.now());
|
|
89696
|
+
if (loopCheck.allowed) {
|
|
89697
|
+
return null;
|
|
89698
|
+
}
|
|
89699
|
+
if (loopCheck.waitMs !== undefined && loopCheck.waitMs > 0) {
|
|
89700
|
+
console.log(` ⏳ Agent restart backoff: waiting ${loopCheck.waitMs}ms before retry`);
|
|
89701
|
+
this.resetSlotIdle(slot);
|
|
89702
|
+
return { success: false, error: "backoff" };
|
|
89703
|
+
}
|
|
89704
|
+
this.deps.backend.mutation(api.machines.emitRestartLimitReached, {
|
|
89705
|
+
sessionId: this.deps.sessionId,
|
|
89706
|
+
machineId: this.deps.machineId,
|
|
89707
|
+
chatroomId: opts.chatroomId,
|
|
89708
|
+
role: opts.role,
|
|
89709
|
+
restartCount: loopCheck.restartCount,
|
|
89710
|
+
windowMs: loopCheck.windowMs
|
|
89711
|
+
}).catch((err) => {
|
|
89712
|
+
console.log(` ⚠️ Failed to emit restartLimitReached event: ${err.message}`);
|
|
89713
|
+
});
|
|
89714
|
+
this.resetSlotIdle(slot);
|
|
89715
|
+
return { success: false, error: "crash_loop" };
|
|
89716
|
+
}
|
|
89717
|
+
async validateWorkingDirGate(opts, slot) {
|
|
88657
89718
|
try {
|
|
88658
|
-
const
|
|
88659
|
-
|
|
89719
|
+
const dirStat = await this.deps.fs.stat(opts.workingDir);
|
|
89720
|
+
if (!dirStat.isDirectory()) {
|
|
89721
|
+
this.resetSlotIdle(slot);
|
|
89722
|
+
return {
|
|
89723
|
+
success: false,
|
|
89724
|
+
error: `Working directory is not a directory: ${opts.workingDir}`
|
|
89725
|
+
};
|
|
89726
|
+
}
|
|
89727
|
+
} catch {
|
|
89728
|
+
this.resetSlotIdle(slot);
|
|
89729
|
+
return { success: false, error: `Working directory does not exist: ${opts.workingDir}` };
|
|
89730
|
+
}
|
|
89731
|
+
return null;
|
|
89732
|
+
}
|
|
89733
|
+
async fetchInitPromptResult(opts, slot) {
|
|
89734
|
+
let initPromptResult;
|
|
89735
|
+
try {
|
|
89736
|
+
initPromptResult = await this.deps.backend.query(api.messages.getInitPrompt, {
|
|
89737
|
+
sessionId: this.deps.sessionId,
|
|
89738
|
+
chatroomId: opts.chatroomId,
|
|
89739
|
+
role: opts.role,
|
|
89740
|
+
convexUrl: this.deps.convexUrl
|
|
88660
89741
|
});
|
|
88661
|
-
|
|
88662
|
-
|
|
88663
|
-
|
|
88664
|
-
|
|
88665
|
-
|
|
88666
|
-
|
|
88667
|
-
|
|
88668
|
-
|
|
88669
|
-
|
|
88670
|
-
|
|
88671
|
-
|
|
88672
|
-
|
|
88673
|
-
|
|
88674
|
-
|
|
88675
|
-
|
|
88676
|
-
|
|
89742
|
+
} catch (e) {
|
|
89743
|
+
this.resetSlotIdle(slot);
|
|
89744
|
+
return {
|
|
89745
|
+
ok: false,
|
|
89746
|
+
result: { success: false, error: `Failed to fetch init prompt: ${e.message}` }
|
|
89747
|
+
};
|
|
89748
|
+
}
|
|
89749
|
+
if (!initPromptResult?.prompt) {
|
|
89750
|
+
this.resetSlotIdle(slot);
|
|
89751
|
+
return {
|
|
89752
|
+
ok: false,
|
|
89753
|
+
result: { success: false, error: "Failed to fetch init prompt from backend" }
|
|
89754
|
+
};
|
|
89755
|
+
}
|
|
89756
|
+
return {
|
|
89757
|
+
ok: true,
|
|
89758
|
+
initialMessage: initPromptResult.initialMessage,
|
|
89759
|
+
rolePrompt: initPromptResult.rolePrompt
|
|
89760
|
+
};
|
|
89761
|
+
}
|
|
89762
|
+
async spawnAgentForEnsureRunning(key, slot, opts, initPrompt, wantResume) {
|
|
89763
|
+
const service3 = this.deps.agentServices.get(opts.agentHarness);
|
|
89764
|
+
if (!service3) {
|
|
89765
|
+
this.resetSlotIdle(slot);
|
|
89766
|
+
return {
|
|
89767
|
+
ok: false,
|
|
89768
|
+
result: { success: false, error: `Unknown agent harness: ${opts.agentHarness}` }
|
|
89769
|
+
};
|
|
89770
|
+
}
|
|
89771
|
+
let spawnResult;
|
|
89772
|
+
const resumePath = decideResumePathOnRestart({
|
|
89773
|
+
supportsSessionResume: getHarnessCapabilities(opts.agentHarness).supportsSessionResume,
|
|
89774
|
+
wantResume,
|
|
89775
|
+
hasStoredSnapshot: this.lastHarnessSessions.has(key)
|
|
89776
|
+
});
|
|
89777
|
+
if (resumePath === "daemon_memory") {
|
|
89778
|
+
spawnResult = await this.tryDaemonMemoryResume({
|
|
89779
|
+
key,
|
|
89780
|
+
chatroomId: opts.chatroomId,
|
|
89781
|
+
role: opts.role,
|
|
89782
|
+
agentHarness: opts.agentHarness,
|
|
89783
|
+
workingDir: opts.workingDir,
|
|
89784
|
+
model: opts.model,
|
|
89785
|
+
initPrompt: initPrompt.initialMessage,
|
|
89786
|
+
systemPrompt: initPrompt.rolePrompt,
|
|
89787
|
+
service: service3
|
|
89788
|
+
}) ?? undefined;
|
|
89789
|
+
}
|
|
89790
|
+
if (!spawnResult) {
|
|
89791
|
+
try {
|
|
89792
|
+
spawnResult = await service3.spawn({
|
|
89793
|
+
workingDir: opts.workingDir,
|
|
89794
|
+
prompt: createSpawnPrompt(initPrompt.initialMessage),
|
|
89795
|
+
systemPrompt: initPrompt.rolePrompt,
|
|
89796
|
+
model: opts.model,
|
|
89797
|
+
context: {
|
|
88677
89798
|
machineId: this.deps.machineId,
|
|
88678
89799
|
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
|
|
89800
|
+
role: opts.role
|
|
89801
|
+
}
|
|
88712
89802
|
});
|
|
88713
89803
|
} 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}` };
|
|
89804
|
+
this.resetSlotIdle(slot);
|
|
89805
|
+
return {
|
|
89806
|
+
ok: false,
|
|
89807
|
+
result: { success: false, error: `Failed to spawn agent: ${e.message}` }
|
|
89808
|
+
};
|
|
88728
89809
|
}
|
|
88729
|
-
|
|
88730
|
-
|
|
88731
|
-
|
|
88732
|
-
|
|
88733
|
-
|
|
89810
|
+
}
|
|
89811
|
+
return { ok: true, spawnResult };
|
|
89812
|
+
}
|
|
89813
|
+
assignRunningSlotState(key, slot, opts, spawnResult, wantResume, pid) {
|
|
89814
|
+
slot.state = "running";
|
|
89815
|
+
slot.pid = pid;
|
|
89816
|
+
slot.harness = opts.agentHarness;
|
|
89817
|
+
slot.harnessSessionId = spawnResult.harnessSessionId;
|
|
89818
|
+
if (spawnResult.harnessSessionId) {
|
|
89819
|
+
this.recordLastHarnessSession(key, {
|
|
89820
|
+
harnessSessionId: spawnResult.harnessSessionId,
|
|
89821
|
+
harness: opts.agentHarness,
|
|
89822
|
+
agentName: spawnResult.harnessReconnect?.agentName ?? "",
|
|
89823
|
+
workingDir: opts.workingDir,
|
|
89824
|
+
model: opts.model ?? spawnResult.harnessReconnect?.model
|
|
88734
89825
|
});
|
|
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,
|
|
89826
|
+
}
|
|
89827
|
+
slot.model = opts.model;
|
|
89828
|
+
slot.wantResume = wantResume;
|
|
89829
|
+
slot.workingDir = opts.workingDir;
|
|
89830
|
+
slot.startedAt = this.deps.clock.now();
|
|
89831
|
+
slot.pendingOperation = undefined;
|
|
89832
|
+
slot.recentLogLines = [];
|
|
89833
|
+
this.deps.resumeStormTracker.reset(opts.chatroomId, opts.role);
|
|
89834
|
+
}
|
|
89835
|
+
emitSpawnedAgentUpdate(opts, spawnResult, pid) {
|
|
89836
|
+
this.deps.backend.mutation(api.machines.updateSpawnedAgent, {
|
|
89837
|
+
sessionId: this.deps.sessionId,
|
|
89838
|
+
machineId: this.deps.machineId,
|
|
89839
|
+
chatroomId: opts.chatroomId,
|
|
89840
|
+
role: opts.role,
|
|
89841
|
+
pid,
|
|
89842
|
+
model: opts.model,
|
|
89843
|
+
reason: opts.reason,
|
|
89844
|
+
...spawnResult.harnessSessionId ? { harnessSessionId: spawnResult.harnessSessionId } : {}
|
|
89845
|
+
}).catch((err) => {
|
|
89846
|
+
console.log(` ⚠️ Failed to update PID in backend: ${err.message}`);
|
|
89847
|
+
});
|
|
89848
|
+
}
|
|
89849
|
+
registerSpawnCallbacks(slot, opts, spawnResult, pid) {
|
|
89850
|
+
if (spawnResult.onLogLine) {
|
|
89851
|
+
spawnResult.onLogLine((line) => appendRecentLogLine(slot, line));
|
|
89852
|
+
}
|
|
89853
|
+
spawnResult.onExit(({ code: code2, signal }) => {
|
|
89854
|
+
this.handleExit({
|
|
88795
89855
|
chatroomId: opts.chatroomId,
|
|
88796
89856
|
role: opts.role,
|
|
88797
89857
|
pid,
|
|
88798
|
-
|
|
88799
|
-
|
|
88800
|
-
...spawnResult.harnessSessionId ? { harnessSessionId: spawnResult.harnessSessionId } : {}
|
|
88801
|
-
}).catch((err) => {
|
|
88802
|
-
console.log(` ⚠️ Failed to update PID in backend: ${err.message}`);
|
|
89858
|
+
code: code2,
|
|
89859
|
+
signal
|
|
88803
89860
|
});
|
|
88804
|
-
|
|
88805
|
-
|
|
88806
|
-
|
|
88807
|
-
|
|
88808
|
-
this.handleExit({
|
|
89861
|
+
});
|
|
89862
|
+
if (spawnResult.onAgentEnd) {
|
|
89863
|
+
spawnResult.onAgentEnd(() => {
|
|
89864
|
+
this.turnEndQueue.enqueue(() => this.runHandleAgentEnd({
|
|
88809
89865
|
chatroomId: opts.chatroomId,
|
|
88810
89866
|
role: opts.role,
|
|
88811
89867
|
pid,
|
|
88812
|
-
|
|
88813
|
-
|
|
88814
|
-
});
|
|
89868
|
+
harness: opts.agentHarness
|
|
89869
|
+
}));
|
|
88815
89870
|
});
|
|
88816
|
-
|
|
88817
|
-
|
|
88818
|
-
|
|
88819
|
-
|
|
88820
|
-
|
|
88821
|
-
|
|
88822
|
-
|
|
88823
|
-
|
|
88824
|
-
|
|
89871
|
+
}
|
|
89872
|
+
let lastReportedTokenAt = 0;
|
|
89873
|
+
spawnResult.onOutput(() => {
|
|
89874
|
+
const now = this.deps.clock.now();
|
|
89875
|
+
if (now - lastReportedTokenAt >= 30000) {
|
|
89876
|
+
lastReportedTokenAt = now;
|
|
89877
|
+
this.deps.backend.mutation(api.participants.updateTokenActivity, {
|
|
89878
|
+
sessionId: this.deps.sessionId,
|
|
89879
|
+
chatroomId: opts.chatroomId,
|
|
89880
|
+
role: opts.role
|
|
89881
|
+
}).catch(() => {});
|
|
88825
89882
|
}
|
|
88826
|
-
|
|
88827
|
-
|
|
88828
|
-
|
|
88829
|
-
|
|
88830
|
-
|
|
88831
|
-
|
|
88832
|
-
|
|
88833
|
-
|
|
88834
|
-
|
|
88835
|
-
|
|
88836
|
-
|
|
88837
|
-
|
|
88838
|
-
|
|
89883
|
+
});
|
|
89884
|
+
}
|
|
89885
|
+
async finalizeRunningSlot(key, slot, opts, spawnResult, wantResume) {
|
|
89886
|
+
const { pid } = spawnResult;
|
|
89887
|
+
this.deps.spawning.recordSpawn(opts.chatroomId);
|
|
89888
|
+
this.assignRunningSlotState(key, slot, opts, spawnResult, wantResume, pid);
|
|
89889
|
+
this.emitSpawnedAgentUpdate(opts, spawnResult, pid);
|
|
89890
|
+
try {
|
|
89891
|
+
await this.deps.persistence.persistAgentPid(this.deps.machineId, opts.chatroomId, opts.role, pid, opts.agentHarness);
|
|
89892
|
+
} catch {}
|
|
89893
|
+
this.registerSpawnCallbacks(slot, opts, spawnResult, pid);
|
|
89894
|
+
}
|
|
89895
|
+
async doEnsureRunning(key, slot, opts) {
|
|
89896
|
+
slot.state = "spawning";
|
|
89897
|
+
const wantResume = opts.wantResume;
|
|
89898
|
+
console.log(`[AgentProcessManager] harness start: role=${opts.role} harness=${opts.agentHarness} wantResume=${wantResume} reason=${opts.reason}`);
|
|
89899
|
+
try {
|
|
89900
|
+
const rateLimit = this.checkRateLimitGate(opts, slot);
|
|
89901
|
+
if (rateLimit)
|
|
89902
|
+
return rateLimit;
|
|
89903
|
+
const crashLoop = this.checkCrashLoopGate(opts, slot);
|
|
89904
|
+
if (crashLoop)
|
|
89905
|
+
return crashLoop;
|
|
89906
|
+
const workingDir = await this.validateWorkingDirGate(opts, slot);
|
|
89907
|
+
if (workingDir)
|
|
89908
|
+
return workingDir;
|
|
89909
|
+
const initPrompt = await this.fetchInitPromptResult(opts, slot);
|
|
89910
|
+
if (!initPrompt.ok)
|
|
89911
|
+
return initPrompt.result;
|
|
89912
|
+
const spawn5 = await this.spawnAgentForEnsureRunning(key, slot, opts, initPrompt, wantResume);
|
|
89913
|
+
if (!spawn5.ok)
|
|
89914
|
+
return spawn5.result;
|
|
89915
|
+
await this.finalizeRunningSlot(key, slot, opts, spawn5.spawnResult, wantResume);
|
|
89916
|
+
return { success: true, pid: spawn5.spawnResult.pid };
|
|
88839
89917
|
} catch (e) {
|
|
88840
|
-
slot
|
|
88841
|
-
slot.pendingOperation = undefined;
|
|
89918
|
+
this.resetSlotIdle(slot);
|
|
88842
89919
|
return { success: false, error: `Unexpected error: ${e.message}` };
|
|
88843
89920
|
}
|
|
88844
89921
|
}
|
|
@@ -88851,64 +89928,75 @@ class AgentProcessManager {
|
|
|
88851
89928
|
readHarnessReconnectMetadata(service3, pid) {
|
|
88852
89929
|
return service3.getHarnessReconnectContext?.(pid);
|
|
88853
89930
|
}
|
|
88854
|
-
|
|
88855
|
-
|
|
88856
|
-
|
|
88857
|
-
|
|
88858
|
-
|
|
88859
|
-
|
|
88860
|
-
|
|
88861
|
-
|
|
88862
|
-
|
|
88863
|
-
|
|
88864
|
-
|
|
88865
|
-
|
|
88866
|
-
|
|
88867
|
-
|
|
88868
|
-
|
|
88869
|
-
|
|
88870
|
-
|
|
88871
|
-
|
|
88872
|
-
|
|
88873
|
-
|
|
89931
|
+
shouldPreserveHarnessOnStop(slot, opts) {
|
|
89932
|
+
const harness = slot.harness;
|
|
89933
|
+
const supportsResume = harness ? getHarnessCapabilities(harness).supportsSessionResume : false;
|
|
89934
|
+
return shouldPreserveHarnessTeardown(opts.reason, supportsResume, Boolean(slot.harnessSessionId));
|
|
89935
|
+
}
|
|
89936
|
+
recordHarnessSessionOnStop(key, slot, pid, service3) {
|
|
89937
|
+
const harness = slot.harness;
|
|
89938
|
+
const harnessMeta = service3 ? this.readHarnessReconnectMetadata(service3, pid) : undefined;
|
|
89939
|
+
this.recordLastHarnessSession(key, {
|
|
89940
|
+
harnessSessionId: slot.harnessSessionId,
|
|
89941
|
+
harness,
|
|
89942
|
+
agentName: harnessMeta?.agentName ?? "",
|
|
89943
|
+
workingDir: slot.workingDir ?? "",
|
|
89944
|
+
model: slot.model ?? harnessMeta?.model
|
|
89945
|
+
});
|
|
89946
|
+
}
|
|
89947
|
+
updateHarnessSessionOnStop(key, slot, pid, service3, preserveForResume) {
|
|
89948
|
+
const harness = slot.harness;
|
|
89949
|
+
if (harness && slot.harnessSessionId) {
|
|
89950
|
+
if (preserveForResume) {
|
|
89951
|
+
this.recordHarnessSessionOnStop(key, slot, pid, service3);
|
|
89952
|
+
} else {
|
|
88874
89953
|
this.clearLastHarnessSession(key);
|
|
88875
89954
|
}
|
|
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
|
-
|
|
89955
|
+
return;
|
|
89956
|
+
}
|
|
89957
|
+
if (!preserveForResume) {
|
|
89958
|
+
this.clearLastHarnessSession(key);
|
|
89959
|
+
}
|
|
89960
|
+
}
|
|
89961
|
+
preserveOrClearHarnessSessionOnStop(key, slot, pid, opts, service3) {
|
|
89962
|
+
const preserveForResume = this.shouldPreserveHarnessOnStop(slot, opts);
|
|
89963
|
+
this.updateHarnessSessionOnStop(key, slot, pid, service3, preserveForResume);
|
|
89964
|
+
return preserveForResume;
|
|
89965
|
+
}
|
|
89966
|
+
async killProcessWithFallback(pid) {
|
|
89967
|
+
try {
|
|
89968
|
+
this.deps.processes.kill(-pid, "SIGTERM");
|
|
89969
|
+
} catch {}
|
|
89970
|
+
let dead = false;
|
|
89971
|
+
for (let i2 = 0;i2 < 20; i2++) {
|
|
89972
|
+
await this.deps.clock.delay(500);
|
|
89973
|
+
if (!isProcessAlive(this.deps.processes.kill, pid)) {
|
|
89974
|
+
dead = true;
|
|
89975
|
+
break;
|
|
89976
|
+
}
|
|
89977
|
+
}
|
|
89978
|
+
if (!dead) {
|
|
89979
|
+
try {
|
|
89980
|
+
this.deps.processes.kill(-pid, "SIGKILL");
|
|
89981
|
+
} catch {}
|
|
89982
|
+
for (let i2 = 0;i2 < 10; i2++) {
|
|
89983
|
+
await this.deps.clock.delay(500);
|
|
89984
|
+
if (!isProcessAlive(this.deps.processes.kill, pid)) {
|
|
89985
|
+
break;
|
|
88905
89986
|
}
|
|
88906
89987
|
}
|
|
88907
|
-
}
|
|
89988
|
+
}
|
|
89989
|
+
for (const svc of this.deps.agentServices.values()) {
|
|
89990
|
+
svc.untrack(pid);
|
|
89991
|
+
}
|
|
89992
|
+
}
|
|
89993
|
+
resetSlotAfterStop(slot) {
|
|
88908
89994
|
slot.state = "idle";
|
|
88909
89995
|
slot.pid = undefined;
|
|
88910
89996
|
slot.startedAt = undefined;
|
|
88911
89997
|
slot.pendingOperation = undefined;
|
|
89998
|
+
}
|
|
89999
|
+
recordStopExit(slot, pid, opts) {
|
|
88912
90000
|
const exitArgs3 = {
|
|
88913
90001
|
sessionId: this.deps.sessionId,
|
|
88914
90002
|
machineId: this.deps.machineId,
|
|
@@ -88924,6 +90012,21 @@ class AgentProcessManager {
|
|
|
88924
90012
|
console.log(` ⚠️ Failed to record agent exit event: ${err.message}`);
|
|
88925
90013
|
this.queueExitRetry({ role: opts.role, args: exitArgs3 });
|
|
88926
90014
|
});
|
|
90015
|
+
}
|
|
90016
|
+
async doStop(key, slot, pid, opts) {
|
|
90017
|
+
try {
|
|
90018
|
+
const harness = slot.harness;
|
|
90019
|
+
const service3 = harness ? this.deps.agentServices.get(harness) : undefined;
|
|
90020
|
+
const preserveForResume = this.preserveOrClearHarnessSessionOnStop(key, slot, pid, opts, service3);
|
|
90021
|
+
if (service3) {
|
|
90022
|
+
await service3.stop(pid, { preserveForResume });
|
|
90023
|
+
service3.untrack(pid);
|
|
90024
|
+
} else {
|
|
90025
|
+
await this.killProcessWithFallback(pid);
|
|
90026
|
+
}
|
|
90027
|
+
} catch {}
|
|
90028
|
+
this.resetSlotAfterStop(slot);
|
|
90029
|
+
this.recordStopExit(slot, pid, opts);
|
|
88927
90030
|
try {
|
|
88928
90031
|
await this.deps.persistence.clearAgentPid(this.deps.machineId, opts.chatroomId, opts.role);
|
|
88929
90032
|
} catch {}
|
|
@@ -88934,12 +90037,15 @@ var AGENT_EXIT_RETRY_INTERVAL_MS = 1e4;
|
|
|
88934
90037
|
var init_agent_process_manager = __esm(() => {
|
|
88935
90038
|
init_generator();
|
|
88936
90039
|
init_types();
|
|
90040
|
+
init_esm();
|
|
88937
90041
|
init_turn_completed_backend();
|
|
88938
90042
|
init_api3();
|
|
88939
90043
|
init_orphan_tracker();
|
|
88940
90044
|
init_agent_lifecycle();
|
|
88941
90045
|
init_classify_resume_storm_reason();
|
|
88942
90046
|
init_handle_turn_completed();
|
|
90047
|
+
init_agent_lifecycle_runtime();
|
|
90048
|
+
init_agent_lifecycle_types();
|
|
88943
90049
|
});
|
|
88944
90050
|
|
|
88945
90051
|
// src/infrastructure/services/harness-spawning/rate-limiter.ts
|
|
@@ -89505,6 +90611,7 @@ var init_models_refresh = __esm(() => {
|
|
|
89505
90611
|
var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(function* () {
|
|
89506
90612
|
const session2 = yield* DaemonSessionService;
|
|
89507
90613
|
const effectContext2 = yield* exports_Effect.context();
|
|
90614
|
+
const runtime4 = yield* exports_Effect.runtime();
|
|
89508
90615
|
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Starting observed-sync subscription (reactive)`);
|
|
89509
90616
|
const observedWorkingDirs = new Map;
|
|
89510
90617
|
const chatroomRefreshState = new Map;
|
|
@@ -89560,7 +90667,7 @@ var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(func
|
|
|
89560
90667
|
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed-sync subscription stopped`);
|
|
89561
90668
|
}
|
|
89562
90669
|
};
|
|
89563
|
-
function
|
|
90670
|
+
function collectWorkingDirChanges(observed) {
|
|
89564
90671
|
const newWorkingDirs = new Set;
|
|
89565
90672
|
const refreshedWorkingDirs = new Set;
|
|
89566
90673
|
for (const chatroom of observed) {
|
|
@@ -89578,55 +90685,77 @@ var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(func
|
|
|
89578
90685
|
newWorkingDirs.add(wd);
|
|
89579
90686
|
}
|
|
89580
90687
|
}
|
|
90688
|
+
return { newWorkingDirs, refreshedWorkingDirs };
|
|
90689
|
+
}
|
|
90690
|
+
function pruneStaleChatroomRefreshState(observed) {
|
|
89581
90691
|
for (const [chatroomId] of chatroomRefreshState) {
|
|
89582
90692
|
const stillObserved = observed.some((c) => c.chatroomId === chatroomId);
|
|
89583
90693
|
if (!stillObserved) {
|
|
89584
90694
|
chatroomRefreshState.delete(chatroomId);
|
|
89585
90695
|
}
|
|
89586
90696
|
}
|
|
90697
|
+
}
|
|
90698
|
+
function removeUnobservedWorkingDirs(newWorkingDirs) {
|
|
89587
90699
|
const currentWorkingDirs = new Set(observedWorkingDirs.keys());
|
|
89588
|
-
let addedCount = 0;
|
|
89589
90700
|
let removedCount = 0;
|
|
89590
90701
|
for (const wd of currentWorkingDirs) {
|
|
89591
|
-
if (
|
|
89592
|
-
|
|
89593
|
-
if (state) {
|
|
89594
|
-
clearInterval(state.intervalHandle);
|
|
89595
|
-
observedWorkingDirs.delete(wd);
|
|
89596
|
-
const skips = skippedPushCount.get(wd) ?? 0;
|
|
89597
|
-
if (skips > 0) {
|
|
89598
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Stopped observing ${wd} (skipped ${skips} overlapping pushes)`);
|
|
89599
|
-
} else {
|
|
89600
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Stopped observing ${wd}`);
|
|
89601
|
-
}
|
|
89602
|
-
skippedPushCount.delete(wd);
|
|
89603
|
-
pendingRefresh.delete(wd);
|
|
89604
|
-
removedCount++;
|
|
89605
|
-
}
|
|
90702
|
+
if (newWorkingDirs.has(wd)) {
|
|
90703
|
+
continue;
|
|
89606
90704
|
}
|
|
90705
|
+
const state = observedWorkingDirs.get(wd);
|
|
90706
|
+
if (!state) {
|
|
90707
|
+
continue;
|
|
90708
|
+
}
|
|
90709
|
+
clearInterval(state.intervalHandle);
|
|
90710
|
+
observedWorkingDirs.delete(wd);
|
|
90711
|
+
const skips = skippedPushCount.get(wd) ?? 0;
|
|
90712
|
+
if (skips > 0) {
|
|
90713
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Stopped observing ${wd} (skipped ${skips} overlapping pushes)`);
|
|
90714
|
+
} else {
|
|
90715
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Stopped observing ${wd}`);
|
|
90716
|
+
}
|
|
90717
|
+
skippedPushCount.delete(wd);
|
|
90718
|
+
pendingRefresh.delete(wd);
|
|
90719
|
+
removedCount++;
|
|
89607
90720
|
}
|
|
90721
|
+
return removedCount;
|
|
90722
|
+
}
|
|
90723
|
+
function addNewlyObservedWorkingDirs(newWorkingDirs) {
|
|
90724
|
+
let addedCount = 0;
|
|
89608
90725
|
for (const wd of newWorkingDirs) {
|
|
90726
|
+
if (observedWorkingDirs.has(wd)) {
|
|
90727
|
+
continue;
|
|
90728
|
+
}
|
|
90729
|
+
observedWorkingDirs.set(wd, {
|
|
90730
|
+
intervalHandle: setInterval(() => {
|
|
90731
|
+
schedulePushForWorkingDir(wd, "safety-poll");
|
|
90732
|
+
}, OBSERVED_SAFETY_POLL_MS),
|
|
90733
|
+
pushInFlight: false
|
|
90734
|
+
});
|
|
90735
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Started observing ${wd}`);
|
|
90736
|
+
schedulePushForWorkingDir(wd, "safety-poll");
|
|
90737
|
+
addedCount++;
|
|
90738
|
+
}
|
|
90739
|
+
return addedCount;
|
|
90740
|
+
}
|
|
90741
|
+
function triggerRefreshedWorkingDirs(refreshedWorkingDirs) {
|
|
90742
|
+
for (const wd of refreshedWorkingDirs) {
|
|
89609
90743
|
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++;
|
|
90744
|
+
continue;
|
|
89619
90745
|
}
|
|
90746
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD04 Refresh triggered for ${wd}`);
|
|
90747
|
+
schedulePushForWorkingDir(wd, "refresh");
|
|
89620
90748
|
}
|
|
90749
|
+
}
|
|
90750
|
+
function handleObservedChange(observed) {
|
|
90751
|
+
const { newWorkingDirs, refreshedWorkingDirs } = collectWorkingDirChanges(observed);
|
|
90752
|
+
pruneStaleChatroomRefreshState(observed);
|
|
90753
|
+
const removedCount = removeUnobservedWorkingDirs(newWorkingDirs);
|
|
90754
|
+
const addedCount = addNewlyObservedWorkingDirs(newWorkingDirs);
|
|
89621
90755
|
if (addedCount > 0 || removedCount > 0) {
|
|
89622
90756
|
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observing ${observedWorkingDirs.size} working dir(s)`);
|
|
89623
90757
|
}
|
|
89624
|
-
|
|
89625
|
-
if (observedWorkingDirs.has(wd)) {
|
|
89626
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDD04 Refresh triggered for ${wd}`);
|
|
89627
|
-
schedulePushForWorkingDir(wd, "refresh");
|
|
89628
|
-
}
|
|
89629
|
-
}
|
|
90758
|
+
triggerRefreshedWorkingDirs(refreshedWorkingDirs);
|
|
89630
90759
|
}
|
|
89631
90760
|
function schedulePushForWorkingDir(workingDir, reason = "safety-poll") {
|
|
89632
90761
|
if (stopped)
|
|
@@ -89644,9 +90773,13 @@ var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(func
|
|
|
89644
90773
|
return;
|
|
89645
90774
|
}
|
|
89646
90775
|
state.pushInFlight = true;
|
|
89647
|
-
pushForWorkingDir(workingDir, reason)
|
|
89648
|
-
|
|
89649
|
-
|
|
90776
|
+
pushForWorkingDir(workingDir, reason);
|
|
90777
|
+
}
|
|
90778
|
+
function pushForWorkingDir(workingDir, reason = "safety-poll") {
|
|
90779
|
+
exports_Runtime.runFork(runtime4)(exports_Effect.all([
|
|
90780
|
+
pushSingleWorkspaceGitSummaryForObservedEffect(workingDir, reason),
|
|
90781
|
+
pushSingleWorkspaceCommandsEffect(workingDir)
|
|
90782
|
+
], { 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
90783
|
const s = observedWorkingDirs.get(workingDir);
|
|
89651
90784
|
if (s) {
|
|
89652
90785
|
s.pushInFlight = false;
|
|
@@ -89655,15 +90788,7 @@ var startObservedSyncSubscriptionEffect = (wsClient2) => exports_Effect.gen(func
|
|
|
89655
90788
|
schedulePushForWorkingDir(workingDir, "refresh");
|
|
89656
90789
|
}
|
|
89657
90790
|
}
|
|
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
|
-
});
|
|
90791
|
+
}))));
|
|
89667
90792
|
}
|
|
89668
90793
|
});
|
|
89669
90794
|
var init_observed_sync = __esm(() => {
|
|
@@ -89736,36 +90861,21 @@ var init_workspace_list_subscription = __esm(() => {
|
|
|
89736
90861
|
});
|
|
89737
90862
|
|
|
89738
90863
|
// src/commands/machine/daemon-start/command-loop.ts
|
|
89739
|
-
function
|
|
89740
|
-
const
|
|
89741
|
-
for (const [id3, ts] of tracker.commandIds) {
|
|
90864
|
+
function evictStaleEntries(entries2, evictBefore) {
|
|
90865
|
+
for (const [id3, ts] of entries2) {
|
|
89742
90866
|
if (ts < evictBefore)
|
|
89743
|
-
|
|
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) {
|
|
89754
|
-
if (ts < evictBefore)
|
|
89755
|
-
tracker.capabilitiesRefreshIds.delete(id3);
|
|
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);
|
|
90867
|
+
entries2.delete(id3);
|
|
89768
90868
|
}
|
|
90869
|
+
}
|
|
90870
|
+
function evictStaleDedupEntries(tracker) {
|
|
90871
|
+
const evictBefore = Date.now() - AGENT_REQUEST_DEADLINE_MS;
|
|
90872
|
+
evictStaleEntries(tracker.commandIds, evictBefore);
|
|
90873
|
+
evictStaleEntries(tracker.pingIds, evictBefore);
|
|
90874
|
+
evictStaleEntries(tracker.gitRefreshIds, evictBefore);
|
|
90875
|
+
evictStaleEntries(tracker.capabilitiesRefreshIds, evictBefore);
|
|
90876
|
+
evictStaleEntries(tracker.localActionIds, evictBefore);
|
|
90877
|
+
evictStaleEntries(tracker.commandRunIds, evictBefore);
|
|
90878
|
+
evictStaleEntries(tracker.commandStopIds, evictBefore);
|
|
89769
90879
|
processManager.evictStalePendingStops();
|
|
89770
90880
|
}
|
|
89771
90881
|
function handleRequestStartEffect(event, tracker) {
|
|
@@ -89936,6 +91046,7 @@ var init_command_loop = __esm(() => {
|
|
|
89936
91046
|
startCommandLoopEffect = exports_Effect.gen(function* () {
|
|
89937
91047
|
const session2 = yield* DaemonSessionService;
|
|
89938
91048
|
const effectContext2 = yield* exports_Effect.context();
|
|
91049
|
+
const runtime4 = yield* exports_Effect.runtime();
|
|
89939
91050
|
const observedSyncEnabled = featureFlags.observedSyncEnabled ?? false;
|
|
89940
91051
|
let heartbeatCount = 0;
|
|
89941
91052
|
const heartbeatTimer = setInterval(() => {
|
|
@@ -89946,15 +91057,9 @@ var init_command_loop = __esm(() => {
|
|
|
89946
91057
|
heartbeatCount++;
|
|
89947
91058
|
console.log(`[${formatTimestamp()}] \uD83D\uDC93 Daemon heartbeat #${heartbeatCount} OK`);
|
|
89948
91059
|
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
|
-
});
|
|
91060
|
+
exports_Runtime.runFork(runtime4)(exports_Effect.all([pushGitStateEffect, pushCommandsEffect, syncCommitDetailsEffect()], {
|
|
91061
|
+
concurrency: "unbounded"
|
|
91062
|
+
}).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[${formatTimestamp()}] ⚠️ Heartbeat sync failed: ${getErrorMessage(err)}`)))));
|
|
89958
91063
|
}
|
|
89959
91064
|
}).catch((err) => {
|
|
89960
91065
|
console.warn(`[${formatTimestamp()}] ⚠️ Daemon heartbeat failed: ${getErrorMessage(err)}`);
|
|
@@ -89976,9 +91081,9 @@ var init_command_loop = __esm(() => {
|
|
|
89976
91081
|
if (observedSyncEnabled) {
|
|
89977
91082
|
console.log(`[${formatTimestamp()}] \uD83D\uDC41️ Observed-sync enabled, skipping immediate push`);
|
|
89978
91083
|
} else {
|
|
89979
|
-
|
|
89980
|
-
|
|
89981
|
-
|
|
91084
|
+
exports_Runtime.runFork(runtime4)(exports_Effect.all([pushGitStateEffect, pushCommandsEffect, syncCommitDetailsEffect()], {
|
|
91085
|
+
concurrency: "unbounded"
|
|
91086
|
+
}).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[${formatTimestamp()}] ⚠️ Startup sync failed: ${getErrorMessage(err)}`)))));
|
|
89982
91087
|
}
|
|
89983
91088
|
const PROCESS_KILL_TIMEOUT_MS = 6000;
|
|
89984
91089
|
const CLOSE_TIMEOUT_MS = 3000;
|
|
@@ -90011,43 +91116,46 @@ var init_command_loop = __esm(() => {
|
|
|
90011
91116
|
return;
|
|
90012
91117
|
isShuttingDown = true;
|
|
90013
91118
|
console.log(`
|
|
90014
|
-
[${formatTimestamp()}] Shutting down... (press Ctrl+
|
|
91119
|
+
[${formatTimestamp()}] Shutting down... (press Ctrl+B again to force)`);
|
|
91120
|
+
const watchdog = setupShutdownWatchdog();
|
|
91121
|
+
clearInterval(heartbeatTimer);
|
|
91122
|
+
stopSubscriptions();
|
|
91123
|
+
await runDaemonShutdownEffect();
|
|
91124
|
+
await closeAllSessionsAndHarnesses();
|
|
91125
|
+
clearTimeout(watchdog);
|
|
91126
|
+
releaseLock();
|
|
91127
|
+
process.exit(0);
|
|
91128
|
+
};
|
|
91129
|
+
const setupShutdownWatchdog = () => {
|
|
90015
91130
|
const watchdog = setTimeout(() => {
|
|
90016
91131
|
console.error(`[${formatTimestamp()}] Shutdown timed out — forcing exit.`);
|
|
90017
91132
|
forceExit(1);
|
|
90018
91133
|
}, SHUTDOWN_WATCHDOG_MS);
|
|
90019
91134
|
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();
|
|
91135
|
+
return watchdog;
|
|
91136
|
+
};
|
|
91137
|
+
const stopSubscriptions = () => {
|
|
91138
|
+
gitSubscriptionHandle?.stop();
|
|
91139
|
+
fileContentSubscriptionHandle?.stop();
|
|
91140
|
+
fileTreeSubscriptionHandle?.stop();
|
|
91141
|
+
workspaceListSubscriptionHandle?.stop();
|
|
91142
|
+
observedSyncSubscriptionHandle?.stop();
|
|
91143
|
+
logObserverSubscriptionHandle?.stop();
|
|
91144
|
+
pendingPromptSubscriptionHandle?.stop();
|
|
91145
|
+
pendingHarnessSessionSubscriptionHandle?.stop();
|
|
91146
|
+
commandSubscriptionHandle?.stop();
|
|
91147
|
+
lifecycleManager?.stopMonitoring();
|
|
91148
|
+
};
|
|
91149
|
+
const runDaemonShutdownEffect = async () => {
|
|
90041
91150
|
await withTimeout3(exports_Effect.runPromise(onDaemonShutdownEffect.pipe(exports_Effect.provide(effectContext2))), PROCESS_KILL_TIMEOUT_MS);
|
|
91151
|
+
};
|
|
91152
|
+
const closeAllSessionsAndHarnesses = async () => {
|
|
90042
91153
|
for (const handle of activeSessions.values()) {
|
|
90043
91154
|
await withTimeout3(handle.close(), CLOSE_TIMEOUT_MS);
|
|
90044
91155
|
}
|
|
90045
91156
|
for (const harness of harnesses.values()) {
|
|
90046
91157
|
await withTimeout3(harness.close(), CLOSE_TIMEOUT_MS);
|
|
90047
91158
|
}
|
|
90048
|
-
clearTimeout(watchdog);
|
|
90049
|
-
releaseLock();
|
|
90050
|
-
process.exit(0);
|
|
90051
91159
|
};
|
|
90052
91160
|
const handleSignal = (signal) => {
|
|
90053
91161
|
signalCount += 1;
|
|
@@ -91316,4 +92424,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
91316
92424
|
});
|
|
91317
92425
|
program2.parse();
|
|
91318
92426
|
|
|
91319
|
-
//# debugId=
|
|
92427
|
+
//# debugId=77F10DD437D49D8264756E2164756E21
|