@adhdev/daemon-standalone 0.9.82-rc.329 → 0.9.82-rc.330
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 +110 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30033,10 +30033,10 @@ var require_dist3 = __commonJS({
|
|
|
30033
30033
|
}
|
|
30034
30034
|
function getDaemonBuildInfo() {
|
|
30035
30035
|
if (cached2) return cached2;
|
|
30036
|
-
const commit = readInjected(true ? "
|
|
30037
|
-
const commitShort = readInjected(true ? "
|
|
30038
|
-
const version2 = readInjected(true ? "0.9.82-rc.
|
|
30039
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
30036
|
+
const commit = readInjected(true ? "ae30dde113f601dc80d6396a625c1dafb3dbaddd" : void 0) ?? "unknown";
|
|
30037
|
+
const commitShort = readInjected(true ? "ae30dde1" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30038
|
+
const version2 = readInjected(true ? "0.9.82-rc.330" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30039
|
+
const builtAt = readInjected(true ? "2026-06-19T17:21:17.821Z" : void 0);
|
|
30040
30040
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30041
30041
|
return cached2;
|
|
30042
30042
|
}
|
|
@@ -40040,7 +40040,11 @@ Next step: ${nextStep}`;
|
|
|
40040
40040
|
event: args.event,
|
|
40041
40041
|
meshId: args.meshId,
|
|
40042
40042
|
nodeId: eventNodeId || void 0,
|
|
40043
|
-
...args.metadataEvent
|
|
40043
|
+
...args.metadataEvent,
|
|
40044
|
+
// Ensure a `workspace` field reaches updateMeshOwnedSession even when the
|
|
40045
|
+
// worker provider event only carried `workspaceName`. The merge spread of
|
|
40046
|
+
// metadataEvent above wins when it already has a non-empty `workspace`.
|
|
40047
|
+
workspace: readNonEmptyString2(args.metadataEvent.workspace) || readNonEmptyString2(args.metadataEvent.workspaceName) || void 0
|
|
40044
40048
|
});
|
|
40045
40049
|
} catch {
|
|
40046
40050
|
}
|
|
@@ -40399,7 +40403,7 @@ Next step: ${nextStep}`;
|
|
|
40399
40403
|
meshId: args.meshId,
|
|
40400
40404
|
nodeLabel: args.nodeLabel,
|
|
40401
40405
|
nodeId: args.nodeId || void 0,
|
|
40402
|
-
workspace: readNonEmptyString2(args.metadataEvent.workspace),
|
|
40406
|
+
workspace: readNonEmptyString2(args.metadataEvent.workspace) || readNonEmptyString2(args.metadataEvent.workspaceName),
|
|
40403
40407
|
metadataEvent: {
|
|
40404
40408
|
...args.metadataEvent,
|
|
40405
40409
|
...recoveryContext ? { recoveryContext } : {}
|
|
@@ -46951,6 +46955,13 @@ ${lastSnapshot}`;
|
|
|
46951
46955
|
if (typeof t.key !== "string" || !t.key) errs.push("pre_launch_trust.key is required");
|
|
46952
46956
|
}
|
|
46953
46957
|
}
|
|
46958
|
+
if (spec.refocus_when_stalled_ms !== void 0) {
|
|
46959
|
+
if (typeof spec.refocus_when_stalled_ms !== "number" || !(spec.refocus_when_stalled_ms > 0)) {
|
|
46960
|
+
errs.push("refocus_when_stalled_ms must be a positive number");
|
|
46961
|
+
} else if (!Array.isArray(spec.send_on_spawn) || spec.send_on_spawn.length === 0) {
|
|
46962
|
+
errs.push("refocus_when_stalled_ms requires send_on_spawn (the wake sequence to re-inject)");
|
|
46963
|
+
}
|
|
46964
|
+
}
|
|
46954
46965
|
if (!Array.isArray(spec.states) || spec.states.length === 0) {
|
|
46955
46966
|
errs.push("states[] must be a non-empty array");
|
|
46956
46967
|
return errs;
|
|
@@ -61493,6 +61504,14 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
61493
61504
|
/** Timer that re-runs evaluate() when a time-condition would flip true
|
|
61494
61505
|
* with no PTY frame to trigger it. */
|
|
61495
61506
|
wakeTimer = null;
|
|
61507
|
+
/** Timer driving the focus-gated stall watchdog (refocus_when_stalled_ms).
|
|
61508
|
+
* Re-arms itself while the machine is generating so a re-prime can fire
|
|
61509
|
+
* even when the PTY has gone completely quiet. */
|
|
61510
|
+
stallTimer = null;
|
|
61511
|
+
/** Wall-clock time the last stall re-prime was injected. The cooldown gate:
|
|
61512
|
+
* after a re-prime we don't re-inject until the screen changes (which
|
|
61513
|
+
* resets the stall reference) or another full stall window lapses. */
|
|
61514
|
+
lastRefocusAt = 0;
|
|
61496
61515
|
currentEval = null;
|
|
61497
61516
|
stateHistory = [];
|
|
61498
61517
|
prevStateAt = 0;
|
|
@@ -61533,11 +61552,18 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
61533
61552
|
const seqs = this.spec.send_on_spawn;
|
|
61534
61553
|
if (!Array.isArray(seqs) || seqs.length === 0) return;
|
|
61535
61554
|
const delay2 = Math.max(0, this.spec.send_on_spawn_delay_ms ?? 250);
|
|
61536
|
-
setTimeout(() =>
|
|
61537
|
-
|
|
61538
|
-
|
|
61539
|
-
|
|
61540
|
-
|
|
61555
|
+
setTimeout(() => this.sendSpawnPrime(), delay2);
|
|
61556
|
+
}
|
|
61557
|
+
/** Write the declared `send_on_spawn` sequences to the PTY once. Used both
|
|
61558
|
+
* at spawn (scheduleSpawnPrime) and, for focus-gated TUIs, by the stall
|
|
61559
|
+
* watchdog to re-inject the focus-in wake mid-turn. No-op when the spec
|
|
61560
|
+
* declares no prime, so non-focus-gated CLIs are never poked. */
|
|
61561
|
+
sendSpawnPrime() {
|
|
61562
|
+
const seqs = this.spec.send_on_spawn;
|
|
61563
|
+
if (!Array.isArray(seqs) || seqs.length === 0) return;
|
|
61564
|
+
for (const seq of seqs) {
|
|
61565
|
+
if (typeof seq === "string" && seq.length > 0) this.adapter.send_keys(seq);
|
|
61566
|
+
}
|
|
61541
61567
|
}
|
|
61542
61568
|
dispatch(cmd) {
|
|
61543
61569
|
switch (cmd.kind) {
|
|
@@ -61598,6 +61624,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
61598
61624
|
clearTimeout(this.wakeTimer);
|
|
61599
61625
|
this.wakeTimer = null;
|
|
61600
61626
|
}
|
|
61627
|
+
if (this.stallTimer) {
|
|
61628
|
+
clearTimeout(this.stallTimer);
|
|
61629
|
+
this.stallTimer = null;
|
|
61630
|
+
}
|
|
61601
61631
|
this.specWatcher?.close();
|
|
61602
61632
|
this.adapter.kill();
|
|
61603
61633
|
}
|
|
@@ -61738,11 +61768,13 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
61738
61768
|
this.commitTransition(ev.fired, now, ev);
|
|
61739
61769
|
this.emitStateChanged(forceEmit);
|
|
61740
61770
|
this.scheduleWakeForState();
|
|
61771
|
+
this.scheduleStallWatchdog();
|
|
61741
61772
|
this.maybeMarkReady();
|
|
61742
61773
|
return;
|
|
61743
61774
|
}
|
|
61744
61775
|
this.emitStateChanged(forceEmit);
|
|
61745
61776
|
this.scheduleWakeForState();
|
|
61777
|
+
this.scheduleStallWatchdog();
|
|
61746
61778
|
this.maybeMarkReady();
|
|
61747
61779
|
}
|
|
61748
61780
|
commitTransition(fired, now, ev) {
|
|
@@ -61890,6 +61922,67 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
61890
61922
|
this.reevaluate();
|
|
61891
61923
|
}, Math.max(soonest + 30, 50));
|
|
61892
61924
|
}
|
|
61925
|
+
// ── Focus-gated stall watchdog (refocus_when_stalled_ms) ──────────────────
|
|
61926
|
+
//
|
|
61927
|
+
// A focus-event TUI (antigravity's `agy`) freezes its render loop the moment
|
|
61928
|
+
// it thinks it has lost focus mid-turn: the screen stops updating and only
|
|
61929
|
+
// repaints on the next keypress, which the daemon never sends. The output
|
|
61930
|
+
// pump is wired entirely to PTY onData (no PTY data → no reevaluate, no
|
|
61931
|
+
// on_screen_changed), so a normal time-wake that only re-reads the screen
|
|
61932
|
+
// can't help — there is nothing new to read. The fix is to re-inject the
|
|
61933
|
+
// focus-in wake (`send_on_spawn`) so the CLI flushes the held output itself.
|
|
61934
|
+
/** True when this spec opts into stall recovery (declares a positive
|
|
61935
|
+
* refocus window AND a wake sequence to re-inject). */
|
|
61936
|
+
stallRecoveryEnabled() {
|
|
61937
|
+
const ms = this.spec.refocus_when_stalled_ms;
|
|
61938
|
+
return typeof ms === "number" && ms > 0 && Array.isArray(this.spec.send_on_spawn) && this.spec.send_on_spawn.length > 0;
|
|
61939
|
+
}
|
|
61940
|
+
/** Wall-clock time the screen last changed in the current state, falling
|
|
61941
|
+
* back to state entry when it has not changed since (i.e. fully stalled
|
|
61942
|
+
* from the start of the state). */
|
|
61943
|
+
lastScreenChangeAt() {
|
|
61944
|
+
return this.regionLastChangedAt.get(-1) ?? this.stateEnteredAt;
|
|
61945
|
+
}
|
|
61946
|
+
/** Arm a timer to re-inject the focus-in prime if the screen stays frozen
|
|
61947
|
+
* through a `generating` state. Only active for opted-in focus-gated specs;
|
|
61948
|
+
* a no-op (and cleared) for every other CLI and every non-generating state.
|
|
61949
|
+
* Re-arms itself so it keeps watching while the PTY is quiet. */
|
|
61950
|
+
scheduleStallWatchdog() {
|
|
61951
|
+
if (this.stallTimer) {
|
|
61952
|
+
clearTimeout(this.stallTimer);
|
|
61953
|
+
this.stallTimer = null;
|
|
61954
|
+
}
|
|
61955
|
+
if (!this.stallRecoveryEnabled()) return;
|
|
61956
|
+
const st = stateById(this.spec, this.currentStateId);
|
|
61957
|
+
if (!st || statusForState(st) !== "generating") return;
|
|
61958
|
+
const windowMs = this.spec.refocus_when_stalled_ms;
|
|
61959
|
+
const since = Math.max(this.lastScreenChangeAt(), this.lastRefocusAt);
|
|
61960
|
+
const remaining = windowMs - (Date.now() - since);
|
|
61961
|
+
this.stallTimer = setTimeout(
|
|
61962
|
+
() => {
|
|
61963
|
+
this.stallTimer = null;
|
|
61964
|
+
this.onStallTick();
|
|
61965
|
+
},
|
|
61966
|
+
Math.max(remaining + 30, 50)
|
|
61967
|
+
);
|
|
61968
|
+
}
|
|
61969
|
+
/** Fire when the stall window elapses: if the screen is still frozen and we
|
|
61970
|
+
* are still generating, re-inject the focus-in wake once, then re-arm. */
|
|
61971
|
+
onStallTick() {
|
|
61972
|
+
if (!this.stallRecoveryEnabled()) return;
|
|
61973
|
+
const st = stateById(this.spec, this.currentStateId);
|
|
61974
|
+
if (!st || statusForState(st) !== "generating") return;
|
|
61975
|
+
const windowMs = this.spec.refocus_when_stalled_ms;
|
|
61976
|
+
const now = Date.now();
|
|
61977
|
+
const stalledFor = now - this.lastScreenChangeAt();
|
|
61978
|
+
const sinceLastRefocus = now - this.lastRefocusAt;
|
|
61979
|
+
if (stalledFor >= windowMs && sinceLastRefocus >= windowMs) {
|
|
61980
|
+
LOG2.info("FsmDriver", `[${this.specTag()}] stall detected (${stalledFor}ms quiet, generating) \u2014 re-injecting focus-in`);
|
|
61981
|
+
this.sendSpawnPrime();
|
|
61982
|
+
this.lastRefocusAt = now;
|
|
61983
|
+
}
|
|
61984
|
+
this.scheduleStallWatchdog();
|
|
61985
|
+
}
|
|
61893
61986
|
maybeMarkReady() {
|
|
61894
61987
|
if (this.readySeenOnce) return;
|
|
61895
61988
|
const st = stateById(this.spec, this.currentStateId);
|
|
@@ -65120,6 +65213,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
65120
65213
|
targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
|
|
65121
65214
|
providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
|
|
65122
65215
|
workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
|
|
65216
|
+
// Carry the workspace under BOTH `workspace` and `workspaceName` so the
|
|
65217
|
+
// downstream mesh forward/merge path — which reads `workspace` — can
|
|
65218
|
+
// propagate it to the coordinator snapshot. Without `workspace` the live
|
|
65219
|
+
// event path delivers an empty workspace and the dashboard falls back to
|
|
65220
|
+
// the generic "Terminal (Mesh Node)" title.
|
|
65221
|
+
workspace: typeof event.workspace === "string" && event.workspace.trim() ? event.workspace : this.workingDir,
|
|
65123
65222
|
providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
|
|
65124
65223
|
};
|
|
65125
65224
|
if (this.context?.emitProviderEvent) {
|