@adhdev/daemon-core 0.5.5 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts
CHANGED
|
@@ -2367,6 +2367,9 @@ declare class ProviderCliAdapter implements CliAdapter {
|
|
|
2367
2367
|
private serverConn;
|
|
2368
2368
|
private logBuffer;
|
|
2369
2369
|
private lastApprovalResolvedAt;
|
|
2370
|
+
private approvalTransitionBuffer;
|
|
2371
|
+
private approvalExitTimeout;
|
|
2372
|
+
private resizeSuppressUntil;
|
|
2370
2373
|
private readonly timeouts;
|
|
2371
2374
|
constructor(provider: CliProviderModule, workingDir: string, extraArgs?: string[]);
|
|
2372
2375
|
setServerConn(serverConn: any): void;
|
|
@@ -2384,6 +2387,12 @@ declare class ProviderCliAdapter implements CliAdapter {
|
|
|
2384
2387
|
isProcessing(): boolean;
|
|
2385
2388
|
isReady(): boolean;
|
|
2386
2389
|
writeRaw(data: string): void;
|
|
2390
|
+
/**
|
|
2391
|
+
* Resolve an approval modal by navigating to the button at `buttonIndex` and pressing Enter.
|
|
2392
|
+
* Index 0 = first option (already selected by default — just Enter).
|
|
2393
|
+
* Index N = press Arrow Down N times, then Enter.
|
|
2394
|
+
*/
|
|
2395
|
+
resolveModal(buttonIndex: number): void;
|
|
2387
2396
|
resize(cols: number, rows: number): void;
|
|
2388
2397
|
}
|
|
2389
2398
|
|
package/dist/index.js
CHANGED
|
@@ -3568,6 +3568,39 @@ async function handleResolveAction(h, args) {
|
|
|
3568
3568
|
const action = args?.action || "approve";
|
|
3569
3569
|
const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
|
|
3570
3570
|
LOG.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
|
|
3571
|
+
if (provider?.category === "cli") {
|
|
3572
|
+
const adapter = h.getCliAdapter(provider.type);
|
|
3573
|
+
if (!adapter) return { success: false, error: "CLI adapter not running" };
|
|
3574
|
+
const status = adapter.getStatus?.();
|
|
3575
|
+
if (status?.status !== "waiting_approval") {
|
|
3576
|
+
return { success: false, error: "Not in approval state" };
|
|
3577
|
+
}
|
|
3578
|
+
const buttons = status.activeModal?.buttons || ["Allow once", "Always allow", "Deny"];
|
|
3579
|
+
let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
|
|
3580
|
+
if (buttonIndex < 0) {
|
|
3581
|
+
const btnLower = button.toLowerCase();
|
|
3582
|
+
buttonIndex = buttons.findIndex((b) => b.toLowerCase().includes(btnLower));
|
|
3583
|
+
}
|
|
3584
|
+
if (buttonIndex < 0) {
|
|
3585
|
+
if (action === "reject" || action === "deny") {
|
|
3586
|
+
buttonIndex = buttons.findIndex((b) => /deny|reject|no/i.test(b));
|
|
3587
|
+
if (buttonIndex < 0) buttonIndex = buttons.length - 1;
|
|
3588
|
+
} else if (action === "always" || /always/i.test(button)) {
|
|
3589
|
+
buttonIndex = buttons.findIndex((b) => /always/i.test(b));
|
|
3590
|
+
if (buttonIndex < 0) buttonIndex = 1;
|
|
3591
|
+
} else {
|
|
3592
|
+
buttonIndex = 0;
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
if (typeof adapter.resolveModal === "function") {
|
|
3596
|
+
adapter.resolveModal(buttonIndex);
|
|
3597
|
+
} else {
|
|
3598
|
+
const keys = "\x1B[B".repeat(Math.max(0, buttonIndex)) + "\r";
|
|
3599
|
+
adapter.writeRaw?.(keys);
|
|
3600
|
+
}
|
|
3601
|
+
LOG.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
|
|
3602
|
+
return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
|
|
3603
|
+
}
|
|
3571
3604
|
if (provider?.category === "extension" && h.agentStream && h.getCdp()) {
|
|
3572
3605
|
const ok = await h.agentStream.resolveAgentAction(
|
|
3573
3606
|
h.getCdp(),
|
|
@@ -6472,28 +6505,32 @@ function coercePatternArray(raw, fallbacks) {
|
|
|
6472
6505
|
}
|
|
6473
6506
|
var FALLBACK_PROMPT = [
|
|
6474
6507
|
/Type your message/i,
|
|
6475
|
-
|
|
6508
|
+
/^>\s*$/m,
|
|
6509
|
+
// '>' alone on its own line
|
|
6476
6510
|
/[›➤]\s*$/,
|
|
6477
6511
|
/for shortcuts/i,
|
|
6478
6512
|
/\?\s*for help/i,
|
|
6479
|
-
/Press enter/i
|
|
6480
|
-
/^[\s\u2500-\u257f]*>\s*$/m
|
|
6513
|
+
/Press enter/i
|
|
6514
|
+
// NOTE: removed /^[\s\u2500-\u257f]*>\s*$/m — the box-drawing char range is too wide and
|
|
6515
|
+
// can match dialog-clearing ANSI output, causing false prompt detection in approval state.
|
|
6481
6516
|
];
|
|
6482
6517
|
var FALLBACK_GENERATING = [
|
|
6483
|
-
/
|
|
6484
|
-
|
|
6485
|
-
/
|
|
6486
|
-
|
|
6487
|
-
/
|
|
6488
|
-
|
|
6518
|
+
/[\u2800-\u28ff]/,
|
|
6519
|
+
// Braille spinner blocks (universal TUI)
|
|
6520
|
+
/esc to (cancel|interrupt|stop)/i,
|
|
6521
|
+
// Common TUI generation status line
|
|
6522
|
+
/generating\.\.\./i,
|
|
6523
|
+
/Claude is (?:thinking|processing|working)/i
|
|
6524
|
+
// Specific Claude Code status
|
|
6489
6525
|
];
|
|
6490
6526
|
var FALLBACK_APPROVAL = [
|
|
6491
|
-
/
|
|
6492
|
-
/
|
|
6527
|
+
/Allow\s+once/i,
|
|
6528
|
+
/Always\s+allow/i,
|
|
6493
6529
|
/\(y\/n\)/i,
|
|
6494
6530
|
/\[Y\/n\]/i,
|
|
6495
|
-
/
|
|
6496
|
-
/
|
|
6531
|
+
/Run\s+this\s+command/i
|
|
6532
|
+
// NOTE: removed /Do you want to (?:run|execute|allow)/i — too broad, matches AI explanation
|
|
6533
|
+
// text like "Do you want to allow this feature?" causing false approval notifications.
|
|
6497
6534
|
];
|
|
6498
6535
|
function defaultCleanOutput(raw, _lastUserInput) {
|
|
6499
6536
|
return stripAnsi(raw).trim();
|
|
@@ -6554,6 +6591,11 @@ var ProviderCliAdapter = class {
|
|
|
6554
6591
|
logBuffer = [];
|
|
6555
6592
|
// Approval cooldown
|
|
6556
6593
|
lastApprovalResolvedAt = 0;
|
|
6594
|
+
// Approval state machine
|
|
6595
|
+
approvalTransitionBuffer = "";
|
|
6596
|
+
approvalExitTimeout = null;
|
|
6597
|
+
// Resize redraw suppression
|
|
6598
|
+
resizeSuppressUntil = 0;
|
|
6557
6599
|
// Resolved timeouts (provider defaults + overrides)
|
|
6558
6600
|
timeouts;
|
|
6559
6601
|
// ─── Lifecycle ─────────────────────────────────
|
|
@@ -6644,6 +6686,7 @@ var ProviderCliAdapter = class {
|
|
|
6644
6686
|
}
|
|
6645
6687
|
// ─── Output state machine ────────────────────────────
|
|
6646
6688
|
handleOutput(rawData) {
|
|
6689
|
+
if (Date.now() < this.resizeSuppressUntil) return;
|
|
6647
6690
|
const cleanData = stripAnsi(rawData);
|
|
6648
6691
|
const { patterns } = this.provider;
|
|
6649
6692
|
if (cleanData.trim()) {
|
|
@@ -6676,30 +6719,55 @@ var ProviderCliAdapter = class {
|
|
|
6676
6719
|
const hasApproval = patterns.approval.some((p) => p.test(this.recentOutputBuffer));
|
|
6677
6720
|
if (hasApproval && this.currentStatus !== "waiting_approval") {
|
|
6678
6721
|
if (this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown) return;
|
|
6722
|
+
const ctxLines = this.recentOutputBuffer.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
|
|
6679
6723
|
this.isWaitingForResponse = true;
|
|
6680
6724
|
this.currentStatus = "waiting_approval";
|
|
6681
6725
|
this.recentOutputBuffer = "";
|
|
6682
|
-
|
|
6726
|
+
this.approvalTransitionBuffer = "";
|
|
6683
6727
|
this.activeModal = {
|
|
6684
6728
|
message: ctxLines.slice(-5).join(" ").slice(0, 200) || "Approval required",
|
|
6685
6729
|
buttons: ["Allow once", "Always allow", "Deny"]
|
|
6686
6730
|
};
|
|
6687
6731
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
6732
|
+
if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
|
|
6733
|
+
this.approvalExitTimeout = setTimeout(() => {
|
|
6734
|
+
if (this.currentStatus === "waiting_approval") {
|
|
6735
|
+
LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-exiting waiting_approval`);
|
|
6736
|
+
this.activeModal = null;
|
|
6737
|
+
this.lastApprovalResolvedAt = Date.now();
|
|
6738
|
+
this.recentOutputBuffer = "";
|
|
6739
|
+
this.approvalTransitionBuffer = "";
|
|
6740
|
+
this.approvalExitTimeout = null;
|
|
6741
|
+
this.currentStatus = this.isWaitingForResponse ? "generating" : "idle";
|
|
6742
|
+
this.onStatusChange?.();
|
|
6743
|
+
}
|
|
6744
|
+
}, 6e4);
|
|
6688
6745
|
this.onStatusChange?.();
|
|
6689
6746
|
return;
|
|
6690
6747
|
}
|
|
6691
6748
|
if (this.currentStatus === "waiting_approval") {
|
|
6692
|
-
|
|
6693
|
-
const
|
|
6749
|
+
this.approvalTransitionBuffer = (this.approvalTransitionBuffer + cleanData).slice(-500);
|
|
6750
|
+
const genResume = patterns.generating.some((p) => p.test(this.approvalTransitionBuffer));
|
|
6751
|
+
const promptResume = patterns.prompt.some((p) => p.test(this.approvalTransitionBuffer));
|
|
6694
6752
|
if (genResume) {
|
|
6753
|
+
if (this.approvalExitTimeout) {
|
|
6754
|
+
clearTimeout(this.approvalExitTimeout);
|
|
6755
|
+
this.approvalExitTimeout = null;
|
|
6756
|
+
}
|
|
6695
6757
|
this.currentStatus = "generating";
|
|
6696
6758
|
this.activeModal = null;
|
|
6697
6759
|
this.recentOutputBuffer = "";
|
|
6760
|
+
this.approvalTransitionBuffer = "";
|
|
6698
6761
|
this.lastApprovalResolvedAt = Date.now();
|
|
6699
6762
|
this.onStatusChange?.();
|
|
6700
6763
|
} else if (promptResume) {
|
|
6764
|
+
if (this.approvalExitTimeout) {
|
|
6765
|
+
clearTimeout(this.approvalExitTimeout);
|
|
6766
|
+
this.approvalExitTimeout = null;
|
|
6767
|
+
}
|
|
6701
6768
|
this.activeModal = null;
|
|
6702
6769
|
this.recentOutputBuffer = "";
|
|
6770
|
+
this.approvalTransitionBuffer = "";
|
|
6703
6771
|
this.lastApprovalResolvedAt = Date.now();
|
|
6704
6772
|
this.finishResponse();
|
|
6705
6773
|
}
|
|
@@ -6725,7 +6793,8 @@ var ProviderCliAdapter = class {
|
|
|
6725
6793
|
this.onStatusChange?.();
|
|
6726
6794
|
return;
|
|
6727
6795
|
}
|
|
6728
|
-
|
|
6796
|
+
const trailingLines = cleanData.split("\n").slice(-2).join("\n");
|
|
6797
|
+
if (patterns.prompt.some((p) => p.test(trailingLines))) {
|
|
6729
6798
|
this.finishResponse();
|
|
6730
6799
|
} else {
|
|
6731
6800
|
this.idleTimeout = setTimeout(() => {
|
|
@@ -6746,6 +6815,10 @@ var ProviderCliAdapter = class {
|
|
|
6746
6815
|
clearTimeout(this.idleTimeout);
|
|
6747
6816
|
this.idleTimeout = null;
|
|
6748
6817
|
}
|
|
6818
|
+
if (this.approvalExitTimeout) {
|
|
6819
|
+
clearTimeout(this.approvalExitTimeout);
|
|
6820
|
+
this.approvalExitTimeout = null;
|
|
6821
|
+
}
|
|
6749
6822
|
const lastUserText = this.messages.filter((m) => m.role === "user").pop()?.content;
|
|
6750
6823
|
let response = this.provider.cleanOutput(this.responseBuffer, lastUserText);
|
|
6751
6824
|
if (lastUserText && response) {
|
|
@@ -6795,6 +6868,10 @@ var ProviderCliAdapter = class {
|
|
|
6795
6868
|
this.shutdown();
|
|
6796
6869
|
}
|
|
6797
6870
|
shutdown() {
|
|
6871
|
+
if (this.approvalExitTimeout) {
|
|
6872
|
+
clearTimeout(this.approvalExitTimeout);
|
|
6873
|
+
this.approvalExitTimeout = null;
|
|
6874
|
+
}
|
|
6798
6875
|
if (this.ptyProcess) {
|
|
6799
6876
|
this.ptyProcess.write("");
|
|
6800
6877
|
setTimeout(() => {
|
|
@@ -6822,10 +6899,22 @@ var ProviderCliAdapter = class {
|
|
|
6822
6899
|
writeRaw(data) {
|
|
6823
6900
|
this.ptyProcess?.write(data);
|
|
6824
6901
|
}
|
|
6902
|
+
/**
|
|
6903
|
+
* Resolve an approval modal by navigating to the button at `buttonIndex` and pressing Enter.
|
|
6904
|
+
* Index 0 = first option (already selected by default — just Enter).
|
|
6905
|
+
* Index N = press Arrow Down N times, then Enter.
|
|
6906
|
+
*/
|
|
6907
|
+
resolveModal(buttonIndex) {
|
|
6908
|
+
if (!this.ptyProcess || this.currentStatus !== "waiting_approval") return;
|
|
6909
|
+
const DOWN = "\x1B[B";
|
|
6910
|
+
const keys = DOWN.repeat(Math.max(0, buttonIndex)) + "\r";
|
|
6911
|
+
this.ptyProcess.write(keys);
|
|
6912
|
+
}
|
|
6825
6913
|
resize(cols, rows) {
|
|
6826
6914
|
if (this.ptyProcess) {
|
|
6827
6915
|
try {
|
|
6828
6916
|
this.ptyProcess.resize(cols, rows);
|
|
6917
|
+
this.resizeSuppressUntil = Date.now() + 300;
|
|
6829
6918
|
} catch {
|
|
6830
6919
|
}
|
|
6831
6920
|
}
|
|
@@ -6950,20 +7039,24 @@ var CliProviderInstance = class {
|
|
|
6950
7039
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
6951
7040
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
6952
7041
|
if (newStatus !== this.lastStatus) {
|
|
7042
|
+
LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
|
|
6953
7043
|
if (this.lastStatus === "idle" && newStatus === "generating") {
|
|
6954
7044
|
this.generatingStartedAt = now;
|
|
6955
7045
|
this.pushEvent({ event: "agent:generating_started", chatTitle, timestamp: now });
|
|
6956
7046
|
} else if (newStatus === "waiting_approval") {
|
|
6957
7047
|
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
7048
|
+
const modal = adapterStatus.activeModal;
|
|
7049
|
+
LOG.info("CLI", `[${this.type}] approval modal: "${modal?.message?.slice(0, 80) ?? "none"}"`);
|
|
6958
7050
|
this.pushEvent({
|
|
6959
7051
|
event: "agent:waiting_approval",
|
|
6960
7052
|
chatTitle,
|
|
6961
7053
|
timestamp: now,
|
|
6962
|
-
modalMessage:
|
|
6963
|
-
modalButtons:
|
|
7054
|
+
modalMessage: modal?.message,
|
|
7055
|
+
modalButtons: modal?.buttons
|
|
6964
7056
|
});
|
|
6965
7057
|
} else if (newStatus === "idle" && (this.lastStatus === "generating" || this.lastStatus === "waiting_approval")) {
|
|
6966
7058
|
const duration = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
7059
|
+
LOG.info("CLI", `[${this.type}] completed in ${duration}s`);
|
|
6967
7060
|
this.pushEvent({ event: "agent:generating_completed", chatTitle, duration, timestamp: now });
|
|
6968
7061
|
this.generatingStartedAt = 0;
|
|
6969
7062
|
} else if (newStatus === "stopped") {
|