adhdev 0.7.46 → 0.8.1
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/index.js +1924 -420
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1960 -416
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/session-host-daemon/index.js +14 -3
- package/vendor/session-host-daemon/index.js.map +1 -1
- package/vendor/session-host-daemon/index.mjs +14 -3
- package/vendor/session-host-daemon/index.mjs.map +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2694,6 +2694,7 @@ var init_chat_history = __esm({
|
|
|
2694
2694
|
role: msg.role,
|
|
2695
2695
|
content: msg.content || "",
|
|
2696
2696
|
kind: typeof msg.kind === "string" ? msg.kind : void 0,
|
|
2697
|
+
senderName: typeof msg.senderName === "string" ? msg.senderName : void 0,
|
|
2697
2698
|
agent: agentType,
|
|
2698
2699
|
instanceId,
|
|
2699
2700
|
historySessionId: effectiveHistoryKey,
|
|
@@ -2732,6 +2733,7 @@ var init_chat_history = __esm({
|
|
|
2732
2733
|
kind: "system",
|
|
2733
2734
|
content,
|
|
2734
2735
|
receivedAt: options.receivedAt,
|
|
2736
|
+
senderName: options.senderName,
|
|
2735
2737
|
historyDedupKey: options.dedupKey
|
|
2736
2738
|
}],
|
|
2737
2739
|
options.sessionTitle,
|
|
@@ -4021,6 +4023,12 @@ function getCurrentManagerKey(h) {
|
|
|
4021
4023
|
function getTargetedCliAdapter(h, args, providerType) {
|
|
4022
4024
|
return h.getCliAdapter(args?.targetSessionId || providerType || h.currentSession?.providerType || h.currentManagerKey);
|
|
4023
4025
|
}
|
|
4026
|
+
function getTargetInstance(h, args) {
|
|
4027
|
+
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
4028
|
+
const sessionId = targetSessionId || h.currentSession?.sessionId || "";
|
|
4029
|
+
if (!sessionId) return null;
|
|
4030
|
+
return h.ctx.instanceManager?.getInstance(sessionId);
|
|
4031
|
+
}
|
|
4024
4032
|
function getTargetTransport(h, provider) {
|
|
4025
4033
|
if (h.currentSession?.transport) return h.currentSession.transport;
|
|
4026
4034
|
switch (provider?.category) {
|
|
@@ -4763,6 +4771,7 @@ async function handleResolveAction(h, args) {
|
|
|
4763
4771
|
adapter.writeRaw?.(keys);
|
|
4764
4772
|
}
|
|
4765
4773
|
LOG.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
|
|
4774
|
+
getTargetInstance(h, args)?.recordApprovalSelection?.(buttons[buttonIndex] ?? button);
|
|
4766
4775
|
return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
|
|
4767
4776
|
}
|
|
4768
4777
|
if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
@@ -15337,10 +15346,10 @@ __export(provider_cli_adapter_exports, {
|
|
|
15337
15346
|
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
15338
15347
|
});
|
|
15339
15348
|
function stripAnsi(str) {
|
|
15340
|
-
return str.replace(/\x1B\[
|
|
15349
|
+
return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
|
|
15341
15350
|
}
|
|
15342
15351
|
function stripTerminalNoise(str) {
|
|
15343
|
-
return String(str || "").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, "").replace(/(^|[\s([])(?:\??\d{1,4}(?:;\d{1,4})*[A-Za-z])(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\[\??\d{1,4}(?:;\d{1,4})*[A-Za-z])(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\d{1,4};\?)(?=$|[\s)\]])/g, "$1").replace(/\r+/g, "\n").replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").replace(/ {2,}/g, " ");
|
|
15352
|
+
return String(str || "").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, "").replace(/(^|[\s([])(?:\??\d{1,4}(?:;\d{1,4})*[A-Za-z])(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\[\??\d{1,4}(?:;\d{1,4})*[A-Za-z])(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\d{1,4};\?)(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\d+\$r[0-9;\" ]*[A-Za-z]?)(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:>\|[A-Za-z0-9_.:-]+(?:\([^)]*\))?)(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:[A-Z]\d(?:\s+[A-Z]\d)+)(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\d+;[^\s)\]]+)(?=$|[\s)\]])/g, "$1").replace(/\r+/g, "\n").replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").replace(/ {2,}/g, " ");
|
|
15344
15353
|
}
|
|
15345
15354
|
function sanitizeTerminalText(str) {
|
|
15346
15355
|
return stripTerminalNoise(stripAnsi(str));
|
|
@@ -15383,12 +15392,12 @@ function findBinary(name) {
|
|
|
15383
15392
|
function isScriptBinary(binaryPath) {
|
|
15384
15393
|
if (!path7.isAbsolute(binaryPath)) return false;
|
|
15385
15394
|
try {
|
|
15386
|
-
const
|
|
15387
|
-
const resolved =
|
|
15395
|
+
const fs19 = require("fs");
|
|
15396
|
+
const resolved = fs19.realpathSync(binaryPath);
|
|
15388
15397
|
const head = Buffer.alloc(8);
|
|
15389
|
-
const fd =
|
|
15390
|
-
|
|
15391
|
-
|
|
15398
|
+
const fd = fs19.openSync(resolved, "r");
|
|
15399
|
+
fs19.readSync(fd, head, 0, 8, 0);
|
|
15400
|
+
fs19.closeSync(fd);
|
|
15392
15401
|
let i = 0;
|
|
15393
15402
|
if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
|
|
15394
15403
|
return head[i] === 35 && head[i + 1] === 33;
|
|
@@ -15399,12 +15408,12 @@ function isScriptBinary(binaryPath) {
|
|
|
15399
15408
|
function looksLikeMachOOrElf(filePath) {
|
|
15400
15409
|
if (!path7.isAbsolute(filePath)) return false;
|
|
15401
15410
|
try {
|
|
15402
|
-
const
|
|
15403
|
-
const resolved =
|
|
15411
|
+
const fs19 = require("fs");
|
|
15412
|
+
const resolved = fs19.realpathSync(filePath);
|
|
15404
15413
|
const buf = Buffer.alloc(8);
|
|
15405
|
-
const fd =
|
|
15406
|
-
|
|
15407
|
-
|
|
15414
|
+
const fd = fs19.openSync(resolved, "r");
|
|
15415
|
+
fs19.readSync(fd, buf, 0, 8, 0);
|
|
15416
|
+
fs19.closeSync(fd);
|
|
15408
15417
|
let i = 0;
|
|
15409
15418
|
if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
|
|
15410
15419
|
const b2 = buf.subarray(i);
|
|
@@ -15457,6 +15466,9 @@ function promptLikelyVisible(screenText, promptSnippet) {
|
|
|
15457
15466
|
).length;
|
|
15458
15467
|
return matched >= required2;
|
|
15459
15468
|
}
|
|
15469
|
+
function normalizeScreenSnapshot(text) {
|
|
15470
|
+
return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
|
|
15471
|
+
}
|
|
15460
15472
|
function parsePatternEntry(x) {
|
|
15461
15473
|
if (x instanceof RegExp) return x;
|
|
15462
15474
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -15495,14 +15507,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
15495
15507
|
pty2 = require("node-pty");
|
|
15496
15508
|
if (os9.platform() !== "win32") {
|
|
15497
15509
|
try {
|
|
15498
|
-
const
|
|
15510
|
+
const fs19 = require("fs");
|
|
15499
15511
|
const ptyDir = path7.resolve(path7.dirname(require.resolve("node-pty")), "..");
|
|
15500
15512
|
const platformArch = `${os9.platform()}-${os9.arch()}`;
|
|
15501
15513
|
const helper = path7.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
|
|
15502
|
-
if (
|
|
15503
|
-
const stat4 =
|
|
15514
|
+
if (fs19.existsSync(helper)) {
|
|
15515
|
+
const stat4 = fs19.statSync(helper);
|
|
15504
15516
|
if (!(stat4.mode & 73)) {
|
|
15505
|
-
|
|
15517
|
+
fs19.chmodSync(helper, stat4.mode | 493);
|
|
15506
15518
|
LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
15507
15519
|
}
|
|
15508
15520
|
}
|
|
@@ -15536,10 +15548,25 @@ var init_provider_cli_adapter = __esm({
|
|
|
15536
15548
|
this.sendDelayMs = typeof provider.sendDelayMs === "number" ? Math.max(0, provider.sendDelayMs) : 0;
|
|
15537
15549
|
this.sendKey = typeof provider.sendKey === "string" && provider.sendKey.length > 0 ? provider.sendKey : "\r";
|
|
15538
15550
|
this.submitStrategy = provider.submitStrategy === "immediate" ? "immediate" : "wait_for_echo";
|
|
15551
|
+
this.providerResolutionMeta = {
|
|
15552
|
+
type: provider.type,
|
|
15553
|
+
name: provider.name,
|
|
15554
|
+
resolvedVersion: provider._resolvedVersion || null,
|
|
15555
|
+
resolvedOs: provider._resolvedOs || null,
|
|
15556
|
+
providerDir: provider._resolvedProviderDir || null,
|
|
15557
|
+
scriptDir: provider._resolvedScriptDir || null,
|
|
15558
|
+
scriptsPath: provider._resolvedScriptsPath || null,
|
|
15559
|
+
scriptsSource: provider._resolvedScriptsSource || null,
|
|
15560
|
+
versionWarning: provider._versionWarning || null
|
|
15561
|
+
};
|
|
15539
15562
|
this.cliScripts = provider.scripts || {};
|
|
15540
15563
|
const scriptNames = Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function");
|
|
15541
15564
|
if (scriptNames.length > 0) {
|
|
15542
15565
|
LOG.info("CLI", `[${this.cliType}] CLI scripts: [${scriptNames.join(", ")}]`);
|
|
15566
|
+
LOG.info(
|
|
15567
|
+
"CLI",
|
|
15568
|
+
`[${this.cliType}] Provider resolution: providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"} source=${this.providerResolutionMeta.scriptsSource || "-"} version=${this.providerResolutionMeta.resolvedVersion || "-"}`
|
|
15569
|
+
);
|
|
15543
15570
|
} else {
|
|
15544
15571
|
LOG.warn("CLI", `[${this.cliType}] \u26A0 No CLI scripts loaded! Provider needs scripts/{version}/scripts.js`);
|
|
15545
15572
|
}
|
|
@@ -15572,6 +15599,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
15572
15599
|
ptyOutputBuffer = "";
|
|
15573
15600
|
ptyOutputFlushTimer = null;
|
|
15574
15601
|
pendingTerminalQueryTail = "";
|
|
15602
|
+
lastOutputAt = 0;
|
|
15603
|
+
lastNonEmptyOutputAt = 0;
|
|
15604
|
+
lastScreenChangeAt = 0;
|
|
15605
|
+
lastScreenSnapshot = "";
|
|
15575
15606
|
// Server log forwarding
|
|
15576
15607
|
serverConn = null;
|
|
15577
15608
|
logBuffer = [];
|
|
@@ -15592,6 +15623,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15592
15623
|
submitRetryTimer = null;
|
|
15593
15624
|
submitRetryUsed = false;
|
|
15594
15625
|
submitRetryPromptSnippet = "";
|
|
15626
|
+
idleFinishCandidate = null;
|
|
15595
15627
|
// Resize redraw suppression
|
|
15596
15628
|
resizeSuppressUntil = 0;
|
|
15597
15629
|
// Debug: status transition history
|
|
@@ -15607,6 +15639,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
15607
15639
|
/** Max accumulated buffer size (last 50KB) */
|
|
15608
15640
|
static MAX_ACCUMULATED_BUFFER = 5e4;
|
|
15609
15641
|
currentTurnScope = null;
|
|
15642
|
+
traceEntries = [];
|
|
15643
|
+
traceSeq = 0;
|
|
15644
|
+
traceSessionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
15645
|
+
static MAX_TRACE_ENTRIES = 250;
|
|
15646
|
+
providerResolutionMeta;
|
|
15647
|
+
static IDLE_FINISH_CONFIRM_MS = 900;
|
|
15610
15648
|
syncMessageViews() {
|
|
15611
15649
|
this.messages = [...this.committedMessages];
|
|
15612
15650
|
this.structuredMessages = [...this.committedMessages];
|
|
@@ -15642,8 +15680,89 @@ var init_provider_cli_adapter = __esm({
|
|
|
15642
15680
|
this.currentStatus = status;
|
|
15643
15681
|
this.statusHistory.push({ status, at: Date.now(), trigger });
|
|
15644
15682
|
if (this.statusHistory.length > 50) this.statusHistory.shift();
|
|
15683
|
+
this.recordTrace("status", {
|
|
15684
|
+
previousStatus: prev,
|
|
15685
|
+
trigger: trigger || null
|
|
15686
|
+
});
|
|
15645
15687
|
LOG.info("CLI", `[${this.cliType}] status: ${prev} \u2192 ${status}${trigger ? ` (${trigger})` : ""}`);
|
|
15646
15688
|
}
|
|
15689
|
+
clearIdleFinishCandidate(reason) {
|
|
15690
|
+
if (!this.idleFinishCandidate) return;
|
|
15691
|
+
this.recordTrace("idle_candidate_reset", {
|
|
15692
|
+
reason,
|
|
15693
|
+
candidate: this.idleFinishCandidate
|
|
15694
|
+
});
|
|
15695
|
+
this.idleFinishCandidate = null;
|
|
15696
|
+
}
|
|
15697
|
+
armIdleFinishCandidate(assistantLength) {
|
|
15698
|
+
const now = Date.now();
|
|
15699
|
+
this.idleFinishCandidate = {
|
|
15700
|
+
armedAt: now,
|
|
15701
|
+
lastOutputAt: this.lastOutputAt,
|
|
15702
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
15703
|
+
responseEpoch: this.responseEpoch,
|
|
15704
|
+
assistantLength
|
|
15705
|
+
};
|
|
15706
|
+
this.recordTrace("idle_candidate_armed", {
|
|
15707
|
+
confirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
|
|
15708
|
+
candidate: this.idleFinishCandidate,
|
|
15709
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
15710
|
+
});
|
|
15711
|
+
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
15712
|
+
this.settleTimer = setTimeout(() => {
|
|
15713
|
+
this.settleTimer = null;
|
|
15714
|
+
this.settledBuffer = this.recentOutputBuffer;
|
|
15715
|
+
this.evaluateSettled();
|
|
15716
|
+
}, _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS);
|
|
15717
|
+
}
|
|
15718
|
+
summarizeTraceText(text, max = 800) {
|
|
15719
|
+
const value = sanitizeTerminalText(String(text || ""));
|
|
15720
|
+
if (value.length <= max) return value;
|
|
15721
|
+
return `\u2026${value.slice(-max)}`;
|
|
15722
|
+
}
|
|
15723
|
+
summarizeTraceMessages(messages, limit = 3) {
|
|
15724
|
+
return messages.slice(-limit).map((message) => ({
|
|
15725
|
+
role: message.role,
|
|
15726
|
+
content: this.summarizeTraceText(message.content, 240),
|
|
15727
|
+
timestamp: message.timestamp
|
|
15728
|
+
}));
|
|
15729
|
+
}
|
|
15730
|
+
buildTraceParseSnapshot(scope, partialResponse = "") {
|
|
15731
|
+
const scopedBuffer = scope ? this.sliceFromOffset(this.accumulatedBuffer, scope.bufferStart) || this.accumulatedBuffer : this.accumulatedBuffer;
|
|
15732
|
+
const scopedRawBuffer = scope ? this.sliceFromOffset(this.accumulatedRawBuffer, scope.rawBufferStart) || this.accumulatedRawBuffer : this.accumulatedRawBuffer;
|
|
15733
|
+
return {
|
|
15734
|
+
currentTurnScope: scope || null,
|
|
15735
|
+
responseBuffer: this.summarizeTraceText(this.responseBuffer, 1200),
|
|
15736
|
+
partialResponse: this.summarizeTraceText(partialResponse || this.responseBuffer, 1200),
|
|
15737
|
+
turnBuffer: this.summarizeTraceText(scopedBuffer, 1600),
|
|
15738
|
+
turnRawPreview: this.summarizeTraceText(scopedRawBuffer, 1600),
|
|
15739
|
+
turnSanitizedRawPreview: this.summarizeTraceText(sanitizeTerminalText(scopedRawBuffer), 1600)
|
|
15740
|
+
};
|
|
15741
|
+
}
|
|
15742
|
+
recordTrace(type, payload = {}) {
|
|
15743
|
+
const entry = {
|
|
15744
|
+
id: ++this.traceSeq,
|
|
15745
|
+
at: Date.now(),
|
|
15746
|
+
type,
|
|
15747
|
+
status: this.currentStatus,
|
|
15748
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
15749
|
+
activeModal: this.activeModal ? { message: this.activeModal.message, buttons: [...this.activeModal.buttons] } : null,
|
|
15750
|
+
payload
|
|
15751
|
+
};
|
|
15752
|
+
this.traceEntries.push(entry);
|
|
15753
|
+
if (this.traceEntries.length > _ProviderCliAdapter.MAX_TRACE_ENTRIES) {
|
|
15754
|
+
this.traceEntries.splice(0, this.traceEntries.length - _ProviderCliAdapter.MAX_TRACE_ENTRIES);
|
|
15755
|
+
}
|
|
15756
|
+
}
|
|
15757
|
+
resetTraceSession() {
|
|
15758
|
+
this.traceEntries = [];
|
|
15759
|
+
this.traceSeq = 0;
|
|
15760
|
+
this.traceSessionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
15761
|
+
this.recordTrace("session_start", {
|
|
15762
|
+
providerType: this.cliType,
|
|
15763
|
+
workingDir: this.workingDir
|
|
15764
|
+
});
|
|
15765
|
+
}
|
|
15647
15766
|
// Resolved timeouts
|
|
15648
15767
|
timeouts;
|
|
15649
15768
|
// Provider approval key mapping
|
|
@@ -15689,6 +15808,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15689
15808
|
const isWin = os9.platform() === "win32";
|
|
15690
15809
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
15691
15810
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
15811
|
+
this.resetTraceSession();
|
|
15692
15812
|
let shellCmd;
|
|
15693
15813
|
let shellArgs;
|
|
15694
15814
|
const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
@@ -15714,6 +15834,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
15714
15834
|
cwd: this.workingDir,
|
|
15715
15835
|
env: buildCliSpawnEnv(process.env, spawnConfig.env)
|
|
15716
15836
|
};
|
|
15837
|
+
this.recordTrace("spawn", {
|
|
15838
|
+
shellCommand: shellCmd,
|
|
15839
|
+
shellArgs,
|
|
15840
|
+
cwd: ptyOpts.cwd,
|
|
15841
|
+
cols: ptyOpts.cols,
|
|
15842
|
+
rows: ptyOpts.rows,
|
|
15843
|
+
providerResolution: this.providerResolutionMeta
|
|
15844
|
+
});
|
|
15717
15845
|
try {
|
|
15718
15846
|
this.ptyProcess = this.transportFactory.spawn(shellCmd, shellArgs, ptyOpts);
|
|
15719
15847
|
} catch (err) {
|
|
@@ -15756,6 +15884,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15756
15884
|
this.ptyProcess.onExit(({ exitCode }) => {
|
|
15757
15885
|
LOG.info("CLI", `[${this.cliType}] Exit code ${exitCode}`);
|
|
15758
15886
|
this.flushPendingOutputParse();
|
|
15887
|
+
this.recordTrace("exit", { exitCode });
|
|
15759
15888
|
this.ptyProcess = null;
|
|
15760
15889
|
this.setStatus("stopped", "pty_exit");
|
|
15761
15890
|
this.ready = false;
|
|
@@ -15771,6 +15900,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
15771
15900
|
this.currentTurnScope = null;
|
|
15772
15901
|
this.ready = false;
|
|
15773
15902
|
await this.ptyProcess.ready;
|
|
15903
|
+
this.recordTrace("ready", {
|
|
15904
|
+
runtimeMeta: this.getRuntimeMetadata()
|
|
15905
|
+
});
|
|
15774
15906
|
this.setStatus("idle", "pty_ready");
|
|
15775
15907
|
this.onStatusChange?.();
|
|
15776
15908
|
}
|
|
@@ -15778,6 +15910,24 @@ var init_provider_cli_adapter = __esm({
|
|
|
15778
15910
|
handleOutput(rawData) {
|
|
15779
15911
|
this.terminalScreen.write(rawData);
|
|
15780
15912
|
const cleanData = sanitizeTerminalText(rawData);
|
|
15913
|
+
const now = Date.now();
|
|
15914
|
+
const normalizedScreenSnapshot = normalizeScreenSnapshot(this.terminalScreen.getText());
|
|
15915
|
+
this.lastOutputAt = now;
|
|
15916
|
+
if (cleanData.trim()) this.lastNonEmptyOutputAt = now;
|
|
15917
|
+
if (normalizedScreenSnapshot !== this.lastScreenSnapshot) {
|
|
15918
|
+
this.lastScreenSnapshot = normalizedScreenSnapshot;
|
|
15919
|
+
this.lastScreenChangeAt = now;
|
|
15920
|
+
}
|
|
15921
|
+
if (this.idleFinishCandidate && (rawData.length > 0 || cleanData.length > 0)) {
|
|
15922
|
+
this.clearIdleFinishCandidate("new_output");
|
|
15923
|
+
}
|
|
15924
|
+
this.recordTrace("output", {
|
|
15925
|
+
rawLength: rawData.length,
|
|
15926
|
+
cleanLength: cleanData.length,
|
|
15927
|
+
rawPreview: this.summarizeTraceText(rawData, 300),
|
|
15928
|
+
cleanPreview: this.summarizeTraceText(cleanData, 300),
|
|
15929
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 1200)
|
|
15930
|
+
});
|
|
15781
15931
|
if (this.isWaitingForResponse && cleanData) {
|
|
15782
15932
|
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
|
|
15783
15933
|
}
|
|
@@ -15795,11 +15945,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
15795
15945
|
this.startupBuffer += cleanData;
|
|
15796
15946
|
const elapsed = Date.now() - this.spawnAt;
|
|
15797
15947
|
const scriptStatus = this.runDetectStatus(this.startupBuffer);
|
|
15798
|
-
const
|
|
15948
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
15949
|
+
const hasInteractivePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
15950
|
+
const startupStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
15951
|
+
const isReady = (scriptStatus === "idle" || scriptStatus === "waiting_approval") && hasInteractivePrompt && startupStableMs >= 700 || elapsed > 8e3 || this.startupBuffer.length > 12e3;
|
|
15799
15952
|
if (isReady) {
|
|
15800
15953
|
this.startupParseGate = false;
|
|
15801
15954
|
this.ready = true;
|
|
15802
|
-
LOG.info(
|
|
15955
|
+
LOG.info(
|
|
15956
|
+
"CLI",
|
|
15957
|
+
`[${this.cliType}] Startup ready (${elapsed}ms, scriptStatus=${scriptStatus}, prompt=${hasInteractivePrompt}, stableMs=${startupStableMs}) providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
15958
|
+
);
|
|
15803
15959
|
this.onStatusChange?.();
|
|
15804
15960
|
}
|
|
15805
15961
|
}
|
|
@@ -15844,6 +16000,41 @@ var init_provider_cli_adapter = __esm({
|
|
|
15844
16000
|
if (!text.trim()) return false;
|
|
15845
16001
|
return /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(text) || /⏎\s+send/i.test(text) || /\?\s*for\s*shortcuts/i.test(text) || /Type your message(?:\s+or\s+@path\/to\/file)?/i.test(text) || /workspace\s*\(\/directory\)/i.test(text) || /for\s*shortcuts/i.test(text);
|
|
15846
16002
|
}
|
|
16003
|
+
async waitForInteractivePrompt(maxWaitMs = 5e3) {
|
|
16004
|
+
const startedAt = Date.now();
|
|
16005
|
+
let loggedWait = false;
|
|
16006
|
+
while (Date.now() - startedAt < maxWaitMs) {
|
|
16007
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
16008
|
+
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
16009
|
+
const stableMs = this.lastScreenChangeAt ? Date.now() - this.lastScreenChangeAt : 0;
|
|
16010
|
+
const recentlyOutput = this.lastNonEmptyOutputAt ? Date.now() - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
16011
|
+
const status = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
|
|
16012
|
+
const startupLikelyActive = /Welcome back|Tips for getting|Recent activity|Claude Code v\d/i.test(screenText);
|
|
16013
|
+
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "starting" && status !== "generating";
|
|
16014
|
+
if (interactiveReady) {
|
|
16015
|
+
if (loggedWait) {
|
|
16016
|
+
LOG.info(
|
|
16017
|
+
"CLI",
|
|
16018
|
+
`[${this.cliType}] Interactive prompt ready after ${Date.now() - startedAt}ms (stableMs=${stableMs}, recentOutputMs=${recentlyOutput}, startup=${startupLikelyActive})`
|
|
16019
|
+
);
|
|
16020
|
+
}
|
|
16021
|
+
return;
|
|
16022
|
+
}
|
|
16023
|
+
if (!loggedWait && Date.now() - startedAt >= 400) {
|
|
16024
|
+
loggedWait = true;
|
|
16025
|
+
LOG.info(
|
|
16026
|
+
"CLI",
|
|
16027
|
+
`[${this.cliType}] Waiting for interactive prompt: hasPrompt=${hasPrompt} stableMs=${stableMs} recentOutputMs=${recentlyOutput} status=${status} startup=${startupLikelyActive} screen=${JSON.stringify(this.summarizeTraceText(screenText, 220)).slice(0, 260)}`
|
|
16028
|
+
);
|
|
16029
|
+
}
|
|
16030
|
+
await new Promise((resolve13) => setTimeout(resolve13, 50));
|
|
16031
|
+
}
|
|
16032
|
+
const finalScreenText = this.terminalScreen.getText() || "";
|
|
16033
|
+
LOG.warn(
|
|
16034
|
+
"CLI",
|
|
16035
|
+
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(this.summarizeTraceText(finalScreenText, 240)).slice(0, 280)}`
|
|
16036
|
+
);
|
|
16037
|
+
}
|
|
15847
16038
|
evaluateSettled() {
|
|
15848
16039
|
const now = Date.now();
|
|
15849
16040
|
if (this.submitPendingUntil > now || this.responseSettleIgnoreUntil > now) {
|
|
@@ -15861,6 +16052,30 @@ var init_provider_cli_adapter = __esm({
|
|
|
15861
16052
|
const modal = this.runParseApproval(tail);
|
|
15862
16053
|
const rawScriptStatus = this.runDetectStatus(tail);
|
|
15863
16054
|
const scriptStatus = rawScriptStatus;
|
|
16055
|
+
const parsedTranscript = this.parseCurrentTranscript(
|
|
16056
|
+
this.committedMessages,
|
|
16057
|
+
this.responseBuffer,
|
|
16058
|
+
this.currentTurnScope
|
|
16059
|
+
);
|
|
16060
|
+
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? this.normalizeParsedMessages(parsedTranscript.messages) : [];
|
|
16061
|
+
const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
|
|
16062
|
+
this.recordTrace("settled", {
|
|
16063
|
+
tail: this.summarizeTraceText(tail, 500),
|
|
16064
|
+
screenText: this.summarizeTraceText(screenText, 1200),
|
|
16065
|
+
detectStatus: scriptStatus,
|
|
16066
|
+
parsedStatus: parsedTranscript?.status || null,
|
|
16067
|
+
parsedMessageCount: parsedMessages.length,
|
|
16068
|
+
parsedLastAssistant: lastParsedAssistant ? this.summarizeTraceText(lastParsedAssistant.content, 280) : "",
|
|
16069
|
+
parsedActiveModal: parsedTranscript?.activeModal ?? null,
|
|
16070
|
+
approval: modal,
|
|
16071
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
16072
|
+
});
|
|
16073
|
+
if (this.currentTurnScope && !lastParsedAssistant) {
|
|
16074
|
+
LOG.info(
|
|
16075
|
+
"CLI",
|
|
16076
|
+
`[${this.cliType}] Settled without assistant: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(this.summarizeTraceText(this.responseBuffer, 220)).slice(0, 260)} screen=${JSON.stringify(this.summarizeTraceText(screenText, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
|
|
16077
|
+
);
|
|
16078
|
+
}
|
|
15864
16079
|
if (!scriptStatus) return;
|
|
15865
16080
|
const prevStatus = this.currentStatus;
|
|
15866
16081
|
const clearPendingScriptStatus = () => {
|
|
@@ -15896,6 +16111,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15896
16111
|
clearPendingScriptStatus();
|
|
15897
16112
|
}
|
|
15898
16113
|
if (scriptStatus === "waiting_approval") {
|
|
16114
|
+
this.clearIdleFinishCandidate("waiting_approval");
|
|
15899
16115
|
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
15900
16116
|
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
15901
16117
|
if ((inCooldown || visibleIdlePrompt) && !modal) {
|
|
@@ -15929,6 +16145,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15929
16145
|
}
|
|
15930
16146
|
}
|
|
15931
16147
|
if (scriptStatus === "generating") {
|
|
16148
|
+
this.clearIdleFinishCandidate("generating");
|
|
15932
16149
|
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
15933
16150
|
const noActiveTurn = !this.currentTurnScope;
|
|
15934
16151
|
const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText) || /accept edits on/i.test(effectiveScreenText) && (/Update available!/i.test(screenText) || /\/effort/i.test(screenText) || /^.*➜\s+\S+/m.test(effectiveScreenText));
|
|
@@ -15965,13 +16182,58 @@ var init_provider_cli_adapter = __esm({
|
|
|
15965
16182
|
this.lastApprovalResolvedAt = Date.now();
|
|
15966
16183
|
}
|
|
15967
16184
|
if (this.isWaitingForResponse) {
|
|
16185
|
+
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
16186
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
16187
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
16188
|
+
const hasAssistantTurn = !!lastParsedAssistant;
|
|
16189
|
+
const assistantLength = lastParsedAssistant?.content?.length || 0;
|
|
16190
|
+
const idleQuietThresholdMs = Math.max(220, this.timeouts.outputSettle);
|
|
16191
|
+
const idleStableThresholdMs = Math.max(120, Math.min(220, this.timeouts.outputSettle));
|
|
16192
|
+
const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
|
|
16193
|
+
const candidate = this.idleFinishCandidate;
|
|
16194
|
+
const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
|
|
16195
|
+
const canFinishImmediately = idleReady && candidateQuiet;
|
|
16196
|
+
this.recordTrace("idle_decision", {
|
|
16197
|
+
visibleIdlePrompt,
|
|
16198
|
+
quietForMs,
|
|
16199
|
+
screenStableMs,
|
|
16200
|
+
hasAssistantTurn,
|
|
16201
|
+
assistantLength,
|
|
16202
|
+
hasModal: !!modal,
|
|
16203
|
+
idleQuietThresholdMs,
|
|
16204
|
+
idleStableThresholdMs,
|
|
16205
|
+
idleReady,
|
|
16206
|
+
idleFinishConfirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
|
|
16207
|
+
idleFinishCandidate: candidate,
|
|
16208
|
+
candidateQuiet,
|
|
16209
|
+
canFinishImmediately,
|
|
16210
|
+
submitPendingUntil: this.submitPendingUntil,
|
|
16211
|
+
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
16212
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
16213
|
+
});
|
|
16214
|
+
if (canFinishImmediately) {
|
|
16215
|
+
this.clearIdleFinishCandidate("finish_response");
|
|
16216
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
16217
|
+
this.finishResponse();
|
|
16218
|
+
return;
|
|
16219
|
+
}
|
|
16220
|
+
if (idleReady) {
|
|
16221
|
+
if (!candidate) {
|
|
16222
|
+
this.armIdleFinishCandidate(assistantLength);
|
|
16223
|
+
return;
|
|
16224
|
+
}
|
|
16225
|
+
} else {
|
|
16226
|
+
this.clearIdleFinishCandidate("idle_not_ready");
|
|
16227
|
+
}
|
|
15968
16228
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
15969
16229
|
this.idleTimeout = setTimeout(() => {
|
|
15970
16230
|
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
16231
|
+
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
15971
16232
|
this.finishResponse();
|
|
15972
16233
|
}
|
|
15973
16234
|
}, this.timeouts.idleFinish);
|
|
15974
16235
|
} else if (prevStatus !== "idle") {
|
|
16236
|
+
this.clearIdleFinishCandidate("idle_without_response");
|
|
15975
16237
|
this.setStatus("idle", "script_detect");
|
|
15976
16238
|
this.onStatusChange?.();
|
|
15977
16239
|
}
|
|
@@ -15980,6 +16242,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
15980
16242
|
finishResponse() {
|
|
15981
16243
|
if (this.submitPendingUntil > Date.now()) return;
|
|
15982
16244
|
if (this.responseSettleIgnoreUntil > Date.now()) return;
|
|
16245
|
+
this.clearIdleFinishCandidate("finish_response_enter");
|
|
16246
|
+
this.recordTrace("finish_response", {
|
|
16247
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
16248
|
+
});
|
|
15983
16249
|
this.commitCurrentTranscript();
|
|
15984
16250
|
if (this.responseTimeout) {
|
|
15985
16251
|
clearTimeout(this.responseTimeout);
|
|
@@ -16016,6 +16282,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
16016
16282
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
16017
16283
|
this.committedMessages = this.normalizeParsedMessages(parsed.messages);
|
|
16018
16284
|
this.syncMessageViews();
|
|
16285
|
+
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
16286
|
+
this.recordTrace("commit_transcript", {
|
|
16287
|
+
parsedStatus: parsed.status || null,
|
|
16288
|
+
messageCount: this.committedMessages.length,
|
|
16289
|
+
lastAssistant: lastAssistant ? this.summarizeTraceText(lastAssistant.content, 320) : "",
|
|
16290
|
+
messages: this.summarizeTraceMessages(this.committedMessages),
|
|
16291
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
16292
|
+
});
|
|
16293
|
+
if (!lastAssistant && this.currentTurnScope) {
|
|
16294
|
+
LOG.warn(
|
|
16295
|
+
"CLI",
|
|
16296
|
+
`[${this.cliType}] Commit without assistant turn: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(this.summarizeTraceText(this.responseBuffer, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
16297
|
+
);
|
|
16298
|
+
}
|
|
16019
16299
|
}
|
|
16020
16300
|
}
|
|
16021
16301
|
// ─── Script Execution ──────────────────────────
|
|
@@ -16139,16 +16419,23 @@ ${data.message || ""}`.trim();
|
|
|
16139
16419
|
}
|
|
16140
16420
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
16141
16421
|
if (this.isWaitingForResponse) return;
|
|
16422
|
+
await this.waitForInteractivePrompt();
|
|
16142
16423
|
this.committedMessages.push({ role: "user", content: text, timestamp: Date.now() });
|
|
16143
16424
|
this.syncMessageViews();
|
|
16144
16425
|
this.isWaitingForResponse = true;
|
|
16145
16426
|
this.responseBuffer = "";
|
|
16427
|
+
this.clearIdleFinishCandidate("send_message");
|
|
16146
16428
|
this.currentTurnScope = {
|
|
16147
16429
|
prompt: text,
|
|
16148
16430
|
startedAt: Date.now(),
|
|
16149
16431
|
bufferStart: this.accumulatedBuffer.length,
|
|
16150
16432
|
rawBufferStart: this.accumulatedRawBuffer.length
|
|
16151
16433
|
};
|
|
16434
|
+
this.recordTrace("send_message", {
|
|
16435
|
+
text: this.summarizeTraceText(text, 500),
|
|
16436
|
+
estimatedLines: estimatePromptDisplayLines(text),
|
|
16437
|
+
turnScope: this.currentTurnScope
|
|
16438
|
+
});
|
|
16152
16439
|
LOG.info("CLI", `[${this.cliType}] sendMessage turn scope buffer=${this.currentTurnScope.bufferStart} raw=${this.currentTurnScope.rawBufferStart} prompt=${JSON.stringify(text).slice(0, 120)}`);
|
|
16153
16440
|
this.submitRetryUsed = false;
|
|
16154
16441
|
this.submitRetryPromptSnippet = extractPromptRetrySnippet(text);
|
|
@@ -16178,6 +16465,11 @@ ${data.message || ""}`.trim();
|
|
|
16178
16465
|
const submit = () => {
|
|
16179
16466
|
if (!this.ptyProcess) return;
|
|
16180
16467
|
this.submitPendingUntil = 0;
|
|
16468
|
+
this.recordTrace("submit_write", {
|
|
16469
|
+
mode: "submit_key",
|
|
16470
|
+
sendKey: this.sendKey,
|
|
16471
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 500)
|
|
16472
|
+
});
|
|
16181
16473
|
this.ptyProcess.write(this.sendKey);
|
|
16182
16474
|
const retrySubmitIfStuck = (attempt) => {
|
|
16183
16475
|
this.submitRetryTimer = null;
|
|
@@ -16189,6 +16481,12 @@ ${data.message || ""}`.trim();
|
|
|
16189
16481
|
if (/Esc to interrupt|Do you want to proceed|This command requires approval|Allow Codex to|Approve and run now|Always approve this session|Running…|Running\.\.\./i.test(screenText)) return;
|
|
16190
16482
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
16191
16483
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
16484
|
+
this.recordTrace("submit_write", {
|
|
16485
|
+
mode: "submit_retry",
|
|
16486
|
+
attempt,
|
|
16487
|
+
sendKey: this.sendKey,
|
|
16488
|
+
screenText: this.summarizeTraceText(screenText, 500)
|
|
16489
|
+
});
|
|
16192
16490
|
this.ptyProcess.write(this.sendKey);
|
|
16193
16491
|
if (attempt >= 3) {
|
|
16194
16492
|
this.submitRetryUsed = true;
|
|
@@ -16201,6 +16499,12 @@ ${data.message || ""}`.trim();
|
|
|
16201
16499
|
};
|
|
16202
16500
|
if (this.submitStrategy === "immediate") {
|
|
16203
16501
|
this.submitPendingUntil = 0;
|
|
16502
|
+
this.recordTrace("submit_write", {
|
|
16503
|
+
mode: "immediate",
|
|
16504
|
+
text: this.summarizeTraceText(text, 500),
|
|
16505
|
+
sendKey: this.sendKey,
|
|
16506
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 500)
|
|
16507
|
+
});
|
|
16204
16508
|
this.ptyProcess.write(text + this.sendKey);
|
|
16205
16509
|
this.submitRetryTimer = setTimeout(() => {
|
|
16206
16510
|
this.submitRetryTimer = null;
|
|
@@ -16211,6 +16515,12 @@ ${data.message || ""}`.trim();
|
|
|
16211
16515
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
16212
16516
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
16213
16517
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
16518
|
+
this.recordTrace("submit_write", {
|
|
16519
|
+
mode: "immediate_retry",
|
|
16520
|
+
attempt: 1,
|
|
16521
|
+
sendKey: this.sendKey,
|
|
16522
|
+
screenText: this.summarizeTraceText(screenText, 500)
|
|
16523
|
+
});
|
|
16214
16524
|
this.ptyProcess.write(this.sendKey);
|
|
16215
16525
|
this.submitRetryUsed = true;
|
|
16216
16526
|
}, retryDelayMs);
|
|
@@ -16221,6 +16531,12 @@ ${data.message || ""}`.trim();
|
|
|
16221
16531
|
this.submitPendingUntil = Date.now() + submitDelayMs;
|
|
16222
16532
|
}
|
|
16223
16533
|
this.ptyProcess.write(text);
|
|
16534
|
+
this.recordTrace("submit_write", {
|
|
16535
|
+
mode: "type_then_submit",
|
|
16536
|
+
text: this.summarizeTraceText(text, 500),
|
|
16537
|
+
sendKey: this.sendKey,
|
|
16538
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 500)
|
|
16539
|
+
});
|
|
16224
16540
|
const submitStartedAt = Date.now();
|
|
16225
16541
|
let lastNormalizedScreen = "";
|
|
16226
16542
|
let lastScreenChangeAt = submitStartedAt;
|
|
@@ -16321,6 +16637,7 @@ ${data.message || ""}`.trim();
|
|
|
16321
16637
|
});
|
|
16322
16638
|
}
|
|
16323
16639
|
shutdown() {
|
|
16640
|
+
this.clearIdleFinishCandidate("shutdown");
|
|
16324
16641
|
if (this.settleTimer) {
|
|
16325
16642
|
clearTimeout(this.settleTimer);
|
|
16326
16643
|
this.settleTimer = null;
|
|
@@ -16361,6 +16678,7 @@ ${data.message || ""}`.trim();
|
|
|
16361
16678
|
}
|
|
16362
16679
|
}
|
|
16363
16680
|
detach() {
|
|
16681
|
+
this.clearIdleFinishCandidate("detach");
|
|
16364
16682
|
if (this.settleTimer) {
|
|
16365
16683
|
clearTimeout(this.settleTimer);
|
|
16366
16684
|
this.settleTimer = null;
|
|
@@ -16401,6 +16719,7 @@ ${data.message || ""}`.trim();
|
|
|
16401
16719
|
this.onStatusChange?.();
|
|
16402
16720
|
}
|
|
16403
16721
|
clearHistory() {
|
|
16722
|
+
this.clearIdleFinishCandidate("clear_history");
|
|
16404
16723
|
this.committedMessages = [];
|
|
16405
16724
|
this.syncMessageViews();
|
|
16406
16725
|
this.accumulatedBuffer = "";
|
|
@@ -16430,10 +16749,19 @@ ${data.message || ""}`.trim();
|
|
|
16430
16749
|
return this.ready;
|
|
16431
16750
|
}
|
|
16432
16751
|
writeRaw(data) {
|
|
16752
|
+
this.recordTrace("write_raw", {
|
|
16753
|
+
keys: JSON.stringify(data),
|
|
16754
|
+
length: data.length
|
|
16755
|
+
});
|
|
16433
16756
|
this.ptyProcess?.write(data);
|
|
16434
16757
|
}
|
|
16435
16758
|
resolveModal(buttonIndex) {
|
|
16436
16759
|
if (!this.ptyProcess || this.currentStatus !== "waiting_approval" && !this.activeModal) return;
|
|
16760
|
+
this.clearIdleFinishCandidate("resolve_modal");
|
|
16761
|
+
this.recordTrace("resolve_modal", {
|
|
16762
|
+
buttonIndex,
|
|
16763
|
+
activeModal: this.activeModal
|
|
16764
|
+
});
|
|
16437
16765
|
this.activeModal = null;
|
|
16438
16766
|
this.lastApprovalResolvedAt = Date.now();
|
|
16439
16767
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
@@ -16465,6 +16793,7 @@ ${data.message || ""}`.trim();
|
|
|
16465
16793
|
return {
|
|
16466
16794
|
type: this.cliType,
|
|
16467
16795
|
name: this.cliName,
|
|
16796
|
+
providerResolution: this.providerResolutionMeta,
|
|
16468
16797
|
status: this.currentStatus,
|
|
16469
16798
|
ready: this.ready,
|
|
16470
16799
|
startupParseGate: this.startupParseGate,
|
|
@@ -16484,6 +16813,10 @@ ${data.message || ""}`.trim();
|
|
|
16484
16813
|
rawBufferPreview: this.accumulatedRawBuffer.slice(-1e3),
|
|
16485
16814
|
sanitizedRawPreview: sanitizeTerminalText(this.accumulatedRawBuffer).slice(-1e3),
|
|
16486
16815
|
responseBuffer: this.responseBuffer.slice(-1e3),
|
|
16816
|
+
lastOutputAt: this.lastOutputAt,
|
|
16817
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
16818
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
16819
|
+
lastScreenSnapshot: this.lastScreenSnapshot.slice(-500),
|
|
16487
16820
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
16488
16821
|
activeModal: this.activeModal,
|
|
16489
16822
|
lastApprovalResolvedAt: this.lastApprovalResolvedAt,
|
|
@@ -16495,6 +16828,8 @@ ${data.message || ""}`.trim();
|
|
|
16495
16828
|
resizeSuppressUntil: this.resizeSuppressUntil,
|
|
16496
16829
|
hasCliScripts: this.hasCliScripts(),
|
|
16497
16830
|
scriptNames: Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function"),
|
|
16831
|
+
traceSessionId: this.traceSessionId,
|
|
16832
|
+
traceEntryCount: this.traceEntries.length,
|
|
16498
16833
|
statusHistory: this.statusHistory.slice(-30),
|
|
16499
16834
|
timeouts: this.timeouts,
|
|
16500
16835
|
pendingOutputParseBufferLength: this.pendingOutputParseBuffer.length,
|
|
@@ -16502,6 +16837,25 @@ ${data.message || ""}`.trim();
|
|
|
16502
16837
|
ptyAlive: !!this.ptyProcess
|
|
16503
16838
|
};
|
|
16504
16839
|
}
|
|
16840
|
+
getTraceState(limit = 120) {
|
|
16841
|
+
const cappedLimit = Math.max(1, Math.min(500, Number.isFinite(limit) ? Math.floor(limit) : 120));
|
|
16842
|
+
return {
|
|
16843
|
+
sessionId: this.traceSessionId,
|
|
16844
|
+
providerResolution: this.providerResolutionMeta,
|
|
16845
|
+
entryCount: this.traceEntries.length,
|
|
16846
|
+
entries: this.traceEntries.slice(-cappedLimit),
|
|
16847
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 4e3),
|
|
16848
|
+
recentOutputBuffer: this.summarizeTraceText(this.recentOutputBuffer, 1e3),
|
|
16849
|
+
responseBuffer: this.summarizeTraceText(this.responseBuffer, 1200),
|
|
16850
|
+
status: this.currentStatus,
|
|
16851
|
+
activeModal: this.activeModal,
|
|
16852
|
+
currentTurnScope: this.currentTurnScope,
|
|
16853
|
+
messages: this.summarizeTraceMessages(this.committedMessages, 5)
|
|
16854
|
+
};
|
|
16855
|
+
}
|
|
16856
|
+
getProviderResolutionMeta() {
|
|
16857
|
+
return { ...this.providerResolutionMeta };
|
|
16858
|
+
}
|
|
16505
16859
|
respondToTerminalQueries(data) {
|
|
16506
16860
|
if (!this.ptyProcess || !data) return;
|
|
16507
16861
|
const combined = this.pendingTerminalQueryTail + data;
|
|
@@ -16573,6 +16927,7 @@ var init_cli_provider_instance = __esm({
|
|
|
16573
16927
|
generatingDebouncePending = null;
|
|
16574
16928
|
lastApprovalEventAt = 0;
|
|
16575
16929
|
historyWriter;
|
|
16930
|
+
runtimeMessages = [];
|
|
16576
16931
|
instanceId;
|
|
16577
16932
|
presentationMode;
|
|
16578
16933
|
providerSessionId;
|
|
@@ -16635,6 +16990,7 @@ var init_cli_provider_instance = __esm({
|
|
|
16635
16990
|
}
|
|
16636
16991
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
16637
16992
|
const parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
|
|
16993
|
+
const mergedMessages = this.mergeConversationMessages(parsedMessages);
|
|
16638
16994
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
16639
16995
|
if (parsedMessages.length > 0) {
|
|
16640
16996
|
let messagesToSave = parsedMessages;
|
|
@@ -16664,7 +17020,7 @@ var init_cli_provider_instance = __esm({
|
|
|
16664
17020
|
id: `${this.type}_${this.workingDir}`,
|
|
16665
17021
|
title: parsedStatus?.title || dirName,
|
|
16666
17022
|
status: parsedStatus?.status || adapterStatus.status,
|
|
16667
|
-
messages:
|
|
17023
|
+
messages: mergedMessages,
|
|
16668
17024
|
activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
|
|
16669
17025
|
inputContent: ""
|
|
16670
17026
|
},
|
|
@@ -16763,6 +17119,11 @@ var init_cli_provider_instance = __esm({
|
|
|
16763
17119
|
const approvalCooldown = 5e3;
|
|
16764
17120
|
if (this.lastStatus !== "waiting_approval" && (!this.lastApprovalEventAt || now - this.lastApprovalEventAt > approvalCooldown)) {
|
|
16765
17121
|
this.lastApprovalEventAt = now;
|
|
17122
|
+
this.appendRuntimeSystemMessage(
|
|
17123
|
+
this.formatApprovalRequestMessage(modal?.message, modal?.buttons),
|
|
17124
|
+
`approval_request:${now}`,
|
|
17125
|
+
now
|
|
17126
|
+
);
|
|
16766
17127
|
this.pushEvent({
|
|
16767
17128
|
event: "agent:waiting_approval",
|
|
16768
17129
|
chatTitle,
|
|
@@ -16834,11 +17195,71 @@ var init_cli_provider_instance = __esm({
|
|
|
16834
17195
|
get cliName() {
|
|
16835
17196
|
return this.provider.name;
|
|
16836
17197
|
}
|
|
17198
|
+
recordApprovalSelection(buttonText) {
|
|
17199
|
+
const cleanButton = String(buttonText || "").trim();
|
|
17200
|
+
if (!cleanButton) return;
|
|
17201
|
+
const now = Date.now();
|
|
17202
|
+
this.appendRuntimeSystemMessage(
|
|
17203
|
+
`Approval selected: ${cleanButton}`,
|
|
17204
|
+
`approval_selection:${now}:${cleanButton}`,
|
|
17205
|
+
now
|
|
17206
|
+
);
|
|
17207
|
+
}
|
|
16837
17208
|
formatMarkerTimestamp(timestamp) {
|
|
16838
17209
|
const date5 = new Date(timestamp);
|
|
16839
17210
|
const pad = (value) => String(value).padStart(2, "0");
|
|
16840
17211
|
return `${date5.getFullYear()}-${pad(date5.getMonth() + 1)}-${pad(date5.getDate())} ${pad(date5.getHours())}:${pad(date5.getMinutes())}:${pad(date5.getSeconds())}`;
|
|
16841
17212
|
}
|
|
17213
|
+
appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
|
|
17214
|
+
const normalizedContent = String(content || "").trim();
|
|
17215
|
+
if (!normalizedContent) return;
|
|
17216
|
+
if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
|
|
17217
|
+
this.runtimeMessages.push({
|
|
17218
|
+
key: dedupKey,
|
|
17219
|
+
message: {
|
|
17220
|
+
role: "system",
|
|
17221
|
+
senderName: "System",
|
|
17222
|
+
content: normalizedContent,
|
|
17223
|
+
receivedAt,
|
|
17224
|
+
timestamp: receivedAt
|
|
17225
|
+
}
|
|
17226
|
+
});
|
|
17227
|
+
if (this.runtimeMessages.length > 50) {
|
|
17228
|
+
this.runtimeMessages = this.runtimeMessages.slice(-50);
|
|
17229
|
+
}
|
|
17230
|
+
this.historyWriter.appendNewMessages(
|
|
17231
|
+
this.type,
|
|
17232
|
+
[{
|
|
17233
|
+
role: "system",
|
|
17234
|
+
senderName: "System",
|
|
17235
|
+
content: normalizedContent,
|
|
17236
|
+
receivedAt,
|
|
17237
|
+
historyDedupKey: dedupKey
|
|
17238
|
+
}],
|
|
17239
|
+
this.adapter.getScriptParsedStatus?.()?.title || this.workingDir.split("/").filter(Boolean).pop() || "session",
|
|
17240
|
+
this.instanceId,
|
|
17241
|
+
this.providerSessionId
|
|
17242
|
+
);
|
|
17243
|
+
}
|
|
17244
|
+
mergeConversationMessages(parsedMessages) {
|
|
17245
|
+
if (this.runtimeMessages.length === 0) return parsedMessages;
|
|
17246
|
+
return [...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
|
|
17247
|
+
const aTime = a.message.receivedAt || a.message.timestamp || 0;
|
|
17248
|
+
const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
|
|
17249
|
+
if (aTime !== bTime) return aTime - bTime;
|
|
17250
|
+
return a.index - b2.index;
|
|
17251
|
+
}).map((entry) => entry.message);
|
|
17252
|
+
}
|
|
17253
|
+
formatApprovalRequestMessage(modalMessage, buttons) {
|
|
17254
|
+
const lines = ["Approval requested"];
|
|
17255
|
+
const cleanMessage = String(modalMessage || "").trim();
|
|
17256
|
+
if (cleanMessage) lines.push(cleanMessage);
|
|
17257
|
+
const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
|
|
17258
|
+
if (labels.length > 0) {
|
|
17259
|
+
lines.push(labels.map((label) => `[${label}]`).join(" "));
|
|
17260
|
+
}
|
|
17261
|
+
return lines.join("\n");
|
|
17262
|
+
}
|
|
16842
17263
|
promoteProviderSessionId(sessionId) {
|
|
16843
17264
|
const nextSessionId = String(sessionId || "").trim();
|
|
16844
17265
|
if (!nextSessionId || nextSessionId === this.providerSessionId) return;
|
|
@@ -17175,10 +17596,10 @@ function mergeDefs(...defs) {
|
|
|
17175
17596
|
function cloneDef(schema) {
|
|
17176
17597
|
return mergeDefs(schema._zod.def);
|
|
17177
17598
|
}
|
|
17178
|
-
function getElementAtPath(obj,
|
|
17179
|
-
if (!
|
|
17599
|
+
function getElementAtPath(obj, path23) {
|
|
17600
|
+
if (!path23)
|
|
17180
17601
|
return obj;
|
|
17181
|
-
return
|
|
17602
|
+
return path23.reduce((acc, key) => acc?.[key], obj);
|
|
17182
17603
|
}
|
|
17183
17604
|
function promiseAllObject(promisesObj) {
|
|
17184
17605
|
const keys = Object.keys(promisesObj);
|
|
@@ -17490,11 +17911,11 @@ function aborted(x, startIndex = 0) {
|
|
|
17490
17911
|
}
|
|
17491
17912
|
return false;
|
|
17492
17913
|
}
|
|
17493
|
-
function prefixIssues(
|
|
17914
|
+
function prefixIssues(path23, issues) {
|
|
17494
17915
|
return issues.map((iss) => {
|
|
17495
17916
|
var _a2;
|
|
17496
17917
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
17497
|
-
iss.path.unshift(
|
|
17918
|
+
iss.path.unshift(path23);
|
|
17498
17919
|
return iss;
|
|
17499
17920
|
});
|
|
17500
17921
|
}
|
|
@@ -17737,7 +18158,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
|
|
|
17737
18158
|
}
|
|
17738
18159
|
function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
17739
18160
|
const result = { errors: [] };
|
|
17740
|
-
const processError = (error49,
|
|
18161
|
+
const processError = (error49, path23 = []) => {
|
|
17741
18162
|
var _a2, _b;
|
|
17742
18163
|
for (const issue2 of error49.issues) {
|
|
17743
18164
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -17747,7 +18168,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
17747
18168
|
} else if (issue2.code === "invalid_element") {
|
|
17748
18169
|
processError({ issues: issue2.issues }, issue2.path);
|
|
17749
18170
|
} else {
|
|
17750
|
-
const fullpath = [...
|
|
18171
|
+
const fullpath = [...path23, ...issue2.path];
|
|
17751
18172
|
if (fullpath.length === 0) {
|
|
17752
18173
|
result.errors.push(mapper(issue2));
|
|
17753
18174
|
continue;
|
|
@@ -17779,8 +18200,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
17779
18200
|
}
|
|
17780
18201
|
function toDotPath(_path) {
|
|
17781
18202
|
const segs = [];
|
|
17782
|
-
const
|
|
17783
|
-
for (const seg of
|
|
18203
|
+
const path23 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
18204
|
+
for (const seg of path23) {
|
|
17784
18205
|
if (typeof seg === "number")
|
|
17785
18206
|
segs.push(`[${seg}]`);
|
|
17786
18207
|
else if (typeof seg === "symbol")
|
|
@@ -30544,13 +30965,13 @@ function resolveRef(ref, ctx) {
|
|
|
30544
30965
|
if (!ref.startsWith("#")) {
|
|
30545
30966
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
30546
30967
|
}
|
|
30547
|
-
const
|
|
30548
|
-
if (
|
|
30968
|
+
const path23 = ref.slice(1).split("/").filter(Boolean);
|
|
30969
|
+
if (path23.length === 0) {
|
|
30549
30970
|
return ctx.rootSchema;
|
|
30550
30971
|
}
|
|
30551
30972
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
30552
|
-
if (
|
|
30553
|
-
const key =
|
|
30973
|
+
if (path23[0] === defsKey) {
|
|
30974
|
+
const key = path23[1];
|
|
30554
30975
|
if (!key || !ctx.defs[key]) {
|
|
30555
30976
|
throw new Error(`Reference not found: ${ref}`);
|
|
30556
30977
|
}
|
|
@@ -34938,7 +35359,7 @@ var init_readdirp = __esm({
|
|
|
34938
35359
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
34939
35360
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
34940
35361
|
if (wantBigintFsStats) {
|
|
34941
|
-
this._stat = (
|
|
35362
|
+
this._stat = (path23) => statMethod(path23, { bigint: true });
|
|
34942
35363
|
} else {
|
|
34943
35364
|
this._stat = statMethod;
|
|
34944
35365
|
}
|
|
@@ -34963,8 +35384,8 @@ var init_readdirp = __esm({
|
|
|
34963
35384
|
const par = this.parent;
|
|
34964
35385
|
const fil = par && par.files;
|
|
34965
35386
|
if (fil && fil.length > 0) {
|
|
34966
|
-
const { path:
|
|
34967
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
35387
|
+
const { path: path23, depth } = par;
|
|
35388
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path23));
|
|
34968
35389
|
const awaited = await Promise.all(slice);
|
|
34969
35390
|
for (const entry of awaited) {
|
|
34970
35391
|
if (!entry)
|
|
@@ -35004,20 +35425,20 @@ var init_readdirp = __esm({
|
|
|
35004
35425
|
this.reading = false;
|
|
35005
35426
|
}
|
|
35006
35427
|
}
|
|
35007
|
-
async _exploreDir(
|
|
35428
|
+
async _exploreDir(path23, depth) {
|
|
35008
35429
|
let files;
|
|
35009
35430
|
try {
|
|
35010
|
-
files = await (0, import_promises.readdir)(
|
|
35431
|
+
files = await (0, import_promises.readdir)(path23, this._rdOptions);
|
|
35011
35432
|
} catch (error48) {
|
|
35012
35433
|
this._onError(error48);
|
|
35013
35434
|
}
|
|
35014
|
-
return { files, depth, path:
|
|
35435
|
+
return { files, depth, path: path23 };
|
|
35015
35436
|
}
|
|
35016
|
-
async _formatEntry(dirent,
|
|
35437
|
+
async _formatEntry(dirent, path23) {
|
|
35017
35438
|
let entry;
|
|
35018
35439
|
const basename7 = this._isDirent ? dirent.name : dirent;
|
|
35019
35440
|
try {
|
|
35020
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
35441
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path23, basename7));
|
|
35021
35442
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename7 };
|
|
35022
35443
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
35023
35444
|
} catch (err) {
|
|
@@ -35074,16 +35495,16 @@ var init_readdirp = __esm({
|
|
|
35074
35495
|
});
|
|
35075
35496
|
|
|
35076
35497
|
// ../../oss/packages/daemon-core/node_modules/chokidar/handler.js
|
|
35077
|
-
function createFsWatchInstance(
|
|
35498
|
+
function createFsWatchInstance(path23, options, listener, errHandler, emitRaw) {
|
|
35078
35499
|
const handleEvent = (rawEvent, evPath) => {
|
|
35079
|
-
listener(
|
|
35080
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
35081
|
-
if (evPath &&
|
|
35082
|
-
fsWatchBroadcast(sp.resolve(
|
|
35500
|
+
listener(path23);
|
|
35501
|
+
emitRaw(rawEvent, evPath, { watchedPath: path23 });
|
|
35502
|
+
if (evPath && path23 !== evPath) {
|
|
35503
|
+
fsWatchBroadcast(sp.resolve(path23, evPath), KEY_LISTENERS, sp.join(path23, evPath));
|
|
35083
35504
|
}
|
|
35084
35505
|
};
|
|
35085
35506
|
try {
|
|
35086
|
-
return (0, import_node_fs.watch)(
|
|
35507
|
+
return (0, import_node_fs.watch)(path23, {
|
|
35087
35508
|
persistent: options.persistent
|
|
35088
35509
|
}, handleEvent);
|
|
35089
35510
|
} catch (error48) {
|
|
@@ -35432,12 +35853,12 @@ var init_handler2 = __esm({
|
|
|
35432
35853
|
listener(val1, val2, val3);
|
|
35433
35854
|
});
|
|
35434
35855
|
};
|
|
35435
|
-
setFsWatchListener = (
|
|
35856
|
+
setFsWatchListener = (path23, fullPath, options, handlers) => {
|
|
35436
35857
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
35437
35858
|
let cont = FsWatchInstances.get(fullPath);
|
|
35438
35859
|
let watcher;
|
|
35439
35860
|
if (!options.persistent) {
|
|
35440
|
-
watcher = createFsWatchInstance(
|
|
35861
|
+
watcher = createFsWatchInstance(path23, options, listener, errHandler, rawEmitter);
|
|
35441
35862
|
if (!watcher)
|
|
35442
35863
|
return;
|
|
35443
35864
|
return watcher.close.bind(watcher);
|
|
@@ -35448,7 +35869,7 @@ var init_handler2 = __esm({
|
|
|
35448
35869
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
35449
35870
|
} else {
|
|
35450
35871
|
watcher = createFsWatchInstance(
|
|
35451
|
-
|
|
35872
|
+
path23,
|
|
35452
35873
|
options,
|
|
35453
35874
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
35454
35875
|
errHandler,
|
|
@@ -35463,7 +35884,7 @@ var init_handler2 = __esm({
|
|
|
35463
35884
|
cont.watcherUnusable = true;
|
|
35464
35885
|
if (isWindows && error48.code === "EPERM") {
|
|
35465
35886
|
try {
|
|
35466
|
-
const fd = await (0, import_promises2.open)(
|
|
35887
|
+
const fd = await (0, import_promises2.open)(path23, "r");
|
|
35467
35888
|
await fd.close();
|
|
35468
35889
|
broadcastErr(error48);
|
|
35469
35890
|
} catch (err) {
|
|
@@ -35494,7 +35915,7 @@ var init_handler2 = __esm({
|
|
|
35494
35915
|
};
|
|
35495
35916
|
};
|
|
35496
35917
|
FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
35497
|
-
setFsWatchFileListener = (
|
|
35918
|
+
setFsWatchFileListener = (path23, fullPath, options, handlers) => {
|
|
35498
35919
|
const { listener, rawEmitter } = handlers;
|
|
35499
35920
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
35500
35921
|
const copts = cont && cont.options;
|
|
@@ -35516,7 +35937,7 @@ var init_handler2 = __esm({
|
|
|
35516
35937
|
});
|
|
35517
35938
|
const currmtime = curr.mtimeMs;
|
|
35518
35939
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
35519
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
35940
|
+
foreach(cont.listeners, (listener2) => listener2(path23, curr));
|
|
35520
35941
|
}
|
|
35521
35942
|
})
|
|
35522
35943
|
};
|
|
@@ -35546,13 +35967,13 @@ var init_handler2 = __esm({
|
|
|
35546
35967
|
* @param listener on fs change
|
|
35547
35968
|
* @returns closer for the watcher instance
|
|
35548
35969
|
*/
|
|
35549
|
-
_watchWithNodeFs(
|
|
35970
|
+
_watchWithNodeFs(path23, listener) {
|
|
35550
35971
|
const opts = this.fsw.options;
|
|
35551
|
-
const directory = sp.dirname(
|
|
35552
|
-
const basename7 = sp.basename(
|
|
35972
|
+
const directory = sp.dirname(path23);
|
|
35973
|
+
const basename7 = sp.basename(path23);
|
|
35553
35974
|
const parent = this.fsw._getWatchedDir(directory);
|
|
35554
35975
|
parent.add(basename7);
|
|
35555
|
-
const absolutePath = sp.resolve(
|
|
35976
|
+
const absolutePath = sp.resolve(path23);
|
|
35556
35977
|
const options = {
|
|
35557
35978
|
persistent: opts.persistent
|
|
35558
35979
|
};
|
|
@@ -35562,12 +35983,12 @@ var init_handler2 = __esm({
|
|
|
35562
35983
|
if (opts.usePolling) {
|
|
35563
35984
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
35564
35985
|
options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
|
|
35565
|
-
closer = setFsWatchFileListener(
|
|
35986
|
+
closer = setFsWatchFileListener(path23, absolutePath, options, {
|
|
35566
35987
|
listener,
|
|
35567
35988
|
rawEmitter: this.fsw._emitRaw
|
|
35568
35989
|
});
|
|
35569
35990
|
} else {
|
|
35570
|
-
closer = setFsWatchListener(
|
|
35991
|
+
closer = setFsWatchListener(path23, absolutePath, options, {
|
|
35571
35992
|
listener,
|
|
35572
35993
|
errHandler: this._boundHandleError,
|
|
35573
35994
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -35589,7 +36010,7 @@ var init_handler2 = __esm({
|
|
|
35589
36010
|
let prevStats = stats;
|
|
35590
36011
|
if (parent.has(basename7))
|
|
35591
36012
|
return;
|
|
35592
|
-
const listener = async (
|
|
36013
|
+
const listener = async (path23, newStats) => {
|
|
35593
36014
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
|
|
35594
36015
|
return;
|
|
35595
36016
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -35603,11 +36024,11 @@ var init_handler2 = __esm({
|
|
|
35603
36024
|
this.fsw._emit(EV.CHANGE, file2, newStats2);
|
|
35604
36025
|
}
|
|
35605
36026
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
35606
|
-
this.fsw._closeFile(
|
|
36027
|
+
this.fsw._closeFile(path23);
|
|
35607
36028
|
prevStats = newStats2;
|
|
35608
36029
|
const closer2 = this._watchWithNodeFs(file2, listener);
|
|
35609
36030
|
if (closer2)
|
|
35610
|
-
this.fsw._addPathCloser(
|
|
36031
|
+
this.fsw._addPathCloser(path23, closer2);
|
|
35611
36032
|
} else {
|
|
35612
36033
|
prevStats = newStats2;
|
|
35613
36034
|
}
|
|
@@ -35639,7 +36060,7 @@ var init_handler2 = __esm({
|
|
|
35639
36060
|
* @param item basename of this item
|
|
35640
36061
|
* @returns true if no more processing is needed for this entry.
|
|
35641
36062
|
*/
|
|
35642
|
-
async _handleSymlink(entry, directory,
|
|
36063
|
+
async _handleSymlink(entry, directory, path23, item) {
|
|
35643
36064
|
if (this.fsw.closed) {
|
|
35644
36065
|
return;
|
|
35645
36066
|
}
|
|
@@ -35649,7 +36070,7 @@ var init_handler2 = __esm({
|
|
|
35649
36070
|
this.fsw._incrReadyCount();
|
|
35650
36071
|
let linkPath;
|
|
35651
36072
|
try {
|
|
35652
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
36073
|
+
linkPath = await (0, import_promises2.realpath)(path23);
|
|
35653
36074
|
} catch (e) {
|
|
35654
36075
|
this.fsw._emitReady();
|
|
35655
36076
|
return true;
|
|
@@ -35659,12 +36080,12 @@ var init_handler2 = __esm({
|
|
|
35659
36080
|
if (dir.has(item)) {
|
|
35660
36081
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
35661
36082
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
35662
|
-
this.fsw._emit(EV.CHANGE,
|
|
36083
|
+
this.fsw._emit(EV.CHANGE, path23, entry.stats);
|
|
35663
36084
|
}
|
|
35664
36085
|
} else {
|
|
35665
36086
|
dir.add(item);
|
|
35666
36087
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
35667
|
-
this.fsw._emit(EV.ADD,
|
|
36088
|
+
this.fsw._emit(EV.ADD, path23, entry.stats);
|
|
35668
36089
|
}
|
|
35669
36090
|
this.fsw._emitReady();
|
|
35670
36091
|
return true;
|
|
@@ -35694,9 +36115,9 @@ var init_handler2 = __esm({
|
|
|
35694
36115
|
return;
|
|
35695
36116
|
}
|
|
35696
36117
|
const item = entry.path;
|
|
35697
|
-
let
|
|
36118
|
+
let path23 = sp.join(directory, item);
|
|
35698
36119
|
current.add(item);
|
|
35699
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
36120
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path23, item)) {
|
|
35700
36121
|
return;
|
|
35701
36122
|
}
|
|
35702
36123
|
if (this.fsw.closed) {
|
|
@@ -35705,8 +36126,8 @@ var init_handler2 = __esm({
|
|
|
35705
36126
|
}
|
|
35706
36127
|
if (item === target || !target && !previous.has(item)) {
|
|
35707
36128
|
this.fsw._incrReadyCount();
|
|
35708
|
-
|
|
35709
|
-
this._addToNodeFs(
|
|
36129
|
+
path23 = sp.join(dir, sp.relative(dir, path23));
|
|
36130
|
+
this._addToNodeFs(path23, initialAdd, wh, depth + 1);
|
|
35710
36131
|
}
|
|
35711
36132
|
}).on(EV.ERROR, this._boundHandleError);
|
|
35712
36133
|
return new Promise((resolve13, reject) => {
|
|
@@ -35775,13 +36196,13 @@ var init_handler2 = __esm({
|
|
|
35775
36196
|
* @param depth Child path actually targeted for watch
|
|
35776
36197
|
* @param target Child path actually targeted for watch
|
|
35777
36198
|
*/
|
|
35778
|
-
async _addToNodeFs(
|
|
36199
|
+
async _addToNodeFs(path23, initialAdd, priorWh, depth, target) {
|
|
35779
36200
|
const ready = this.fsw._emitReady;
|
|
35780
|
-
if (this.fsw._isIgnored(
|
|
36201
|
+
if (this.fsw._isIgnored(path23) || this.fsw.closed) {
|
|
35781
36202
|
ready();
|
|
35782
36203
|
return false;
|
|
35783
36204
|
}
|
|
35784
|
-
const wh = this.fsw._getWatchHelpers(
|
|
36205
|
+
const wh = this.fsw._getWatchHelpers(path23);
|
|
35785
36206
|
if (priorWh) {
|
|
35786
36207
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
35787
36208
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -35797,8 +36218,8 @@ var init_handler2 = __esm({
|
|
|
35797
36218
|
const follow = this.fsw.options.followSymlinks;
|
|
35798
36219
|
let closer;
|
|
35799
36220
|
if (stats.isDirectory()) {
|
|
35800
|
-
const absPath = sp.resolve(
|
|
35801
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
36221
|
+
const absPath = sp.resolve(path23);
|
|
36222
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path23) : path23;
|
|
35802
36223
|
if (this.fsw.closed)
|
|
35803
36224
|
return;
|
|
35804
36225
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -35808,29 +36229,29 @@ var init_handler2 = __esm({
|
|
|
35808
36229
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
35809
36230
|
}
|
|
35810
36231
|
} else if (stats.isSymbolicLink()) {
|
|
35811
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
36232
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path23) : path23;
|
|
35812
36233
|
if (this.fsw.closed)
|
|
35813
36234
|
return;
|
|
35814
36235
|
const parent = sp.dirname(wh.watchPath);
|
|
35815
36236
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
35816
36237
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
35817
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
36238
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path23, wh, targetPath);
|
|
35818
36239
|
if (this.fsw.closed)
|
|
35819
36240
|
return;
|
|
35820
36241
|
if (targetPath !== void 0) {
|
|
35821
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
36242
|
+
this.fsw._symlinkPaths.set(sp.resolve(path23), targetPath);
|
|
35822
36243
|
}
|
|
35823
36244
|
} else {
|
|
35824
36245
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
35825
36246
|
}
|
|
35826
36247
|
ready();
|
|
35827
36248
|
if (closer)
|
|
35828
|
-
this.fsw._addPathCloser(
|
|
36249
|
+
this.fsw._addPathCloser(path23, closer);
|
|
35829
36250
|
return false;
|
|
35830
36251
|
} catch (error48) {
|
|
35831
36252
|
if (this.fsw._handleError(error48)) {
|
|
35832
36253
|
ready();
|
|
35833
|
-
return
|
|
36254
|
+
return path23;
|
|
35834
36255
|
}
|
|
35835
36256
|
}
|
|
35836
36257
|
}
|
|
@@ -35865,24 +36286,24 @@ function createPattern(matcher) {
|
|
|
35865
36286
|
}
|
|
35866
36287
|
return () => false;
|
|
35867
36288
|
}
|
|
35868
|
-
function normalizePath(
|
|
35869
|
-
if (typeof
|
|
36289
|
+
function normalizePath(path23) {
|
|
36290
|
+
if (typeof path23 !== "string")
|
|
35870
36291
|
throw new Error("string expected");
|
|
35871
|
-
|
|
35872
|
-
|
|
36292
|
+
path23 = sp2.normalize(path23);
|
|
36293
|
+
path23 = path23.replace(/\\/g, "/");
|
|
35873
36294
|
let prepend = false;
|
|
35874
|
-
if (
|
|
36295
|
+
if (path23.startsWith("//"))
|
|
35875
36296
|
prepend = true;
|
|
35876
|
-
|
|
36297
|
+
path23 = path23.replace(DOUBLE_SLASH_RE, "/");
|
|
35877
36298
|
if (prepend)
|
|
35878
|
-
|
|
35879
|
-
return
|
|
36299
|
+
path23 = "/" + path23;
|
|
36300
|
+
return path23;
|
|
35880
36301
|
}
|
|
35881
36302
|
function matchPatterns(patterns, testString, stats) {
|
|
35882
|
-
const
|
|
36303
|
+
const path23 = normalizePath(testString);
|
|
35883
36304
|
for (let index = 0; index < patterns.length; index++) {
|
|
35884
36305
|
const pattern = patterns[index];
|
|
35885
|
-
if (pattern(
|
|
36306
|
+
if (pattern(path23, stats)) {
|
|
35886
36307
|
return true;
|
|
35887
36308
|
}
|
|
35888
36309
|
}
|
|
@@ -35945,19 +36366,19 @@ var init_chokidar = __esm({
|
|
|
35945
36366
|
}
|
|
35946
36367
|
return str;
|
|
35947
36368
|
};
|
|
35948
|
-
normalizePathToUnix = (
|
|
35949
|
-
normalizeIgnored = (cwd = "") => (
|
|
35950
|
-
if (typeof
|
|
35951
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
36369
|
+
normalizePathToUnix = (path23) => toUnix(sp2.normalize(toUnix(path23)));
|
|
36370
|
+
normalizeIgnored = (cwd = "") => (path23) => {
|
|
36371
|
+
if (typeof path23 === "string") {
|
|
36372
|
+
return normalizePathToUnix(sp2.isAbsolute(path23) ? path23 : sp2.join(cwd, path23));
|
|
35952
36373
|
} else {
|
|
35953
|
-
return
|
|
36374
|
+
return path23;
|
|
35954
36375
|
}
|
|
35955
36376
|
};
|
|
35956
|
-
getAbsolutePath = (
|
|
35957
|
-
if (sp2.isAbsolute(
|
|
35958
|
-
return
|
|
36377
|
+
getAbsolutePath = (path23, cwd) => {
|
|
36378
|
+
if (sp2.isAbsolute(path23)) {
|
|
36379
|
+
return path23;
|
|
35959
36380
|
}
|
|
35960
|
-
return sp2.join(cwd,
|
|
36381
|
+
return sp2.join(cwd, path23);
|
|
35961
36382
|
};
|
|
35962
36383
|
EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
35963
36384
|
DirEntry = class {
|
|
@@ -36022,10 +36443,10 @@ var init_chokidar = __esm({
|
|
|
36022
36443
|
dirParts;
|
|
36023
36444
|
followSymlinks;
|
|
36024
36445
|
statMethod;
|
|
36025
|
-
constructor(
|
|
36446
|
+
constructor(path23, follow, fsw) {
|
|
36026
36447
|
this.fsw = fsw;
|
|
36027
|
-
const watchPath =
|
|
36028
|
-
this.path =
|
|
36448
|
+
const watchPath = path23;
|
|
36449
|
+
this.path = path23 = path23.replace(REPLACER_RE, "");
|
|
36029
36450
|
this.watchPath = watchPath;
|
|
36030
36451
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
36031
36452
|
this.dirParts = [];
|
|
@@ -36165,20 +36586,20 @@ var init_chokidar = __esm({
|
|
|
36165
36586
|
this._closePromise = void 0;
|
|
36166
36587
|
let paths = unifyPaths(paths_);
|
|
36167
36588
|
if (cwd) {
|
|
36168
|
-
paths = paths.map((
|
|
36169
|
-
const absPath = getAbsolutePath(
|
|
36589
|
+
paths = paths.map((path23) => {
|
|
36590
|
+
const absPath = getAbsolutePath(path23, cwd);
|
|
36170
36591
|
return absPath;
|
|
36171
36592
|
});
|
|
36172
36593
|
}
|
|
36173
|
-
paths.forEach((
|
|
36174
|
-
this._removeIgnoredPath(
|
|
36594
|
+
paths.forEach((path23) => {
|
|
36595
|
+
this._removeIgnoredPath(path23);
|
|
36175
36596
|
});
|
|
36176
36597
|
this._userIgnored = void 0;
|
|
36177
36598
|
if (!this._readyCount)
|
|
36178
36599
|
this._readyCount = 0;
|
|
36179
36600
|
this._readyCount += paths.length;
|
|
36180
|
-
Promise.all(paths.map(async (
|
|
36181
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
36601
|
+
Promise.all(paths.map(async (path23) => {
|
|
36602
|
+
const res = await this._nodeFsHandler._addToNodeFs(path23, !_internal, void 0, 0, _origAdd);
|
|
36182
36603
|
if (res)
|
|
36183
36604
|
this._emitReady();
|
|
36184
36605
|
return res;
|
|
@@ -36200,17 +36621,17 @@ var init_chokidar = __esm({
|
|
|
36200
36621
|
return this;
|
|
36201
36622
|
const paths = unifyPaths(paths_);
|
|
36202
36623
|
const { cwd } = this.options;
|
|
36203
|
-
paths.forEach((
|
|
36204
|
-
if (!sp2.isAbsolute(
|
|
36624
|
+
paths.forEach((path23) => {
|
|
36625
|
+
if (!sp2.isAbsolute(path23) && !this._closers.has(path23)) {
|
|
36205
36626
|
if (cwd)
|
|
36206
|
-
|
|
36207
|
-
|
|
36627
|
+
path23 = sp2.join(cwd, path23);
|
|
36628
|
+
path23 = sp2.resolve(path23);
|
|
36208
36629
|
}
|
|
36209
|
-
this._closePath(
|
|
36210
|
-
this._addIgnoredPath(
|
|
36211
|
-
if (this._watched.has(
|
|
36630
|
+
this._closePath(path23);
|
|
36631
|
+
this._addIgnoredPath(path23);
|
|
36632
|
+
if (this._watched.has(path23)) {
|
|
36212
36633
|
this._addIgnoredPath({
|
|
36213
|
-
path:
|
|
36634
|
+
path: path23,
|
|
36214
36635
|
recursive: true
|
|
36215
36636
|
});
|
|
36216
36637
|
}
|
|
@@ -36274,38 +36695,38 @@ var init_chokidar = __esm({
|
|
|
36274
36695
|
* @param stats arguments to be passed with event
|
|
36275
36696
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
36276
36697
|
*/
|
|
36277
|
-
async _emit(event,
|
|
36698
|
+
async _emit(event, path23, stats) {
|
|
36278
36699
|
if (this.closed)
|
|
36279
36700
|
return;
|
|
36280
36701
|
const opts = this.options;
|
|
36281
36702
|
if (isWindows)
|
|
36282
|
-
|
|
36703
|
+
path23 = sp2.normalize(path23);
|
|
36283
36704
|
if (opts.cwd)
|
|
36284
|
-
|
|
36285
|
-
const args = [
|
|
36705
|
+
path23 = sp2.relative(opts.cwd, path23);
|
|
36706
|
+
const args = [path23];
|
|
36286
36707
|
if (stats != null)
|
|
36287
36708
|
args.push(stats);
|
|
36288
36709
|
const awf = opts.awaitWriteFinish;
|
|
36289
36710
|
let pw;
|
|
36290
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
36711
|
+
if (awf && (pw = this._pendingWrites.get(path23))) {
|
|
36291
36712
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
36292
36713
|
return this;
|
|
36293
36714
|
}
|
|
36294
36715
|
if (opts.atomic) {
|
|
36295
36716
|
if (event === EVENTS.UNLINK) {
|
|
36296
|
-
this._pendingUnlinks.set(
|
|
36717
|
+
this._pendingUnlinks.set(path23, [event, ...args]);
|
|
36297
36718
|
setTimeout(() => {
|
|
36298
|
-
this._pendingUnlinks.forEach((entry,
|
|
36719
|
+
this._pendingUnlinks.forEach((entry, path24) => {
|
|
36299
36720
|
this.emit(...entry);
|
|
36300
36721
|
this.emit(EVENTS.ALL, ...entry);
|
|
36301
|
-
this._pendingUnlinks.delete(
|
|
36722
|
+
this._pendingUnlinks.delete(path24);
|
|
36302
36723
|
});
|
|
36303
36724
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
36304
36725
|
return this;
|
|
36305
36726
|
}
|
|
36306
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
36727
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path23)) {
|
|
36307
36728
|
event = EVENTS.CHANGE;
|
|
36308
|
-
this._pendingUnlinks.delete(
|
|
36729
|
+
this._pendingUnlinks.delete(path23);
|
|
36309
36730
|
}
|
|
36310
36731
|
}
|
|
36311
36732
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -36323,16 +36744,16 @@ var init_chokidar = __esm({
|
|
|
36323
36744
|
this.emitWithAll(event, args);
|
|
36324
36745
|
}
|
|
36325
36746
|
};
|
|
36326
|
-
this._awaitWriteFinish(
|
|
36747
|
+
this._awaitWriteFinish(path23, awf.stabilityThreshold, event, awfEmit);
|
|
36327
36748
|
return this;
|
|
36328
36749
|
}
|
|
36329
36750
|
if (event === EVENTS.CHANGE) {
|
|
36330
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
36751
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path23, 50);
|
|
36331
36752
|
if (isThrottled)
|
|
36332
36753
|
return this;
|
|
36333
36754
|
}
|
|
36334
36755
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
36335
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
36756
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path23) : path23;
|
|
36336
36757
|
let stats2;
|
|
36337
36758
|
try {
|
|
36338
36759
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -36363,23 +36784,23 @@ var init_chokidar = __esm({
|
|
|
36363
36784
|
* @param timeout duration of time to suppress duplicate actions
|
|
36364
36785
|
* @returns tracking object or false if action should be suppressed
|
|
36365
36786
|
*/
|
|
36366
|
-
_throttle(actionType,
|
|
36787
|
+
_throttle(actionType, path23, timeout) {
|
|
36367
36788
|
if (!this._throttled.has(actionType)) {
|
|
36368
36789
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
36369
36790
|
}
|
|
36370
36791
|
const action = this._throttled.get(actionType);
|
|
36371
36792
|
if (!action)
|
|
36372
36793
|
throw new Error("invalid throttle");
|
|
36373
|
-
const actionPath = action.get(
|
|
36794
|
+
const actionPath = action.get(path23);
|
|
36374
36795
|
if (actionPath) {
|
|
36375
36796
|
actionPath.count++;
|
|
36376
36797
|
return false;
|
|
36377
36798
|
}
|
|
36378
36799
|
let timeoutObject;
|
|
36379
36800
|
const clear = () => {
|
|
36380
|
-
const item = action.get(
|
|
36801
|
+
const item = action.get(path23);
|
|
36381
36802
|
const count = item ? item.count : 0;
|
|
36382
|
-
action.delete(
|
|
36803
|
+
action.delete(path23);
|
|
36383
36804
|
clearTimeout(timeoutObject);
|
|
36384
36805
|
if (item)
|
|
36385
36806
|
clearTimeout(item.timeoutObject);
|
|
@@ -36387,7 +36808,7 @@ var init_chokidar = __esm({
|
|
|
36387
36808
|
};
|
|
36388
36809
|
timeoutObject = setTimeout(clear, timeout);
|
|
36389
36810
|
const thr = { timeoutObject, clear, count: 0 };
|
|
36390
|
-
action.set(
|
|
36811
|
+
action.set(path23, thr);
|
|
36391
36812
|
return thr;
|
|
36392
36813
|
}
|
|
36393
36814
|
_incrReadyCount() {
|
|
@@ -36401,44 +36822,44 @@ var init_chokidar = __esm({
|
|
|
36401
36822
|
* @param event
|
|
36402
36823
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
36403
36824
|
*/
|
|
36404
|
-
_awaitWriteFinish(
|
|
36825
|
+
_awaitWriteFinish(path23, threshold, event, awfEmit) {
|
|
36405
36826
|
const awf = this.options.awaitWriteFinish;
|
|
36406
36827
|
if (typeof awf !== "object")
|
|
36407
36828
|
return;
|
|
36408
36829
|
const pollInterval = awf.pollInterval;
|
|
36409
36830
|
let timeoutHandler;
|
|
36410
|
-
let fullPath =
|
|
36411
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
36412
|
-
fullPath = sp2.join(this.options.cwd,
|
|
36831
|
+
let fullPath = path23;
|
|
36832
|
+
if (this.options.cwd && !sp2.isAbsolute(path23)) {
|
|
36833
|
+
fullPath = sp2.join(this.options.cwd, path23);
|
|
36413
36834
|
}
|
|
36414
36835
|
const now = /* @__PURE__ */ new Date();
|
|
36415
36836
|
const writes = this._pendingWrites;
|
|
36416
36837
|
function awaitWriteFinishFn(prevStat) {
|
|
36417
36838
|
(0, import_node_fs2.stat)(fullPath, (err, curStat) => {
|
|
36418
|
-
if (err || !writes.has(
|
|
36839
|
+
if (err || !writes.has(path23)) {
|
|
36419
36840
|
if (err && err.code !== "ENOENT")
|
|
36420
36841
|
awfEmit(err);
|
|
36421
36842
|
return;
|
|
36422
36843
|
}
|
|
36423
36844
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
36424
36845
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
36425
|
-
writes.get(
|
|
36846
|
+
writes.get(path23).lastChange = now2;
|
|
36426
36847
|
}
|
|
36427
|
-
const pw = writes.get(
|
|
36848
|
+
const pw = writes.get(path23);
|
|
36428
36849
|
const df = now2 - pw.lastChange;
|
|
36429
36850
|
if (df >= threshold) {
|
|
36430
|
-
writes.delete(
|
|
36851
|
+
writes.delete(path23);
|
|
36431
36852
|
awfEmit(void 0, curStat);
|
|
36432
36853
|
} else {
|
|
36433
36854
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
36434
36855
|
}
|
|
36435
36856
|
});
|
|
36436
36857
|
}
|
|
36437
|
-
if (!writes.has(
|
|
36438
|
-
writes.set(
|
|
36858
|
+
if (!writes.has(path23)) {
|
|
36859
|
+
writes.set(path23, {
|
|
36439
36860
|
lastChange: now,
|
|
36440
36861
|
cancelWait: () => {
|
|
36441
|
-
writes.delete(
|
|
36862
|
+
writes.delete(path23);
|
|
36442
36863
|
clearTimeout(timeoutHandler);
|
|
36443
36864
|
return event;
|
|
36444
36865
|
}
|
|
@@ -36449,8 +36870,8 @@ var init_chokidar = __esm({
|
|
|
36449
36870
|
/**
|
|
36450
36871
|
* Determines whether user has asked to ignore this path.
|
|
36451
36872
|
*/
|
|
36452
|
-
_isIgnored(
|
|
36453
|
-
if (this.options.atomic && DOT_RE.test(
|
|
36873
|
+
_isIgnored(path23, stats) {
|
|
36874
|
+
if (this.options.atomic && DOT_RE.test(path23))
|
|
36454
36875
|
return true;
|
|
36455
36876
|
if (!this._userIgnored) {
|
|
36456
36877
|
const { cwd } = this.options;
|
|
@@ -36460,17 +36881,17 @@ var init_chokidar = __esm({
|
|
|
36460
36881
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
36461
36882
|
this._userIgnored = anymatch(list, void 0);
|
|
36462
36883
|
}
|
|
36463
|
-
return this._userIgnored(
|
|
36884
|
+
return this._userIgnored(path23, stats);
|
|
36464
36885
|
}
|
|
36465
|
-
_isntIgnored(
|
|
36466
|
-
return !this._isIgnored(
|
|
36886
|
+
_isntIgnored(path23, stat4) {
|
|
36887
|
+
return !this._isIgnored(path23, stat4);
|
|
36467
36888
|
}
|
|
36468
36889
|
/**
|
|
36469
36890
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
36470
36891
|
* @param path file or directory pattern being watched
|
|
36471
36892
|
*/
|
|
36472
|
-
_getWatchHelpers(
|
|
36473
|
-
return new WatchHelper(
|
|
36893
|
+
_getWatchHelpers(path23) {
|
|
36894
|
+
return new WatchHelper(path23, this.options.followSymlinks, this);
|
|
36474
36895
|
}
|
|
36475
36896
|
// Directory helpers
|
|
36476
36897
|
// -----------------
|
|
@@ -36502,63 +36923,63 @@ var init_chokidar = __esm({
|
|
|
36502
36923
|
* @param item base path of item/directory
|
|
36503
36924
|
*/
|
|
36504
36925
|
_remove(directory, item, isDirectory) {
|
|
36505
|
-
const
|
|
36506
|
-
const fullPath = sp2.resolve(
|
|
36507
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
36508
|
-
if (!this._throttle("remove",
|
|
36926
|
+
const path23 = sp2.join(directory, item);
|
|
36927
|
+
const fullPath = sp2.resolve(path23);
|
|
36928
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path23) || this._watched.has(fullPath);
|
|
36929
|
+
if (!this._throttle("remove", path23, 100))
|
|
36509
36930
|
return;
|
|
36510
36931
|
if (!isDirectory && this._watched.size === 1) {
|
|
36511
36932
|
this.add(directory, item, true);
|
|
36512
36933
|
}
|
|
36513
|
-
const wp = this._getWatchedDir(
|
|
36934
|
+
const wp = this._getWatchedDir(path23);
|
|
36514
36935
|
const nestedDirectoryChildren = wp.getChildren();
|
|
36515
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
36936
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path23, nested));
|
|
36516
36937
|
const parent = this._getWatchedDir(directory);
|
|
36517
36938
|
const wasTracked = parent.has(item);
|
|
36518
36939
|
parent.remove(item);
|
|
36519
36940
|
if (this._symlinkPaths.has(fullPath)) {
|
|
36520
36941
|
this._symlinkPaths.delete(fullPath);
|
|
36521
36942
|
}
|
|
36522
|
-
let relPath =
|
|
36943
|
+
let relPath = path23;
|
|
36523
36944
|
if (this.options.cwd)
|
|
36524
|
-
relPath = sp2.relative(this.options.cwd,
|
|
36945
|
+
relPath = sp2.relative(this.options.cwd, path23);
|
|
36525
36946
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
36526
36947
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
36527
36948
|
if (event === EVENTS.ADD)
|
|
36528
36949
|
return;
|
|
36529
36950
|
}
|
|
36530
|
-
this._watched.delete(
|
|
36951
|
+
this._watched.delete(path23);
|
|
36531
36952
|
this._watched.delete(fullPath);
|
|
36532
36953
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
36533
|
-
if (wasTracked && !this._isIgnored(
|
|
36534
|
-
this._emit(eventName,
|
|
36535
|
-
this._closePath(
|
|
36954
|
+
if (wasTracked && !this._isIgnored(path23))
|
|
36955
|
+
this._emit(eventName, path23);
|
|
36956
|
+
this._closePath(path23);
|
|
36536
36957
|
}
|
|
36537
36958
|
/**
|
|
36538
36959
|
* Closes all watchers for a path
|
|
36539
36960
|
*/
|
|
36540
|
-
_closePath(
|
|
36541
|
-
this._closeFile(
|
|
36542
|
-
const dir = sp2.dirname(
|
|
36543
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
36961
|
+
_closePath(path23) {
|
|
36962
|
+
this._closeFile(path23);
|
|
36963
|
+
const dir = sp2.dirname(path23);
|
|
36964
|
+
this._getWatchedDir(dir).remove(sp2.basename(path23));
|
|
36544
36965
|
}
|
|
36545
36966
|
/**
|
|
36546
36967
|
* Closes only file-specific watchers
|
|
36547
36968
|
*/
|
|
36548
|
-
_closeFile(
|
|
36549
|
-
const closers = this._closers.get(
|
|
36969
|
+
_closeFile(path23) {
|
|
36970
|
+
const closers = this._closers.get(path23);
|
|
36550
36971
|
if (!closers)
|
|
36551
36972
|
return;
|
|
36552
36973
|
closers.forEach((closer) => closer());
|
|
36553
|
-
this._closers.delete(
|
|
36974
|
+
this._closers.delete(path23);
|
|
36554
36975
|
}
|
|
36555
|
-
_addPathCloser(
|
|
36976
|
+
_addPathCloser(path23, closer) {
|
|
36556
36977
|
if (!closer)
|
|
36557
36978
|
return;
|
|
36558
|
-
let list = this._closers.get(
|
|
36979
|
+
let list = this._closers.get(path23);
|
|
36559
36980
|
if (!list) {
|
|
36560
36981
|
list = [];
|
|
36561
|
-
this._closers.set(
|
|
36982
|
+
this._closers.set(path23, list);
|
|
36562
36983
|
}
|
|
36563
36984
|
list.push(closer);
|
|
36564
36985
|
}
|
|
@@ -36934,6 +37355,7 @@ var init_provider_loader = __esm({
|
|
|
36934
37355
|
resolve(type, context) {
|
|
36935
37356
|
const base = this.providers.get(type);
|
|
36936
37357
|
if (!base) return void 0;
|
|
37358
|
+
const providerDir = this.findProviderDirInternal(type) || void 0;
|
|
36937
37359
|
const currentOs = context?.os || process.platform;
|
|
36938
37360
|
const currentVersion = context?.version ?? this.versionArchive?.getLatest(type) ?? void 0;
|
|
36939
37361
|
const resolved = JSON.parse(JSON.stringify(base));
|
|
@@ -36943,6 +37365,9 @@ var init_provider_loader = __esm({
|
|
|
36943
37365
|
if (base.scripts) {
|
|
36944
37366
|
resolved.scripts = { ...base.scripts };
|
|
36945
37367
|
}
|
|
37368
|
+
if (providerDir) {
|
|
37369
|
+
resolved._resolvedProviderDir = providerDir;
|
|
37370
|
+
}
|
|
36946
37371
|
if (base.os?.[currentOs]) {
|
|
36947
37372
|
const osOverride = base.os[currentOs];
|
|
36948
37373
|
if (osOverride.scripts) {
|
|
@@ -36963,6 +37388,12 @@ var init_provider_loader = __esm({
|
|
|
36963
37388
|
if (loaded) {
|
|
36964
37389
|
resolved.scripts = loaded;
|
|
36965
37390
|
this.log(` [compatibility] ${type} v${currentVersion} \u2192 ${entry.scriptDir}`);
|
|
37391
|
+
resolved._resolvedScriptDir = entry.scriptDir;
|
|
37392
|
+
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
37393
|
+
if (providerDir) {
|
|
37394
|
+
const fullDir = path10.join(providerDir, entry.scriptDir);
|
|
37395
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
|
|
37396
|
+
}
|
|
36966
37397
|
matched = true;
|
|
36967
37398
|
}
|
|
36968
37399
|
break;
|
|
@@ -36973,6 +37404,12 @@ var init_provider_loader = __esm({
|
|
|
36973
37404
|
if (loaded) {
|
|
36974
37405
|
resolved.scripts = loaded;
|
|
36975
37406
|
this.log(` [compatibility] ${type} v${currentVersion} \u2192 default: ${base.defaultScriptDir}`);
|
|
37407
|
+
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
37408
|
+
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
37409
|
+
if (providerDir) {
|
|
37410
|
+
const fullDir = path10.join(providerDir, base.defaultScriptDir);
|
|
37411
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
|
|
37412
|
+
}
|
|
36976
37413
|
}
|
|
36977
37414
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
36978
37415
|
}
|
|
@@ -36985,6 +37422,12 @@ var init_provider_loader = __esm({
|
|
|
36985
37422
|
if (loaded) {
|
|
36986
37423
|
resolved.scripts = loaded;
|
|
36987
37424
|
this.log(` [version override] ${type} ${range} \u2192 ${dirOverride}`);
|
|
37425
|
+
resolved._resolvedScriptDir = dirOverride;
|
|
37426
|
+
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
37427
|
+
if (providerDir) {
|
|
37428
|
+
const fullDir = path10.join(providerDir, dirOverride);
|
|
37429
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
|
|
37430
|
+
}
|
|
36988
37431
|
}
|
|
36989
37432
|
} else if (override.scripts) {
|
|
36990
37433
|
resolved.scripts = { ...resolved.scripts, ...override.scripts };
|
|
@@ -36996,6 +37439,12 @@ var init_provider_loader = __esm({
|
|
|
36996
37439
|
if (loaded) {
|
|
36997
37440
|
resolved.scripts = loaded;
|
|
36998
37441
|
this.log(` [compatibility] ${type} no version detected \u2192 default: ${base.defaultScriptDir}`);
|
|
37442
|
+
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
37443
|
+
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
37444
|
+
if (providerDir) {
|
|
37445
|
+
const fullDir = path10.join(providerDir, base.defaultScriptDir);
|
|
37446
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
|
|
37447
|
+
}
|
|
36999
37448
|
}
|
|
37000
37449
|
}
|
|
37001
37450
|
if (base.overrides) {
|
|
@@ -37064,6 +37513,9 @@ var init_provider_loader = __esm({
|
|
|
37064
37513
|
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
|
|
37065
37514
|
});
|
|
37066
37515
|
const handleChange = (filePath) => {
|
|
37516
|
+
if (/[\/\\]fixtures[\/\\]/.test(filePath)) {
|
|
37517
|
+
return;
|
|
37518
|
+
}
|
|
37067
37519
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
37068
37520
|
this.log(`File changed: ${path10.basename(filePath)}, reloading...`);
|
|
37069
37521
|
this.reload();
|
|
@@ -37757,7 +38209,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
37757
38209
|
}
|
|
37758
38210
|
} else if (plat === "win32") {
|
|
37759
38211
|
try {
|
|
37760
|
-
const
|
|
38212
|
+
const fs19 = require("fs");
|
|
37761
38213
|
const appNameMap = getMacAppIdentifiers();
|
|
37762
38214
|
const appName = appNameMap[ideId];
|
|
37763
38215
|
if (appName) {
|
|
@@ -37766,8 +38218,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
37766
38218
|
appName,
|
|
37767
38219
|
"storage.json"
|
|
37768
38220
|
);
|
|
37769
|
-
if (
|
|
37770
|
-
const data = JSON.parse(
|
|
38221
|
+
if (fs19.existsSync(storagePath)) {
|
|
38222
|
+
const data = JSON.parse(fs19.readFileSync(storagePath, "utf-8"));
|
|
37771
38223
|
const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
|
|
37772
38224
|
if (workspaces.length > 0) {
|
|
37773
38225
|
const recent = workspaces[0];
|
|
@@ -39587,6 +40039,15 @@ var init_poller = __esm({
|
|
|
39587
40039
|
cdpManagerKey: ideType,
|
|
39588
40040
|
instanceKey: `ide:${ideType}`
|
|
39589
40041
|
});
|
|
40042
|
+
const activeSessionId2 = agentStreamManager.getActiveSessionId(parentSessionId);
|
|
40043
|
+
if (!activeSessionId2 || enabledExtTypes.size === 1) {
|
|
40044
|
+
await agentStreamManager.setActiveSession(
|
|
40045
|
+
cdp,
|
|
40046
|
+
parentSessionId,
|
|
40047
|
+
extInstance.getInstanceId()
|
|
40048
|
+
);
|
|
40049
|
+
LOG.info("AgentStream", `Auto-activated enabled extension: ${extType} (${ideType})`);
|
|
40050
|
+
}
|
|
39590
40051
|
}
|
|
39591
40052
|
LOG.info("AgentStream", `Extension added: ${extType} (enabled for ${ideType})`);
|
|
39592
40053
|
}
|
|
@@ -41422,6 +41883,160 @@ var init_dev_cdp_handlers = __esm({
|
|
|
41422
41883
|
});
|
|
41423
41884
|
|
|
41424
41885
|
// ../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts
|
|
41886
|
+
function slugifyFixtureName(value) {
|
|
41887
|
+
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
41888
|
+
return normalized || `fixture-${Date.now()}`;
|
|
41889
|
+
}
|
|
41890
|
+
function getCliFixtureDir(ctx, type) {
|
|
41891
|
+
const providerDir = ctx.providerLoader.findProviderDir(type);
|
|
41892
|
+
if (!providerDir) {
|
|
41893
|
+
throw new Error(`Provider directory not found for '${type}'`);
|
|
41894
|
+
}
|
|
41895
|
+
return path16.join(providerDir, "fixtures");
|
|
41896
|
+
}
|
|
41897
|
+
function readCliFixture(ctx, type, name) {
|
|
41898
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
41899
|
+
const filePath = path16.join(fixtureDir, `${name}.json`);
|
|
41900
|
+
if (!fs13.existsSync(filePath)) {
|
|
41901
|
+
throw new Error(`Fixture not found: ${filePath}`);
|
|
41902
|
+
}
|
|
41903
|
+
return JSON.parse(fs13.readFileSync(filePath, "utf-8"));
|
|
41904
|
+
}
|
|
41905
|
+
function getExerciseTranscriptText(result) {
|
|
41906
|
+
const parts = [];
|
|
41907
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41908
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41909
|
+
for (const message of [...debugMessages, ...traceMessages]) {
|
|
41910
|
+
if (!message || typeof message.content !== "string") continue;
|
|
41911
|
+
parts.push(message.content);
|
|
41912
|
+
}
|
|
41913
|
+
if (typeof result?.debug?.partialResponse === "string") parts.push(result.debug.partialResponse);
|
|
41914
|
+
if (typeof result?.trace?.responseBuffer === "string") parts.push(result.trace.responseBuffer);
|
|
41915
|
+
return parts.join("\n");
|
|
41916
|
+
}
|
|
41917
|
+
function getExerciseLastAssistant(result) {
|
|
41918
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41919
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41920
|
+
for (const messages of [debugMessages, traceMessages]) {
|
|
41921
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
41922
|
+
const message = messages[i];
|
|
41923
|
+
if (message?.role === "assistant" && typeof message.content === "string" && message.content.trim()) {
|
|
41924
|
+
return message.content;
|
|
41925
|
+
}
|
|
41926
|
+
}
|
|
41927
|
+
}
|
|
41928
|
+
return "";
|
|
41929
|
+
}
|
|
41930
|
+
function getExerciseMessageCount(result) {
|
|
41931
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41932
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41933
|
+
return Math.max(debugMessages.length, traceMessages.length);
|
|
41934
|
+
}
|
|
41935
|
+
function compileFixtureRegex(source) {
|
|
41936
|
+
const value = String(source || "").trim();
|
|
41937
|
+
if (!value) return null;
|
|
41938
|
+
const delimited = value.match(/^\/([\s\S]+)\/([dgimsuvy]*)$/);
|
|
41939
|
+
try {
|
|
41940
|
+
if (delimited) {
|
|
41941
|
+
return new RegExp(delimited[1], delimited[2]);
|
|
41942
|
+
}
|
|
41943
|
+
return new RegExp(value, "m");
|
|
41944
|
+
} catch {
|
|
41945
|
+
return null;
|
|
41946
|
+
}
|
|
41947
|
+
}
|
|
41948
|
+
function statusesContainSequence(actual, expected) {
|
|
41949
|
+
if (!expected.length) return true;
|
|
41950
|
+
let index = 0;
|
|
41951
|
+
for (const status of actual) {
|
|
41952
|
+
if (status === expected[index]) index += 1;
|
|
41953
|
+
if (index >= expected.length) return true;
|
|
41954
|
+
}
|
|
41955
|
+
return false;
|
|
41956
|
+
}
|
|
41957
|
+
function validateCliFixtureResult(result, assertions) {
|
|
41958
|
+
const failures = [];
|
|
41959
|
+
const transcriptText = getExerciseTranscriptText(result);
|
|
41960
|
+
const lastAssistant = getExerciseLastAssistant(result);
|
|
41961
|
+
const mustContainAny = assertions.mustContainAny || [];
|
|
41962
|
+
const mustNotContainAny = assertions.mustNotContainAny || [];
|
|
41963
|
+
const mustMatchAny = assertions.mustMatchAny || [];
|
|
41964
|
+
const mustNotMatchAny = assertions.mustNotMatchAny || [];
|
|
41965
|
+
const lastAssistantMustContainAny = assertions.lastAssistantMustContainAny || [];
|
|
41966
|
+
const lastAssistantMustNotContainAny = assertions.lastAssistantMustNotContainAny || [];
|
|
41967
|
+
const lastAssistantMustMatchAny = assertions.lastAssistantMustMatchAny || [];
|
|
41968
|
+
const lastAssistantMustNotMatchAny = assertions.lastAssistantMustNotMatchAny || [];
|
|
41969
|
+
const statusesSeen = Array.isArray(result?.statusesSeen) ? result.statusesSeen.map((value) => String(value)) : [];
|
|
41970
|
+
if (assertions.requireNotTimedOut !== false && result?.timedOut) {
|
|
41971
|
+
failures.push("Exercise timed out");
|
|
41972
|
+
}
|
|
41973
|
+
const missingRequired = mustContainAny.filter((value) => !transcriptText.includes(value));
|
|
41974
|
+
if (missingRequired.length > 0) {
|
|
41975
|
+
failures.push(`Missing required substrings: ${missingRequired.join(", ")}`);
|
|
41976
|
+
}
|
|
41977
|
+
const presentBanned = mustNotContainAny.filter((value) => transcriptText.includes(value));
|
|
41978
|
+
if (presentBanned.length > 0) {
|
|
41979
|
+
failures.push(`Found banned substrings: ${presentBanned.join(", ")}`);
|
|
41980
|
+
}
|
|
41981
|
+
const missingRegex = mustMatchAny.filter((value) => {
|
|
41982
|
+
const regex = compileFixtureRegex(value);
|
|
41983
|
+
return !regex || !regex.test(transcriptText);
|
|
41984
|
+
});
|
|
41985
|
+
if (missingRegex.length > 0) {
|
|
41986
|
+
failures.push(`Missing required regex matches: ${missingRegex.join(", ")}`);
|
|
41987
|
+
}
|
|
41988
|
+
const presentBannedRegex = mustNotMatchAny.filter((value) => {
|
|
41989
|
+
const regex = compileFixtureRegex(value);
|
|
41990
|
+
return !!regex && regex.test(transcriptText);
|
|
41991
|
+
});
|
|
41992
|
+
if (presentBannedRegex.length > 0) {
|
|
41993
|
+
failures.push(`Found banned regex matches: ${presentBannedRegex.join(", ")}`);
|
|
41994
|
+
}
|
|
41995
|
+
const missingLastAssistant = lastAssistantMustContainAny.filter((value) => !lastAssistant.includes(value));
|
|
41996
|
+
if (missingLastAssistant.length > 0) {
|
|
41997
|
+
failures.push(`Missing required lastAssistant substrings: ${missingLastAssistant.join(", ")}`);
|
|
41998
|
+
}
|
|
41999
|
+
const presentBannedLastAssistant = lastAssistantMustNotContainAny.filter((value) => lastAssistant.includes(value));
|
|
42000
|
+
if (presentBannedLastAssistant.length > 0) {
|
|
42001
|
+
failures.push(`Found banned lastAssistant substrings: ${presentBannedLastAssistant.join(", ")}`);
|
|
42002
|
+
}
|
|
42003
|
+
const missingLastAssistantRegex = lastAssistantMustMatchAny.filter((value) => {
|
|
42004
|
+
const regex = compileFixtureRegex(value);
|
|
42005
|
+
return !regex || !regex.test(lastAssistant);
|
|
42006
|
+
});
|
|
42007
|
+
if (missingLastAssistantRegex.length > 0) {
|
|
42008
|
+
failures.push(`Missing required lastAssistant regex matches: ${missingLastAssistantRegex.join(", ")}`);
|
|
42009
|
+
}
|
|
42010
|
+
const presentBannedLastAssistantRegex = lastAssistantMustNotMatchAny.filter((value) => {
|
|
42011
|
+
const regex = compileFixtureRegex(value);
|
|
42012
|
+
return !!regex && regex.test(lastAssistant);
|
|
42013
|
+
});
|
|
42014
|
+
if (presentBannedLastAssistantRegex.length > 0) {
|
|
42015
|
+
failures.push(`Found banned lastAssistant regex matches: ${presentBannedLastAssistantRegex.join(", ")}`);
|
|
42016
|
+
}
|
|
42017
|
+
if (assertions.statusesSeen?.length && !statusesContainSequence(statusesSeen, assertions.statusesSeen)) {
|
|
42018
|
+
failures.push(`Expected statuses sequence not observed: ${assertions.statusesSeen.join(" -> ")}`);
|
|
42019
|
+
}
|
|
42020
|
+
if (result && typeof result === "object") {
|
|
42021
|
+
result.lastAssistant = lastAssistant;
|
|
42022
|
+
}
|
|
42023
|
+
return failures;
|
|
42024
|
+
}
|
|
42025
|
+
function getCliProviderResolutionMeta(ctx, type, adapter) {
|
|
42026
|
+
const adapterMeta = typeof adapter?.getProviderResolutionMeta === "function" ? adapter.getProviderResolutionMeta() : adapter?.getDebugState?.()?.providerResolution || null;
|
|
42027
|
+
const resolvedProvider = ctx.providerLoader.resolve(type);
|
|
42028
|
+
if (!adapterMeta && !resolvedProvider) return null;
|
|
42029
|
+
return {
|
|
42030
|
+
type,
|
|
42031
|
+
providerDir: adapterMeta?.providerDir || resolvedProvider?._resolvedProviderDir || ctx.providerLoader.findProviderDir(type),
|
|
42032
|
+
scriptDir: adapterMeta?.scriptDir || resolvedProvider?._resolvedScriptDir || null,
|
|
42033
|
+
scriptsPath: adapterMeta?.scriptsPath || resolvedProvider?._resolvedScriptsPath || null,
|
|
42034
|
+
scriptsSource: adapterMeta?.scriptsSource || resolvedProvider?._resolvedScriptsSource || null,
|
|
42035
|
+
resolvedVersion: adapterMeta?.resolvedVersion || resolvedProvider?._resolvedVersion || null,
|
|
42036
|
+
resolvedOs: adapterMeta?.resolvedOs || resolvedProvider?._resolvedOs || null,
|
|
42037
|
+
versionWarning: adapterMeta?.versionWarning || resolvedProvider?._versionWarning || null
|
|
42038
|
+
};
|
|
42039
|
+
}
|
|
41425
42040
|
function findCliTarget(ctx, type, instanceId) {
|
|
41426
42041
|
if (!ctx.instanceManager) return null;
|
|
41427
42042
|
const cliStates = ctx.instanceManager.collectAllStates().filter((s15) => s15.category === "cli" || s15.category === "acp");
|
|
@@ -41430,6 +42045,331 @@ function findCliTarget(ctx, type, instanceId) {
|
|
|
41430
42045
|
const matches = cliStates.filter((s15) => s15.type === type);
|
|
41431
42046
|
return matches[matches.length - 1] || null;
|
|
41432
42047
|
}
|
|
42048
|
+
function getCliTargetBundle(ctx, type, instanceId) {
|
|
42049
|
+
if (!ctx.instanceManager) return null;
|
|
42050
|
+
const target = findCliTarget(ctx, type, instanceId);
|
|
42051
|
+
if (!target) return null;
|
|
42052
|
+
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
42053
|
+
if (!instance) return null;
|
|
42054
|
+
const adapter = instance.getAdapter?.() || instance.adapter;
|
|
42055
|
+
if (!adapter) return null;
|
|
42056
|
+
return { target, instance, adapter };
|
|
42057
|
+
}
|
|
42058
|
+
function sleep(ms2) {
|
|
42059
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms2));
|
|
42060
|
+
}
|
|
42061
|
+
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
42062
|
+
const startedAt = Date.now();
|
|
42063
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
42064
|
+
const bundle = getCliTargetBundle(ctx, type, instanceId);
|
|
42065
|
+
if (bundle) {
|
|
42066
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
42067
|
+
const startupParseGate = !!debug?.startupParseGate;
|
|
42068
|
+
const adapterReady = !!debug?.ready;
|
|
42069
|
+
const visibleStatusReady = bundle.target.status === "generating" || bundle.target.status === "waiting_approval";
|
|
42070
|
+
const idleReady = bundle.target.status === "idle" && !startupParseGate;
|
|
42071
|
+
if (adapterReady || visibleStatusReady || idleReady) {
|
|
42072
|
+
return bundle;
|
|
42073
|
+
}
|
|
42074
|
+
}
|
|
42075
|
+
await sleep(100);
|
|
42076
|
+
}
|
|
42077
|
+
return getCliTargetBundle(ctx, type, instanceId);
|
|
42078
|
+
}
|
|
42079
|
+
async function runCliExerciseInternal(ctx, body) {
|
|
42080
|
+
if (!ctx.cliManager) {
|
|
42081
|
+
throw new Error("CliManager not available");
|
|
42082
|
+
}
|
|
42083
|
+
if (!ctx.instanceManager) {
|
|
42084
|
+
throw new Error("InstanceManager not available");
|
|
42085
|
+
}
|
|
42086
|
+
const {
|
|
42087
|
+
type,
|
|
42088
|
+
text,
|
|
42089
|
+
instanceId: requestedInstanceId,
|
|
42090
|
+
workingDir,
|
|
42091
|
+
args,
|
|
42092
|
+
autoLaunch = true,
|
|
42093
|
+
freshSession = true,
|
|
42094
|
+
autoResolveApprovals = true,
|
|
42095
|
+
approvalButtonIndex = 0,
|
|
42096
|
+
timeoutMs = 45e3,
|
|
42097
|
+
readyTimeoutMs = 15e3,
|
|
42098
|
+
idleSettledMs = 1200,
|
|
42099
|
+
traceLimit = 160,
|
|
42100
|
+
stopWhenDone = false
|
|
42101
|
+
} = body || {};
|
|
42102
|
+
if (!type) {
|
|
42103
|
+
throw new Error("type required (e.g. claude-cli, codex-cli)");
|
|
42104
|
+
}
|
|
42105
|
+
if (!text || typeof text !== "string") {
|
|
42106
|
+
throw new Error("text required (prompt to send to the CLI)");
|
|
42107
|
+
}
|
|
42108
|
+
let resolvedInstanceId = requestedInstanceId;
|
|
42109
|
+
if (freshSession) {
|
|
42110
|
+
const staleTargets = ctx.instanceManager.collectAllStates().filter((state) => (state.category === "cli" || state.category === "acp") && state.type === type).map((state) => state.instanceId);
|
|
42111
|
+
for (const staleId of staleTargets) {
|
|
42112
|
+
ctx.instanceManager.removeInstance(staleId);
|
|
42113
|
+
}
|
|
42114
|
+
resolvedInstanceId = void 0;
|
|
42115
|
+
}
|
|
42116
|
+
let bundle = getCliTargetBundle(ctx, type, resolvedInstanceId);
|
|
42117
|
+
if (!bundle && autoLaunch) {
|
|
42118
|
+
const launchArgs = [type, workingDir || process.cwd(), Array.isArray(args) ? args : []];
|
|
42119
|
+
let launched = null;
|
|
42120
|
+
let lastLaunchError = null;
|
|
42121
|
+
for (let attempt = 1; attempt <= 2; attempt += 1) {
|
|
42122
|
+
try {
|
|
42123
|
+
launched = await ctx.cliManager.startSession(...launchArgs);
|
|
42124
|
+
lastLaunchError = null;
|
|
42125
|
+
break;
|
|
42126
|
+
} catch (error48) {
|
|
42127
|
+
lastLaunchError = error48 instanceof Error ? error48 : new Error(String(error48?.message || error48));
|
|
42128
|
+
const message = String(lastLaunchError.message || "");
|
|
42129
|
+
const retryable = /ECONNREFUSED|session-host|Session host/i.test(message);
|
|
42130
|
+
if (!retryable || attempt === 2) break;
|
|
42131
|
+
await sleep(1e3);
|
|
42132
|
+
}
|
|
42133
|
+
}
|
|
42134
|
+
if (!launched) {
|
|
42135
|
+
throw lastLaunchError || new Error(`Failed to start ${type}`);
|
|
42136
|
+
}
|
|
42137
|
+
resolvedInstanceId = launched.runtimeSessionId;
|
|
42138
|
+
bundle = await waitForCliReady(ctx, type, resolvedInstanceId, Math.max(1e3, readyTimeoutMs));
|
|
42139
|
+
}
|
|
42140
|
+
if (!bundle) {
|
|
42141
|
+
throw new Error(`No running instance found for: ${resolvedInstanceId || type}`);
|
|
42142
|
+
}
|
|
42143
|
+
const initialDebug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
42144
|
+
const initialTrace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
42145
|
+
const providerResolution = getCliProviderResolutionMeta(ctx, bundle.target.type, bundle.adapter);
|
|
42146
|
+
const preTraceCount = Number(initialTrace?.entryCount || 0);
|
|
42147
|
+
const startAt = Date.now();
|
|
42148
|
+
const statusesSeen = [];
|
|
42149
|
+
const approvalsResolved = [];
|
|
42150
|
+
let lastStatus = "";
|
|
42151
|
+
let lastModalKey = "";
|
|
42152
|
+
let idleSince = 0;
|
|
42153
|
+
let sawBusy = false;
|
|
42154
|
+
ctx.instanceManager.sendEvent(bundle.target.instanceId, "send_message", { text });
|
|
42155
|
+
while (Date.now() - startAt < Math.max(1e3, timeoutMs)) {
|
|
42156
|
+
await sleep(150);
|
|
42157
|
+
bundle = getCliTargetBundle(ctx, type, bundle.target.instanceId);
|
|
42158
|
+
if (!bundle) {
|
|
42159
|
+
throw new Error("CLI instance disappeared during exercise");
|
|
42160
|
+
}
|
|
42161
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
42162
|
+
const trace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
42163
|
+
const status = String(debug?.status || bundle.target.status || "unknown");
|
|
42164
|
+
const traceEntries = Array.isArray(trace?.entries) ? trace.entries : [];
|
|
42165
|
+
const sawSendMessage = traceEntries.some((entry) => entry?.type === "send_message");
|
|
42166
|
+
const sawSubmitWrite = traceEntries.some((entry) => entry?.type === "submit_write");
|
|
42167
|
+
const hasTurnStarted = sawSendMessage || sawSubmitWrite || !!debug?.currentTurnScope;
|
|
42168
|
+
if (status !== lastStatus) {
|
|
42169
|
+
statusesSeen.push(status);
|
|
42170
|
+
lastStatus = status;
|
|
42171
|
+
}
|
|
42172
|
+
if (status === "generating" || status === "waiting_approval") {
|
|
42173
|
+
sawBusy = true;
|
|
42174
|
+
idleSince = 0;
|
|
42175
|
+
}
|
|
42176
|
+
const modal = debug?.activeModal || trace?.activeModal || null;
|
|
42177
|
+
if (autoResolveApprovals && status === "waiting_approval" && modal && Array.isArray(modal.buttons) && modal.buttons.length > 0) {
|
|
42178
|
+
const clampedIndex = Math.max(0, Math.min(Number(approvalButtonIndex) || 0, modal.buttons.length - 1));
|
|
42179
|
+
const modalKey = JSON.stringify({
|
|
42180
|
+
message: modal.message || "",
|
|
42181
|
+
buttons: modal.buttons,
|
|
42182
|
+
index: clampedIndex
|
|
42183
|
+
});
|
|
42184
|
+
if (modalKey !== lastModalKey && typeof bundle.adapter.resolveModal === "function") {
|
|
42185
|
+
lastModalKey = modalKey;
|
|
42186
|
+
approvalsResolved.push({
|
|
42187
|
+
at: Date.now(),
|
|
42188
|
+
buttonIndex: clampedIndex,
|
|
42189
|
+
label: modal.buttons[clampedIndex] || null
|
|
42190
|
+
});
|
|
42191
|
+
bundle.adapter.resolveModal(clampedIndex);
|
|
42192
|
+
continue;
|
|
42193
|
+
}
|
|
42194
|
+
}
|
|
42195
|
+
const traceCount = Number(trace?.entryCount || 0);
|
|
42196
|
+
const hasProgress = hasTurnStarted && (traceCount > preTraceCount || statusesSeen.length > 1 || approvalsResolved.length > 0);
|
|
42197
|
+
if (status === "idle" && hasProgress && sawBusy) {
|
|
42198
|
+
if (!idleSince) idleSince = Date.now();
|
|
42199
|
+
if (Date.now() - idleSince >= Math.max(200, idleSettledMs)) {
|
|
42200
|
+
const payload2 = {
|
|
42201
|
+
exercised: true,
|
|
42202
|
+
instanceId: bundle.target.instanceId,
|
|
42203
|
+
providerState: {
|
|
42204
|
+
type: bundle.target.type,
|
|
42205
|
+
name: bundle.target.name,
|
|
42206
|
+
status: bundle.target.status,
|
|
42207
|
+
mode: "mode" in bundle.target ? bundle.target.mode : void 0
|
|
42208
|
+
},
|
|
42209
|
+
providerResolution,
|
|
42210
|
+
initialDebug,
|
|
42211
|
+
initialTrace,
|
|
42212
|
+
debug,
|
|
42213
|
+
trace,
|
|
42214
|
+
statusesSeen,
|
|
42215
|
+
approvalsResolved,
|
|
42216
|
+
elapsedMs: Date.now() - startAt,
|
|
42217
|
+
timedOut: false
|
|
42218
|
+
};
|
|
42219
|
+
payload2.lastAssistant = getExerciseLastAssistant(payload2);
|
|
42220
|
+
payload2.messageCount = getExerciseMessageCount(payload2);
|
|
42221
|
+
if (stopWhenDone) {
|
|
42222
|
+
ctx.instanceManager.removeInstance(bundle.target.instanceId);
|
|
42223
|
+
}
|
|
42224
|
+
return payload2;
|
|
42225
|
+
}
|
|
42226
|
+
} else if (status === "idle" && hasProgress) {
|
|
42227
|
+
if (!idleSince) idleSince = Date.now();
|
|
42228
|
+
if (Date.now() - idleSince >= Math.max(500, idleSettledMs) && Date.now() - startAt >= 750) {
|
|
42229
|
+
const payload2 = {
|
|
42230
|
+
exercised: true,
|
|
42231
|
+
instanceId: bundle.target.instanceId,
|
|
42232
|
+
providerState: {
|
|
42233
|
+
type: bundle.target.type,
|
|
42234
|
+
name: bundle.target.name,
|
|
42235
|
+
status: bundle.target.status,
|
|
42236
|
+
mode: "mode" in bundle.target ? bundle.target.mode : void 0
|
|
42237
|
+
},
|
|
42238
|
+
providerResolution,
|
|
42239
|
+
initialDebug,
|
|
42240
|
+
initialTrace,
|
|
42241
|
+
debug,
|
|
42242
|
+
trace,
|
|
42243
|
+
statusesSeen,
|
|
42244
|
+
approvalsResolved,
|
|
42245
|
+
elapsedMs: Date.now() - startAt,
|
|
42246
|
+
timedOut: false
|
|
42247
|
+
};
|
|
42248
|
+
payload2.lastAssistant = getExerciseLastAssistant(payload2);
|
|
42249
|
+
payload2.messageCount = getExerciseMessageCount(payload2);
|
|
42250
|
+
if (stopWhenDone) {
|
|
42251
|
+
ctx.instanceManager.removeInstance(bundle.target.instanceId);
|
|
42252
|
+
}
|
|
42253
|
+
return payload2;
|
|
42254
|
+
}
|
|
42255
|
+
} else {
|
|
42256
|
+
idleSince = 0;
|
|
42257
|
+
}
|
|
42258
|
+
}
|
|
42259
|
+
const finalBundle = getCliTargetBundle(ctx, type, bundle.target.instanceId) || bundle;
|
|
42260
|
+
const finalDebug = typeof finalBundle.adapter.getDebugState === "function" ? finalBundle.adapter.getDebugState() : null;
|
|
42261
|
+
const finalTrace = typeof finalBundle.adapter.getTraceState === "function" ? finalBundle.adapter.getTraceState(traceLimit) : null;
|
|
42262
|
+
if (stopWhenDone) {
|
|
42263
|
+
ctx.instanceManager.removeInstance(finalBundle.target.instanceId);
|
|
42264
|
+
}
|
|
42265
|
+
const payload = {
|
|
42266
|
+
exercised: true,
|
|
42267
|
+
instanceId: finalBundle.target.instanceId,
|
|
42268
|
+
providerState: {
|
|
42269
|
+
type: finalBundle.target.type,
|
|
42270
|
+
name: finalBundle.target.name,
|
|
42271
|
+
status: finalBundle.target.status,
|
|
42272
|
+
mode: "mode" in finalBundle.target ? finalBundle.target.mode : void 0
|
|
42273
|
+
},
|
|
42274
|
+
providerResolution: getCliProviderResolutionMeta(ctx, finalBundle.target.type, finalBundle.adapter),
|
|
42275
|
+
initialDebug,
|
|
42276
|
+
initialTrace,
|
|
42277
|
+
debug: finalDebug,
|
|
42278
|
+
trace: finalTrace,
|
|
42279
|
+
statusesSeen,
|
|
42280
|
+
approvalsResolved,
|
|
42281
|
+
elapsedMs: Date.now() - startAt,
|
|
42282
|
+
timedOut: true
|
|
42283
|
+
};
|
|
42284
|
+
payload.lastAssistant = getExerciseLastAssistant(payload);
|
|
42285
|
+
payload.messageCount = getExerciseMessageCount(payload);
|
|
42286
|
+
return payload;
|
|
42287
|
+
}
|
|
42288
|
+
async function runCliAutoImplVerification(ctx, type, verification) {
|
|
42289
|
+
const assertions = {
|
|
42290
|
+
mustContainAny: verification?.mustContainAny || [],
|
|
42291
|
+
mustNotContainAny: verification?.mustNotContainAny || [],
|
|
42292
|
+
mustMatchAny: verification?.mustMatchAny || [],
|
|
42293
|
+
mustNotMatchAny: verification?.mustNotMatchAny || [],
|
|
42294
|
+
lastAssistantMustContainAny: verification?.lastAssistantMustContainAny || [],
|
|
42295
|
+
lastAssistantMustNotContainAny: verification?.lastAssistantMustNotContainAny || [],
|
|
42296
|
+
lastAssistantMustMatchAny: verification?.lastAssistantMustMatchAny || [],
|
|
42297
|
+
lastAssistantMustNotMatchAny: verification?.lastAssistantMustNotMatchAny || [],
|
|
42298
|
+
requireNotTimedOut: true
|
|
42299
|
+
};
|
|
42300
|
+
const rawFixtureNames = Array.isArray(verification?.fixtureNames) ? verification.fixtureNames.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
42301
|
+
if (rawFixtureNames.length > 0) {
|
|
42302
|
+
const results = [];
|
|
42303
|
+
for (const rawFixtureName2 of rawFixtureNames) {
|
|
42304
|
+
const name = slugifyFixtureName(rawFixtureName2);
|
|
42305
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
42306
|
+
const mergedAssertions = {
|
|
42307
|
+
...fixture.assertions,
|
|
42308
|
+
...assertions
|
|
42309
|
+
};
|
|
42310
|
+
const result2 = await runCliExerciseInternal(ctx, {
|
|
42311
|
+
...fixture.request,
|
|
42312
|
+
type
|
|
42313
|
+
});
|
|
42314
|
+
const failures2 = validateCliFixtureResult(result2, mergedAssertions);
|
|
42315
|
+
results.push({
|
|
42316
|
+
fixtureName: name,
|
|
42317
|
+
pass: failures2.length === 0,
|
|
42318
|
+
failures: failures2,
|
|
42319
|
+
result: result2,
|
|
42320
|
+
assertions: mergedAssertions,
|
|
42321
|
+
fixture
|
|
42322
|
+
});
|
|
42323
|
+
}
|
|
42324
|
+
const firstFailure = results.find((item) => !item.pass) || results[results.length - 1];
|
|
42325
|
+
return {
|
|
42326
|
+
mode: "fixture_replay_suite",
|
|
42327
|
+
pass: results.every((item) => item.pass),
|
|
42328
|
+
failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
|
|
42329
|
+
result: firstFailure.result,
|
|
42330
|
+
assertions: firstFailure.assertions,
|
|
42331
|
+
fixture: firstFailure.fixture,
|
|
42332
|
+
results
|
|
42333
|
+
};
|
|
42334
|
+
}
|
|
42335
|
+
const rawFixtureName = String(verification?.fixtureName || "").trim();
|
|
42336
|
+
if (rawFixtureName) {
|
|
42337
|
+
const name = slugifyFixtureName(rawFixtureName);
|
|
42338
|
+
try {
|
|
42339
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
42340
|
+
const mergedAssertions = {
|
|
42341
|
+
...fixture.assertions,
|
|
42342
|
+
...assertions
|
|
42343
|
+
};
|
|
42344
|
+
const result2 = await runCliExerciseInternal(ctx, {
|
|
42345
|
+
...fixture.request,
|
|
42346
|
+
type
|
|
42347
|
+
});
|
|
42348
|
+
const failures2 = validateCliFixtureResult(result2, mergedAssertions);
|
|
42349
|
+
return {
|
|
42350
|
+
mode: "fixture_replay",
|
|
42351
|
+
pass: failures2.length === 0,
|
|
42352
|
+
failures: failures2,
|
|
42353
|
+
result: result2,
|
|
42354
|
+
assertions: mergedAssertions,
|
|
42355
|
+
fixture
|
|
42356
|
+
};
|
|
42357
|
+
} catch {
|
|
42358
|
+
}
|
|
42359
|
+
}
|
|
42360
|
+
const result = await runCliExerciseInternal(ctx, {
|
|
42361
|
+
...verification?.request || {},
|
|
42362
|
+
type
|
|
42363
|
+
});
|
|
42364
|
+
const failures = validateCliFixtureResult(result, assertions);
|
|
42365
|
+
return {
|
|
42366
|
+
mode: "exercise",
|
|
42367
|
+
pass: failures.length === 0,
|
|
42368
|
+
failures,
|
|
42369
|
+
result,
|
|
42370
|
+
assertions
|
|
42371
|
+
};
|
|
42372
|
+
}
|
|
41433
42373
|
async function handleCliStatus(ctx, _req, res) {
|
|
41434
42374
|
if (!ctx.instanceManager) {
|
|
41435
42375
|
ctx.json(res, 503, { error: "InstanceManager not available (daemon not fully initialized)" });
|
|
@@ -41568,12 +42508,14 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
41568
42508
|
status: target.status,
|
|
41569
42509
|
mode: "mode" in target ? target.mode : void 0
|
|
41570
42510
|
},
|
|
42511
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
41571
42512
|
debug: debugState
|
|
41572
42513
|
});
|
|
41573
42514
|
} else {
|
|
41574
42515
|
ctx.json(res, 200, {
|
|
41575
42516
|
instanceId: target.instanceId,
|
|
41576
42517
|
providerState: target,
|
|
42518
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
41577
42519
|
debug: null,
|
|
41578
42520
|
message: "No debug state available (adapter.getDebugState not found)"
|
|
41579
42521
|
});
|
|
@@ -41582,6 +42524,191 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
41582
42524
|
ctx.json(res, 500, { error: `Debug state failed: ${e.message}` });
|
|
41583
42525
|
}
|
|
41584
42526
|
}
|
|
42527
|
+
async function handleCliTrace(ctx, type, req, res) {
|
|
42528
|
+
if (!ctx.instanceManager) {
|
|
42529
|
+
ctx.json(res, 503, { error: "InstanceManager not available" });
|
|
42530
|
+
return;
|
|
42531
|
+
}
|
|
42532
|
+
const target = findCliTarget(ctx, type);
|
|
42533
|
+
if (!target) {
|
|
42534
|
+
const allStates = ctx.instanceManager.collectAllStates();
|
|
42535
|
+
ctx.json(res, 404, {
|
|
42536
|
+
error: `No running instance for: ${type}`,
|
|
42537
|
+
available: allStates.filter((s15) => s15.category === "cli" || s15.category === "acp").map((s15) => s15.type)
|
|
42538
|
+
});
|
|
42539
|
+
return;
|
|
42540
|
+
}
|
|
42541
|
+
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
42542
|
+
if (!instance) {
|
|
42543
|
+
ctx.json(res, 404, { error: `Instance not found: ${target.instanceId}` });
|
|
42544
|
+
return;
|
|
42545
|
+
}
|
|
42546
|
+
try {
|
|
42547
|
+
const adapter = instance.getAdapter?.() || instance.adapter;
|
|
42548
|
+
const url2 = new URL(req.url || "/", "http://127.0.0.1");
|
|
42549
|
+
const limit = parseInt(url2.searchParams.get("limit") || "120", 10);
|
|
42550
|
+
if (adapter && typeof adapter.getTraceState === "function") {
|
|
42551
|
+
const trace = adapter.getTraceState(limit);
|
|
42552
|
+
const debug = typeof adapter.getDebugState === "function" ? adapter.getDebugState() : null;
|
|
42553
|
+
ctx.json(res, 200, {
|
|
42554
|
+
instanceId: target.instanceId,
|
|
42555
|
+
providerState: {
|
|
42556
|
+
type: target.type,
|
|
42557
|
+
name: target.name,
|
|
42558
|
+
status: target.status,
|
|
42559
|
+
mode: "mode" in target ? target.mode : void 0
|
|
42560
|
+
},
|
|
42561
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
42562
|
+
debug,
|
|
42563
|
+
trace
|
|
42564
|
+
});
|
|
42565
|
+
} else {
|
|
42566
|
+
ctx.json(res, 200, {
|
|
42567
|
+
instanceId: target.instanceId,
|
|
42568
|
+
providerState: target,
|
|
42569
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
42570
|
+
debug: typeof adapter?.getDebugState === "function" ? adapter.getDebugState() : null,
|
|
42571
|
+
trace: null,
|
|
42572
|
+
message: "No trace state available (adapter.getTraceState not found)"
|
|
42573
|
+
});
|
|
42574
|
+
}
|
|
42575
|
+
} catch (e) {
|
|
42576
|
+
ctx.json(res, 500, { error: `Trace state failed: ${e.message}` });
|
|
42577
|
+
}
|
|
42578
|
+
}
|
|
42579
|
+
async function handleCliExercise(ctx, req, res) {
|
|
42580
|
+
try {
|
|
42581
|
+
const body = await ctx.readBody(req);
|
|
42582
|
+
const result = await runCliExerciseInternal(ctx, body || {});
|
|
42583
|
+
ctx.json(res, 200, result);
|
|
42584
|
+
} catch (e) {
|
|
42585
|
+
ctx.json(res, 500, { error: `Exercise failed: ${e.message}` });
|
|
42586
|
+
}
|
|
42587
|
+
}
|
|
42588
|
+
async function handleCliFixtureCapture(ctx, req, res) {
|
|
42589
|
+
try {
|
|
42590
|
+
const body = await ctx.readBody(req);
|
|
42591
|
+
const type = String(body?.type || "");
|
|
42592
|
+
const request = body?.request || {};
|
|
42593
|
+
if (!type) {
|
|
42594
|
+
ctx.json(res, 400, { error: "type required" });
|
|
42595
|
+
return;
|
|
42596
|
+
}
|
|
42597
|
+
if (!request?.text) {
|
|
42598
|
+
ctx.json(res, 400, { error: "request.text required" });
|
|
42599
|
+
return;
|
|
42600
|
+
}
|
|
42601
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
42602
|
+
fs13.mkdirSync(fixtureDir, { recursive: true });
|
|
42603
|
+
const name = slugifyFixtureName(String(body?.name || `${type}-${Date.now()}`));
|
|
42604
|
+
const result = await runCliExerciseInternal(ctx, { ...request, type });
|
|
42605
|
+
const fixture = {
|
|
42606
|
+
version: 1,
|
|
42607
|
+
kind: "cli-exercise-fixture",
|
|
42608
|
+
name,
|
|
42609
|
+
type,
|
|
42610
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
42611
|
+
providerDir: ctx.providerLoader.findProviderDir(type),
|
|
42612
|
+
providerResolution: result?.providerResolution || null,
|
|
42613
|
+
request: { ...request, type },
|
|
42614
|
+
result,
|
|
42615
|
+
assertions: {
|
|
42616
|
+
mustContainAny: Array.isArray(body?.assertions?.mustContainAny) ? body.assertions.mustContainAny : [],
|
|
42617
|
+
mustNotContainAny: Array.isArray(body?.assertions?.mustNotContainAny) ? body.assertions.mustNotContainAny : [],
|
|
42618
|
+
mustMatchAny: Array.isArray(body?.assertions?.mustMatchAny) ? body.assertions.mustMatchAny : [],
|
|
42619
|
+
mustNotMatchAny: Array.isArray(body?.assertions?.mustNotMatchAny) ? body.assertions.mustNotMatchAny : [],
|
|
42620
|
+
lastAssistantMustContainAny: Array.isArray(body?.assertions?.lastAssistantMustContainAny) ? body.assertions.lastAssistantMustContainAny : [],
|
|
42621
|
+
lastAssistantMustNotContainAny: Array.isArray(body?.assertions?.lastAssistantMustNotContainAny) ? body.assertions.lastAssistantMustNotContainAny : [],
|
|
42622
|
+
lastAssistantMustMatchAny: Array.isArray(body?.assertions?.lastAssistantMustMatchAny) ? body.assertions.lastAssistantMustMatchAny : [],
|
|
42623
|
+
lastAssistantMustNotMatchAny: Array.isArray(body?.assertions?.lastAssistantMustNotMatchAny) ? body.assertions.lastAssistantMustNotMatchAny : [],
|
|
42624
|
+
statusesSeen: Array.isArray(body?.assertions?.statusesSeen) ? body.assertions.statusesSeen : void 0,
|
|
42625
|
+
requireNotTimedOut: body?.assertions?.requireNotTimedOut !== false
|
|
42626
|
+
},
|
|
42627
|
+
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
42628
|
+
};
|
|
42629
|
+
const filePath = path16.join(fixtureDir, `${name}.json`);
|
|
42630
|
+
fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
42631
|
+
ctx.json(res, 200, {
|
|
42632
|
+
saved: true,
|
|
42633
|
+
name,
|
|
42634
|
+
path: filePath,
|
|
42635
|
+
fixture,
|
|
42636
|
+
verification: {
|
|
42637
|
+
pass: validateCliFixtureResult(result, fixture.assertions).length === 0,
|
|
42638
|
+
failures: validateCliFixtureResult(result, fixture.assertions)
|
|
42639
|
+
}
|
|
42640
|
+
});
|
|
42641
|
+
} catch (e) {
|
|
42642
|
+
ctx.json(res, 500, { error: `Fixture capture failed: ${e.message}` });
|
|
42643
|
+
}
|
|
42644
|
+
}
|
|
42645
|
+
async function handleCliFixtureList(ctx, type, _req, res) {
|
|
42646
|
+
try {
|
|
42647
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
42648
|
+
if (!fs13.existsSync(fixtureDir)) {
|
|
42649
|
+
ctx.json(res, 200, { fixtures: [], count: 0 });
|
|
42650
|
+
return;
|
|
42651
|
+
}
|
|
42652
|
+
const fixtures = fs13.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
|
|
42653
|
+
const fullPath = path16.join(fixtureDir, file2);
|
|
42654
|
+
try {
|
|
42655
|
+
const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
|
|
42656
|
+
return {
|
|
42657
|
+
name: raw.name || file2.replace(/\.json$/i, ""),
|
|
42658
|
+
path: fullPath,
|
|
42659
|
+
createdAt: raw.createdAt || null,
|
|
42660
|
+
notes: raw.notes || null,
|
|
42661
|
+
requestText: raw.request?.text || "",
|
|
42662
|
+
assertions: raw.assertions || {}
|
|
42663
|
+
};
|
|
42664
|
+
} catch {
|
|
42665
|
+
return {
|
|
42666
|
+
name: file2.replace(/\.json$/i, ""),
|
|
42667
|
+
path: fullPath,
|
|
42668
|
+
createdAt: null,
|
|
42669
|
+
notes: "Unreadable fixture",
|
|
42670
|
+
requestText: "",
|
|
42671
|
+
assertions: {}
|
|
42672
|
+
};
|
|
42673
|
+
}
|
|
42674
|
+
});
|
|
42675
|
+
ctx.json(res, 200, { fixtures, count: fixtures.length });
|
|
42676
|
+
} catch (e) {
|
|
42677
|
+
ctx.json(res, 500, { error: `Fixture list failed: ${e.message}` });
|
|
42678
|
+
}
|
|
42679
|
+
}
|
|
42680
|
+
async function handleCliFixtureReplay(ctx, req, res) {
|
|
42681
|
+
try {
|
|
42682
|
+
const body = await ctx.readBody(req);
|
|
42683
|
+
const type = String(body?.type || "");
|
|
42684
|
+
const rawName = String(body?.name || "").trim();
|
|
42685
|
+
if (!type || !rawName) {
|
|
42686
|
+
ctx.json(res, 400, { error: "type and name required" });
|
|
42687
|
+
return;
|
|
42688
|
+
}
|
|
42689
|
+
const name = slugifyFixtureName(rawName);
|
|
42690
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
42691
|
+
const result = await runCliExerciseInternal(ctx, {
|
|
42692
|
+
...fixture.request,
|
|
42693
|
+
type
|
|
42694
|
+
});
|
|
42695
|
+
const assertions = {
|
|
42696
|
+
...fixture.assertions,
|
|
42697
|
+
...body?.assertions || {}
|
|
42698
|
+
};
|
|
42699
|
+
const failures = validateCliFixtureResult(result, assertions);
|
|
42700
|
+
ctx.json(res, 200, {
|
|
42701
|
+
replayed: true,
|
|
42702
|
+
pass: failures.length === 0,
|
|
42703
|
+
failures,
|
|
42704
|
+
fixture,
|
|
42705
|
+
result,
|
|
42706
|
+
assertions
|
|
42707
|
+
});
|
|
42708
|
+
} catch (e) {
|
|
42709
|
+
ctx.json(res, 500, { error: `Fixture replay failed: ${e.message}` });
|
|
42710
|
+
}
|
|
42711
|
+
}
|
|
41585
42712
|
async function handleCliResolve(ctx, req, res) {
|
|
41586
42713
|
const body = await ctx.readBody(req);
|
|
41587
42714
|
const { type, buttonIndex, instanceId } = body;
|
|
@@ -41656,13 +42783,36 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
41656
42783
|
ctx.json(res, 500, { error: `Raw send failed: ${e.message}` });
|
|
41657
42784
|
}
|
|
41658
42785
|
}
|
|
42786
|
+
var fs13, path16;
|
|
41659
42787
|
var init_dev_cli_debug = __esm({
|
|
41660
42788
|
"../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts"() {
|
|
41661
42789
|
"use strict";
|
|
42790
|
+
fs13 = __toESM(require("fs"));
|
|
42791
|
+
path16 = __toESM(require("path"));
|
|
41662
42792
|
}
|
|
41663
42793
|
});
|
|
41664
42794
|
|
|
41665
42795
|
// ../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts
|
|
42796
|
+
function getAutoImplPid(ctx) {
|
|
42797
|
+
const proc = ctx.autoImplProcess;
|
|
42798
|
+
return proc && typeof proc.pid === "number" && proc.pid > 0 ? proc.pid : null;
|
|
42799
|
+
}
|
|
42800
|
+
function isPidAlive(pid) {
|
|
42801
|
+
try {
|
|
42802
|
+
process.kill(pid, 0);
|
|
42803
|
+
return true;
|
|
42804
|
+
} catch (error48) {
|
|
42805
|
+
return error48?.code === "EPERM";
|
|
42806
|
+
}
|
|
42807
|
+
}
|
|
42808
|
+
function clearStaleAutoImplState(ctx, reason) {
|
|
42809
|
+
if (!ctx.autoImplStatus.running && !ctx.autoImplProcess) return;
|
|
42810
|
+
const pid = getAutoImplPid(ctx);
|
|
42811
|
+
if (pid && isPidAlive(pid)) return;
|
|
42812
|
+
ctx.log(`Clearing stale auto-implement state: ${reason}${pid ? ` (pid ${pid})` : ""}`);
|
|
42813
|
+
ctx.autoImplProcess = null;
|
|
42814
|
+
ctx.autoImplStatus.running = false;
|
|
42815
|
+
}
|
|
41666
42816
|
function getDefaultAutoImplReference(ctx, category, type) {
|
|
41667
42817
|
if (category === "cli") {
|
|
41668
42818
|
return type === "codex-cli" ? "claude-cli" : "codex-cli";
|
|
@@ -41678,45 +42828,45 @@ function resolveAutoImplReference(ctx, category, requestedReference, targetType)
|
|
|
41678
42828
|
return fallback?.type || null;
|
|
41679
42829
|
}
|
|
41680
42830
|
function getLatestScriptVersionDir(scriptsDir) {
|
|
41681
|
-
if (!
|
|
41682
|
-
const versions =
|
|
42831
|
+
if (!fs14.existsSync(scriptsDir)) return null;
|
|
42832
|
+
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
41683
42833
|
try {
|
|
41684
|
-
return
|
|
42834
|
+
return fs14.statSync(path17.join(scriptsDir, d)).isDirectory();
|
|
41685
42835
|
} catch {
|
|
41686
42836
|
return false;
|
|
41687
42837
|
}
|
|
41688
42838
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
41689
42839
|
if (versions.length === 0) return null;
|
|
41690
|
-
return
|
|
42840
|
+
return path17.join(scriptsDir, versions[0]);
|
|
41691
42841
|
}
|
|
41692
42842
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
41693
|
-
const canonicalUserDir =
|
|
41694
|
-
const desiredDir = requestedDir ?
|
|
41695
|
-
const upstreamRoot =
|
|
41696
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
42843
|
+
const canonicalUserDir = path17.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
42844
|
+
const desiredDir = requestedDir ? path17.resolve(requestedDir) : canonicalUserDir;
|
|
42845
|
+
const upstreamRoot = path17.resolve(ctx.providerLoader.getUpstreamDir());
|
|
42846
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path17.sep}`)) {
|
|
41697
42847
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
41698
42848
|
}
|
|
41699
|
-
if (
|
|
42849
|
+
if (path17.basename(desiredDir) !== type) {
|
|
41700
42850
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
41701
42851
|
}
|
|
41702
42852
|
const sourceDir = ctx.findProviderDir(type);
|
|
41703
42853
|
if (!sourceDir) {
|
|
41704
42854
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
41705
42855
|
}
|
|
41706
|
-
if (!
|
|
41707
|
-
|
|
41708
|
-
|
|
42856
|
+
if (!fs14.existsSync(desiredDir)) {
|
|
42857
|
+
fs14.mkdirSync(path17.dirname(desiredDir), { recursive: true });
|
|
42858
|
+
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
41709
42859
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
41710
42860
|
}
|
|
41711
|
-
const providerJson =
|
|
41712
|
-
if (!
|
|
42861
|
+
const providerJson = path17.join(desiredDir, "provider.json");
|
|
42862
|
+
if (!fs14.existsSync(providerJson)) {
|
|
41713
42863
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
41714
42864
|
}
|
|
41715
42865
|
try {
|
|
41716
|
-
const providerData = JSON.parse(
|
|
42866
|
+
const providerData = JSON.parse(fs14.readFileSync(providerJson, "utf-8"));
|
|
41717
42867
|
if (providerData.disableUpstream !== true) {
|
|
41718
42868
|
providerData.disableUpstream = true;
|
|
41719
|
-
|
|
42869
|
+
fs14.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
41720
42870
|
}
|
|
41721
42871
|
} catch (error48) {
|
|
41722
42872
|
return {
|
|
@@ -41729,15 +42879,15 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
41729
42879
|
function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
41730
42880
|
if (!referenceType) return {};
|
|
41731
42881
|
const refDir = ctx.findProviderDir(referenceType);
|
|
41732
|
-
if (!refDir || !
|
|
42882
|
+
if (!refDir || !fs14.existsSync(refDir)) return {};
|
|
41733
42883
|
const referenceScripts = {};
|
|
41734
|
-
const scriptsDir =
|
|
42884
|
+
const scriptsDir = path17.join(refDir, "scripts");
|
|
41735
42885
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
41736
42886
|
if (!latestDir) return referenceScripts;
|
|
41737
|
-
for (const file2 of
|
|
42887
|
+
for (const file2 of fs14.readdirSync(latestDir)) {
|
|
41738
42888
|
if (!file2.endsWith(".js")) continue;
|
|
41739
42889
|
try {
|
|
41740
|
-
referenceScripts[file2] =
|
|
42890
|
+
referenceScripts[file2] = fs14.readFileSync(path17.join(latestDir, file2), "utf-8");
|
|
41741
42891
|
} catch {
|
|
41742
42892
|
}
|
|
41743
42893
|
}
|
|
@@ -41745,11 +42895,20 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
41745
42895
|
}
|
|
41746
42896
|
async function handleAutoImplement(ctx, type, req, res) {
|
|
41747
42897
|
const body = await ctx.readBody(req);
|
|
41748
|
-
const {
|
|
42898
|
+
const {
|
|
42899
|
+
agent = "claude-cli",
|
|
42900
|
+
functions,
|
|
42901
|
+
reference,
|
|
42902
|
+
model,
|
|
42903
|
+
comment,
|
|
42904
|
+
providerDir: requestedProviderDir,
|
|
42905
|
+
verification
|
|
42906
|
+
} = body;
|
|
41749
42907
|
if (!functions || !Array.isArray(functions) || functions.length === 0) {
|
|
41750
42908
|
ctx.json(res, 400, { error: 'functions[] is required (e.g. ["readChat", "sendMessage"])' });
|
|
41751
42909
|
return;
|
|
41752
42910
|
}
|
|
42911
|
+
clearStaleAutoImplState(ctx, "new auto-implement request");
|
|
41753
42912
|
if (ctx.autoImplStatus.running) {
|
|
41754
42913
|
ctx.json(res, 409, { error: "Auto-implement already in progress", type: ctx.autoImplStatus.type });
|
|
41755
42914
|
return;
|
|
@@ -41767,7 +42926,55 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41767
42926
|
return;
|
|
41768
42927
|
}
|
|
41769
42928
|
const providerDir = writableProvider.dir;
|
|
42929
|
+
ctx.autoImplStatus = { running: false, type, progress: [] };
|
|
42930
|
+
if (provider.category === "cli" && verification && (verification.fixtureName || verification.fixtureNames && verification.fixtureNames.length > 0)) {
|
|
42931
|
+
sendAutoImplSSE(ctx, {
|
|
42932
|
+
event: "progress",
|
|
42933
|
+
data: {
|
|
42934
|
+
function: "_preflight",
|
|
42935
|
+
status: "verifying",
|
|
42936
|
+
message: "Running preflight verification before spawning agent..."
|
|
42937
|
+
}
|
|
42938
|
+
});
|
|
42939
|
+
try {
|
|
42940
|
+
const preflight = await runCliAutoImplVerification(ctx, type, verification);
|
|
42941
|
+
sendAutoImplSSE(ctx, { event: "verification", data: preflight });
|
|
42942
|
+
if (preflight.pass) {
|
|
42943
|
+
sendAutoImplSSE(ctx, {
|
|
42944
|
+
event: "complete",
|
|
42945
|
+
data: {
|
|
42946
|
+
success: true,
|
|
42947
|
+
exitCode: 0,
|
|
42948
|
+
functions,
|
|
42949
|
+
message: `\u2705 No-op: exact ${preflight.mode} already passes`,
|
|
42950
|
+
verification: preflight,
|
|
42951
|
+
skipped: true
|
|
42952
|
+
}
|
|
42953
|
+
});
|
|
42954
|
+
ctx.json(res, 200, {
|
|
42955
|
+
started: false,
|
|
42956
|
+
skipped: true,
|
|
42957
|
+
type,
|
|
42958
|
+
functions,
|
|
42959
|
+
providerDir,
|
|
42960
|
+
verification: preflight,
|
|
42961
|
+
message: "Preflight verification already passes. No auto-implement run needed."
|
|
42962
|
+
});
|
|
42963
|
+
return;
|
|
42964
|
+
}
|
|
42965
|
+
} catch (error48) {
|
|
42966
|
+
sendAutoImplSSE(ctx, {
|
|
42967
|
+
event: "progress",
|
|
42968
|
+
data: {
|
|
42969
|
+
function: "_preflight",
|
|
42970
|
+
status: "verify_failed",
|
|
42971
|
+
message: `Preflight verification errored, continuing to agent run: ${error48?.message || error48}`
|
|
42972
|
+
}
|
|
42973
|
+
});
|
|
42974
|
+
}
|
|
42975
|
+
}
|
|
41770
42976
|
try {
|
|
42977
|
+
ctx.autoImplStatus = { running: true, type, progress: ctx.autoImplStatus.progress };
|
|
41771
42978
|
const resolvedReference = resolveAutoImplReference(ctx, provider.category, reference, type);
|
|
41772
42979
|
sendAutoImplSSE(ctx, {
|
|
41773
42980
|
event: "progress",
|
|
@@ -41787,17 +42994,17 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41787
42994
|
}
|
|
41788
42995
|
});
|
|
41789
42996
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
41790
|
-
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
|
|
41791
|
-
const tmpDir =
|
|
41792
|
-
if (!
|
|
41793
|
-
const promptFile =
|
|
41794
|
-
|
|
42997
|
+
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
42998
|
+
const tmpDir = path17.join(os18.tmpdir(), "adhdev-autoimpl");
|
|
42999
|
+
if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
|
|
43000
|
+
const promptFile = path17.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
43001
|
+
fs14.writeFileSync(promptFile, prompt, "utf-8");
|
|
41795
43002
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
41796
43003
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
41797
43004
|
const spawn5 = agentProvider?.spawn;
|
|
41798
43005
|
if (!spawn5?.command) {
|
|
41799
43006
|
try {
|
|
41800
|
-
|
|
43007
|
+
fs14.unlinkSync(promptFile);
|
|
41801
43008
|
} catch {
|
|
41802
43009
|
}
|
|
41803
43010
|
ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -41806,7 +43013,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41806
43013
|
const agentCategory = agentProvider?.category;
|
|
41807
43014
|
if (agentCategory === "acp") {
|
|
41808
43015
|
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn5.command} ${(spawn5.args || []).join(" ")}` } });
|
|
41809
|
-
ctx.autoImplStatus =
|
|
43016
|
+
ctx.autoImplStatus.running = true;
|
|
43017
|
+
ctx.autoImplStatus.type = type;
|
|
41810
43018
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
41811
43019
|
const { Readable: Readable3, Writable: Writable2 } = await import("stream");
|
|
41812
43020
|
const { spawn: spawnFn2 } = await import("child_process");
|
|
@@ -41898,7 +43106,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41898
43106
|
} catch {
|
|
41899
43107
|
}
|
|
41900
43108
|
try {
|
|
41901
|
-
|
|
43109
|
+
fs14.unlinkSync(promptFile);
|
|
41902
43110
|
} catch {
|
|
41903
43111
|
}
|
|
41904
43112
|
ctx.log(`Auto-implement (ACP) ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -41976,7 +43184,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41976
43184
|
}
|
|
41977
43185
|
}
|
|
41978
43186
|
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning agent: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
|
|
41979
|
-
ctx.autoImplStatus =
|
|
43187
|
+
ctx.autoImplStatus.running = true;
|
|
43188
|
+
ctx.autoImplStatus.type = type;
|
|
41980
43189
|
const spawnedAt = Date.now();
|
|
41981
43190
|
let child;
|
|
41982
43191
|
let isPty = false;
|
|
@@ -42019,6 +43228,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42019
43228
|
let approvalKeys = { 0: "y\r" };
|
|
42020
43229
|
let approvalBuffer = "";
|
|
42021
43230
|
let lastApprovalTime = 0;
|
|
43231
|
+
let completionSignalSeen = false;
|
|
42022
43232
|
try {
|
|
42023
43233
|
const { normalizeCliProviderForRuntime: normalizeCliProviderForRuntime2 } = await Promise.resolve().then(() => (init_provider_cli_adapter(), provider_cli_adapter_exports));
|
|
42024
43234
|
const normalized = normalizeCliProviderForRuntime2(agentProvider);
|
|
@@ -42032,6 +43242,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42032
43242
|
approvalBuffer = (approvalBuffer + cleanData).slice(-1500);
|
|
42033
43243
|
const elapsed = Date.now() - spawnedAt;
|
|
42034
43244
|
if (elapsed > 15e3 && cleanData.includes("_PIPELINE_COMPLETE_SIGNAL_")) {
|
|
43245
|
+
completionSignalSeen = true;
|
|
42035
43246
|
ctx.log(`Agent finished task after ${Math.round(elapsed / 1e3)}s. Terminating interactive CLI session to unblock pipeline.`);
|
|
42036
43247
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: `
|
|
42037
43248
|
[\u{1F916} ADHDev Pipeline] Completion token detected. Proceeding...
|
|
@@ -42055,6 +43266,55 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42055
43266
|
lastApprovalTime = Date.now();
|
|
42056
43267
|
}
|
|
42057
43268
|
};
|
|
43269
|
+
const finalizeCliAutoImpl = async (code) => {
|
|
43270
|
+
ctx.autoImplProcess = null;
|
|
43271
|
+
let success2 = completionSignalSeen || code === 0;
|
|
43272
|
+
let message = success2 ? completionSignalSeen && code !== 0 ? "\u2705 Auto-implement complete (completion signal)" : "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`;
|
|
43273
|
+
let verificationSummary = null;
|
|
43274
|
+
try {
|
|
43275
|
+
ctx.providerLoader.reload();
|
|
43276
|
+
} catch {
|
|
43277
|
+
}
|
|
43278
|
+
if (provider.category === "cli" && verification) {
|
|
43279
|
+
sendAutoImplSSE(ctx, {
|
|
43280
|
+
event: "progress",
|
|
43281
|
+
data: {
|
|
43282
|
+
function: "_verify",
|
|
43283
|
+
status: "running",
|
|
43284
|
+
message: "Running exact post-patch verification..."
|
|
43285
|
+
}
|
|
43286
|
+
});
|
|
43287
|
+
try {
|
|
43288
|
+
verificationSummary = await runCliAutoImplVerification(ctx, type, verification);
|
|
43289
|
+
sendAutoImplSSE(ctx, { event: "verification", data: verificationSummary });
|
|
43290
|
+
success2 = verificationSummary.pass;
|
|
43291
|
+
message = verificationSummary.pass ? `\u2705 Auto-implement complete (${verificationSummary.mode})` : `\u274C Post-patch verification failed (${verificationSummary.mode}): ${verificationSummary.failures.join("; ") || "unknown failure"}`;
|
|
43292
|
+
} catch (error48) {
|
|
43293
|
+
success2 = false;
|
|
43294
|
+
message = `\u274C Post-patch verification error: ${error48?.message || error48}`;
|
|
43295
|
+
sendAutoImplSSE(ctx, {
|
|
43296
|
+
event: "verification",
|
|
43297
|
+
data: { pass: false, error: error48?.message || String(error48) }
|
|
43298
|
+
});
|
|
43299
|
+
}
|
|
43300
|
+
}
|
|
43301
|
+
ctx.autoImplStatus.running = false;
|
|
43302
|
+
sendAutoImplSSE(ctx, {
|
|
43303
|
+
event: "complete",
|
|
43304
|
+
data: {
|
|
43305
|
+
success: success2,
|
|
43306
|
+
exitCode: code,
|
|
43307
|
+
functions,
|
|
43308
|
+
message,
|
|
43309
|
+
verification: verificationSummary
|
|
43310
|
+
}
|
|
43311
|
+
});
|
|
43312
|
+
try {
|
|
43313
|
+
fs14.unlinkSync(promptFile);
|
|
43314
|
+
} catch {
|
|
43315
|
+
}
|
|
43316
|
+
ctx.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})${verificationSummary ? ` verify=${verificationSummary.pass ? "pass" : "fail"}` : ""}`);
|
|
43317
|
+
};
|
|
42058
43318
|
if (isPty) {
|
|
42059
43319
|
child.onData((data) => {
|
|
42060
43320
|
stdout += data;
|
|
@@ -42066,21 +43326,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42066
43326
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
|
|
42067
43327
|
});
|
|
42068
43328
|
child.onExit(({ exitCode: code }) => {
|
|
42069
|
-
|
|
42070
|
-
ctx.autoImplStatus.running = false;
|
|
42071
|
-
const success2 = code === 0;
|
|
42072
|
-
sendAutoImplSSE(ctx, {
|
|
42073
|
-
event: "complete",
|
|
42074
|
-
data: { success: success2, exitCode: code, functions, message: success2 ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})` }
|
|
42075
|
-
});
|
|
42076
|
-
try {
|
|
42077
|
-
ctx.providerLoader.reload();
|
|
42078
|
-
} catch {
|
|
42079
|
-
}
|
|
42080
|
-
try {
|
|
42081
|
-
fs13.unlinkSync(promptFile);
|
|
42082
|
-
} catch {
|
|
42083
|
-
}
|
|
43329
|
+
void finalizeCliAutoImpl(code);
|
|
42084
43330
|
});
|
|
42085
43331
|
} else {
|
|
42086
43332
|
child.stdout?.on("data", (d) => {
|
|
@@ -42097,27 +43343,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42097
43343
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
|
|
42098
43344
|
});
|
|
42099
43345
|
child.on("exit", (code) => {
|
|
42100
|
-
|
|
42101
|
-
ctx.autoImplStatus.running = false;
|
|
42102
|
-
const success2 = code === 0;
|
|
42103
|
-
sendAutoImplSSE(ctx, {
|
|
42104
|
-
event: "complete",
|
|
42105
|
-
data: {
|
|
42106
|
-
success: success2,
|
|
42107
|
-
exitCode: code,
|
|
42108
|
-
functions,
|
|
42109
|
-
message: success2 ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`
|
|
42110
|
-
}
|
|
42111
|
-
});
|
|
42112
|
-
try {
|
|
42113
|
-
ctx.providerLoader.reload();
|
|
42114
|
-
} catch {
|
|
42115
|
-
}
|
|
42116
|
-
try {
|
|
42117
|
-
fs13.unlinkSync(promptFile);
|
|
42118
|
-
} catch {
|
|
42119
|
-
}
|
|
42120
|
-
ctx.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
43346
|
+
void finalizeCliAutoImpl(code);
|
|
42121
43347
|
});
|
|
42122
43348
|
}
|
|
42123
43349
|
ctx.json(res, 202, {
|
|
@@ -42134,9 +43360,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42134
43360
|
ctx.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
|
|
42135
43361
|
}
|
|
42136
43362
|
}
|
|
42137
|
-
function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType) {
|
|
43363
|
+
function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType, verification) {
|
|
42138
43364
|
if (provider.category === "cli") {
|
|
42139
|
-
return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType);
|
|
43365
|
+
return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification);
|
|
42140
43366
|
}
|
|
42141
43367
|
const lines = [];
|
|
42142
43368
|
lines.push("You are implementing browser automation scripts for an IDE provider.");
|
|
@@ -42161,7 +43387,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42161
43387
|
setMode: "set_mode.js"
|
|
42162
43388
|
};
|
|
42163
43389
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
42164
|
-
const scriptsDir =
|
|
43390
|
+
const scriptsDir = path17.join(providerDir, "scripts");
|
|
42165
43391
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
42166
43392
|
if (latestScriptsDir) {
|
|
42167
43393
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -42169,10 +43395,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42169
43395
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
42170
43396
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
42171
43397
|
lines.push("");
|
|
42172
|
-
for (const file2 of
|
|
43398
|
+
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
42173
43399
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
42174
43400
|
try {
|
|
42175
|
-
const content =
|
|
43401
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
42176
43402
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
42177
43403
|
lines.push("```javascript");
|
|
42178
43404
|
lines.push(content);
|
|
@@ -42182,14 +43408,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42182
43408
|
}
|
|
42183
43409
|
}
|
|
42184
43410
|
}
|
|
42185
|
-
const refFiles =
|
|
43411
|
+
const refFiles = fs14.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
42186
43412
|
if (refFiles.length > 0) {
|
|
42187
43413
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
42188
43414
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
42189
43415
|
lines.push("");
|
|
42190
43416
|
for (const file2 of refFiles) {
|
|
42191
43417
|
try {
|
|
42192
|
-
const content =
|
|
43418
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
42193
43419
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
42194
43420
|
lines.push("```javascript");
|
|
42195
43421
|
lines.push(content);
|
|
@@ -42230,11 +43456,11 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42230
43456
|
lines.push("");
|
|
42231
43457
|
}
|
|
42232
43458
|
}
|
|
42233
|
-
const docsDir =
|
|
43459
|
+
const docsDir = path17.join(providerDir, "../../docs");
|
|
42234
43460
|
const loadGuide = (name) => {
|
|
42235
43461
|
try {
|
|
42236
|
-
const p =
|
|
42237
|
-
if (
|
|
43462
|
+
const p = path17.join(docsDir, name);
|
|
43463
|
+
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
42238
43464
|
} catch {
|
|
42239
43465
|
}
|
|
42240
43466
|
return null;
|
|
@@ -42392,8 +43618,69 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42392
43618
|
lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
|
|
42393
43619
|
return lines.join("\n");
|
|
42394
43620
|
}
|
|
42395
|
-
function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType) {
|
|
43621
|
+
function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification) {
|
|
42396
43622
|
const lines = [];
|
|
43623
|
+
const defaultExercisePayload = {
|
|
43624
|
+
type,
|
|
43625
|
+
workingDir: providerDir,
|
|
43626
|
+
freshSession: true,
|
|
43627
|
+
autoLaunch: true,
|
|
43628
|
+
autoResolveApprovals: true,
|
|
43629
|
+
approvalButtonIndex: 0,
|
|
43630
|
+
timeoutMs: 45e3,
|
|
43631
|
+
traceLimit: 200,
|
|
43632
|
+
text: "Create a file at tmp/adhdev_provider_fix_test.py that prints the current working directory and the squares of 1 through 5, then run python3 tmp/adhdev_provider_fix_test.py and tell me the exact output."
|
|
43633
|
+
};
|
|
43634
|
+
const exercisePayload = {
|
|
43635
|
+
...defaultExercisePayload,
|
|
43636
|
+
...verification?.request || {},
|
|
43637
|
+
type,
|
|
43638
|
+
workingDir: providerDir
|
|
43639
|
+
};
|
|
43640
|
+
const exerciseJson = JSON.stringify(exercisePayload).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43641
|
+
const verificationInspectFields = verification?.inspectFields?.length ? verification.inspectFields : [
|
|
43642
|
+
"debug.messages",
|
|
43643
|
+
"trace.entries[].payload.parsedLastAssistant",
|
|
43644
|
+
"trace.entries[].payload.lastAssistant"
|
|
43645
|
+
];
|
|
43646
|
+
const verificationMustContainAny = verification?.mustContainAny || [];
|
|
43647
|
+
const verificationMustNotContainAny = verification?.mustNotContainAny || [];
|
|
43648
|
+
const verificationMustMatchAny = verification?.mustMatchAny || [];
|
|
43649
|
+
const verificationMustNotMatchAny = verification?.mustNotMatchAny || [];
|
|
43650
|
+
const verificationLastAssistantMustContainAny = verification?.lastAssistantMustContainAny || [];
|
|
43651
|
+
const verificationLastAssistantMustNotContainAny = verification?.lastAssistantMustNotContainAny || [];
|
|
43652
|
+
const verificationLastAssistantMustMatchAny = verification?.lastAssistantMustMatchAny || [];
|
|
43653
|
+
const verificationLastAssistantMustNotMatchAny = verification?.lastAssistantMustNotMatchAny || [];
|
|
43654
|
+
const quotedMustContain = verificationMustContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43655
|
+
const quotedMustNotContain = verificationMustNotContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43656
|
+
const quotedMustMatch = verificationMustMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43657
|
+
const quotedMustNotMatch = verificationMustNotMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43658
|
+
const quotedLastAssistantMustContain = verificationLastAssistantMustContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43659
|
+
const quotedLastAssistantMustNotContain = verificationLastAssistantMustNotContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43660
|
+
const quotedLastAssistantMustMatch = verificationLastAssistantMustMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43661
|
+
const quotedLastAssistantMustNotMatch = verificationLastAssistantMustNotMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43662
|
+
const fixtureName = verification?.fixtureName || `${type}-provider-fix`;
|
|
43663
|
+
const fixtureNames = Array.isArray(verification?.fixtureNames) ? verification.fixtureNames.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
43664
|
+
const fixtureCaptureJson = JSON.stringify({
|
|
43665
|
+
type,
|
|
43666
|
+
name: fixtureName,
|
|
43667
|
+
request: exercisePayload,
|
|
43668
|
+
assertions: {
|
|
43669
|
+
mustContainAny: verificationMustContainAny,
|
|
43670
|
+
mustNotContainAny: verificationMustNotContainAny,
|
|
43671
|
+
mustMatchAny: verificationMustMatchAny,
|
|
43672
|
+
mustNotMatchAny: verificationMustNotMatchAny,
|
|
43673
|
+
lastAssistantMustContainAny: verificationLastAssistantMustContainAny,
|
|
43674
|
+
lastAssistantMustNotContainAny: verificationLastAssistantMustNotContainAny,
|
|
43675
|
+
lastAssistantMustMatchAny: verificationLastAssistantMustMatchAny,
|
|
43676
|
+
lastAssistantMustNotMatchAny: verificationLastAssistantMustNotMatchAny,
|
|
43677
|
+
requireNotTimedOut: true
|
|
43678
|
+
}
|
|
43679
|
+
}).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43680
|
+
const fixtureReplayJson = JSON.stringify({
|
|
43681
|
+
type,
|
|
43682
|
+
name: fixtureName
|
|
43683
|
+
}).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
42397
43684
|
lines.push("You are implementing PTY parsing scripts for a CLI provider.");
|
|
42398
43685
|
lines.push("Be concise. Do NOT explain your reasoning. Edit files directly and verify with the local DevServer.");
|
|
42399
43686
|
lines.push("");
|
|
@@ -42407,7 +43694,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42407
43694
|
parseApproval: "parse_approval.js"
|
|
42408
43695
|
};
|
|
42409
43696
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
42410
|
-
const scriptsDir =
|
|
43697
|
+
const scriptsDir = path17.join(providerDir, "scripts");
|
|
42411
43698
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
42412
43699
|
if (latestScriptsDir) {
|
|
42413
43700
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -42415,11 +43702,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42415
43702
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
42416
43703
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
42417
43704
|
lines.push("");
|
|
42418
|
-
for (const file2 of
|
|
43705
|
+
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
42419
43706
|
if (!file2.endsWith(".js")) continue;
|
|
42420
43707
|
if (!targetFileNames.has(file2)) continue;
|
|
42421
43708
|
try {
|
|
42422
|
-
const content =
|
|
43709
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
42423
43710
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
42424
43711
|
lines.push("```javascript");
|
|
42425
43712
|
lines.push(content);
|
|
@@ -42428,14 +43715,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42428
43715
|
} catch {
|
|
42429
43716
|
}
|
|
42430
43717
|
}
|
|
42431
|
-
const refFiles =
|
|
43718
|
+
const refFiles = fs14.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
42432
43719
|
if (refFiles.length > 0) {
|
|
42433
43720
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
42434
43721
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
42435
43722
|
lines.push("");
|
|
42436
43723
|
for (const file2 of refFiles) {
|
|
42437
43724
|
try {
|
|
42438
|
-
const content =
|
|
43725
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
42439
43726
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
42440
43727
|
lines.push("```javascript");
|
|
42441
43728
|
lines.push(content);
|
|
@@ -42468,17 +43755,17 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42468
43755
|
lines.push("");
|
|
42469
43756
|
}
|
|
42470
43757
|
}
|
|
42471
|
-
const docsDir =
|
|
43758
|
+
const docsDir = path17.join(providerDir, "../../docs");
|
|
42472
43759
|
const loadGuide = (name) => {
|
|
42473
43760
|
try {
|
|
42474
|
-
const p =
|
|
42475
|
-
if (
|
|
43761
|
+
const p = path17.join(docsDir, name);
|
|
43762
|
+
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
42476
43763
|
} catch {
|
|
42477
43764
|
}
|
|
42478
43765
|
return null;
|
|
42479
43766
|
};
|
|
42480
43767
|
const providerGuide = loadGuide("PROVIDER_GUIDE.md");
|
|
42481
|
-
if (providerGuide) {
|
|
43768
|
+
if (providerGuide && provider.category !== "cli") {
|
|
42482
43769
|
lines.push("## Documentation: PROVIDER_GUIDE.md");
|
|
42483
43770
|
lines.push("```markdown");
|
|
42484
43771
|
lines.push(providerGuide);
|
|
@@ -42520,6 +43807,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42520
43807
|
lines.push("13. After the first successful live repro, stop broad diagnosis. Edit the scripts, reload, and verify. Do not burn tokens on repeated re-inspection without code changes.");
|
|
42521
43808
|
lines.push("14. If the visible current screen is clean and sufficient, do NOT fall back to complex buffer heuristics. Simpler current-screen parsing is preferred.");
|
|
42522
43809
|
lines.push("15. Before changing parser logic, verify whether `provider.json` submit/approval behavior (`sendDelayMs`, `approvalKeys`, submit strategy) is the simpler and more correct fix.");
|
|
43810
|
+
lines.push('16. Do NOT patch transcript bugs by piling up one-off literal string exceptions (`includes("foo")`, `=== "bar"`, ad hoc allowlists/denylists) for every observed variant. Model the UI as PATTERN FAMILIES using reusable regex classifiers and normalization first.');
|
|
43811
|
+
lines.push("17. If you find yourself adding a second or third near-duplicate literal check for spinner words, tool headers, approval prompts, footer chrome, or OSC residue, STOP and replace them with a broader regex or helper classifier.");
|
|
43812
|
+
lines.push('18. Prefer a small number of named classifiers such as "status line", "tool header", "tool detail", "footer chrome", "approval cue", "prompt line", and "OSC residue" over a long chain of unrelated string checks.');
|
|
43813
|
+
lines.push("19. Literal string checks are allowed only for stable proper nouns or exact product chrome that cannot be expressed safely as a broader pattern. Everything else should generalize.");
|
|
43814
|
+
lines.push("20. When a bug comes from noisy PTY text, first normalize and classify the line family; do NOT just append another special-case substring to the parser.");
|
|
42523
43815
|
lines.push("");
|
|
42524
43816
|
lines.push("## Task");
|
|
42525
43817
|
lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(", ")}**`);
|
|
@@ -42527,35 +43819,145 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42527
43819
|
lines.push("## Verification API");
|
|
42528
43820
|
lines.push("Use the DevServer CLI debug endpoints, not DOM/CDP routes.");
|
|
42529
43821
|
lines.push("");
|
|
42530
|
-
lines.push("### 1.
|
|
43822
|
+
lines.push("### 1. Preferred: run a full autonomous repro");
|
|
43823
|
+
lines.push("Use the exercise endpoint first. It launches a fresh CLI session, sends the repro prompt, auto-resolves approvals, waits for the session to settle, and returns the final debug + trace payload in one response.");
|
|
42531
43824
|
lines.push("```bash");
|
|
42532
|
-
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/
|
|
43825
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/exercise \\`);
|
|
42533
43826
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
42534
|
-
lines.push(` -d '
|
|
43827
|
+
lines.push(` -d '${exerciseJson}'`);
|
|
43828
|
+
lines.push("```");
|
|
43829
|
+
lines.push("");
|
|
43830
|
+
if (verification?.description) {
|
|
43831
|
+
lines.push("Verification intent:");
|
|
43832
|
+
lines.push(verification.description);
|
|
43833
|
+
lines.push("");
|
|
43834
|
+
}
|
|
43835
|
+
lines.push("Read the JSON response carefully. It already includes:");
|
|
43836
|
+
lines.push("1. `instanceId`");
|
|
43837
|
+
lines.push("2. `statusesSeen` and `approvalsResolved`");
|
|
43838
|
+
lines.push("3. `debug` for the final settled state");
|
|
43839
|
+
lines.push("4. `trace.entries` for the repro turn");
|
|
43840
|
+
lines.push("");
|
|
43841
|
+
lines.push("Save the response to a temp file and inspect the exact parsed transcript fields before editing:");
|
|
43842
|
+
lines.push("```bash");
|
|
43843
|
+
lines.push(`EXERCISE_JSON=$(mktemp)`);
|
|
43844
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/exercise \\`);
|
|
43845
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43846
|
+
lines.push(` -d '${exerciseJson}' > "$EXERCISE_JSON"`);
|
|
43847
|
+
lines.push(`jq '{timedOut,statusesSeen,approvalsResolved,inspect:{${verificationInspectFields.map((field, index) => `f${index + 1}: .${field}`).join(", ")}}}' "$EXERCISE_JSON"`);
|
|
42535
43848
|
lines.push("```");
|
|
42536
43849
|
lines.push("");
|
|
43850
|
+
if (verificationMustContainAny.length > 0 || verificationMustNotContainAny.length > 0 || verificationMustMatchAny.length > 0 || verificationMustNotMatchAny.length > 0 || verificationLastAssistantMustContainAny.length > 0 || verificationLastAssistantMustNotContainAny.length > 0 || verificationLastAssistantMustMatchAny.length > 0 || verificationLastAssistantMustNotMatchAny.length > 0) {
|
|
43851
|
+
lines.push("The exact repro below is mandatory. Do NOT declare success unless these transcript assertions pass on the exercise JSON from the PATCHED provider.");
|
|
43852
|
+
lines.push("```bash");
|
|
43853
|
+
if (verificationMustContainAny.length > 0) {
|
|
43854
|
+
lines.push(`node -e 'const fs=require("fs");const text=fs.readFileSync(process.argv[1],"utf8");const required=[${quotedMustContain}];const missing=required.filter(v=>!text.includes(v));if(missing.length){console.error("Missing required substrings:\\n"+missing.join("\\n"));process.exit(1);}' "$EXERCISE_JSON"`);
|
|
43855
|
+
}
|
|
43856
|
+
if (verificationMustNotContainAny.length > 0) {
|
|
43857
|
+
lines.push(`node -e 'const fs=require("fs");const text=fs.readFileSync(process.argv[1],"utf8");const banned=[${quotedMustNotContain}];const hits=banned.filter(v=>text.includes(v));if(hits.length){console.error("Found banned substrings:\\n"+hits.join("\\n"));process.exit(1);}' "$EXERCISE_JSON"`);
|
|
43858
|
+
}
|
|
43859
|
+
if (verificationMustMatchAny.length > 0) {
|
|
43860
|
+
lines.push(`node -e 'const fs=require("fs");const text=fs.readFileSync(process.argv[1],"utf8");const required=[${quotedMustMatch}].map(v=>new RegExp(v,"m"));const missing=required.filter(v=>!v.test(text)).map(v=>String(v));if(missing.length){console.error("Missing required regex matches:\\n"+missing.join("\\n"));process.exit(1);}' "$EXERCISE_JSON"`);
|
|
43861
|
+
}
|
|
43862
|
+
if (verificationMustNotMatchAny.length > 0) {
|
|
43863
|
+
lines.push(`node -e 'const fs=require("fs");const text=fs.readFileSync(process.argv[1],"utf8");const banned=[${quotedMustNotMatch}].map(v=>new RegExp(v,"m"));const hits=banned.filter(v=>v.test(text)).map(v=>String(v));if(hits.length){console.error("Found banned regex matches:\\n"+hits.join("\\n"));process.exit(1);}' "$EXERCISE_JSON"`);
|
|
43864
|
+
}
|
|
43865
|
+
if (verificationLastAssistantMustContainAny.length > 0) {
|
|
43866
|
+
lines.push(`node -e 'const fs=require("fs");const payload=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));const text=String(payload.lastAssistant||"");const required=[${quotedLastAssistantMustContain}];const missing=required.filter(v=>!text.includes(v));if(missing.length){console.error("Missing required lastAssistant substrings:\\n"+missing.join("\\n"));process.exit(1);}' "$EXERCISE_JSON"`);
|
|
43867
|
+
}
|
|
43868
|
+
if (verificationLastAssistantMustNotContainAny.length > 0) {
|
|
43869
|
+
lines.push(`node -e 'const fs=require("fs");const payload=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));const text=String(payload.lastAssistant||"");const banned=[${quotedLastAssistantMustNotContain}];const hits=banned.filter(v=>text.includes(v));if(hits.length){console.error("Found banned lastAssistant substrings:\\n"+hits.join("\\n"));process.exit(1);}' "$EXERCISE_JSON"`);
|
|
43870
|
+
}
|
|
43871
|
+
if (verificationLastAssistantMustMatchAny.length > 0) {
|
|
43872
|
+
lines.push(`node -e 'const fs=require("fs");const payload=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));const text=String(payload.lastAssistant||"");const required=[${quotedLastAssistantMustMatch}].map(v=>new RegExp(v,"m"));const missing=required.filter(v=>!v.test(text)).map(v=>String(v));if(missing.length){console.error("Missing required lastAssistant regex matches:\\n"+missing.join("\\n"));process.exit(1);}' "$EXERCISE_JSON"`);
|
|
43873
|
+
}
|
|
43874
|
+
if (verificationLastAssistantMustNotMatchAny.length > 0) {
|
|
43875
|
+
lines.push(`node -e 'const fs=require("fs");const payload=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));const text=String(payload.lastAssistant||"");const banned=[${quotedLastAssistantMustNotMatch}].map(v=>new RegExp(v,"m"));const hits=banned.filter(v=>v.test(text)).map(v=>String(v));if(hits.length){console.error("Found banned lastAssistant regex matches:\\n"+hits.join("\\n"));process.exit(1);}' "$EXERCISE_JSON"`);
|
|
43876
|
+
}
|
|
43877
|
+
lines.push("```");
|
|
43878
|
+
lines.push("");
|
|
43879
|
+
}
|
|
43880
|
+
lines.push("If you need a manual follow-up repro after patching, use the SAME endpoint again with the SAME prompt and compare the new trace to the previous one.");
|
|
43881
|
+
lines.push("");
|
|
43882
|
+
lines.push("### 1b. Persist or replay the exact repro as a reusable fixture");
|
|
43883
|
+
if (fixtureNames.length > 0) {
|
|
43884
|
+
lines.push(`Replay this exact fixture suite before editing, and replay the SAME suite again after patching. Do not declare success unless EVERY fixture passes: ${fixtureNames.map((name) => `\`${name}\``).join(", ")}.`);
|
|
43885
|
+
for (const name of fixtureNames) {
|
|
43886
|
+
const replayJson = JSON.stringify({ type, name }).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43887
|
+
lines.push("```bash");
|
|
43888
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43889
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43890
|
+
lines.push(` -d '${replayJson}'`);
|
|
43891
|
+
lines.push("```");
|
|
43892
|
+
lines.push("");
|
|
43893
|
+
}
|
|
43894
|
+
lines.push("Do not create new fixtures unless one of the listed fixtures is missing or stale.");
|
|
43895
|
+
} else if (verification?.fixtureName) {
|
|
43896
|
+
lines.push(`Replay the EXISTING saved fixture \`${fixtureName}\` before editing, and replay the SAME fixture again after patching. Do not declare success unless that exact fixture passes.`);
|
|
43897
|
+
lines.push("```bash");
|
|
43898
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43899
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43900
|
+
lines.push(` -d '${fixtureReplayJson}'`);
|
|
43901
|
+
lines.push("```");
|
|
43902
|
+
lines.push("");
|
|
43903
|
+
lines.push("Only if the named fixture is missing or outdated should you recapture it. Prefer replaying the existing failing fixture over creating a new one.");
|
|
43904
|
+
lines.push("```bash");
|
|
43905
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/capture \\`);
|
|
43906
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43907
|
+
lines.push(` -d '${fixtureCaptureJson}'`);
|
|
43908
|
+
lines.push("```");
|
|
43909
|
+
} else {
|
|
43910
|
+
lines.push("Capture the exact exercise once before editing. After patching, replay THIS fixture and do not declare success unless replay passes.");
|
|
43911
|
+
lines.push("```bash");
|
|
43912
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/capture \\`);
|
|
43913
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43914
|
+
lines.push(` -d '${fixtureCaptureJson}'`);
|
|
43915
|
+
lines.push("");
|
|
43916
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43917
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43918
|
+
lines.push(` -d '${fixtureReplayJson}'`);
|
|
43919
|
+
lines.push("```");
|
|
43920
|
+
}
|
|
43921
|
+
lines.push("");
|
|
43922
|
+
lines.push("The capture endpoint saves the exact request, initial result, and transcript assertions into the provider directory. The replay endpoint reruns the SAME exercise against your patched scripts and returns pass/fail.");
|
|
43923
|
+
lines.push("");
|
|
42537
43924
|
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
42538
43925
|
lines.push("```bash");
|
|
43926
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/launch \\`);
|
|
43927
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43928
|
+
lines.push(` -d '{"type":"${type}","workingDir":"${providerDir.replace(/\\/g, "\\\\")}"}'`);
|
|
42539
43929
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
43930
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/trace/${type}`);
|
|
42540
43931
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
42541
43932
|
lines.push("```");
|
|
42542
43933
|
lines.push("");
|
|
43934
|
+
lines.push("The CLI trace endpoint is the primary debugging source. Read it BEFORE editing any parser code.");
|
|
43935
|
+
lines.push("Use the trace timeline to find the latest `settled` or `commit_transcript` frame for the repro turn and inspect these fields first:");
|
|
43936
|
+
lines.push("1. `payload.screenText`");
|
|
43937
|
+
lines.push("2. `payload.detectStatus` and `payload.parsedStatus`");
|
|
43938
|
+
lines.push("3. `payload.parsedLastAssistant`");
|
|
43939
|
+
lines.push("4. `payload.approval` / `payload.parsedActiveModal`");
|
|
43940
|
+
lines.push("5. `payload.rawPreview` only when control-sequence residue matters");
|
|
43941
|
+
lines.push("");
|
|
42543
43942
|
lines.push("The debug payload should be read in this priority order:");
|
|
42544
43943
|
lines.push("1. `screenText` / current visible state");
|
|
42545
43944
|
lines.push("2. parsed `status`, `messages`, `activeModal`");
|
|
42546
43945
|
lines.push("3. `rawBuffer` only for style/control-sequence cues");
|
|
42547
43946
|
lines.push("4. `buffer` only when the current screen is insufficient");
|
|
42548
43947
|
lines.push("");
|
|
42549
|
-
lines.push("
|
|
43948
|
+
lines.push("If the bug is transcript corruption, quote the exact bad `parsedLastAssistant` or bad committed assistant message from the trace and patch against that concrete failure.");
|
|
43949
|
+
lines.push("Do NOT guess based only on the final chat bubble or a truncated UI preview.");
|
|
43950
|
+
lines.push("");
|
|
43951
|
+
lines.push("Extract the current `instanceId` from the exercise, launch, or status response and keep using it below.");
|
|
42550
43952
|
lines.push("");
|
|
42551
|
-
lines.push("### 3.
|
|
43953
|
+
lines.push("### 3. Manual fallback only: send a realistic approval-triggering prompt");
|
|
42552
43954
|
lines.push("```bash");
|
|
42553
43955
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/send \\`);
|
|
42554
43956
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
42555
43957
|
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>","text":"Create a file at tmp/adhdev_provider_fix_test.py that prints the current working directory and the squares of 1 through 5, then run python3 tmp/adhdev_provider_fix_test.py and tell me the exact output."}'`);
|
|
42556
43958
|
lines.push("```");
|
|
42557
43959
|
lines.push("");
|
|
42558
|
-
lines.push("### 4.
|
|
43960
|
+
lines.push("### 4. Manual fallback only: if approval appears, resolve it until the CLI reaches idle");
|
|
42559
43961
|
lines.push("```bash");
|
|
42560
43962
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/resolve \\`);
|
|
42561
43963
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
@@ -42565,10 +43967,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42565
43967
|
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>","keys":"1"}'`);
|
|
42566
43968
|
lines.push("```");
|
|
42567
43969
|
lines.push("");
|
|
42568
|
-
lines.push("Use `resolve` when the parsed modal buttons are correct. Use `raw` when the CLI expects a literal keystroke like `1`, `y`, or Enter. Repeat until idle.");
|
|
43970
|
+
lines.push("Use `resolve` when the parsed modal buttons are correct. Use `raw` when the CLI expects a literal keystroke like `1`, `y`, or Enter. Repeat until idle. Prefer the exercise endpoint instead of doing this by hand.");
|
|
42569
43971
|
lines.push("");
|
|
42570
43972
|
lines.push("### Patch Discipline");
|
|
42571
43973
|
lines.push("Once the repro is confirmed, immediately edit the target files. Avoid loops where you keep re-reading long files or re-running the same debug commands without changing code.");
|
|
43974
|
+
lines.push("For CLI transcript bugs, reproduce once with the exercise endpoint, inspect the returned trace once, patch immediately, then re-run the SAME exercise and compare the new `commit_transcript` frame.");
|
|
43975
|
+
lines.push("If the patched run still fails the exact required/banned substring checks above, the task is NOT complete even if the CLI exits normally.");
|
|
43976
|
+
lines.push("When you patch, write down the pattern family you are fixing: e.g. spinner/status, tool block, approval modal, footer chrome, OSC/control residue, prompt echo, or long-output continuation. Patch that family once instead of adding case-by-case literals.");
|
|
43977
|
+
lines.push('Bad fix pattern: add another `includes("Drizzling")` or `includes("Show more (")` check. Good fix pattern: broaden the regex/helper that recognizes spinner words, collapsed tool overflow lines, or footer chrome as a family.');
|
|
42572
43978
|
lines.push("");
|
|
42573
43979
|
lines.push("### 5. Verify the side effects outside the CLI");
|
|
42574
43980
|
lines.push("```bash");
|
|
@@ -42593,6 +43999,8 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42593
43999
|
lines.push("7. Re-run the debug endpoints after edits. Do NOT finish until the parsed result looks correct.");
|
|
42594
44000
|
lines.push("8. Confirm the parser still works after a redraw or scroll change without duplicating transcript history.");
|
|
42595
44001
|
lines.push("9. Confirm the implementation prefers current-screen signals over stale history when both are present.");
|
|
44002
|
+
lines.push("10. For transcript-cleanliness bugs, confirm the latest `commit_transcript` trace frame no longer contains tool headers, approval prompts, OSC residue like `0;`, or footer chrome unless they are truly user-facing answer content.");
|
|
44003
|
+
lines.push("11. Confirm the implementation uses generalized pattern classifiers or regexes for noisy UI families instead of accumulating one-off literal string exceptions for each observed sample.");
|
|
42596
44004
|
lines.push("");
|
|
42597
44005
|
if (userComment) {
|
|
42598
44006
|
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
@@ -42601,10 +44009,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42601
44009
|
lines.push(userComment);
|
|
42602
44010
|
lines.push("");
|
|
42603
44011
|
}
|
|
42604
|
-
lines.push("Start NOW. Launch the CLI, inspect PTY state, edit the scripts, and verify via the CLI debug endpoints.");
|
|
44012
|
+
lines.push("Start NOW. Launch the CLI, inspect the trace and PTY state, edit the scripts, and verify via the CLI debug + trace endpoints.");
|
|
42605
44013
|
return lines.join("\n");
|
|
42606
44014
|
}
|
|
42607
44015
|
function handleAutoImplSSE(ctx, type, req, res) {
|
|
44016
|
+
clearStaleAutoImplState(ctx, "SSE connection opened");
|
|
42608
44017
|
res.writeHead(200, {
|
|
42609
44018
|
"Content-Type": "text/event-stream",
|
|
42610
44019
|
"Cache-Control": "no-cache",
|
|
@@ -42626,6 +44035,7 @@ data: ${JSON.stringify(p.data)}
|
|
|
42626
44035
|
});
|
|
42627
44036
|
}
|
|
42628
44037
|
function handleAutoImplCancel(ctx, _type, _req, res) {
|
|
44038
|
+
clearStaleAutoImplState(ctx, "cancel request");
|
|
42629
44039
|
if (ctx.autoImplProcess) {
|
|
42630
44040
|
ctx.autoImplProcess.kill("SIGTERM");
|
|
42631
44041
|
setTimeout(() => {
|
|
@@ -42653,25 +44063,26 @@ data: ${JSON.stringify(msg.data)}
|
|
|
42653
44063
|
}
|
|
42654
44064
|
}
|
|
42655
44065
|
}
|
|
42656
|
-
var
|
|
44066
|
+
var fs14, path17, os18;
|
|
42657
44067
|
var init_dev_auto_implement = __esm({
|
|
42658
44068
|
"../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts"() {
|
|
42659
44069
|
"use strict";
|
|
42660
|
-
|
|
42661
|
-
|
|
44070
|
+
fs14 = __toESM(require("fs"));
|
|
44071
|
+
path17 = __toESM(require("path"));
|
|
42662
44072
|
os18 = __toESM(require("os"));
|
|
42663
44073
|
init_dev_server();
|
|
44074
|
+
init_dev_cli_debug();
|
|
42664
44075
|
}
|
|
42665
44076
|
});
|
|
42666
44077
|
|
|
42667
44078
|
// ../../oss/packages/daemon-core/src/daemon/dev-server.ts
|
|
42668
|
-
var http2,
|
|
44079
|
+
var http2, fs15, path18, DEV_SERVER_PORT, DevServer;
|
|
42669
44080
|
var init_dev_server = __esm({
|
|
42670
44081
|
"../../oss/packages/daemon-core/src/daemon/dev-server.ts"() {
|
|
42671
44082
|
"use strict";
|
|
42672
44083
|
http2 = __toESM(require("http"));
|
|
42673
|
-
|
|
42674
|
-
|
|
44084
|
+
fs15 = __toESM(require("fs"));
|
|
44085
|
+
path18 = __toESM(require("path"));
|
|
42675
44086
|
init_scaffold_template();
|
|
42676
44087
|
init_version_archive();
|
|
42677
44088
|
init_logger();
|
|
@@ -42732,11 +44143,16 @@ var init_dev_server = __esm({
|
|
|
42732
44143
|
{ method: "GET", pattern: "/api/cli/status", handler: (q2, s15) => this.handleCliStatus(q2, s15) },
|
|
42733
44144
|
{ method: "POST", pattern: "/api/cli/launch", handler: (q2, s15) => this.handleCliLaunch(q2, s15) },
|
|
42734
44145
|
{ method: "POST", pattern: "/api/cli/send", handler: (q2, s15) => this.handleCliSend(q2, s15) },
|
|
44146
|
+
{ method: "POST", pattern: "/api/cli/exercise", handler: (q2, s15) => this.handleCliExercise(q2, s15) },
|
|
44147
|
+
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q2, s15) => this.handleCliFixtureCapture(q2, s15) },
|
|
44148
|
+
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q2, s15) => this.handleCliFixtureReplay(q2, s15) },
|
|
42735
44149
|
{ method: "POST", pattern: "/api/cli/resolve", handler: (q2, s15) => this.handleCliResolve(q2, s15) },
|
|
42736
44150
|
{ method: "POST", pattern: "/api/cli/raw", handler: (q2, s15) => this.handleCliRaw(q2, s15) },
|
|
42737
44151
|
{ method: "POST", pattern: "/api/cli/stop", handler: (q2, s15) => this.handleCliStop(q2, s15) },
|
|
42738
44152
|
{ method: "GET", pattern: "/api/cli/events", handler: (q2, s15) => this.handleCliSSE(q2, s15) },
|
|
42739
44153
|
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliDebug(p[0], q2, s15) },
|
|
44154
|
+
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliTrace(p[0], q2, s15) },
|
|
44155
|
+
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliFixtureList(p[0], q2, s15) },
|
|
42740
44156
|
// Dynamic routes (provider :type param)
|
|
42741
44157
|
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q2, s15, p) => this.handleRunScript(p[0], q2, s15) },
|
|
42742
44158
|
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q2, s15, p) => this.handleListFiles(p[0], q2, s15) },
|
|
@@ -42770,8 +44186,8 @@ var init_dev_server = __esm({
|
|
|
42770
44186
|
}
|
|
42771
44187
|
getEndpointList() {
|
|
42772
44188
|
return this.routes.map((r) => {
|
|
42773
|
-
const
|
|
42774
|
-
return `${r.method.padEnd(5)} ${
|
|
44189
|
+
const path23 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
44190
|
+
return `${r.method.padEnd(5)} ${path23}`;
|
|
42775
44191
|
});
|
|
42776
44192
|
}
|
|
42777
44193
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -43053,12 +44469,12 @@ var init_dev_server = __esm({
|
|
|
43053
44469
|
// ─── DevConsole SPA ───
|
|
43054
44470
|
getConsoleDistDir() {
|
|
43055
44471
|
const candidates = [
|
|
43056
|
-
|
|
43057
|
-
|
|
43058
|
-
|
|
44472
|
+
path18.resolve(__dirname, "../../web-devconsole/dist"),
|
|
44473
|
+
path18.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
44474
|
+
path18.join(process.cwd(), "packages/web-devconsole/dist")
|
|
43059
44475
|
];
|
|
43060
44476
|
for (const dir of candidates) {
|
|
43061
|
-
if (
|
|
44477
|
+
if (fs15.existsSync(path18.join(dir, "index.html"))) return dir;
|
|
43062
44478
|
}
|
|
43063
44479
|
return null;
|
|
43064
44480
|
}
|
|
@@ -43068,9 +44484,9 @@ var init_dev_server = __esm({
|
|
|
43068
44484
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
43069
44485
|
return;
|
|
43070
44486
|
}
|
|
43071
|
-
const htmlPath =
|
|
44487
|
+
const htmlPath = path18.join(distDir, "index.html");
|
|
43072
44488
|
try {
|
|
43073
|
-
const html =
|
|
44489
|
+
const html = fs15.readFileSync(htmlPath, "utf-8");
|
|
43074
44490
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
43075
44491
|
res.end(html);
|
|
43076
44492
|
} catch (e) {
|
|
@@ -43093,15 +44509,15 @@ var init_dev_server = __esm({
|
|
|
43093
44509
|
this.json(res, 404, { error: "Not found" });
|
|
43094
44510
|
return;
|
|
43095
44511
|
}
|
|
43096
|
-
const safePath =
|
|
43097
|
-
const filePath =
|
|
44512
|
+
const safePath = path18.normalize(pathname).replace(/^\.\.\//, "");
|
|
44513
|
+
const filePath = path18.join(distDir, safePath);
|
|
43098
44514
|
if (!filePath.startsWith(distDir)) {
|
|
43099
44515
|
this.json(res, 403, { error: "Forbidden" });
|
|
43100
44516
|
return;
|
|
43101
44517
|
}
|
|
43102
44518
|
try {
|
|
43103
|
-
const content =
|
|
43104
|
-
const ext =
|
|
44519
|
+
const content = fs15.readFileSync(filePath);
|
|
44520
|
+
const ext = path18.extname(filePath);
|
|
43105
44521
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
43106
44522
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
43107
44523
|
res.end(content);
|
|
@@ -43209,14 +44625,14 @@ var init_dev_server = __esm({
|
|
|
43209
44625
|
const files = [];
|
|
43210
44626
|
const scan = (d, prefix) => {
|
|
43211
44627
|
try {
|
|
43212
|
-
for (const entry of
|
|
44628
|
+
for (const entry of fs15.readdirSync(d, { withFileTypes: true })) {
|
|
43213
44629
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
43214
44630
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
43215
44631
|
if (entry.isDirectory()) {
|
|
43216
44632
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
43217
|
-
scan(
|
|
44633
|
+
scan(path18.join(d, entry.name), rel);
|
|
43218
44634
|
} else {
|
|
43219
|
-
const stat4 =
|
|
44635
|
+
const stat4 = fs15.statSync(path18.join(d, entry.name));
|
|
43220
44636
|
files.push({ path: rel, size: stat4.size, type: "file" });
|
|
43221
44637
|
}
|
|
43222
44638
|
}
|
|
@@ -43239,16 +44655,16 @@ var init_dev_server = __esm({
|
|
|
43239
44655
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
43240
44656
|
return;
|
|
43241
44657
|
}
|
|
43242
|
-
const fullPath =
|
|
44658
|
+
const fullPath = path18.resolve(dir, path18.normalize(filePath));
|
|
43243
44659
|
if (!fullPath.startsWith(dir)) {
|
|
43244
44660
|
this.json(res, 403, { error: "Forbidden" });
|
|
43245
44661
|
return;
|
|
43246
44662
|
}
|
|
43247
|
-
if (!
|
|
44663
|
+
if (!fs15.existsSync(fullPath) || fs15.statSync(fullPath).isDirectory()) {
|
|
43248
44664
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
43249
44665
|
return;
|
|
43250
44666
|
}
|
|
43251
|
-
const content =
|
|
44667
|
+
const content = fs15.readFileSync(fullPath, "utf-8");
|
|
43252
44668
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
43253
44669
|
}
|
|
43254
44670
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -43264,15 +44680,15 @@ var init_dev_server = __esm({
|
|
|
43264
44680
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
43265
44681
|
return;
|
|
43266
44682
|
}
|
|
43267
|
-
const fullPath =
|
|
44683
|
+
const fullPath = path18.resolve(dir, path18.normalize(filePath));
|
|
43268
44684
|
if (!fullPath.startsWith(dir)) {
|
|
43269
44685
|
this.json(res, 403, { error: "Forbidden" });
|
|
43270
44686
|
return;
|
|
43271
44687
|
}
|
|
43272
44688
|
try {
|
|
43273
|
-
if (
|
|
43274
|
-
|
|
43275
|
-
|
|
44689
|
+
if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
|
|
44690
|
+
fs15.mkdirSync(path18.dirname(fullPath), { recursive: true });
|
|
44691
|
+
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
43276
44692
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
43277
44693
|
this.providerLoader.reload();
|
|
43278
44694
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -43288,9 +44704,9 @@ var init_dev_server = __esm({
|
|
|
43288
44704
|
return;
|
|
43289
44705
|
}
|
|
43290
44706
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
43291
|
-
const p =
|
|
43292
|
-
if (
|
|
43293
|
-
const source =
|
|
44707
|
+
const p = path18.join(dir, name);
|
|
44708
|
+
if (fs15.existsSync(p)) {
|
|
44709
|
+
const source = fs15.readFileSync(p, "utf-8");
|
|
43294
44710
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
43295
44711
|
return;
|
|
43296
44712
|
}
|
|
@@ -43309,11 +44725,11 @@ var init_dev_server = __esm({
|
|
|
43309
44725
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
43310
44726
|
return;
|
|
43311
44727
|
}
|
|
43312
|
-
const target =
|
|
43313
|
-
const targetPath =
|
|
44728
|
+
const target = fs15.existsSync(path18.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
44729
|
+
const targetPath = path18.join(dir, target);
|
|
43314
44730
|
try {
|
|
43315
|
-
if (
|
|
43316
|
-
|
|
44731
|
+
if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
|
|
44732
|
+
fs15.writeFileSync(targetPath, source, "utf-8");
|
|
43317
44733
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
43318
44734
|
this.providerLoader.reload();
|
|
43319
44735
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -43470,21 +44886,21 @@ var init_dev_server = __esm({
|
|
|
43470
44886
|
}
|
|
43471
44887
|
let targetDir;
|
|
43472
44888
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
43473
|
-
const jsonPath =
|
|
43474
|
-
if (
|
|
44889
|
+
const jsonPath = path18.join(targetDir, "provider.json");
|
|
44890
|
+
if (fs15.existsSync(jsonPath)) {
|
|
43475
44891
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
43476
44892
|
return;
|
|
43477
44893
|
}
|
|
43478
44894
|
try {
|
|
43479
44895
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2, osPaths, processNames });
|
|
43480
|
-
|
|
43481
|
-
|
|
44896
|
+
fs15.mkdirSync(targetDir, { recursive: true });
|
|
44897
|
+
fs15.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
43482
44898
|
const createdFiles = ["provider.json"];
|
|
43483
44899
|
if (result.files) {
|
|
43484
44900
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
43485
|
-
const fullPath =
|
|
43486
|
-
|
|
43487
|
-
|
|
44901
|
+
const fullPath = path18.join(targetDir, relPath);
|
|
44902
|
+
fs15.mkdirSync(path18.dirname(fullPath), { recursive: true });
|
|
44903
|
+
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
43488
44904
|
createdFiles.push(relPath);
|
|
43489
44905
|
}
|
|
43490
44906
|
}
|
|
@@ -43533,45 +44949,45 @@ var init_dev_server = __esm({
|
|
|
43533
44949
|
}
|
|
43534
44950
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
43535
44951
|
getLatestScriptVersionDir(scriptsDir) {
|
|
43536
|
-
if (!
|
|
43537
|
-
const versions =
|
|
44952
|
+
if (!fs15.existsSync(scriptsDir)) return null;
|
|
44953
|
+
const versions = fs15.readdirSync(scriptsDir).filter((d) => {
|
|
43538
44954
|
try {
|
|
43539
|
-
return
|
|
44955
|
+
return fs15.statSync(path18.join(scriptsDir, d)).isDirectory();
|
|
43540
44956
|
} catch {
|
|
43541
44957
|
return false;
|
|
43542
44958
|
}
|
|
43543
44959
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
43544
44960
|
if (versions.length === 0) return null;
|
|
43545
|
-
return
|
|
44961
|
+
return path18.join(scriptsDir, versions[0]);
|
|
43546
44962
|
}
|
|
43547
44963
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
43548
|
-
const canonicalUserDir =
|
|
43549
|
-
const desiredDir = requestedDir ?
|
|
43550
|
-
const upstreamRoot =
|
|
43551
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
44964
|
+
const canonicalUserDir = path18.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
44965
|
+
const desiredDir = requestedDir ? path18.resolve(requestedDir) : canonicalUserDir;
|
|
44966
|
+
const upstreamRoot = path18.resolve(this.providerLoader.getUpstreamDir());
|
|
44967
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path18.sep}`)) {
|
|
43552
44968
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
43553
44969
|
}
|
|
43554
|
-
if (
|
|
44970
|
+
if (path18.basename(desiredDir) !== type) {
|
|
43555
44971
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
43556
44972
|
}
|
|
43557
44973
|
const sourceDir = this.findProviderDir(type);
|
|
43558
44974
|
if (!sourceDir) {
|
|
43559
44975
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
43560
44976
|
}
|
|
43561
|
-
if (!
|
|
43562
|
-
|
|
43563
|
-
|
|
44977
|
+
if (!fs15.existsSync(desiredDir)) {
|
|
44978
|
+
fs15.mkdirSync(path18.dirname(desiredDir), { recursive: true });
|
|
44979
|
+
fs15.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
43564
44980
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
43565
44981
|
}
|
|
43566
|
-
const providerJson =
|
|
43567
|
-
if (!
|
|
44982
|
+
const providerJson = path18.join(desiredDir, "provider.json");
|
|
44983
|
+
if (!fs15.existsSync(providerJson)) {
|
|
43568
44984
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
43569
44985
|
}
|
|
43570
44986
|
try {
|
|
43571
|
-
const providerData = JSON.parse(
|
|
44987
|
+
const providerData = JSON.parse(fs15.readFileSync(providerJson, "utf-8"));
|
|
43572
44988
|
if (providerData.disableUpstream !== true) {
|
|
43573
44989
|
providerData.disableUpstream = true;
|
|
43574
|
-
|
|
44990
|
+
fs15.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
43575
44991
|
}
|
|
43576
44992
|
} catch (error48) {
|
|
43577
44993
|
return {
|
|
@@ -43611,7 +45027,7 @@ var init_dev_server = __esm({
|
|
|
43611
45027
|
setMode: "set_mode.js"
|
|
43612
45028
|
};
|
|
43613
45029
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
43614
|
-
const scriptsDir =
|
|
45030
|
+
const scriptsDir = path18.join(providerDir, "scripts");
|
|
43615
45031
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
43616
45032
|
if (latestScriptsDir) {
|
|
43617
45033
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -43619,10 +45035,10 @@ var init_dev_server = __esm({
|
|
|
43619
45035
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
43620
45036
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
43621
45037
|
lines.push("");
|
|
43622
|
-
for (const file2 of
|
|
45038
|
+
for (const file2 of fs15.readdirSync(latestScriptsDir)) {
|
|
43623
45039
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
43624
45040
|
try {
|
|
43625
|
-
const content =
|
|
45041
|
+
const content = fs15.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
|
|
43626
45042
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
43627
45043
|
lines.push("```javascript");
|
|
43628
45044
|
lines.push(content);
|
|
@@ -43632,14 +45048,14 @@ var init_dev_server = __esm({
|
|
|
43632
45048
|
}
|
|
43633
45049
|
}
|
|
43634
45050
|
}
|
|
43635
|
-
const refFiles =
|
|
45051
|
+
const refFiles = fs15.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
43636
45052
|
if (refFiles.length > 0) {
|
|
43637
45053
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
43638
45054
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
43639
45055
|
lines.push("");
|
|
43640
45056
|
for (const file2 of refFiles) {
|
|
43641
45057
|
try {
|
|
43642
|
-
const content =
|
|
45058
|
+
const content = fs15.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
|
|
43643
45059
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
43644
45060
|
lines.push("```javascript");
|
|
43645
45061
|
lines.push(content);
|
|
@@ -43680,11 +45096,11 @@ var init_dev_server = __esm({
|
|
|
43680
45096
|
lines.push("");
|
|
43681
45097
|
}
|
|
43682
45098
|
}
|
|
43683
|
-
const docsDir =
|
|
45099
|
+
const docsDir = path18.join(providerDir, "../../docs");
|
|
43684
45100
|
const loadGuide = (name) => {
|
|
43685
45101
|
try {
|
|
43686
|
-
const p =
|
|
43687
|
-
if (
|
|
45102
|
+
const p = path18.join(docsDir, name);
|
|
45103
|
+
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
43688
45104
|
} catch {
|
|
43689
45105
|
}
|
|
43690
45106
|
return null;
|
|
@@ -43857,7 +45273,7 @@ var init_dev_server = __esm({
|
|
|
43857
45273
|
parseApproval: "parse_approval.js"
|
|
43858
45274
|
};
|
|
43859
45275
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
43860
|
-
const scriptsDir =
|
|
45276
|
+
const scriptsDir = path18.join(providerDir, "scripts");
|
|
43861
45277
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
43862
45278
|
if (latestScriptsDir) {
|
|
43863
45279
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -43865,11 +45281,11 @@ var init_dev_server = __esm({
|
|
|
43865
45281
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
43866
45282
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
43867
45283
|
lines.push("");
|
|
43868
|
-
for (const file2 of
|
|
45284
|
+
for (const file2 of fs15.readdirSync(latestScriptsDir)) {
|
|
43869
45285
|
if (!file2.endsWith(".js")) continue;
|
|
43870
45286
|
if (!targetFileNames.has(file2)) continue;
|
|
43871
45287
|
try {
|
|
43872
|
-
const content =
|
|
45288
|
+
const content = fs15.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
|
|
43873
45289
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
43874
45290
|
lines.push("```javascript");
|
|
43875
45291
|
lines.push(content);
|
|
@@ -43878,14 +45294,14 @@ var init_dev_server = __esm({
|
|
|
43878
45294
|
} catch {
|
|
43879
45295
|
}
|
|
43880
45296
|
}
|
|
43881
|
-
const refFiles =
|
|
45297
|
+
const refFiles = fs15.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
43882
45298
|
if (refFiles.length > 0) {
|
|
43883
45299
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
43884
45300
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
43885
45301
|
lines.push("");
|
|
43886
45302
|
for (const file2 of refFiles) {
|
|
43887
45303
|
try {
|
|
43888
|
-
const content =
|
|
45304
|
+
const content = fs15.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
|
|
43889
45305
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
43890
45306
|
lines.push("```javascript");
|
|
43891
45307
|
lines.push(content);
|
|
@@ -43918,11 +45334,11 @@ var init_dev_server = __esm({
|
|
|
43918
45334
|
lines.push("");
|
|
43919
45335
|
}
|
|
43920
45336
|
}
|
|
43921
|
-
const docsDir =
|
|
45337
|
+
const docsDir = path18.join(providerDir, "../../docs");
|
|
43922
45338
|
const loadGuide = (name) => {
|
|
43923
45339
|
try {
|
|
43924
|
-
const p =
|
|
43925
|
-
if (
|
|
45340
|
+
const p = path18.join(docsDir, name);
|
|
45341
|
+
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
43926
45342
|
} catch {
|
|
43927
45343
|
}
|
|
43928
45344
|
return null;
|
|
@@ -43987,6 +45403,7 @@ var init_dev_server = __esm({
|
|
|
43987
45403
|
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
43988
45404
|
lines.push("```bash");
|
|
43989
45405
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
45406
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/trace/${type}`);
|
|
43990
45407
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
43991
45408
|
lines.push("```");
|
|
43992
45409
|
lines.push("");
|
|
@@ -44121,6 +45538,16 @@ data: ${JSON.stringify(msg.data)}
|
|
|
44121
45538
|
async handleCliSend(req, res) {
|
|
44122
45539
|
return handleCliSend(this, req, res);
|
|
44123
45540
|
}
|
|
45541
|
+
/** POST /api/cli/exercise — launch/send/approve/wait helper for provider-fix loops */
|
|
45542
|
+
async handleCliExercise(req, res) {
|
|
45543
|
+
return handleCliExercise(this, req, res);
|
|
45544
|
+
}
|
|
45545
|
+
async handleCliFixtureCapture(req, res) {
|
|
45546
|
+
return handleCliFixtureCapture(this, req, res);
|
|
45547
|
+
}
|
|
45548
|
+
async handleCliFixtureReplay(req, res) {
|
|
45549
|
+
return handleCliFixtureReplay(this, req, res);
|
|
45550
|
+
}
|
|
44124
45551
|
/** POST /api/cli/stop — stop a running CLI { type } */
|
|
44125
45552
|
async handleCliStop(req, res) {
|
|
44126
45553
|
return handleCliStop(this, req, res);
|
|
@@ -44144,6 +45571,13 @@ data: ${JSON.stringify(msg.data)}
|
|
|
44144
45571
|
async handleCliDebug(type, _req, res) {
|
|
44145
45572
|
return handleCliDebug(this, type, _req, res);
|
|
44146
45573
|
}
|
|
45574
|
+
/** GET /api/cli/trace/:type — recent CLI trace timeline plus current debug snapshot */
|
|
45575
|
+
async handleCliTrace(type, _req, res) {
|
|
45576
|
+
return handleCliTrace(this, type, _req, res);
|
|
45577
|
+
}
|
|
45578
|
+
async handleCliFixtureList(type, _req, res) {
|
|
45579
|
+
return handleCliFixtureList(this, type, _req, res);
|
|
45580
|
+
}
|
|
44147
45581
|
/** POST /api/cli/resolve — resolve an approval modal { type, buttonIndex } */
|
|
44148
45582
|
async handleCliResolve(req, res) {
|
|
44149
45583
|
return handleCliResolve(this, req, res);
|
|
@@ -44451,7 +45885,18 @@ var init_session_host_transport = __esm({
|
|
|
44451
45885
|
});
|
|
44452
45886
|
}
|
|
44453
45887
|
async boot() {
|
|
44454
|
-
|
|
45888
|
+
if (typeof this.options.ensureReady === "function") {
|
|
45889
|
+
await this.options.ensureReady();
|
|
45890
|
+
}
|
|
45891
|
+
try {
|
|
45892
|
+
await this.client.connect();
|
|
45893
|
+
} catch (error48) {
|
|
45894
|
+
if (typeof this.options.ensureReady !== "function") {
|
|
45895
|
+
throw error48;
|
|
45896
|
+
}
|
|
45897
|
+
await this.options.ensureReady();
|
|
45898
|
+
await this.client.connect();
|
|
45899
|
+
}
|
|
44455
45900
|
this.unsubscribe = this.client.onEvent((event) => this.handleEvent(event));
|
|
44456
45901
|
let record2 = null;
|
|
44457
45902
|
if (this.options.attachExisting) {
|
|
@@ -44764,8 +46209,8 @@ async function installExtension(ide, extension) {
|
|
|
44764
46209
|
const res = await fetch(extension.vsixUrl);
|
|
44765
46210
|
if (res.ok) {
|
|
44766
46211
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
44767
|
-
const
|
|
44768
|
-
|
|
46212
|
+
const fs19 = await import("fs");
|
|
46213
|
+
fs19.writeFileSync(vsixPath, buffer);
|
|
44769
46214
|
return new Promise((resolve13) => {
|
|
44770
46215
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
44771
46216
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
|
|
@@ -45604,17 +47049,17 @@ function canPeerUsePrivilegedShareCommand(commandType, permission) {
|
|
|
45604
47049
|
return false;
|
|
45605
47050
|
}
|
|
45606
47051
|
}
|
|
45607
|
-
var
|
|
47052
|
+
var fs16, path19, os20, import_node_module2, esmRequire, logFile, log, logDebug, DaemonP2PSender;
|
|
45608
47053
|
var init_daemon_p2p = __esm({
|
|
45609
47054
|
"src/daemon-p2p.ts"() {
|
|
45610
47055
|
"use strict";
|
|
45611
|
-
|
|
47056
|
+
fs16 = __toESM(require("fs"));
|
|
45612
47057
|
init_src();
|
|
45613
|
-
|
|
47058
|
+
path19 = __toESM(require("path"));
|
|
45614
47059
|
os20 = __toESM(require("os"));
|
|
45615
47060
|
import_node_module2 = require("module");
|
|
45616
47061
|
esmRequire = (0, import_node_module2.createRequire)(__filename);
|
|
45617
|
-
logFile =
|
|
47062
|
+
logFile = path19.join(os20.tmpdir(), "adhdev_daemon_p2p.log");
|
|
45618
47063
|
log = (msg) => {
|
|
45619
47064
|
LOG.info("P2P", `[${(/* @__PURE__ */ new Date()).toISOString()}] [P2P] ${msg}`);
|
|
45620
47065
|
};
|
|
@@ -45682,17 +47127,17 @@ ${e?.stack || ""}`);
|
|
|
45682
47127
|
const prebuildKey = `${platform11}-${arch3}`;
|
|
45683
47128
|
try {
|
|
45684
47129
|
const candidates = [
|
|
45685
|
-
|
|
45686
|
-
|
|
45687
|
-
|
|
47130
|
+
path19.join(__dirname, "node_modules", "node-datachannel"),
|
|
47131
|
+
path19.join(__dirname, "..", "node_modules", "node-datachannel"),
|
|
47132
|
+
path19.join(__dirname, "..", "..", "node_modules", "node-datachannel")
|
|
45688
47133
|
];
|
|
45689
47134
|
for (const candidate of candidates) {
|
|
45690
|
-
const prebuildPath =
|
|
45691
|
-
if (
|
|
45692
|
-
const targetDir =
|
|
45693
|
-
const targetPath =
|
|
45694
|
-
|
|
45695
|
-
|
|
47135
|
+
const prebuildPath = path19.join(candidate, "prebuilds", prebuildKey, "node_datachannel.node");
|
|
47136
|
+
if (fs16.existsSync(prebuildPath)) {
|
|
47137
|
+
const targetDir = path19.join(candidate, "build", "Release");
|
|
47138
|
+
const targetPath = path19.join(targetDir, "node_datachannel.node");
|
|
47139
|
+
fs16.mkdirSync(targetDir, { recursive: true });
|
|
47140
|
+
fs16.copyFileSync(prebuildPath, targetPath);
|
|
45696
47141
|
try {
|
|
45697
47142
|
delete esmRequire.cache[esmRequire.resolve("node-datachannel")];
|
|
45698
47143
|
} catch {
|
|
@@ -46592,20 +48037,34 @@ __export(session_host_exports, {
|
|
|
46592
48037
|
listHostedCliRuntimes: () => listHostedCliRuntimes2,
|
|
46593
48038
|
stopSessionHost: () => stopSessionHost
|
|
46594
48039
|
});
|
|
48040
|
+
function buildSessionHostEnv(baseEnv) {
|
|
48041
|
+
const env = {};
|
|
48042
|
+
for (const [key, value] of Object.entries(baseEnv)) {
|
|
48043
|
+
if (typeof value !== "string") continue;
|
|
48044
|
+
env[key] = value;
|
|
48045
|
+
}
|
|
48046
|
+
for (const key of Object.keys(env)) {
|
|
48047
|
+
if (key === "INIT_CWD" || key === "NO_COLOR" || key === "FORCE_COLOR" || key === "npm_command" || key === "npm_execpath" || key === "npm_node_execpath" || key.startsWith("npm_") || key.startsWith("npm_config_") || key.startsWith("npm_package_") || key.startsWith("npm_lifecycle_") || key.startsWith("PNPM_") || key.startsWith("YARN_") || key.startsWith("BUN_")) {
|
|
48048
|
+
delete env[key];
|
|
48049
|
+
}
|
|
48050
|
+
}
|
|
48051
|
+
env.ADHDEV_SESSION_HOST_NAME = SESSION_HOST_APP_NAME;
|
|
48052
|
+
return env;
|
|
48053
|
+
}
|
|
46595
48054
|
function resolveSessionHostEntry() {
|
|
46596
48055
|
const packagedCandidates = [
|
|
46597
|
-
|
|
46598
|
-
|
|
48056
|
+
path20.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
|
|
48057
|
+
path20.resolve(__dirname, "../../vendor/session-host-daemon/index.js")
|
|
46599
48058
|
];
|
|
46600
48059
|
for (const candidate of packagedCandidates) {
|
|
46601
|
-
if (
|
|
48060
|
+
if (fs17.existsSync(candidate)) {
|
|
46602
48061
|
return candidate;
|
|
46603
48062
|
}
|
|
46604
48063
|
}
|
|
46605
48064
|
return require.resolve("@adhdev/session-host-daemon");
|
|
46606
48065
|
}
|
|
46607
48066
|
function getSessionHostPidFile() {
|
|
46608
|
-
return
|
|
48067
|
+
return path20.join(os21.homedir(), ".adhdev", `${SESSION_HOST_APP_NAME}-session-host.pid`);
|
|
46609
48068
|
}
|
|
46610
48069
|
function killPid2(pid) {
|
|
46611
48070
|
try {
|
|
@@ -46623,8 +48082,8 @@ function stopSessionHost() {
|
|
|
46623
48082
|
let stopped = false;
|
|
46624
48083
|
const pidFile = getSessionHostPidFile();
|
|
46625
48084
|
try {
|
|
46626
|
-
if (
|
|
46627
|
-
const pid = Number.parseInt(
|
|
48085
|
+
if (fs17.existsSync(pidFile)) {
|
|
48086
|
+
const pid = Number.parseInt(fs17.readFileSync(pidFile, "utf8").trim(), 10);
|
|
46628
48087
|
if (Number.isFinite(pid)) {
|
|
46629
48088
|
stopped = killPid2(pid) || stopped;
|
|
46630
48089
|
}
|
|
@@ -46632,7 +48091,7 @@ function stopSessionHost() {
|
|
|
46632
48091
|
} catch {
|
|
46633
48092
|
} finally {
|
|
46634
48093
|
try {
|
|
46635
|
-
|
|
48094
|
+
fs17.unlinkSync(pidFile);
|
|
46636
48095
|
} catch {
|
|
46637
48096
|
}
|
|
46638
48097
|
}
|
|
@@ -46651,36 +48110,49 @@ function stopSessionHost() {
|
|
|
46651
48110
|
return stopped;
|
|
46652
48111
|
}
|
|
46653
48112
|
async function ensureSessionHostReady2() {
|
|
46654
|
-
|
|
46655
|
-
|
|
46656
|
-
|
|
46657
|
-
|
|
46658
|
-
|
|
46659
|
-
|
|
46660
|
-
|
|
46661
|
-
|
|
46662
|
-
|
|
46663
|
-
|
|
46664
|
-
|
|
46665
|
-
|
|
46666
|
-
|
|
46667
|
-
|
|
46668
|
-
|
|
46669
|
-
|
|
48113
|
+
const spawnHost = () => {
|
|
48114
|
+
const entry = resolveSessionHostEntry();
|
|
48115
|
+
const child = (0, import_child_process11.spawn)(process.execPath, [entry], {
|
|
48116
|
+
detached: true,
|
|
48117
|
+
stdio: "ignore",
|
|
48118
|
+
windowsHide: true,
|
|
48119
|
+
env: buildSessionHostEnv(process.env)
|
|
48120
|
+
});
|
|
48121
|
+
child.unref();
|
|
48122
|
+
};
|
|
48123
|
+
try {
|
|
48124
|
+
return await ensureSessionHostReady({
|
|
48125
|
+
appName: SESSION_HOST_APP_NAME,
|
|
48126
|
+
spawnHost,
|
|
48127
|
+
timeoutMs: SESSION_HOST_START_TIMEOUT_MS
|
|
48128
|
+
});
|
|
48129
|
+
} catch (error48) {
|
|
48130
|
+
stopSessionHost();
|
|
48131
|
+
return ensureSessionHostReady({
|
|
48132
|
+
appName: SESSION_HOST_APP_NAME,
|
|
48133
|
+
spawnHost,
|
|
48134
|
+
timeoutMs: SESSION_HOST_START_TIMEOUT_MS
|
|
48135
|
+
}).catch((retryError) => {
|
|
48136
|
+
const initialMessage = error48 instanceof Error ? error48.message : String(error48);
|
|
48137
|
+
const retryMessage = retryError instanceof Error ? retryError.message : String(retryError);
|
|
48138
|
+
throw new Error(`Session host failed to start after retry (${initialMessage}; retry: ${retryMessage})`);
|
|
48139
|
+
});
|
|
48140
|
+
}
|
|
46670
48141
|
}
|
|
46671
48142
|
async function listHostedCliRuntimes2(endpoint) {
|
|
46672
48143
|
return listHostedCliRuntimes(endpoint);
|
|
46673
48144
|
}
|
|
46674
|
-
var import_child_process11,
|
|
48145
|
+
var import_child_process11, fs17, os21, path20, SESSION_HOST_APP_NAME, SESSION_HOST_START_TIMEOUT_MS;
|
|
46675
48146
|
var init_session_host = __esm({
|
|
46676
48147
|
"src/session-host.ts"() {
|
|
46677
48148
|
"use strict";
|
|
46678
48149
|
import_child_process11 = require("child_process");
|
|
46679
|
-
|
|
48150
|
+
fs17 = __toESM(require("fs"));
|
|
46680
48151
|
os21 = __toESM(require("os"));
|
|
46681
|
-
|
|
48152
|
+
path20 = __toESM(require("path"));
|
|
46682
48153
|
init_src();
|
|
46683
48154
|
SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
|
|
48155
|
+
SESSION_HOST_START_TIMEOUT_MS = 15e3;
|
|
46684
48156
|
}
|
|
46685
48157
|
});
|
|
46686
48158
|
|
|
@@ -46692,24 +48164,24 @@ __export(adhdev_daemon_exports, {
|
|
|
46692
48164
|
stopDaemon: () => stopDaemon
|
|
46693
48165
|
});
|
|
46694
48166
|
function getDaemonPidFile() {
|
|
46695
|
-
const dir =
|
|
46696
|
-
if (!
|
|
46697
|
-
return
|
|
48167
|
+
const dir = path21.join(os22.homedir(), ".adhdev");
|
|
48168
|
+
if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
|
|
48169
|
+
return path21.join(dir, "daemon.pid");
|
|
46698
48170
|
}
|
|
46699
48171
|
function writeDaemonPid(pid) {
|
|
46700
|
-
|
|
48172
|
+
fs18.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
|
|
46701
48173
|
}
|
|
46702
48174
|
function removeDaemonPid() {
|
|
46703
48175
|
try {
|
|
46704
|
-
|
|
48176
|
+
fs18.unlinkSync(getDaemonPidFile());
|
|
46705
48177
|
} catch (e) {
|
|
46706
48178
|
}
|
|
46707
48179
|
}
|
|
46708
48180
|
function isDaemonRunning() {
|
|
46709
48181
|
const pidFile = getDaemonPidFile();
|
|
46710
48182
|
try {
|
|
46711
|
-
if (!
|
|
46712
|
-
const pid = parseInt(
|
|
48183
|
+
if (!fs18.existsSync(pidFile)) return false;
|
|
48184
|
+
const pid = parseInt(fs18.readFileSync(pidFile, "utf-8").trim());
|
|
46713
48185
|
process.kill(pid, 0);
|
|
46714
48186
|
return true;
|
|
46715
48187
|
} catch {
|
|
@@ -46720,8 +48192,8 @@ function isDaemonRunning() {
|
|
|
46720
48192
|
function stopDaemon() {
|
|
46721
48193
|
const pidFile = getDaemonPidFile();
|
|
46722
48194
|
try {
|
|
46723
|
-
if (!
|
|
46724
|
-
const pid = parseInt(
|
|
48195
|
+
if (!fs18.existsSync(pidFile)) return false;
|
|
48196
|
+
const pid = parseInt(fs18.readFileSync(pidFile, "utf-8").trim());
|
|
46725
48197
|
process.kill(pid, "SIGTERM");
|
|
46726
48198
|
removeDaemonPid();
|
|
46727
48199
|
return true;
|
|
@@ -46730,7 +48202,7 @@ function stopDaemon() {
|
|
|
46730
48202
|
return false;
|
|
46731
48203
|
}
|
|
46732
48204
|
}
|
|
46733
|
-
var os22,
|
|
48205
|
+
var os22, fs18, path21, import_chalk2, pkgVersion, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
46734
48206
|
var init_adhdev_daemon = __esm({
|
|
46735
48207
|
"src/adhdev-daemon.ts"() {
|
|
46736
48208
|
"use strict";
|
|
@@ -46741,19 +48213,19 @@ var init_adhdev_daemon = __esm({
|
|
|
46741
48213
|
init_session_host();
|
|
46742
48214
|
init_dist();
|
|
46743
48215
|
os22 = __toESM(require("os"));
|
|
46744
|
-
|
|
46745
|
-
|
|
48216
|
+
fs18 = __toESM(require("fs"));
|
|
48217
|
+
path21 = __toESM(require("path"));
|
|
46746
48218
|
import_chalk2 = __toESM(require("chalk"));
|
|
46747
|
-
pkgVersion = "0.
|
|
48219
|
+
pkgVersion = "0.8.1";
|
|
46748
48220
|
if (pkgVersion === "unknown") {
|
|
46749
48221
|
try {
|
|
46750
48222
|
const possiblePaths = [
|
|
46751
|
-
|
|
46752
|
-
|
|
48223
|
+
path21.join(__dirname, "..", "package.json"),
|
|
48224
|
+
path21.join(__dirname, "package.json")
|
|
46753
48225
|
];
|
|
46754
48226
|
for (const p of possiblePaths) {
|
|
46755
48227
|
try {
|
|
46756
|
-
const data = JSON.parse(
|
|
48228
|
+
const data = JSON.parse(fs18.readFileSync(p, "utf-8"));
|
|
46757
48229
|
if (data.version) {
|
|
46758
48230
|
pkgVersion = data.version;
|
|
46759
48231
|
break;
|
|
@@ -46851,6 +48323,10 @@ ${err?.stack || ""}`);
|
|
|
46851
48323
|
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
46852
48324
|
createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, providerSessionId, attachExisting }) => new SessionHostPtyTransportFactory({
|
|
46853
48325
|
endpoint: sessionHostEndpoint,
|
|
48326
|
+
ensureReady: async () => {
|
|
48327
|
+
const activeEndpoint = await ensureSessionHostReady2();
|
|
48328
|
+
this.sessionHostEndpoint = activeEndpoint;
|
|
48329
|
+
},
|
|
46854
48330
|
clientId: `daemon_${config2.machineId}`,
|
|
46855
48331
|
runtimeId,
|
|
46856
48332
|
providerType,
|
|
@@ -47221,9 +48697,13 @@ var wizard_exports = {};
|
|
|
47221
48697
|
__export(wizard_exports, {
|
|
47222
48698
|
runWizard: () => runWizard
|
|
47223
48699
|
});
|
|
48700
|
+
function hasCloudMachineAuth() {
|
|
48701
|
+
const config2 = loadConfig();
|
|
48702
|
+
return Boolean(config2.machineSecret && config2.machineSecret.trim());
|
|
48703
|
+
}
|
|
47224
48704
|
async function runWizard(options = {}) {
|
|
47225
48705
|
console.log(LOGO);
|
|
47226
|
-
if (isSetupComplete() && !options.force) {
|
|
48706
|
+
if (isSetupComplete() && hasCloudMachineAuth() && !options.force) {
|
|
47227
48707
|
const config2 = loadConfig();
|
|
47228
48708
|
console.log(import_chalk3.default.green("\u2713") + " ADHDev is already configured.");
|
|
47229
48709
|
console.log(import_chalk3.default.gray(` Account: ${config2.userEmail || "not logged in"}`));
|
|
@@ -47288,29 +48768,46 @@ async function checkForUpdate() {
|
|
|
47288
48768
|
async function quickSetup() {
|
|
47289
48769
|
console.log(import_chalk3.default.bold("\n\u{1F680} Quick Setup\n"));
|
|
47290
48770
|
const loginResult = await loginFlow();
|
|
48771
|
+
const setupDate = (/* @__PURE__ */ new Date()).toISOString();
|
|
47291
48772
|
if (!loginResult) {
|
|
47292
|
-
|
|
48773
|
+
updateConfig({
|
|
48774
|
+
selectedIde: "daemon",
|
|
48775
|
+
configuredIdes: ["daemon"],
|
|
48776
|
+
installedExtensions: ["adhdev"],
|
|
48777
|
+
setupCompleted: false,
|
|
48778
|
+
setupDate,
|
|
48779
|
+
userEmail: null,
|
|
48780
|
+
userName: null,
|
|
48781
|
+
machineSecret: null
|
|
48782
|
+
});
|
|
48783
|
+
console.log(import_chalk3.default.yellow("\u26A0 Setup is not complete without login. Run `adhdev setup` after signing in."));
|
|
47293
48784
|
}
|
|
47294
|
-
markSetupComplete(["daemon"], ["adhdev"]);
|
|
47295
48785
|
if (loginResult) {
|
|
48786
|
+
markSetupComplete(["daemon"], ["adhdev"]);
|
|
47296
48787
|
const configUpdate = {
|
|
47297
48788
|
machineSecret: loginResult.machineSecret,
|
|
47298
48789
|
userEmail: loginResult.email,
|
|
47299
48790
|
userName: loginResult.name,
|
|
48791
|
+
setupDate,
|
|
47300
48792
|
...loginResult.registeredMachineId ? { registeredMachineId: loginResult.registeredMachineId } : {}
|
|
47301
48793
|
};
|
|
47302
48794
|
updateConfig(configUpdate);
|
|
47303
48795
|
console.log(import_chalk3.default.green(` \u2713 Machine registered`));
|
|
47304
48796
|
}
|
|
47305
48797
|
await installCliOnly();
|
|
47306
|
-
|
|
48798
|
+
if (loginResult) {
|
|
48799
|
+
await startDaemonFlow();
|
|
48800
|
+
} else {
|
|
48801
|
+
console.log(import_chalk3.default.gray(" Start daemon after login: adhdev setup"));
|
|
48802
|
+
console.log();
|
|
48803
|
+
}
|
|
47307
48804
|
console.log(DIVIDER);
|
|
47308
48805
|
console.log(import_chalk3.default.bold("\n\u{1F389} Setup Complete!\n"));
|
|
47309
48806
|
console.log(` ${import_chalk3.default.bold("User:")} ${loginResult?.email || "not logged in"}`);
|
|
47310
|
-
console.log(` ${import_chalk3.default.bold("Status:")} ${import_chalk3.default.green("Ready to connect")}`);
|
|
48807
|
+
console.log(` ${import_chalk3.default.bold("Status:")} ${loginResult ? import_chalk3.default.green("Ready to connect") : import_chalk3.default.yellow("Login required")}`);
|
|
47311
48808
|
console.log();
|
|
47312
48809
|
console.log(import_chalk3.default.gray(" Next steps:"));
|
|
47313
|
-
console.log(import_chalk3.default.gray("
|
|
48810
|
+
console.log(import_chalk3.default.gray(` ${loginResult ? "adhdev daemon \u2014 Start the main daemon (required for all features)" : "adhdev setup \u2014 Sign in to finish setup and enable the daemon"}`));
|
|
47314
48811
|
console.log(import_chalk3.default.gray(" adhdev launch cursor \u2014 Launch Cursor IDE with remote control"));
|
|
47315
48812
|
console.log(import_chalk3.default.gray(" adhdev launch windsurf \u2014 Launch Windsurf IDE with remote control"));
|
|
47316
48813
|
console.log(import_chalk3.default.gray(" adhdev launch gemini \u2014 Start Gemini CLI agent via daemon"));
|
|
@@ -47446,8 +48943,8 @@ async function startDaemonFlow() {
|
|
|
47446
48943
|
const daemon = new AdhdevDaemon2();
|
|
47447
48944
|
const { execSync: execSync7 } = await import("child_process");
|
|
47448
48945
|
const os23 = await import("os");
|
|
47449
|
-
const
|
|
47450
|
-
const logPath =
|
|
48946
|
+
const path23 = await import("path");
|
|
48947
|
+
const logPath = path23.join(os23.homedir(), ".adhdev", "daemon.log");
|
|
47451
48948
|
const platform11 = os23.platform();
|
|
47452
48949
|
try {
|
|
47453
48950
|
if (platform11 === "win32") {
|
|
@@ -47926,12 +49423,19 @@ function registerSetupCommands(program2, providerLoader) {
|
|
|
47926
49423
|
program2.command("status").description("Show current ADHDev setup status").action(async () => {
|
|
47927
49424
|
const { loadConfig: loadConfig2, detectIDEs: detectIDEs2, detectCLIs: detectCLIs2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
47928
49425
|
const config2 = loadConfig2();
|
|
49426
|
+
const hasMachineSecret = Boolean(config2.machineSecret && config2.machineSecret.trim());
|
|
47929
49427
|
console.log(import_chalk4.default.bold("\n\u{1F9A6} ADHDev Status\n"));
|
|
47930
49428
|
if (!config2.setupCompleted) {
|
|
47931
49429
|
console.log(import_chalk4.default.yellow(" Status: Not configured"));
|
|
47932
49430
|
console.log(import_chalk4.default.gray(" Run `adhdev setup` to get started.\n"));
|
|
47933
49431
|
return;
|
|
47934
49432
|
}
|
|
49433
|
+
if (!hasMachineSecret) {
|
|
49434
|
+
console.log(` ${import_chalk4.default.bold("Status:")} ${import_chalk4.default.yellow("Login required")}`);
|
|
49435
|
+
console.log(import_chalk4.default.gray(" Setup was started, but this machine is not linked to an ADHDev account yet."));
|
|
49436
|
+
console.log(import_chalk4.default.gray(" Run `adhdev setup` to finish authentication.\n"));
|
|
49437
|
+
return;
|
|
49438
|
+
}
|
|
47935
49439
|
const ideList = config2.configuredIdes?.length ? config2.configuredIdes : config2.selectedIde ? [config2.selectedIde] : [];
|
|
47936
49440
|
console.log(` ${import_chalk4.default.bold("Status:")} ${import_chalk4.default.green("\u2713 Configured")}`);
|
|
47937
49441
|
if (ideList.length > 0) {
|
|
@@ -48437,35 +49941,35 @@ function registerProviderCommands(program2) {
|
|
|
48437
49941
|
let osPaths = {};
|
|
48438
49942
|
let processNames = {};
|
|
48439
49943
|
if (category === "ide") {
|
|
48440
|
-
const
|
|
48441
|
-
const
|
|
49944
|
+
const fs19 = await import("fs");
|
|
49945
|
+
const path23 = await import("path");
|
|
48442
49946
|
const os23 = await import("os");
|
|
48443
49947
|
if (os23.platform() === "darwin") {
|
|
48444
49948
|
while (true) {
|
|
48445
49949
|
const p = (await rl.question(`macOS Application Path (e.g. /Applications/${defaultName}.app): `)).trim() || `/Applications/${defaultName}.app`;
|
|
48446
49950
|
if (p === "skip") break;
|
|
48447
|
-
if (!
|
|
49951
|
+
if (!fs19.existsSync(p)) {
|
|
48448
49952
|
console.log(import_chalk6.default.red(` \u2717 Path not found: ${p}`));
|
|
48449
49953
|
console.log(import_chalk6.default.gray(` (Please provide the exact absolute path to the .app or binary, or type 'skip')`));
|
|
48450
49954
|
continue;
|
|
48451
49955
|
}
|
|
48452
49956
|
console.log(import_chalk6.default.green(` \u2713 Path verified: ${p}`));
|
|
48453
49957
|
osPaths["darwin"] = [p];
|
|
48454
|
-
processNames["darwin"] =
|
|
49958
|
+
processNames["darwin"] = path23.basename(p, ".app");
|
|
48455
49959
|
break;
|
|
48456
49960
|
}
|
|
48457
49961
|
} else if (os23.platform() === "win32") {
|
|
48458
49962
|
while (true) {
|
|
48459
49963
|
const p = (await rl.question(`Windows Executable Path (e.g. C:\\Program Files\\${defaultName}\\${defaultName}.exe): `)).trim();
|
|
48460
49964
|
if (!p || p === "skip") break;
|
|
48461
|
-
if (!
|
|
49965
|
+
if (!fs19.existsSync(p)) {
|
|
48462
49966
|
console.log(import_chalk6.default.red(` \u2717 Path not found: ${p}`));
|
|
48463
49967
|
console.log(import_chalk6.default.gray(` (Please provide the exact absolute path, or type 'skip')`));
|
|
48464
49968
|
continue;
|
|
48465
49969
|
}
|
|
48466
49970
|
console.log(import_chalk6.default.green(` \u2713 Path verified: ${p}`));
|
|
48467
49971
|
osPaths["win32"] = [p];
|
|
48468
|
-
processNames["win32"] =
|
|
49972
|
+
processNames["win32"] = path23.basename(p, ".exe");
|
|
48469
49973
|
break;
|
|
48470
49974
|
}
|
|
48471
49975
|
}
|
|
@@ -49141,8 +50645,8 @@ function registerCdpCommands(program2) {
|
|
|
49141
50645
|
}
|
|
49142
50646
|
const output = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
49143
50647
|
if (options.output) {
|
|
49144
|
-
const
|
|
49145
|
-
|
|
50648
|
+
const fs19 = await import("fs");
|
|
50649
|
+
fs19.writeFileSync(options.output, output, "utf-8");
|
|
49146
50650
|
console.log(import_chalk6.default.green(`
|
|
49147
50651
|
\u2713 Saved to ${options.output} (${output.length} chars)
|
|
49148
50652
|
`));
|
|
@@ -49245,8 +50749,8 @@ function registerCdpCommands(program2) {
|
|
|
49245
50749
|
ws2.on("message", async (data) => {
|
|
49246
50750
|
const msg = JSON.parse(data.toString());
|
|
49247
50751
|
if (msg.id === 1 && msg.result?.data) {
|
|
49248
|
-
const
|
|
49249
|
-
|
|
50752
|
+
const fs19 = await import("fs");
|
|
50753
|
+
fs19.writeFileSync(options.output, Buffer.from(msg.result.data, "base64"));
|
|
49250
50754
|
console.log(import_chalk6.default.green(`
|
|
49251
50755
|
\u2713 Screenshot saved to ${options.output}
|
|
49252
50756
|
`));
|