@adhdev/daemon-core 0.9.82-rc.268 → 0.9.82-rc.269
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +3 -0
- package/dist/cli-adapters/terminal-backends/types.d.ts +9 -0
- package/dist/cli-adapters/terminal-screen.d.ts +2 -0
- package/dist/index.js +139 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +139 -29
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +24 -0
- package/dist/providers/spec/adapter.d.ts +7 -0
- package/dist/providers/spec/fsm-driver.d.ts +4 -0
- package/package.json +2 -2
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +28 -10
- package/src/cli-adapters/terminal-backends/types.ts +9 -0
- package/src/cli-adapters/terminal-screen.ts +5 -0
- package/src/providers/cli-provider-instance.ts +87 -13
- package/src/providers/spec/adapter.ts +10 -0
- package/src/providers/spec/fsm-driver.ts +31 -2
package/dist/index.mjs
CHANGED
|
@@ -260,10 +260,10 @@ function readInjected(value) {
|
|
|
260
260
|
}
|
|
261
261
|
function getDaemonBuildInfo() {
|
|
262
262
|
if (cached) return cached;
|
|
263
|
-
const commit = readInjected(true ? "
|
|
264
|
-
const commitShort = readInjected(true ? "
|
|
265
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
266
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
263
|
+
const commit = readInjected(true ? "025d8bef81a66e7b44a5ba5d5a04e063db46db4e" : void 0) ?? "unknown";
|
|
264
|
+
const commitShort = readInjected(true ? "025d8bef" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
265
|
+
const version = readInjected(true ? "0.9.82-rc.269" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
266
|
+
const builtAt = readInjected(true ? "2026-06-14T22:11:38.134Z" : void 0);
|
|
267
267
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
268
268
|
return cached;
|
|
269
269
|
}
|
|
@@ -9496,7 +9496,7 @@ var init_ghostty_vt_backend = __esm({
|
|
|
9496
9496
|
"@adhdev/ghostty-vt-node"
|
|
9497
9497
|
];
|
|
9498
9498
|
cachedBindingError = null;
|
|
9499
|
-
GhosttyVtTerminalBackend = class {
|
|
9499
|
+
GhosttyVtTerminalBackend = class _GhosttyVtTerminalBackend {
|
|
9500
9500
|
kind = "ghostty-vt";
|
|
9501
9501
|
terminal;
|
|
9502
9502
|
rows;
|
|
@@ -9518,17 +9518,30 @@ var init_ghostty_vt_backend = __esm({
|
|
|
9518
9518
|
if (!data || this.disposed) return;
|
|
9519
9519
|
this.terminal.write(data);
|
|
9520
9520
|
}
|
|
9521
|
+
formatLines() {
|
|
9522
|
+
const raw = this.terminal.formatPlainText({ trim: false }) || "";
|
|
9523
|
+
if (!raw) return [];
|
|
9524
|
+
return raw.split("\n").map((row) => row.replace(/\s+$/, ""));
|
|
9525
|
+
}
|
|
9526
|
+
static trimBlankEnds(lines) {
|
|
9527
|
+
let first = 0;
|
|
9528
|
+
let last = lines.length;
|
|
9529
|
+
while (first < last && !lines[first]) first += 1;
|
|
9530
|
+
while (last > first && !lines[last - 1]) last -= 1;
|
|
9531
|
+
return lines.slice(first, last).join("\n");
|
|
9532
|
+
}
|
|
9521
9533
|
getText() {
|
|
9522
9534
|
if (this.disposed) return "";
|
|
9523
|
-
const
|
|
9524
|
-
if (
|
|
9525
|
-
const lines = raw.split("\n").map((row) => row.replace(/\s+$/, ""));
|
|
9535
|
+
const lines = this.formatLines();
|
|
9536
|
+
if (lines.length === 0) return "";
|
|
9526
9537
|
const viewport = lines.length > this.rows ? lines.slice(-this.rows) : lines;
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9538
|
+
return _GhosttyVtTerminalBackend.trimBlankEnds(viewport);
|
|
9539
|
+
}
|
|
9540
|
+
getTextWithScrollback() {
|
|
9541
|
+
if (this.disposed) return "";
|
|
9542
|
+
const lines = this.formatLines();
|
|
9543
|
+
if (lines.length === 0) return "";
|
|
9544
|
+
return _GhosttyVtTerminalBackend.trimBlankEnds(lines);
|
|
9532
9545
|
}
|
|
9533
9546
|
getCursorPosition() {
|
|
9534
9547
|
if (this.disposed) return { col: 0, row: 0 };
|
|
@@ -9581,6 +9594,10 @@ var init_terminal_screen = __esm({
|
|
|
9581
9594
|
getText() {
|
|
9582
9595
|
return this.terminal.getText();
|
|
9583
9596
|
}
|
|
9597
|
+
/** Full buffer including scrollback history (see backend doc). */
|
|
9598
|
+
getTextWithScrollback() {
|
|
9599
|
+
return this.terminal.getTextWithScrollback();
|
|
9600
|
+
}
|
|
9584
9601
|
getCursorPosition() {
|
|
9585
9602
|
return this.terminal.getCursorPosition();
|
|
9586
9603
|
}
|
|
@@ -28985,6 +29002,15 @@ var TerminalAdapter = class {
|
|
|
28985
29002
|
snapshot() {
|
|
28986
29003
|
return this.lastScreen || this.computeScreen();
|
|
28987
29004
|
}
|
|
29005
|
+
/**
|
|
29006
|
+
* Full-buffer snapshot including scrollback history. Unlike snapshot()
|
|
29007
|
+
* (visible viewport only), this survives a tall prompt whose top has
|
|
29008
|
+
* scrolled off-screen — used for content-pattern extraction (modal
|
|
29009
|
+
* buttons / approval anchors), NOT for cursor-relative conditions.
|
|
29010
|
+
*/
|
|
29011
|
+
snapshotWithScrollback() {
|
|
29012
|
+
return this.screen.getTextWithScrollback();
|
|
29013
|
+
}
|
|
28988
29014
|
getCursorPosition() {
|
|
28989
29015
|
const pos = this.screen.getCursorPosition();
|
|
28990
29016
|
return { row: pos.row, col: pos.col };
|
|
@@ -29159,6 +29185,18 @@ var FsmDriver = class {
|
|
|
29159
29185
|
getScreen() {
|
|
29160
29186
|
return this.adapter.snapshot();
|
|
29161
29187
|
}
|
|
29188
|
+
/** Scrollback-inclusive screen as line array — used only for modal/button
|
|
29189
|
+
* content extraction so a tall prompt's off-screen anchors stay matchable.
|
|
29190
|
+
* Falls back to the viewport snapshot if scrollback read is unavailable. */
|
|
29191
|
+
scrollbackLines() {
|
|
29192
|
+
let screen = "";
|
|
29193
|
+
try {
|
|
29194
|
+
screen = this.adapter.snapshotWithScrollback();
|
|
29195
|
+
} catch {
|
|
29196
|
+
}
|
|
29197
|
+
if (!screen) screen = this.adapter.snapshot();
|
|
29198
|
+
return screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
|
|
29199
|
+
}
|
|
29162
29200
|
getSpecPath() {
|
|
29163
29201
|
return this.opts.specPath;
|
|
29164
29202
|
}
|
|
@@ -29340,9 +29378,12 @@ var FsmDriver = class {
|
|
|
29340
29378
|
const screen = this.adapter.snapshot();
|
|
29341
29379
|
const lines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
|
|
29342
29380
|
const sections = resolveSections(this.spec.sections ?? {}, lines);
|
|
29343
|
-
const
|
|
29381
|
+
const modalLines = state.modal ? this.scrollbackLines() : lines;
|
|
29382
|
+
const modalSections = state.modal ? resolveSections(this.spec.sections ?? {}, modalLines) : sections;
|
|
29383
|
+
const modalFullScreen = modalLines.join("\n");
|
|
29384
|
+
const modal = this.deriveModal(state, modalSections, modalFullScreen);
|
|
29344
29385
|
const controls = this.deriveControls(state.id);
|
|
29345
|
-
const title = modal?.title ?? this.deriveTitle(state,
|
|
29386
|
+
const title = modal?.title ?? this.deriveTitle(state, modalSections, modalFullScreen);
|
|
29346
29387
|
const next = {
|
|
29347
29388
|
// status is derived from the FSM state itself (statusForState), NOT from
|
|
29348
29389
|
// whether a modal was parsed this frame. A modal state whose buttons briefly
|
|
@@ -31213,7 +31254,7 @@ async function waitForCliAdapterReady(adapter, options) {
|
|
|
31213
31254
|
}
|
|
31214
31255
|
throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
|
|
31215
31256
|
}
|
|
31216
|
-
var CliProviderInstance = class {
|
|
31257
|
+
var CliProviderInstance = class _CliProviderInstance {
|
|
31217
31258
|
constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, options) {
|
|
31218
31259
|
this.provider = provider;
|
|
31219
31260
|
this.workingDir = workingDir;
|
|
@@ -31233,6 +31274,18 @@ var CliProviderInstance = class {
|
|
|
31233
31274
|
}
|
|
31234
31275
|
type;
|
|
31235
31276
|
category = "cli";
|
|
31277
|
+
/**
|
|
31278
|
+
* Quiet period an approval modal's signature must be stable before
|
|
31279
|
+
* auto-approve sends the approve key. Guards against firing on a prompt
|
|
31280
|
+
* that is still streaming into the PTY (the "resolves too fast" symptom):
|
|
31281
|
+
* while the modal text/buttons are still changing, every frame yields a
|
|
31282
|
+
* new signature and the settle clock restarts. Once the prompt finishes
|
|
31283
|
+
* rendering the signature holds and the key is sent after this window.
|
|
31284
|
+
* Bounded + small so genuine approvals stay timely. The FSM is already
|
|
31285
|
+
* authoritative over the `waiting_approval` state; this only delays the
|
|
31286
|
+
* keystroke until the modal *content* has settled.
|
|
31287
|
+
*/
|
|
31288
|
+
static AUTO_APPROVE_SETTLE_MS = 600;
|
|
31236
31289
|
adapter;
|
|
31237
31290
|
context = null;
|
|
31238
31291
|
events = [];
|
|
@@ -31246,6 +31299,14 @@ var CliProviderInstance = class {
|
|
|
31246
31299
|
autoApproveBusy = false;
|
|
31247
31300
|
autoApproveBusyTimer = null;
|
|
31248
31301
|
lastAutoApprovalSignature = "";
|
|
31302
|
+
// Settle gate: the approval modal's signature + the wall-clock when this
|
|
31303
|
+
// exact signature was first observed. Auto-approve only fires once the
|
|
31304
|
+
// SAME signature has been stable for AUTO_APPROVE_SETTLE_MS, so a prompt
|
|
31305
|
+
// still streaming into the PTY (its buttons/message changing frame to
|
|
31306
|
+
// frame) keeps resetting the timer and is never approved half-rendered.
|
|
31307
|
+
pendingAutoApprovalSignature = "";
|
|
31308
|
+
pendingAutoApprovalSince = 0;
|
|
31309
|
+
autoApproveSettleTimer = null;
|
|
31249
31310
|
controlValues = {};
|
|
31250
31311
|
summaryMetadata = void 0;
|
|
31251
31312
|
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
@@ -31680,6 +31741,14 @@ var CliProviderInstance = class {
|
|
|
31680
31741
|
dispose() {
|
|
31681
31742
|
this.adapter.shutdown();
|
|
31682
31743
|
this.monitor.reset();
|
|
31744
|
+
if (this.autoApproveSettleTimer) {
|
|
31745
|
+
clearTimeout(this.autoApproveSettleTimer);
|
|
31746
|
+
this.autoApproveSettleTimer = null;
|
|
31747
|
+
}
|
|
31748
|
+
if (this.autoApproveBusyTimer) {
|
|
31749
|
+
clearTimeout(this.autoApproveBusyTimer);
|
|
31750
|
+
this.autoApproveBusyTimer = null;
|
|
31751
|
+
}
|
|
31683
31752
|
this.appliedEffectKeys.clear();
|
|
31684
31753
|
try {
|
|
31685
31754
|
this.cachedSqliteDb?.close();
|
|
@@ -32030,6 +32099,12 @@ var CliProviderInstance = class {
|
|
|
32030
32099
|
const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
|
|
32031
32100
|
if (!autoApproveActive) {
|
|
32032
32101
|
this.lastAutoApprovalSignature = "";
|
|
32102
|
+
this.pendingAutoApprovalSignature = "";
|
|
32103
|
+
this.pendingAutoApprovalSince = 0;
|
|
32104
|
+
if (this.autoApproveSettleTimer) {
|
|
32105
|
+
clearTimeout(this.autoApproveSettleTimer);
|
|
32106
|
+
this.autoApproveSettleTimer = null;
|
|
32107
|
+
}
|
|
32033
32108
|
return autoApproveActive;
|
|
32034
32109
|
}
|
|
32035
32110
|
const modal = adapterStatus.activeModal;
|
|
@@ -32048,22 +32123,57 @@ var CliProviderInstance = class {
|
|
|
32048
32123
|
buttons.join("|"),
|
|
32049
32124
|
buttonIndex
|
|
32050
32125
|
].join("::");
|
|
32051
|
-
if (
|
|
32052
|
-
|
|
32053
|
-
this.lastAutoApprovalSignature = signature;
|
|
32054
|
-
if (this.autoApproveBusyTimer) clearTimeout(this.autoApproveBusyTimer);
|
|
32055
|
-
this.autoApproveBusyTimer = setTimeout(() => {
|
|
32056
|
-
this.autoApproveBusy = false;
|
|
32057
|
-
this.autoApproveBusyTimer = null;
|
|
32058
|
-
this.lastAutoApprovalSignature = "";
|
|
32059
|
-
}, 5e3);
|
|
32060
|
-
this.recordAutoApproval(modal?.message, buttonLabel, now);
|
|
32061
|
-
setTimeout(() => {
|
|
32062
|
-
this.adapter.resolveModal(buttonIndex);
|
|
32063
|
-
}, 0);
|
|
32126
|
+
if (this.autoApproveBusy && signature === this.lastAutoApprovalSignature) {
|
|
32127
|
+
return autoApproveActive;
|
|
32064
32128
|
}
|
|
32129
|
+
if (signature !== this.pendingAutoApprovalSignature) {
|
|
32130
|
+
this.pendingAutoApprovalSignature = signature;
|
|
32131
|
+
this.pendingAutoApprovalSince = now;
|
|
32132
|
+
}
|
|
32133
|
+
const settledForMs = now - this.pendingAutoApprovalSince;
|
|
32134
|
+
if (settledForMs < _CliProviderInstance.AUTO_APPROVE_SETTLE_MS) {
|
|
32135
|
+
if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
|
|
32136
|
+
this.autoApproveSettleTimer = setTimeout(() => {
|
|
32137
|
+
this.autoApproveSettleTimer = null;
|
|
32138
|
+
this.recheckAutoApproveSettled();
|
|
32139
|
+
}, _CliProviderInstance.AUTO_APPROVE_SETTLE_MS - settledForMs + 20);
|
|
32140
|
+
return autoApproveActive;
|
|
32141
|
+
}
|
|
32142
|
+
if (this.autoApproveSettleTimer) {
|
|
32143
|
+
clearTimeout(this.autoApproveSettleTimer);
|
|
32144
|
+
this.autoApproveSettleTimer = null;
|
|
32145
|
+
}
|
|
32146
|
+
this.autoApproveBusy = true;
|
|
32147
|
+
this.lastAutoApprovalSignature = signature;
|
|
32148
|
+
this.pendingAutoApprovalSignature = "";
|
|
32149
|
+
this.pendingAutoApprovalSince = 0;
|
|
32150
|
+
if (this.autoApproveBusyTimer) clearTimeout(this.autoApproveBusyTimer);
|
|
32151
|
+
this.autoApproveBusyTimer = setTimeout(() => {
|
|
32152
|
+
this.autoApproveBusy = false;
|
|
32153
|
+
this.autoApproveBusyTimer = null;
|
|
32154
|
+
this.lastAutoApprovalSignature = "";
|
|
32155
|
+
}, 5e3);
|
|
32156
|
+
this.recordAutoApproval(modal?.message, buttonLabel, now);
|
|
32157
|
+
setTimeout(() => {
|
|
32158
|
+
this.adapter.resolveModal(buttonIndex);
|
|
32159
|
+
}, 0);
|
|
32065
32160
|
return autoApproveActive;
|
|
32066
32161
|
}
|
|
32162
|
+
/**
|
|
32163
|
+
* Re-drive the auto-approve check after the settle quiet window elapses.
|
|
32164
|
+
* The PTY may have gone silent once the approval prompt finished painting,
|
|
32165
|
+
* so no status-change frame is guaranteed to re-enter maybeAutoApproveStatus
|
|
32166
|
+
* — this timer-driven re-check picks up the now-settled modal and fires.
|
|
32167
|
+
* Deliberately lighter than detectStatusTransition(): it only re-evaluates
|
|
32168
|
+
* the approval decision; the next real PTY frame refreshes visible status.
|
|
32169
|
+
*/
|
|
32170
|
+
recheckAutoApproveSettled() {
|
|
32171
|
+
try {
|
|
32172
|
+
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
32173
|
+
this.maybeAutoApproveStatus(adapterStatus, Date.now());
|
|
32174
|
+
} catch {
|
|
32175
|
+
}
|
|
32176
|
+
}
|
|
32067
32177
|
detectStatusTransition() {
|
|
32068
32178
|
const now = Date.now();
|
|
32069
32179
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|