adhdev 0.7.46 → 0.8.0
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 +1881 -414
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1924 -410
- 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];
|
|
@@ -41422,6 +41874,160 @@ var init_dev_cdp_handlers = __esm({
|
|
|
41422
41874
|
});
|
|
41423
41875
|
|
|
41424
41876
|
// ../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts
|
|
41877
|
+
function slugifyFixtureName(value) {
|
|
41878
|
+
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
41879
|
+
return normalized || `fixture-${Date.now()}`;
|
|
41880
|
+
}
|
|
41881
|
+
function getCliFixtureDir(ctx, type) {
|
|
41882
|
+
const providerDir = ctx.providerLoader.findProviderDir(type);
|
|
41883
|
+
if (!providerDir) {
|
|
41884
|
+
throw new Error(`Provider directory not found for '${type}'`);
|
|
41885
|
+
}
|
|
41886
|
+
return path16.join(providerDir, "fixtures");
|
|
41887
|
+
}
|
|
41888
|
+
function readCliFixture(ctx, type, name) {
|
|
41889
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
41890
|
+
const filePath = path16.join(fixtureDir, `${name}.json`);
|
|
41891
|
+
if (!fs13.existsSync(filePath)) {
|
|
41892
|
+
throw new Error(`Fixture not found: ${filePath}`);
|
|
41893
|
+
}
|
|
41894
|
+
return JSON.parse(fs13.readFileSync(filePath, "utf-8"));
|
|
41895
|
+
}
|
|
41896
|
+
function getExerciseTranscriptText(result) {
|
|
41897
|
+
const parts = [];
|
|
41898
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41899
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41900
|
+
for (const message of [...debugMessages, ...traceMessages]) {
|
|
41901
|
+
if (!message || typeof message.content !== "string") continue;
|
|
41902
|
+
parts.push(message.content);
|
|
41903
|
+
}
|
|
41904
|
+
if (typeof result?.debug?.partialResponse === "string") parts.push(result.debug.partialResponse);
|
|
41905
|
+
if (typeof result?.trace?.responseBuffer === "string") parts.push(result.trace.responseBuffer);
|
|
41906
|
+
return parts.join("\n");
|
|
41907
|
+
}
|
|
41908
|
+
function getExerciseLastAssistant(result) {
|
|
41909
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41910
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41911
|
+
for (const messages of [debugMessages, traceMessages]) {
|
|
41912
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
41913
|
+
const message = messages[i];
|
|
41914
|
+
if (message?.role === "assistant" && typeof message.content === "string" && message.content.trim()) {
|
|
41915
|
+
return message.content;
|
|
41916
|
+
}
|
|
41917
|
+
}
|
|
41918
|
+
}
|
|
41919
|
+
return "";
|
|
41920
|
+
}
|
|
41921
|
+
function getExerciseMessageCount(result) {
|
|
41922
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41923
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41924
|
+
return Math.max(debugMessages.length, traceMessages.length);
|
|
41925
|
+
}
|
|
41926
|
+
function compileFixtureRegex(source) {
|
|
41927
|
+
const value = String(source || "").trim();
|
|
41928
|
+
if (!value) return null;
|
|
41929
|
+
const delimited = value.match(/^\/([\s\S]+)\/([dgimsuvy]*)$/);
|
|
41930
|
+
try {
|
|
41931
|
+
if (delimited) {
|
|
41932
|
+
return new RegExp(delimited[1], delimited[2]);
|
|
41933
|
+
}
|
|
41934
|
+
return new RegExp(value, "m");
|
|
41935
|
+
} catch {
|
|
41936
|
+
return null;
|
|
41937
|
+
}
|
|
41938
|
+
}
|
|
41939
|
+
function statusesContainSequence(actual, expected) {
|
|
41940
|
+
if (!expected.length) return true;
|
|
41941
|
+
let index = 0;
|
|
41942
|
+
for (const status of actual) {
|
|
41943
|
+
if (status === expected[index]) index += 1;
|
|
41944
|
+
if (index >= expected.length) return true;
|
|
41945
|
+
}
|
|
41946
|
+
return false;
|
|
41947
|
+
}
|
|
41948
|
+
function validateCliFixtureResult(result, assertions) {
|
|
41949
|
+
const failures = [];
|
|
41950
|
+
const transcriptText = getExerciseTranscriptText(result);
|
|
41951
|
+
const lastAssistant = getExerciseLastAssistant(result);
|
|
41952
|
+
const mustContainAny = assertions.mustContainAny || [];
|
|
41953
|
+
const mustNotContainAny = assertions.mustNotContainAny || [];
|
|
41954
|
+
const mustMatchAny = assertions.mustMatchAny || [];
|
|
41955
|
+
const mustNotMatchAny = assertions.mustNotMatchAny || [];
|
|
41956
|
+
const lastAssistantMustContainAny = assertions.lastAssistantMustContainAny || [];
|
|
41957
|
+
const lastAssistantMustNotContainAny = assertions.lastAssistantMustNotContainAny || [];
|
|
41958
|
+
const lastAssistantMustMatchAny = assertions.lastAssistantMustMatchAny || [];
|
|
41959
|
+
const lastAssistantMustNotMatchAny = assertions.lastAssistantMustNotMatchAny || [];
|
|
41960
|
+
const statusesSeen = Array.isArray(result?.statusesSeen) ? result.statusesSeen.map((value) => String(value)) : [];
|
|
41961
|
+
if (assertions.requireNotTimedOut !== false && result?.timedOut) {
|
|
41962
|
+
failures.push("Exercise timed out");
|
|
41963
|
+
}
|
|
41964
|
+
const missingRequired = mustContainAny.filter((value) => !transcriptText.includes(value));
|
|
41965
|
+
if (missingRequired.length > 0) {
|
|
41966
|
+
failures.push(`Missing required substrings: ${missingRequired.join(", ")}`);
|
|
41967
|
+
}
|
|
41968
|
+
const presentBanned = mustNotContainAny.filter((value) => transcriptText.includes(value));
|
|
41969
|
+
if (presentBanned.length > 0) {
|
|
41970
|
+
failures.push(`Found banned substrings: ${presentBanned.join(", ")}`);
|
|
41971
|
+
}
|
|
41972
|
+
const missingRegex = mustMatchAny.filter((value) => {
|
|
41973
|
+
const regex = compileFixtureRegex(value);
|
|
41974
|
+
return !regex || !regex.test(transcriptText);
|
|
41975
|
+
});
|
|
41976
|
+
if (missingRegex.length > 0) {
|
|
41977
|
+
failures.push(`Missing required regex matches: ${missingRegex.join(", ")}`);
|
|
41978
|
+
}
|
|
41979
|
+
const presentBannedRegex = mustNotMatchAny.filter((value) => {
|
|
41980
|
+
const regex = compileFixtureRegex(value);
|
|
41981
|
+
return !!regex && regex.test(transcriptText);
|
|
41982
|
+
});
|
|
41983
|
+
if (presentBannedRegex.length > 0) {
|
|
41984
|
+
failures.push(`Found banned regex matches: ${presentBannedRegex.join(", ")}`);
|
|
41985
|
+
}
|
|
41986
|
+
const missingLastAssistant = lastAssistantMustContainAny.filter((value) => !lastAssistant.includes(value));
|
|
41987
|
+
if (missingLastAssistant.length > 0) {
|
|
41988
|
+
failures.push(`Missing required lastAssistant substrings: ${missingLastAssistant.join(", ")}`);
|
|
41989
|
+
}
|
|
41990
|
+
const presentBannedLastAssistant = lastAssistantMustNotContainAny.filter((value) => lastAssistant.includes(value));
|
|
41991
|
+
if (presentBannedLastAssistant.length > 0) {
|
|
41992
|
+
failures.push(`Found banned lastAssistant substrings: ${presentBannedLastAssistant.join(", ")}`);
|
|
41993
|
+
}
|
|
41994
|
+
const missingLastAssistantRegex = lastAssistantMustMatchAny.filter((value) => {
|
|
41995
|
+
const regex = compileFixtureRegex(value);
|
|
41996
|
+
return !regex || !regex.test(lastAssistant);
|
|
41997
|
+
});
|
|
41998
|
+
if (missingLastAssistantRegex.length > 0) {
|
|
41999
|
+
failures.push(`Missing required lastAssistant regex matches: ${missingLastAssistantRegex.join(", ")}`);
|
|
42000
|
+
}
|
|
42001
|
+
const presentBannedLastAssistantRegex = lastAssistantMustNotMatchAny.filter((value) => {
|
|
42002
|
+
const regex = compileFixtureRegex(value);
|
|
42003
|
+
return !!regex && regex.test(lastAssistant);
|
|
42004
|
+
});
|
|
42005
|
+
if (presentBannedLastAssistantRegex.length > 0) {
|
|
42006
|
+
failures.push(`Found banned lastAssistant regex matches: ${presentBannedLastAssistantRegex.join(", ")}`);
|
|
42007
|
+
}
|
|
42008
|
+
if (assertions.statusesSeen?.length && !statusesContainSequence(statusesSeen, assertions.statusesSeen)) {
|
|
42009
|
+
failures.push(`Expected statuses sequence not observed: ${assertions.statusesSeen.join(" -> ")}`);
|
|
42010
|
+
}
|
|
42011
|
+
if (result && typeof result === "object") {
|
|
42012
|
+
result.lastAssistant = lastAssistant;
|
|
42013
|
+
}
|
|
42014
|
+
return failures;
|
|
42015
|
+
}
|
|
42016
|
+
function getCliProviderResolutionMeta(ctx, type, adapter) {
|
|
42017
|
+
const adapterMeta = typeof adapter?.getProviderResolutionMeta === "function" ? adapter.getProviderResolutionMeta() : adapter?.getDebugState?.()?.providerResolution || null;
|
|
42018
|
+
const resolvedProvider = ctx.providerLoader.resolve(type);
|
|
42019
|
+
if (!adapterMeta && !resolvedProvider) return null;
|
|
42020
|
+
return {
|
|
42021
|
+
type,
|
|
42022
|
+
providerDir: adapterMeta?.providerDir || resolvedProvider?._resolvedProviderDir || ctx.providerLoader.findProviderDir(type),
|
|
42023
|
+
scriptDir: adapterMeta?.scriptDir || resolvedProvider?._resolvedScriptDir || null,
|
|
42024
|
+
scriptsPath: adapterMeta?.scriptsPath || resolvedProvider?._resolvedScriptsPath || null,
|
|
42025
|
+
scriptsSource: adapterMeta?.scriptsSource || resolvedProvider?._resolvedScriptsSource || null,
|
|
42026
|
+
resolvedVersion: adapterMeta?.resolvedVersion || resolvedProvider?._resolvedVersion || null,
|
|
42027
|
+
resolvedOs: adapterMeta?.resolvedOs || resolvedProvider?._resolvedOs || null,
|
|
42028
|
+
versionWarning: adapterMeta?.versionWarning || resolvedProvider?._versionWarning || null
|
|
42029
|
+
};
|
|
42030
|
+
}
|
|
41425
42031
|
function findCliTarget(ctx, type, instanceId) {
|
|
41426
42032
|
if (!ctx.instanceManager) return null;
|
|
41427
42033
|
const cliStates = ctx.instanceManager.collectAllStates().filter((s15) => s15.category === "cli" || s15.category === "acp");
|
|
@@ -41430,6 +42036,331 @@ function findCliTarget(ctx, type, instanceId) {
|
|
|
41430
42036
|
const matches = cliStates.filter((s15) => s15.type === type);
|
|
41431
42037
|
return matches[matches.length - 1] || null;
|
|
41432
42038
|
}
|
|
42039
|
+
function getCliTargetBundle(ctx, type, instanceId) {
|
|
42040
|
+
if (!ctx.instanceManager) return null;
|
|
42041
|
+
const target = findCliTarget(ctx, type, instanceId);
|
|
42042
|
+
if (!target) return null;
|
|
42043
|
+
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
42044
|
+
if (!instance) return null;
|
|
42045
|
+
const adapter = instance.getAdapter?.() || instance.adapter;
|
|
42046
|
+
if (!adapter) return null;
|
|
42047
|
+
return { target, instance, adapter };
|
|
42048
|
+
}
|
|
42049
|
+
function sleep(ms2) {
|
|
42050
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms2));
|
|
42051
|
+
}
|
|
42052
|
+
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
42053
|
+
const startedAt = Date.now();
|
|
42054
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
42055
|
+
const bundle = getCliTargetBundle(ctx, type, instanceId);
|
|
42056
|
+
if (bundle) {
|
|
42057
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
42058
|
+
const startupParseGate = !!debug?.startupParseGate;
|
|
42059
|
+
const adapterReady = !!debug?.ready;
|
|
42060
|
+
const visibleStatusReady = bundle.target.status === "generating" || bundle.target.status === "waiting_approval";
|
|
42061
|
+
const idleReady = bundle.target.status === "idle" && !startupParseGate;
|
|
42062
|
+
if (adapterReady || visibleStatusReady || idleReady) {
|
|
42063
|
+
return bundle;
|
|
42064
|
+
}
|
|
42065
|
+
}
|
|
42066
|
+
await sleep(100);
|
|
42067
|
+
}
|
|
42068
|
+
return getCliTargetBundle(ctx, type, instanceId);
|
|
42069
|
+
}
|
|
42070
|
+
async function runCliExerciseInternal(ctx, body) {
|
|
42071
|
+
if (!ctx.cliManager) {
|
|
42072
|
+
throw new Error("CliManager not available");
|
|
42073
|
+
}
|
|
42074
|
+
if (!ctx.instanceManager) {
|
|
42075
|
+
throw new Error("InstanceManager not available");
|
|
42076
|
+
}
|
|
42077
|
+
const {
|
|
42078
|
+
type,
|
|
42079
|
+
text,
|
|
42080
|
+
instanceId: requestedInstanceId,
|
|
42081
|
+
workingDir,
|
|
42082
|
+
args,
|
|
42083
|
+
autoLaunch = true,
|
|
42084
|
+
freshSession = true,
|
|
42085
|
+
autoResolveApprovals = true,
|
|
42086
|
+
approvalButtonIndex = 0,
|
|
42087
|
+
timeoutMs = 45e3,
|
|
42088
|
+
readyTimeoutMs = 15e3,
|
|
42089
|
+
idleSettledMs = 1200,
|
|
42090
|
+
traceLimit = 160,
|
|
42091
|
+
stopWhenDone = false
|
|
42092
|
+
} = body || {};
|
|
42093
|
+
if (!type) {
|
|
42094
|
+
throw new Error("type required (e.g. claude-cli, codex-cli)");
|
|
42095
|
+
}
|
|
42096
|
+
if (!text || typeof text !== "string") {
|
|
42097
|
+
throw new Error("text required (prompt to send to the CLI)");
|
|
42098
|
+
}
|
|
42099
|
+
let resolvedInstanceId = requestedInstanceId;
|
|
42100
|
+
if (freshSession) {
|
|
42101
|
+
const staleTargets = ctx.instanceManager.collectAllStates().filter((state) => (state.category === "cli" || state.category === "acp") && state.type === type).map((state) => state.instanceId);
|
|
42102
|
+
for (const staleId of staleTargets) {
|
|
42103
|
+
ctx.instanceManager.removeInstance(staleId);
|
|
42104
|
+
}
|
|
42105
|
+
resolvedInstanceId = void 0;
|
|
42106
|
+
}
|
|
42107
|
+
let bundle = getCliTargetBundle(ctx, type, resolvedInstanceId);
|
|
42108
|
+
if (!bundle && autoLaunch) {
|
|
42109
|
+
const launchArgs = [type, workingDir || process.cwd(), Array.isArray(args) ? args : []];
|
|
42110
|
+
let launched = null;
|
|
42111
|
+
let lastLaunchError = null;
|
|
42112
|
+
for (let attempt = 1; attempt <= 2; attempt += 1) {
|
|
42113
|
+
try {
|
|
42114
|
+
launched = await ctx.cliManager.startSession(...launchArgs);
|
|
42115
|
+
lastLaunchError = null;
|
|
42116
|
+
break;
|
|
42117
|
+
} catch (error48) {
|
|
42118
|
+
lastLaunchError = error48 instanceof Error ? error48 : new Error(String(error48?.message || error48));
|
|
42119
|
+
const message = String(lastLaunchError.message || "");
|
|
42120
|
+
const retryable = /ECONNREFUSED|session-host|Session host/i.test(message);
|
|
42121
|
+
if (!retryable || attempt === 2) break;
|
|
42122
|
+
await sleep(1e3);
|
|
42123
|
+
}
|
|
42124
|
+
}
|
|
42125
|
+
if (!launched) {
|
|
42126
|
+
throw lastLaunchError || new Error(`Failed to start ${type}`);
|
|
42127
|
+
}
|
|
42128
|
+
resolvedInstanceId = launched.runtimeSessionId;
|
|
42129
|
+
bundle = await waitForCliReady(ctx, type, resolvedInstanceId, Math.max(1e3, readyTimeoutMs));
|
|
42130
|
+
}
|
|
42131
|
+
if (!bundle) {
|
|
42132
|
+
throw new Error(`No running instance found for: ${resolvedInstanceId || type}`);
|
|
42133
|
+
}
|
|
42134
|
+
const initialDebug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
42135
|
+
const initialTrace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
42136
|
+
const providerResolution = getCliProviderResolutionMeta(ctx, bundle.target.type, bundle.adapter);
|
|
42137
|
+
const preTraceCount = Number(initialTrace?.entryCount || 0);
|
|
42138
|
+
const startAt = Date.now();
|
|
42139
|
+
const statusesSeen = [];
|
|
42140
|
+
const approvalsResolved = [];
|
|
42141
|
+
let lastStatus = "";
|
|
42142
|
+
let lastModalKey = "";
|
|
42143
|
+
let idleSince = 0;
|
|
42144
|
+
let sawBusy = false;
|
|
42145
|
+
ctx.instanceManager.sendEvent(bundle.target.instanceId, "send_message", { text });
|
|
42146
|
+
while (Date.now() - startAt < Math.max(1e3, timeoutMs)) {
|
|
42147
|
+
await sleep(150);
|
|
42148
|
+
bundle = getCliTargetBundle(ctx, type, bundle.target.instanceId);
|
|
42149
|
+
if (!bundle) {
|
|
42150
|
+
throw new Error("CLI instance disappeared during exercise");
|
|
42151
|
+
}
|
|
42152
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
42153
|
+
const trace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
42154
|
+
const status = String(debug?.status || bundle.target.status || "unknown");
|
|
42155
|
+
const traceEntries = Array.isArray(trace?.entries) ? trace.entries : [];
|
|
42156
|
+
const sawSendMessage = traceEntries.some((entry) => entry?.type === "send_message");
|
|
42157
|
+
const sawSubmitWrite = traceEntries.some((entry) => entry?.type === "submit_write");
|
|
42158
|
+
const hasTurnStarted = sawSendMessage || sawSubmitWrite || !!debug?.currentTurnScope;
|
|
42159
|
+
if (status !== lastStatus) {
|
|
42160
|
+
statusesSeen.push(status);
|
|
42161
|
+
lastStatus = status;
|
|
42162
|
+
}
|
|
42163
|
+
if (status === "generating" || status === "waiting_approval") {
|
|
42164
|
+
sawBusy = true;
|
|
42165
|
+
idleSince = 0;
|
|
42166
|
+
}
|
|
42167
|
+
const modal = debug?.activeModal || trace?.activeModal || null;
|
|
42168
|
+
if (autoResolveApprovals && status === "waiting_approval" && modal && Array.isArray(modal.buttons) && modal.buttons.length > 0) {
|
|
42169
|
+
const clampedIndex = Math.max(0, Math.min(Number(approvalButtonIndex) || 0, modal.buttons.length - 1));
|
|
42170
|
+
const modalKey = JSON.stringify({
|
|
42171
|
+
message: modal.message || "",
|
|
42172
|
+
buttons: modal.buttons,
|
|
42173
|
+
index: clampedIndex
|
|
42174
|
+
});
|
|
42175
|
+
if (modalKey !== lastModalKey && typeof bundle.adapter.resolveModal === "function") {
|
|
42176
|
+
lastModalKey = modalKey;
|
|
42177
|
+
approvalsResolved.push({
|
|
42178
|
+
at: Date.now(),
|
|
42179
|
+
buttonIndex: clampedIndex,
|
|
42180
|
+
label: modal.buttons[clampedIndex] || null
|
|
42181
|
+
});
|
|
42182
|
+
bundle.adapter.resolveModal(clampedIndex);
|
|
42183
|
+
continue;
|
|
42184
|
+
}
|
|
42185
|
+
}
|
|
42186
|
+
const traceCount = Number(trace?.entryCount || 0);
|
|
42187
|
+
const hasProgress = hasTurnStarted && (traceCount > preTraceCount || statusesSeen.length > 1 || approvalsResolved.length > 0);
|
|
42188
|
+
if (status === "idle" && hasProgress && sawBusy) {
|
|
42189
|
+
if (!idleSince) idleSince = Date.now();
|
|
42190
|
+
if (Date.now() - idleSince >= Math.max(200, idleSettledMs)) {
|
|
42191
|
+
const payload2 = {
|
|
42192
|
+
exercised: true,
|
|
42193
|
+
instanceId: bundle.target.instanceId,
|
|
42194
|
+
providerState: {
|
|
42195
|
+
type: bundle.target.type,
|
|
42196
|
+
name: bundle.target.name,
|
|
42197
|
+
status: bundle.target.status,
|
|
42198
|
+
mode: "mode" in bundle.target ? bundle.target.mode : void 0
|
|
42199
|
+
},
|
|
42200
|
+
providerResolution,
|
|
42201
|
+
initialDebug,
|
|
42202
|
+
initialTrace,
|
|
42203
|
+
debug,
|
|
42204
|
+
trace,
|
|
42205
|
+
statusesSeen,
|
|
42206
|
+
approvalsResolved,
|
|
42207
|
+
elapsedMs: Date.now() - startAt,
|
|
42208
|
+
timedOut: false
|
|
42209
|
+
};
|
|
42210
|
+
payload2.lastAssistant = getExerciseLastAssistant(payload2);
|
|
42211
|
+
payload2.messageCount = getExerciseMessageCount(payload2);
|
|
42212
|
+
if (stopWhenDone) {
|
|
42213
|
+
ctx.instanceManager.removeInstance(bundle.target.instanceId);
|
|
42214
|
+
}
|
|
42215
|
+
return payload2;
|
|
42216
|
+
}
|
|
42217
|
+
} else if (status === "idle" && hasProgress) {
|
|
42218
|
+
if (!idleSince) idleSince = Date.now();
|
|
42219
|
+
if (Date.now() - idleSince >= Math.max(500, idleSettledMs) && Date.now() - startAt >= 750) {
|
|
42220
|
+
const payload2 = {
|
|
42221
|
+
exercised: true,
|
|
42222
|
+
instanceId: bundle.target.instanceId,
|
|
42223
|
+
providerState: {
|
|
42224
|
+
type: bundle.target.type,
|
|
42225
|
+
name: bundle.target.name,
|
|
42226
|
+
status: bundle.target.status,
|
|
42227
|
+
mode: "mode" in bundle.target ? bundle.target.mode : void 0
|
|
42228
|
+
},
|
|
42229
|
+
providerResolution,
|
|
42230
|
+
initialDebug,
|
|
42231
|
+
initialTrace,
|
|
42232
|
+
debug,
|
|
42233
|
+
trace,
|
|
42234
|
+
statusesSeen,
|
|
42235
|
+
approvalsResolved,
|
|
42236
|
+
elapsedMs: Date.now() - startAt,
|
|
42237
|
+
timedOut: false
|
|
42238
|
+
};
|
|
42239
|
+
payload2.lastAssistant = getExerciseLastAssistant(payload2);
|
|
42240
|
+
payload2.messageCount = getExerciseMessageCount(payload2);
|
|
42241
|
+
if (stopWhenDone) {
|
|
42242
|
+
ctx.instanceManager.removeInstance(bundle.target.instanceId);
|
|
42243
|
+
}
|
|
42244
|
+
return payload2;
|
|
42245
|
+
}
|
|
42246
|
+
} else {
|
|
42247
|
+
idleSince = 0;
|
|
42248
|
+
}
|
|
42249
|
+
}
|
|
42250
|
+
const finalBundle = getCliTargetBundle(ctx, type, bundle.target.instanceId) || bundle;
|
|
42251
|
+
const finalDebug = typeof finalBundle.adapter.getDebugState === "function" ? finalBundle.adapter.getDebugState() : null;
|
|
42252
|
+
const finalTrace = typeof finalBundle.adapter.getTraceState === "function" ? finalBundle.adapter.getTraceState(traceLimit) : null;
|
|
42253
|
+
if (stopWhenDone) {
|
|
42254
|
+
ctx.instanceManager.removeInstance(finalBundle.target.instanceId);
|
|
42255
|
+
}
|
|
42256
|
+
const payload = {
|
|
42257
|
+
exercised: true,
|
|
42258
|
+
instanceId: finalBundle.target.instanceId,
|
|
42259
|
+
providerState: {
|
|
42260
|
+
type: finalBundle.target.type,
|
|
42261
|
+
name: finalBundle.target.name,
|
|
42262
|
+
status: finalBundle.target.status,
|
|
42263
|
+
mode: "mode" in finalBundle.target ? finalBundle.target.mode : void 0
|
|
42264
|
+
},
|
|
42265
|
+
providerResolution: getCliProviderResolutionMeta(ctx, finalBundle.target.type, finalBundle.adapter),
|
|
42266
|
+
initialDebug,
|
|
42267
|
+
initialTrace,
|
|
42268
|
+
debug: finalDebug,
|
|
42269
|
+
trace: finalTrace,
|
|
42270
|
+
statusesSeen,
|
|
42271
|
+
approvalsResolved,
|
|
42272
|
+
elapsedMs: Date.now() - startAt,
|
|
42273
|
+
timedOut: true
|
|
42274
|
+
};
|
|
42275
|
+
payload.lastAssistant = getExerciseLastAssistant(payload);
|
|
42276
|
+
payload.messageCount = getExerciseMessageCount(payload);
|
|
42277
|
+
return payload;
|
|
42278
|
+
}
|
|
42279
|
+
async function runCliAutoImplVerification(ctx, type, verification) {
|
|
42280
|
+
const assertions = {
|
|
42281
|
+
mustContainAny: verification?.mustContainAny || [],
|
|
42282
|
+
mustNotContainAny: verification?.mustNotContainAny || [],
|
|
42283
|
+
mustMatchAny: verification?.mustMatchAny || [],
|
|
42284
|
+
mustNotMatchAny: verification?.mustNotMatchAny || [],
|
|
42285
|
+
lastAssistantMustContainAny: verification?.lastAssistantMustContainAny || [],
|
|
42286
|
+
lastAssistantMustNotContainAny: verification?.lastAssistantMustNotContainAny || [],
|
|
42287
|
+
lastAssistantMustMatchAny: verification?.lastAssistantMustMatchAny || [],
|
|
42288
|
+
lastAssistantMustNotMatchAny: verification?.lastAssistantMustNotMatchAny || [],
|
|
42289
|
+
requireNotTimedOut: true
|
|
42290
|
+
};
|
|
42291
|
+
const rawFixtureNames = Array.isArray(verification?.fixtureNames) ? verification.fixtureNames.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
42292
|
+
if (rawFixtureNames.length > 0) {
|
|
42293
|
+
const results = [];
|
|
42294
|
+
for (const rawFixtureName2 of rawFixtureNames) {
|
|
42295
|
+
const name = slugifyFixtureName(rawFixtureName2);
|
|
42296
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
42297
|
+
const mergedAssertions = {
|
|
42298
|
+
...fixture.assertions,
|
|
42299
|
+
...assertions
|
|
42300
|
+
};
|
|
42301
|
+
const result2 = await runCliExerciseInternal(ctx, {
|
|
42302
|
+
...fixture.request,
|
|
42303
|
+
type
|
|
42304
|
+
});
|
|
42305
|
+
const failures2 = validateCliFixtureResult(result2, mergedAssertions);
|
|
42306
|
+
results.push({
|
|
42307
|
+
fixtureName: name,
|
|
42308
|
+
pass: failures2.length === 0,
|
|
42309
|
+
failures: failures2,
|
|
42310
|
+
result: result2,
|
|
42311
|
+
assertions: mergedAssertions,
|
|
42312
|
+
fixture
|
|
42313
|
+
});
|
|
42314
|
+
}
|
|
42315
|
+
const firstFailure = results.find((item) => !item.pass) || results[results.length - 1];
|
|
42316
|
+
return {
|
|
42317
|
+
mode: "fixture_replay_suite",
|
|
42318
|
+
pass: results.every((item) => item.pass),
|
|
42319
|
+
failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
|
|
42320
|
+
result: firstFailure.result,
|
|
42321
|
+
assertions: firstFailure.assertions,
|
|
42322
|
+
fixture: firstFailure.fixture,
|
|
42323
|
+
results
|
|
42324
|
+
};
|
|
42325
|
+
}
|
|
42326
|
+
const rawFixtureName = String(verification?.fixtureName || "").trim();
|
|
42327
|
+
if (rawFixtureName) {
|
|
42328
|
+
const name = slugifyFixtureName(rawFixtureName);
|
|
42329
|
+
try {
|
|
42330
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
42331
|
+
const mergedAssertions = {
|
|
42332
|
+
...fixture.assertions,
|
|
42333
|
+
...assertions
|
|
42334
|
+
};
|
|
42335
|
+
const result2 = await runCliExerciseInternal(ctx, {
|
|
42336
|
+
...fixture.request,
|
|
42337
|
+
type
|
|
42338
|
+
});
|
|
42339
|
+
const failures2 = validateCliFixtureResult(result2, mergedAssertions);
|
|
42340
|
+
return {
|
|
42341
|
+
mode: "fixture_replay",
|
|
42342
|
+
pass: failures2.length === 0,
|
|
42343
|
+
failures: failures2,
|
|
42344
|
+
result: result2,
|
|
42345
|
+
assertions: mergedAssertions,
|
|
42346
|
+
fixture
|
|
42347
|
+
};
|
|
42348
|
+
} catch {
|
|
42349
|
+
}
|
|
42350
|
+
}
|
|
42351
|
+
const result = await runCliExerciseInternal(ctx, {
|
|
42352
|
+
...verification?.request || {},
|
|
42353
|
+
type
|
|
42354
|
+
});
|
|
42355
|
+
const failures = validateCliFixtureResult(result, assertions);
|
|
42356
|
+
return {
|
|
42357
|
+
mode: "exercise",
|
|
42358
|
+
pass: failures.length === 0,
|
|
42359
|
+
failures,
|
|
42360
|
+
result,
|
|
42361
|
+
assertions
|
|
42362
|
+
};
|
|
42363
|
+
}
|
|
41433
42364
|
async function handleCliStatus(ctx, _req, res) {
|
|
41434
42365
|
if (!ctx.instanceManager) {
|
|
41435
42366
|
ctx.json(res, 503, { error: "InstanceManager not available (daemon not fully initialized)" });
|
|
@@ -41568,12 +42499,14 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
41568
42499
|
status: target.status,
|
|
41569
42500
|
mode: "mode" in target ? target.mode : void 0
|
|
41570
42501
|
},
|
|
42502
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
41571
42503
|
debug: debugState
|
|
41572
42504
|
});
|
|
41573
42505
|
} else {
|
|
41574
42506
|
ctx.json(res, 200, {
|
|
41575
42507
|
instanceId: target.instanceId,
|
|
41576
42508
|
providerState: target,
|
|
42509
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
41577
42510
|
debug: null,
|
|
41578
42511
|
message: "No debug state available (adapter.getDebugState not found)"
|
|
41579
42512
|
});
|
|
@@ -41582,6 +42515,191 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
41582
42515
|
ctx.json(res, 500, { error: `Debug state failed: ${e.message}` });
|
|
41583
42516
|
}
|
|
41584
42517
|
}
|
|
42518
|
+
async function handleCliTrace(ctx, type, req, res) {
|
|
42519
|
+
if (!ctx.instanceManager) {
|
|
42520
|
+
ctx.json(res, 503, { error: "InstanceManager not available" });
|
|
42521
|
+
return;
|
|
42522
|
+
}
|
|
42523
|
+
const target = findCliTarget(ctx, type);
|
|
42524
|
+
if (!target) {
|
|
42525
|
+
const allStates = ctx.instanceManager.collectAllStates();
|
|
42526
|
+
ctx.json(res, 404, {
|
|
42527
|
+
error: `No running instance for: ${type}`,
|
|
42528
|
+
available: allStates.filter((s15) => s15.category === "cli" || s15.category === "acp").map((s15) => s15.type)
|
|
42529
|
+
});
|
|
42530
|
+
return;
|
|
42531
|
+
}
|
|
42532
|
+
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
42533
|
+
if (!instance) {
|
|
42534
|
+
ctx.json(res, 404, { error: `Instance not found: ${target.instanceId}` });
|
|
42535
|
+
return;
|
|
42536
|
+
}
|
|
42537
|
+
try {
|
|
42538
|
+
const adapter = instance.getAdapter?.() || instance.adapter;
|
|
42539
|
+
const url2 = new URL(req.url || "/", "http://127.0.0.1");
|
|
42540
|
+
const limit = parseInt(url2.searchParams.get("limit") || "120", 10);
|
|
42541
|
+
if (adapter && typeof adapter.getTraceState === "function") {
|
|
42542
|
+
const trace = adapter.getTraceState(limit);
|
|
42543
|
+
const debug = typeof adapter.getDebugState === "function" ? adapter.getDebugState() : null;
|
|
42544
|
+
ctx.json(res, 200, {
|
|
42545
|
+
instanceId: target.instanceId,
|
|
42546
|
+
providerState: {
|
|
42547
|
+
type: target.type,
|
|
42548
|
+
name: target.name,
|
|
42549
|
+
status: target.status,
|
|
42550
|
+
mode: "mode" in target ? target.mode : void 0
|
|
42551
|
+
},
|
|
42552
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
42553
|
+
debug,
|
|
42554
|
+
trace
|
|
42555
|
+
});
|
|
42556
|
+
} else {
|
|
42557
|
+
ctx.json(res, 200, {
|
|
42558
|
+
instanceId: target.instanceId,
|
|
42559
|
+
providerState: target,
|
|
42560
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
42561
|
+
debug: typeof adapter?.getDebugState === "function" ? adapter.getDebugState() : null,
|
|
42562
|
+
trace: null,
|
|
42563
|
+
message: "No trace state available (adapter.getTraceState not found)"
|
|
42564
|
+
});
|
|
42565
|
+
}
|
|
42566
|
+
} catch (e) {
|
|
42567
|
+
ctx.json(res, 500, { error: `Trace state failed: ${e.message}` });
|
|
42568
|
+
}
|
|
42569
|
+
}
|
|
42570
|
+
async function handleCliExercise(ctx, req, res) {
|
|
42571
|
+
try {
|
|
42572
|
+
const body = await ctx.readBody(req);
|
|
42573
|
+
const result = await runCliExerciseInternal(ctx, body || {});
|
|
42574
|
+
ctx.json(res, 200, result);
|
|
42575
|
+
} catch (e) {
|
|
42576
|
+
ctx.json(res, 500, { error: `Exercise failed: ${e.message}` });
|
|
42577
|
+
}
|
|
42578
|
+
}
|
|
42579
|
+
async function handleCliFixtureCapture(ctx, req, res) {
|
|
42580
|
+
try {
|
|
42581
|
+
const body = await ctx.readBody(req);
|
|
42582
|
+
const type = String(body?.type || "");
|
|
42583
|
+
const request = body?.request || {};
|
|
42584
|
+
if (!type) {
|
|
42585
|
+
ctx.json(res, 400, { error: "type required" });
|
|
42586
|
+
return;
|
|
42587
|
+
}
|
|
42588
|
+
if (!request?.text) {
|
|
42589
|
+
ctx.json(res, 400, { error: "request.text required" });
|
|
42590
|
+
return;
|
|
42591
|
+
}
|
|
42592
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
42593
|
+
fs13.mkdirSync(fixtureDir, { recursive: true });
|
|
42594
|
+
const name = slugifyFixtureName(String(body?.name || `${type}-${Date.now()}`));
|
|
42595
|
+
const result = await runCliExerciseInternal(ctx, { ...request, type });
|
|
42596
|
+
const fixture = {
|
|
42597
|
+
version: 1,
|
|
42598
|
+
kind: "cli-exercise-fixture",
|
|
42599
|
+
name,
|
|
42600
|
+
type,
|
|
42601
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
42602
|
+
providerDir: ctx.providerLoader.findProviderDir(type),
|
|
42603
|
+
providerResolution: result?.providerResolution || null,
|
|
42604
|
+
request: { ...request, type },
|
|
42605
|
+
result,
|
|
42606
|
+
assertions: {
|
|
42607
|
+
mustContainAny: Array.isArray(body?.assertions?.mustContainAny) ? body.assertions.mustContainAny : [],
|
|
42608
|
+
mustNotContainAny: Array.isArray(body?.assertions?.mustNotContainAny) ? body.assertions.mustNotContainAny : [],
|
|
42609
|
+
mustMatchAny: Array.isArray(body?.assertions?.mustMatchAny) ? body.assertions.mustMatchAny : [],
|
|
42610
|
+
mustNotMatchAny: Array.isArray(body?.assertions?.mustNotMatchAny) ? body.assertions.mustNotMatchAny : [],
|
|
42611
|
+
lastAssistantMustContainAny: Array.isArray(body?.assertions?.lastAssistantMustContainAny) ? body.assertions.lastAssistantMustContainAny : [],
|
|
42612
|
+
lastAssistantMustNotContainAny: Array.isArray(body?.assertions?.lastAssistantMustNotContainAny) ? body.assertions.lastAssistantMustNotContainAny : [],
|
|
42613
|
+
lastAssistantMustMatchAny: Array.isArray(body?.assertions?.lastAssistantMustMatchAny) ? body.assertions.lastAssistantMustMatchAny : [],
|
|
42614
|
+
lastAssistantMustNotMatchAny: Array.isArray(body?.assertions?.lastAssistantMustNotMatchAny) ? body.assertions.lastAssistantMustNotMatchAny : [],
|
|
42615
|
+
statusesSeen: Array.isArray(body?.assertions?.statusesSeen) ? body.assertions.statusesSeen : void 0,
|
|
42616
|
+
requireNotTimedOut: body?.assertions?.requireNotTimedOut !== false
|
|
42617
|
+
},
|
|
42618
|
+
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
42619
|
+
};
|
|
42620
|
+
const filePath = path16.join(fixtureDir, `${name}.json`);
|
|
42621
|
+
fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
42622
|
+
ctx.json(res, 200, {
|
|
42623
|
+
saved: true,
|
|
42624
|
+
name,
|
|
42625
|
+
path: filePath,
|
|
42626
|
+
fixture,
|
|
42627
|
+
verification: {
|
|
42628
|
+
pass: validateCliFixtureResult(result, fixture.assertions).length === 0,
|
|
42629
|
+
failures: validateCliFixtureResult(result, fixture.assertions)
|
|
42630
|
+
}
|
|
42631
|
+
});
|
|
42632
|
+
} catch (e) {
|
|
42633
|
+
ctx.json(res, 500, { error: `Fixture capture failed: ${e.message}` });
|
|
42634
|
+
}
|
|
42635
|
+
}
|
|
42636
|
+
async function handleCliFixtureList(ctx, type, _req, res) {
|
|
42637
|
+
try {
|
|
42638
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
42639
|
+
if (!fs13.existsSync(fixtureDir)) {
|
|
42640
|
+
ctx.json(res, 200, { fixtures: [], count: 0 });
|
|
42641
|
+
return;
|
|
42642
|
+
}
|
|
42643
|
+
const fixtures = fs13.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
|
|
42644
|
+
const fullPath = path16.join(fixtureDir, file2);
|
|
42645
|
+
try {
|
|
42646
|
+
const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
|
|
42647
|
+
return {
|
|
42648
|
+
name: raw.name || file2.replace(/\.json$/i, ""),
|
|
42649
|
+
path: fullPath,
|
|
42650
|
+
createdAt: raw.createdAt || null,
|
|
42651
|
+
notes: raw.notes || null,
|
|
42652
|
+
requestText: raw.request?.text || "",
|
|
42653
|
+
assertions: raw.assertions || {}
|
|
42654
|
+
};
|
|
42655
|
+
} catch {
|
|
42656
|
+
return {
|
|
42657
|
+
name: file2.replace(/\.json$/i, ""),
|
|
42658
|
+
path: fullPath,
|
|
42659
|
+
createdAt: null,
|
|
42660
|
+
notes: "Unreadable fixture",
|
|
42661
|
+
requestText: "",
|
|
42662
|
+
assertions: {}
|
|
42663
|
+
};
|
|
42664
|
+
}
|
|
42665
|
+
});
|
|
42666
|
+
ctx.json(res, 200, { fixtures, count: fixtures.length });
|
|
42667
|
+
} catch (e) {
|
|
42668
|
+
ctx.json(res, 500, { error: `Fixture list failed: ${e.message}` });
|
|
42669
|
+
}
|
|
42670
|
+
}
|
|
42671
|
+
async function handleCliFixtureReplay(ctx, req, res) {
|
|
42672
|
+
try {
|
|
42673
|
+
const body = await ctx.readBody(req);
|
|
42674
|
+
const type = String(body?.type || "");
|
|
42675
|
+
const rawName = String(body?.name || "").trim();
|
|
42676
|
+
if (!type || !rawName) {
|
|
42677
|
+
ctx.json(res, 400, { error: "type and name required" });
|
|
42678
|
+
return;
|
|
42679
|
+
}
|
|
42680
|
+
const name = slugifyFixtureName(rawName);
|
|
42681
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
42682
|
+
const result = await runCliExerciseInternal(ctx, {
|
|
42683
|
+
...fixture.request,
|
|
42684
|
+
type
|
|
42685
|
+
});
|
|
42686
|
+
const assertions = {
|
|
42687
|
+
...fixture.assertions,
|
|
42688
|
+
...body?.assertions || {}
|
|
42689
|
+
};
|
|
42690
|
+
const failures = validateCliFixtureResult(result, assertions);
|
|
42691
|
+
ctx.json(res, 200, {
|
|
42692
|
+
replayed: true,
|
|
42693
|
+
pass: failures.length === 0,
|
|
42694
|
+
failures,
|
|
42695
|
+
fixture,
|
|
42696
|
+
result,
|
|
42697
|
+
assertions
|
|
42698
|
+
});
|
|
42699
|
+
} catch (e) {
|
|
42700
|
+
ctx.json(res, 500, { error: `Fixture replay failed: ${e.message}` });
|
|
42701
|
+
}
|
|
42702
|
+
}
|
|
41585
42703
|
async function handleCliResolve(ctx, req, res) {
|
|
41586
42704
|
const body = await ctx.readBody(req);
|
|
41587
42705
|
const { type, buttonIndex, instanceId } = body;
|
|
@@ -41656,13 +42774,36 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
41656
42774
|
ctx.json(res, 500, { error: `Raw send failed: ${e.message}` });
|
|
41657
42775
|
}
|
|
41658
42776
|
}
|
|
42777
|
+
var fs13, path16;
|
|
41659
42778
|
var init_dev_cli_debug = __esm({
|
|
41660
42779
|
"../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts"() {
|
|
41661
42780
|
"use strict";
|
|
42781
|
+
fs13 = __toESM(require("fs"));
|
|
42782
|
+
path16 = __toESM(require("path"));
|
|
41662
42783
|
}
|
|
41663
42784
|
});
|
|
41664
42785
|
|
|
41665
42786
|
// ../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts
|
|
42787
|
+
function getAutoImplPid(ctx) {
|
|
42788
|
+
const proc = ctx.autoImplProcess;
|
|
42789
|
+
return proc && typeof proc.pid === "number" && proc.pid > 0 ? proc.pid : null;
|
|
42790
|
+
}
|
|
42791
|
+
function isPidAlive(pid) {
|
|
42792
|
+
try {
|
|
42793
|
+
process.kill(pid, 0);
|
|
42794
|
+
return true;
|
|
42795
|
+
} catch (error48) {
|
|
42796
|
+
return error48?.code === "EPERM";
|
|
42797
|
+
}
|
|
42798
|
+
}
|
|
42799
|
+
function clearStaleAutoImplState(ctx, reason) {
|
|
42800
|
+
if (!ctx.autoImplStatus.running && !ctx.autoImplProcess) return;
|
|
42801
|
+
const pid = getAutoImplPid(ctx);
|
|
42802
|
+
if (pid && isPidAlive(pid)) return;
|
|
42803
|
+
ctx.log(`Clearing stale auto-implement state: ${reason}${pid ? ` (pid ${pid})` : ""}`);
|
|
42804
|
+
ctx.autoImplProcess = null;
|
|
42805
|
+
ctx.autoImplStatus.running = false;
|
|
42806
|
+
}
|
|
41666
42807
|
function getDefaultAutoImplReference(ctx, category, type) {
|
|
41667
42808
|
if (category === "cli") {
|
|
41668
42809
|
return type === "codex-cli" ? "claude-cli" : "codex-cli";
|
|
@@ -41678,45 +42819,45 @@ function resolveAutoImplReference(ctx, category, requestedReference, targetType)
|
|
|
41678
42819
|
return fallback?.type || null;
|
|
41679
42820
|
}
|
|
41680
42821
|
function getLatestScriptVersionDir(scriptsDir) {
|
|
41681
|
-
if (!
|
|
41682
|
-
const versions =
|
|
42822
|
+
if (!fs14.existsSync(scriptsDir)) return null;
|
|
42823
|
+
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
41683
42824
|
try {
|
|
41684
|
-
return
|
|
42825
|
+
return fs14.statSync(path17.join(scriptsDir, d)).isDirectory();
|
|
41685
42826
|
} catch {
|
|
41686
42827
|
return false;
|
|
41687
42828
|
}
|
|
41688
42829
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
41689
42830
|
if (versions.length === 0) return null;
|
|
41690
|
-
return
|
|
42831
|
+
return path17.join(scriptsDir, versions[0]);
|
|
41691
42832
|
}
|
|
41692
42833
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
41693
|
-
const canonicalUserDir =
|
|
41694
|
-
const desiredDir = requestedDir ?
|
|
41695
|
-
const upstreamRoot =
|
|
41696
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
42834
|
+
const canonicalUserDir = path17.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
42835
|
+
const desiredDir = requestedDir ? path17.resolve(requestedDir) : canonicalUserDir;
|
|
42836
|
+
const upstreamRoot = path17.resolve(ctx.providerLoader.getUpstreamDir());
|
|
42837
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path17.sep}`)) {
|
|
41697
42838
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
41698
42839
|
}
|
|
41699
|
-
if (
|
|
42840
|
+
if (path17.basename(desiredDir) !== type) {
|
|
41700
42841
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
41701
42842
|
}
|
|
41702
42843
|
const sourceDir = ctx.findProviderDir(type);
|
|
41703
42844
|
if (!sourceDir) {
|
|
41704
42845
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
41705
42846
|
}
|
|
41706
|
-
if (!
|
|
41707
|
-
|
|
41708
|
-
|
|
42847
|
+
if (!fs14.existsSync(desiredDir)) {
|
|
42848
|
+
fs14.mkdirSync(path17.dirname(desiredDir), { recursive: true });
|
|
42849
|
+
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
41709
42850
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
41710
42851
|
}
|
|
41711
|
-
const providerJson =
|
|
41712
|
-
if (!
|
|
42852
|
+
const providerJson = path17.join(desiredDir, "provider.json");
|
|
42853
|
+
if (!fs14.existsSync(providerJson)) {
|
|
41713
42854
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
41714
42855
|
}
|
|
41715
42856
|
try {
|
|
41716
|
-
const providerData = JSON.parse(
|
|
42857
|
+
const providerData = JSON.parse(fs14.readFileSync(providerJson, "utf-8"));
|
|
41717
42858
|
if (providerData.disableUpstream !== true) {
|
|
41718
42859
|
providerData.disableUpstream = true;
|
|
41719
|
-
|
|
42860
|
+
fs14.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
41720
42861
|
}
|
|
41721
42862
|
} catch (error48) {
|
|
41722
42863
|
return {
|
|
@@ -41729,15 +42870,15 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
41729
42870
|
function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
41730
42871
|
if (!referenceType) return {};
|
|
41731
42872
|
const refDir = ctx.findProviderDir(referenceType);
|
|
41732
|
-
if (!refDir || !
|
|
42873
|
+
if (!refDir || !fs14.existsSync(refDir)) return {};
|
|
41733
42874
|
const referenceScripts = {};
|
|
41734
|
-
const scriptsDir =
|
|
42875
|
+
const scriptsDir = path17.join(refDir, "scripts");
|
|
41735
42876
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
41736
42877
|
if (!latestDir) return referenceScripts;
|
|
41737
|
-
for (const file2 of
|
|
42878
|
+
for (const file2 of fs14.readdirSync(latestDir)) {
|
|
41738
42879
|
if (!file2.endsWith(".js")) continue;
|
|
41739
42880
|
try {
|
|
41740
|
-
referenceScripts[file2] =
|
|
42881
|
+
referenceScripts[file2] = fs14.readFileSync(path17.join(latestDir, file2), "utf-8");
|
|
41741
42882
|
} catch {
|
|
41742
42883
|
}
|
|
41743
42884
|
}
|
|
@@ -41745,11 +42886,20 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
41745
42886
|
}
|
|
41746
42887
|
async function handleAutoImplement(ctx, type, req, res) {
|
|
41747
42888
|
const body = await ctx.readBody(req);
|
|
41748
|
-
const {
|
|
42889
|
+
const {
|
|
42890
|
+
agent = "claude-cli",
|
|
42891
|
+
functions,
|
|
42892
|
+
reference,
|
|
42893
|
+
model,
|
|
42894
|
+
comment,
|
|
42895
|
+
providerDir: requestedProviderDir,
|
|
42896
|
+
verification
|
|
42897
|
+
} = body;
|
|
41749
42898
|
if (!functions || !Array.isArray(functions) || functions.length === 0) {
|
|
41750
42899
|
ctx.json(res, 400, { error: 'functions[] is required (e.g. ["readChat", "sendMessage"])' });
|
|
41751
42900
|
return;
|
|
41752
42901
|
}
|
|
42902
|
+
clearStaleAutoImplState(ctx, "new auto-implement request");
|
|
41753
42903
|
if (ctx.autoImplStatus.running) {
|
|
41754
42904
|
ctx.json(res, 409, { error: "Auto-implement already in progress", type: ctx.autoImplStatus.type });
|
|
41755
42905
|
return;
|
|
@@ -41767,7 +42917,55 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41767
42917
|
return;
|
|
41768
42918
|
}
|
|
41769
42919
|
const providerDir = writableProvider.dir;
|
|
42920
|
+
ctx.autoImplStatus = { running: false, type, progress: [] };
|
|
42921
|
+
if (provider.category === "cli" && verification && (verification.fixtureName || verification.fixtureNames && verification.fixtureNames.length > 0)) {
|
|
42922
|
+
sendAutoImplSSE(ctx, {
|
|
42923
|
+
event: "progress",
|
|
42924
|
+
data: {
|
|
42925
|
+
function: "_preflight",
|
|
42926
|
+
status: "verifying",
|
|
42927
|
+
message: "Running preflight verification before spawning agent..."
|
|
42928
|
+
}
|
|
42929
|
+
});
|
|
42930
|
+
try {
|
|
42931
|
+
const preflight = await runCliAutoImplVerification(ctx, type, verification);
|
|
42932
|
+
sendAutoImplSSE(ctx, { event: "verification", data: preflight });
|
|
42933
|
+
if (preflight.pass) {
|
|
42934
|
+
sendAutoImplSSE(ctx, {
|
|
42935
|
+
event: "complete",
|
|
42936
|
+
data: {
|
|
42937
|
+
success: true,
|
|
42938
|
+
exitCode: 0,
|
|
42939
|
+
functions,
|
|
42940
|
+
message: `\u2705 No-op: exact ${preflight.mode} already passes`,
|
|
42941
|
+
verification: preflight,
|
|
42942
|
+
skipped: true
|
|
42943
|
+
}
|
|
42944
|
+
});
|
|
42945
|
+
ctx.json(res, 200, {
|
|
42946
|
+
started: false,
|
|
42947
|
+
skipped: true,
|
|
42948
|
+
type,
|
|
42949
|
+
functions,
|
|
42950
|
+
providerDir,
|
|
42951
|
+
verification: preflight,
|
|
42952
|
+
message: "Preflight verification already passes. No auto-implement run needed."
|
|
42953
|
+
});
|
|
42954
|
+
return;
|
|
42955
|
+
}
|
|
42956
|
+
} catch (error48) {
|
|
42957
|
+
sendAutoImplSSE(ctx, {
|
|
42958
|
+
event: "progress",
|
|
42959
|
+
data: {
|
|
42960
|
+
function: "_preflight",
|
|
42961
|
+
status: "verify_failed",
|
|
42962
|
+
message: `Preflight verification errored, continuing to agent run: ${error48?.message || error48}`
|
|
42963
|
+
}
|
|
42964
|
+
});
|
|
42965
|
+
}
|
|
42966
|
+
}
|
|
41770
42967
|
try {
|
|
42968
|
+
ctx.autoImplStatus = { running: true, type, progress: ctx.autoImplStatus.progress };
|
|
41771
42969
|
const resolvedReference = resolveAutoImplReference(ctx, provider.category, reference, type);
|
|
41772
42970
|
sendAutoImplSSE(ctx, {
|
|
41773
42971
|
event: "progress",
|
|
@@ -41787,17 +42985,17 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41787
42985
|
}
|
|
41788
42986
|
});
|
|
41789
42987
|
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
|
-
|
|
42988
|
+
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
42989
|
+
const tmpDir = path17.join(os18.tmpdir(), "adhdev-autoimpl");
|
|
42990
|
+
if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
|
|
42991
|
+
const promptFile = path17.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
42992
|
+
fs14.writeFileSync(promptFile, prompt, "utf-8");
|
|
41795
42993
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
41796
42994
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
41797
42995
|
const spawn5 = agentProvider?.spawn;
|
|
41798
42996
|
if (!spawn5?.command) {
|
|
41799
42997
|
try {
|
|
41800
|
-
|
|
42998
|
+
fs14.unlinkSync(promptFile);
|
|
41801
42999
|
} catch {
|
|
41802
43000
|
}
|
|
41803
43001
|
ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -41806,7 +43004,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41806
43004
|
const agentCategory = agentProvider?.category;
|
|
41807
43005
|
if (agentCategory === "acp") {
|
|
41808
43006
|
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn5.command} ${(spawn5.args || []).join(" ")}` } });
|
|
41809
|
-
ctx.autoImplStatus =
|
|
43007
|
+
ctx.autoImplStatus.running = true;
|
|
43008
|
+
ctx.autoImplStatus.type = type;
|
|
41810
43009
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
41811
43010
|
const { Readable: Readable3, Writable: Writable2 } = await import("stream");
|
|
41812
43011
|
const { spawn: spawnFn2 } = await import("child_process");
|
|
@@ -41898,7 +43097,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41898
43097
|
} catch {
|
|
41899
43098
|
}
|
|
41900
43099
|
try {
|
|
41901
|
-
|
|
43100
|
+
fs14.unlinkSync(promptFile);
|
|
41902
43101
|
} catch {
|
|
41903
43102
|
}
|
|
41904
43103
|
ctx.log(`Auto-implement (ACP) ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -41976,7 +43175,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41976
43175
|
}
|
|
41977
43176
|
}
|
|
41978
43177
|
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning agent: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
|
|
41979
|
-
ctx.autoImplStatus =
|
|
43178
|
+
ctx.autoImplStatus.running = true;
|
|
43179
|
+
ctx.autoImplStatus.type = type;
|
|
41980
43180
|
const spawnedAt = Date.now();
|
|
41981
43181
|
let child;
|
|
41982
43182
|
let isPty = false;
|
|
@@ -42019,6 +43219,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42019
43219
|
let approvalKeys = { 0: "y\r" };
|
|
42020
43220
|
let approvalBuffer = "";
|
|
42021
43221
|
let lastApprovalTime = 0;
|
|
43222
|
+
let completionSignalSeen = false;
|
|
42022
43223
|
try {
|
|
42023
43224
|
const { normalizeCliProviderForRuntime: normalizeCliProviderForRuntime2 } = await Promise.resolve().then(() => (init_provider_cli_adapter(), provider_cli_adapter_exports));
|
|
42024
43225
|
const normalized = normalizeCliProviderForRuntime2(agentProvider);
|
|
@@ -42032,6 +43233,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42032
43233
|
approvalBuffer = (approvalBuffer + cleanData).slice(-1500);
|
|
42033
43234
|
const elapsed = Date.now() - spawnedAt;
|
|
42034
43235
|
if (elapsed > 15e3 && cleanData.includes("_PIPELINE_COMPLETE_SIGNAL_")) {
|
|
43236
|
+
completionSignalSeen = true;
|
|
42035
43237
|
ctx.log(`Agent finished task after ${Math.round(elapsed / 1e3)}s. Terminating interactive CLI session to unblock pipeline.`);
|
|
42036
43238
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: `
|
|
42037
43239
|
[\u{1F916} ADHDev Pipeline] Completion token detected. Proceeding...
|
|
@@ -42055,6 +43257,55 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42055
43257
|
lastApprovalTime = Date.now();
|
|
42056
43258
|
}
|
|
42057
43259
|
};
|
|
43260
|
+
const finalizeCliAutoImpl = async (code) => {
|
|
43261
|
+
ctx.autoImplProcess = null;
|
|
43262
|
+
let success2 = completionSignalSeen || code === 0;
|
|
43263
|
+
let message = success2 ? completionSignalSeen && code !== 0 ? "\u2705 Auto-implement complete (completion signal)" : "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`;
|
|
43264
|
+
let verificationSummary = null;
|
|
43265
|
+
try {
|
|
43266
|
+
ctx.providerLoader.reload();
|
|
43267
|
+
} catch {
|
|
43268
|
+
}
|
|
43269
|
+
if (provider.category === "cli" && verification) {
|
|
43270
|
+
sendAutoImplSSE(ctx, {
|
|
43271
|
+
event: "progress",
|
|
43272
|
+
data: {
|
|
43273
|
+
function: "_verify",
|
|
43274
|
+
status: "running",
|
|
43275
|
+
message: "Running exact post-patch verification..."
|
|
43276
|
+
}
|
|
43277
|
+
});
|
|
43278
|
+
try {
|
|
43279
|
+
verificationSummary = await runCliAutoImplVerification(ctx, type, verification);
|
|
43280
|
+
sendAutoImplSSE(ctx, { event: "verification", data: verificationSummary });
|
|
43281
|
+
success2 = verificationSummary.pass;
|
|
43282
|
+
message = verificationSummary.pass ? `\u2705 Auto-implement complete (${verificationSummary.mode})` : `\u274C Post-patch verification failed (${verificationSummary.mode}): ${verificationSummary.failures.join("; ") || "unknown failure"}`;
|
|
43283
|
+
} catch (error48) {
|
|
43284
|
+
success2 = false;
|
|
43285
|
+
message = `\u274C Post-patch verification error: ${error48?.message || error48}`;
|
|
43286
|
+
sendAutoImplSSE(ctx, {
|
|
43287
|
+
event: "verification",
|
|
43288
|
+
data: { pass: false, error: error48?.message || String(error48) }
|
|
43289
|
+
});
|
|
43290
|
+
}
|
|
43291
|
+
}
|
|
43292
|
+
ctx.autoImplStatus.running = false;
|
|
43293
|
+
sendAutoImplSSE(ctx, {
|
|
43294
|
+
event: "complete",
|
|
43295
|
+
data: {
|
|
43296
|
+
success: success2,
|
|
43297
|
+
exitCode: code,
|
|
43298
|
+
functions,
|
|
43299
|
+
message,
|
|
43300
|
+
verification: verificationSummary
|
|
43301
|
+
}
|
|
43302
|
+
});
|
|
43303
|
+
try {
|
|
43304
|
+
fs14.unlinkSync(promptFile);
|
|
43305
|
+
} catch {
|
|
43306
|
+
}
|
|
43307
|
+
ctx.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})${verificationSummary ? ` verify=${verificationSummary.pass ? "pass" : "fail"}` : ""}`);
|
|
43308
|
+
};
|
|
42058
43309
|
if (isPty) {
|
|
42059
43310
|
child.onData((data) => {
|
|
42060
43311
|
stdout += data;
|
|
@@ -42066,21 +43317,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42066
43317
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
|
|
42067
43318
|
});
|
|
42068
43319
|
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
|
-
}
|
|
43320
|
+
void finalizeCliAutoImpl(code);
|
|
42084
43321
|
});
|
|
42085
43322
|
} else {
|
|
42086
43323
|
child.stdout?.on("data", (d) => {
|
|
@@ -42097,27 +43334,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42097
43334
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
|
|
42098
43335
|
});
|
|
42099
43336
|
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})`);
|
|
43337
|
+
void finalizeCliAutoImpl(code);
|
|
42121
43338
|
});
|
|
42122
43339
|
}
|
|
42123
43340
|
ctx.json(res, 202, {
|
|
@@ -42134,9 +43351,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
42134
43351
|
ctx.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
|
|
42135
43352
|
}
|
|
42136
43353
|
}
|
|
42137
|
-
function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType) {
|
|
43354
|
+
function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType, verification) {
|
|
42138
43355
|
if (provider.category === "cli") {
|
|
42139
|
-
return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType);
|
|
43356
|
+
return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification);
|
|
42140
43357
|
}
|
|
42141
43358
|
const lines = [];
|
|
42142
43359
|
lines.push("You are implementing browser automation scripts for an IDE provider.");
|
|
@@ -42161,7 +43378,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42161
43378
|
setMode: "set_mode.js"
|
|
42162
43379
|
};
|
|
42163
43380
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
42164
|
-
const scriptsDir =
|
|
43381
|
+
const scriptsDir = path17.join(providerDir, "scripts");
|
|
42165
43382
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
42166
43383
|
if (latestScriptsDir) {
|
|
42167
43384
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -42169,10 +43386,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42169
43386
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
42170
43387
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
42171
43388
|
lines.push("");
|
|
42172
|
-
for (const file2 of
|
|
43389
|
+
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
42173
43390
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
42174
43391
|
try {
|
|
42175
|
-
const content =
|
|
43392
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
42176
43393
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
42177
43394
|
lines.push("```javascript");
|
|
42178
43395
|
lines.push(content);
|
|
@@ -42182,14 +43399,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42182
43399
|
}
|
|
42183
43400
|
}
|
|
42184
43401
|
}
|
|
42185
|
-
const refFiles =
|
|
43402
|
+
const refFiles = fs14.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
42186
43403
|
if (refFiles.length > 0) {
|
|
42187
43404
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
42188
43405
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
42189
43406
|
lines.push("");
|
|
42190
43407
|
for (const file2 of refFiles) {
|
|
42191
43408
|
try {
|
|
42192
|
-
const content =
|
|
43409
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
42193
43410
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
42194
43411
|
lines.push("```javascript");
|
|
42195
43412
|
lines.push(content);
|
|
@@ -42230,11 +43447,11 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42230
43447
|
lines.push("");
|
|
42231
43448
|
}
|
|
42232
43449
|
}
|
|
42233
|
-
const docsDir =
|
|
43450
|
+
const docsDir = path17.join(providerDir, "../../docs");
|
|
42234
43451
|
const loadGuide = (name) => {
|
|
42235
43452
|
try {
|
|
42236
|
-
const p =
|
|
42237
|
-
if (
|
|
43453
|
+
const p = path17.join(docsDir, name);
|
|
43454
|
+
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
42238
43455
|
} catch {
|
|
42239
43456
|
}
|
|
42240
43457
|
return null;
|
|
@@ -42392,8 +43609,69 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42392
43609
|
lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
|
|
42393
43610
|
return lines.join("\n");
|
|
42394
43611
|
}
|
|
42395
|
-
function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType) {
|
|
43612
|
+
function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification) {
|
|
42396
43613
|
const lines = [];
|
|
43614
|
+
const defaultExercisePayload = {
|
|
43615
|
+
type,
|
|
43616
|
+
workingDir: providerDir,
|
|
43617
|
+
freshSession: true,
|
|
43618
|
+
autoLaunch: true,
|
|
43619
|
+
autoResolveApprovals: true,
|
|
43620
|
+
approvalButtonIndex: 0,
|
|
43621
|
+
timeoutMs: 45e3,
|
|
43622
|
+
traceLimit: 200,
|
|
43623
|
+
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."
|
|
43624
|
+
};
|
|
43625
|
+
const exercisePayload = {
|
|
43626
|
+
...defaultExercisePayload,
|
|
43627
|
+
...verification?.request || {},
|
|
43628
|
+
type,
|
|
43629
|
+
workingDir: providerDir
|
|
43630
|
+
};
|
|
43631
|
+
const exerciseJson = JSON.stringify(exercisePayload).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43632
|
+
const verificationInspectFields = verification?.inspectFields?.length ? verification.inspectFields : [
|
|
43633
|
+
"debug.messages",
|
|
43634
|
+
"trace.entries[].payload.parsedLastAssistant",
|
|
43635
|
+
"trace.entries[].payload.lastAssistant"
|
|
43636
|
+
];
|
|
43637
|
+
const verificationMustContainAny = verification?.mustContainAny || [];
|
|
43638
|
+
const verificationMustNotContainAny = verification?.mustNotContainAny || [];
|
|
43639
|
+
const verificationMustMatchAny = verification?.mustMatchAny || [];
|
|
43640
|
+
const verificationMustNotMatchAny = verification?.mustNotMatchAny || [];
|
|
43641
|
+
const verificationLastAssistantMustContainAny = verification?.lastAssistantMustContainAny || [];
|
|
43642
|
+
const verificationLastAssistantMustNotContainAny = verification?.lastAssistantMustNotContainAny || [];
|
|
43643
|
+
const verificationLastAssistantMustMatchAny = verification?.lastAssistantMustMatchAny || [];
|
|
43644
|
+
const verificationLastAssistantMustNotMatchAny = verification?.lastAssistantMustNotMatchAny || [];
|
|
43645
|
+
const quotedMustContain = verificationMustContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43646
|
+
const quotedMustNotContain = verificationMustNotContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43647
|
+
const quotedMustMatch = verificationMustMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43648
|
+
const quotedMustNotMatch = verificationMustNotMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43649
|
+
const quotedLastAssistantMustContain = verificationLastAssistantMustContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43650
|
+
const quotedLastAssistantMustNotContain = verificationLastAssistantMustNotContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43651
|
+
const quotedLastAssistantMustMatch = verificationLastAssistantMustMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43652
|
+
const quotedLastAssistantMustNotMatch = verificationLastAssistantMustNotMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43653
|
+
const fixtureName = verification?.fixtureName || `${type}-provider-fix`;
|
|
43654
|
+
const fixtureNames = Array.isArray(verification?.fixtureNames) ? verification.fixtureNames.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
43655
|
+
const fixtureCaptureJson = JSON.stringify({
|
|
43656
|
+
type,
|
|
43657
|
+
name: fixtureName,
|
|
43658
|
+
request: exercisePayload,
|
|
43659
|
+
assertions: {
|
|
43660
|
+
mustContainAny: verificationMustContainAny,
|
|
43661
|
+
mustNotContainAny: verificationMustNotContainAny,
|
|
43662
|
+
mustMatchAny: verificationMustMatchAny,
|
|
43663
|
+
mustNotMatchAny: verificationMustNotMatchAny,
|
|
43664
|
+
lastAssistantMustContainAny: verificationLastAssistantMustContainAny,
|
|
43665
|
+
lastAssistantMustNotContainAny: verificationLastAssistantMustNotContainAny,
|
|
43666
|
+
lastAssistantMustMatchAny: verificationLastAssistantMustMatchAny,
|
|
43667
|
+
lastAssistantMustNotMatchAny: verificationLastAssistantMustNotMatchAny,
|
|
43668
|
+
requireNotTimedOut: true
|
|
43669
|
+
}
|
|
43670
|
+
}).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43671
|
+
const fixtureReplayJson = JSON.stringify({
|
|
43672
|
+
type,
|
|
43673
|
+
name: fixtureName
|
|
43674
|
+
}).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
42397
43675
|
lines.push("You are implementing PTY parsing scripts for a CLI provider.");
|
|
42398
43676
|
lines.push("Be concise. Do NOT explain your reasoning. Edit files directly and verify with the local DevServer.");
|
|
42399
43677
|
lines.push("");
|
|
@@ -42407,7 +43685,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42407
43685
|
parseApproval: "parse_approval.js"
|
|
42408
43686
|
};
|
|
42409
43687
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
42410
|
-
const scriptsDir =
|
|
43688
|
+
const scriptsDir = path17.join(providerDir, "scripts");
|
|
42411
43689
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
42412
43690
|
if (latestScriptsDir) {
|
|
42413
43691
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -42415,11 +43693,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42415
43693
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
42416
43694
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
42417
43695
|
lines.push("");
|
|
42418
|
-
for (const file2 of
|
|
43696
|
+
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
42419
43697
|
if (!file2.endsWith(".js")) continue;
|
|
42420
43698
|
if (!targetFileNames.has(file2)) continue;
|
|
42421
43699
|
try {
|
|
42422
|
-
const content =
|
|
43700
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
42423
43701
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
42424
43702
|
lines.push("```javascript");
|
|
42425
43703
|
lines.push(content);
|
|
@@ -42428,14 +43706,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42428
43706
|
} catch {
|
|
42429
43707
|
}
|
|
42430
43708
|
}
|
|
42431
|
-
const refFiles =
|
|
43709
|
+
const refFiles = fs14.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
42432
43710
|
if (refFiles.length > 0) {
|
|
42433
43711
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
42434
43712
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
42435
43713
|
lines.push("");
|
|
42436
43714
|
for (const file2 of refFiles) {
|
|
42437
43715
|
try {
|
|
42438
|
-
const content =
|
|
43716
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
42439
43717
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
42440
43718
|
lines.push("```javascript");
|
|
42441
43719
|
lines.push(content);
|
|
@@ -42468,17 +43746,17 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42468
43746
|
lines.push("");
|
|
42469
43747
|
}
|
|
42470
43748
|
}
|
|
42471
|
-
const docsDir =
|
|
43749
|
+
const docsDir = path17.join(providerDir, "../../docs");
|
|
42472
43750
|
const loadGuide = (name) => {
|
|
42473
43751
|
try {
|
|
42474
|
-
const p =
|
|
42475
|
-
if (
|
|
43752
|
+
const p = path17.join(docsDir, name);
|
|
43753
|
+
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
42476
43754
|
} catch {
|
|
42477
43755
|
}
|
|
42478
43756
|
return null;
|
|
42479
43757
|
};
|
|
42480
43758
|
const providerGuide = loadGuide("PROVIDER_GUIDE.md");
|
|
42481
|
-
if (providerGuide) {
|
|
43759
|
+
if (providerGuide && provider.category !== "cli") {
|
|
42482
43760
|
lines.push("## Documentation: PROVIDER_GUIDE.md");
|
|
42483
43761
|
lines.push("```markdown");
|
|
42484
43762
|
lines.push(providerGuide);
|
|
@@ -42520,6 +43798,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42520
43798
|
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
43799
|
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
43800
|
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.");
|
|
43801
|
+
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.');
|
|
43802
|
+
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.");
|
|
43803
|
+
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.');
|
|
43804
|
+
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.");
|
|
43805
|
+
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
43806
|
lines.push("");
|
|
42524
43807
|
lines.push("## Task");
|
|
42525
43808
|
lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(", ")}**`);
|
|
@@ -42527,35 +43810,145 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42527
43810
|
lines.push("## Verification API");
|
|
42528
43811
|
lines.push("Use the DevServer CLI debug endpoints, not DOM/CDP routes.");
|
|
42529
43812
|
lines.push("");
|
|
42530
|
-
lines.push("### 1.
|
|
43813
|
+
lines.push("### 1. Preferred: run a full autonomous repro");
|
|
43814
|
+
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
43815
|
lines.push("```bash");
|
|
42532
|
-
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/
|
|
43816
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/exercise \\`);
|
|
42533
43817
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
42534
|
-
lines.push(` -d '
|
|
43818
|
+
lines.push(` -d '${exerciseJson}'`);
|
|
43819
|
+
lines.push("```");
|
|
43820
|
+
lines.push("");
|
|
43821
|
+
if (verification?.description) {
|
|
43822
|
+
lines.push("Verification intent:");
|
|
43823
|
+
lines.push(verification.description);
|
|
43824
|
+
lines.push("");
|
|
43825
|
+
}
|
|
43826
|
+
lines.push("Read the JSON response carefully. It already includes:");
|
|
43827
|
+
lines.push("1. `instanceId`");
|
|
43828
|
+
lines.push("2. `statusesSeen` and `approvalsResolved`");
|
|
43829
|
+
lines.push("3. `debug` for the final settled state");
|
|
43830
|
+
lines.push("4. `trace.entries` for the repro turn");
|
|
43831
|
+
lines.push("");
|
|
43832
|
+
lines.push("Save the response to a temp file and inspect the exact parsed transcript fields before editing:");
|
|
43833
|
+
lines.push("```bash");
|
|
43834
|
+
lines.push(`EXERCISE_JSON=$(mktemp)`);
|
|
43835
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/exercise \\`);
|
|
43836
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43837
|
+
lines.push(` -d '${exerciseJson}' > "$EXERCISE_JSON"`);
|
|
43838
|
+
lines.push(`jq '{timedOut,statusesSeen,approvalsResolved,inspect:{${verificationInspectFields.map((field, index) => `f${index + 1}: .${field}`).join(", ")}}}' "$EXERCISE_JSON"`);
|
|
42535
43839
|
lines.push("```");
|
|
42536
43840
|
lines.push("");
|
|
43841
|
+
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) {
|
|
43842
|
+
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.");
|
|
43843
|
+
lines.push("```bash");
|
|
43844
|
+
if (verificationMustContainAny.length > 0) {
|
|
43845
|
+
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"`);
|
|
43846
|
+
}
|
|
43847
|
+
if (verificationMustNotContainAny.length > 0) {
|
|
43848
|
+
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"`);
|
|
43849
|
+
}
|
|
43850
|
+
if (verificationMustMatchAny.length > 0) {
|
|
43851
|
+
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"`);
|
|
43852
|
+
}
|
|
43853
|
+
if (verificationMustNotMatchAny.length > 0) {
|
|
43854
|
+
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"`);
|
|
43855
|
+
}
|
|
43856
|
+
if (verificationLastAssistantMustContainAny.length > 0) {
|
|
43857
|
+
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"`);
|
|
43858
|
+
}
|
|
43859
|
+
if (verificationLastAssistantMustNotContainAny.length > 0) {
|
|
43860
|
+
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"`);
|
|
43861
|
+
}
|
|
43862
|
+
if (verificationLastAssistantMustMatchAny.length > 0) {
|
|
43863
|
+
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"`);
|
|
43864
|
+
}
|
|
43865
|
+
if (verificationLastAssistantMustNotMatchAny.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 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"`);
|
|
43867
|
+
}
|
|
43868
|
+
lines.push("```");
|
|
43869
|
+
lines.push("");
|
|
43870
|
+
}
|
|
43871
|
+
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.");
|
|
43872
|
+
lines.push("");
|
|
43873
|
+
lines.push("### 1b. Persist or replay the exact repro as a reusable fixture");
|
|
43874
|
+
if (fixtureNames.length > 0) {
|
|
43875
|
+
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(", ")}.`);
|
|
43876
|
+
for (const name of fixtureNames) {
|
|
43877
|
+
const replayJson = JSON.stringify({ type, name }).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43878
|
+
lines.push("```bash");
|
|
43879
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43880
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43881
|
+
lines.push(` -d '${replayJson}'`);
|
|
43882
|
+
lines.push("```");
|
|
43883
|
+
lines.push("");
|
|
43884
|
+
}
|
|
43885
|
+
lines.push("Do not create new fixtures unless one of the listed fixtures is missing or stale.");
|
|
43886
|
+
} else if (verification?.fixtureName) {
|
|
43887
|
+
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.`);
|
|
43888
|
+
lines.push("```bash");
|
|
43889
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43890
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43891
|
+
lines.push(` -d '${fixtureReplayJson}'`);
|
|
43892
|
+
lines.push("```");
|
|
43893
|
+
lines.push("");
|
|
43894
|
+
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.");
|
|
43895
|
+
lines.push("```bash");
|
|
43896
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/capture \\`);
|
|
43897
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43898
|
+
lines.push(` -d '${fixtureCaptureJson}'`);
|
|
43899
|
+
lines.push("```");
|
|
43900
|
+
} else {
|
|
43901
|
+
lines.push("Capture the exact exercise once before editing. After patching, replay THIS fixture and do not declare success unless replay passes.");
|
|
43902
|
+
lines.push("```bash");
|
|
43903
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/capture \\`);
|
|
43904
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43905
|
+
lines.push(` -d '${fixtureCaptureJson}'`);
|
|
43906
|
+
lines.push("");
|
|
43907
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43908
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43909
|
+
lines.push(` -d '${fixtureReplayJson}'`);
|
|
43910
|
+
lines.push("```");
|
|
43911
|
+
}
|
|
43912
|
+
lines.push("");
|
|
43913
|
+
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.");
|
|
43914
|
+
lines.push("");
|
|
42537
43915
|
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
42538
43916
|
lines.push("```bash");
|
|
43917
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/launch \\`);
|
|
43918
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43919
|
+
lines.push(` -d '{"type":"${type}","workingDir":"${providerDir.replace(/\\/g, "\\\\")}"}'`);
|
|
42539
43920
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
43921
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/trace/${type}`);
|
|
42540
43922
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
42541
43923
|
lines.push("```");
|
|
42542
43924
|
lines.push("");
|
|
43925
|
+
lines.push("The CLI trace endpoint is the primary debugging source. Read it BEFORE editing any parser code.");
|
|
43926
|
+
lines.push("Use the trace timeline to find the latest `settled` or `commit_transcript` frame for the repro turn and inspect these fields first:");
|
|
43927
|
+
lines.push("1. `payload.screenText`");
|
|
43928
|
+
lines.push("2. `payload.detectStatus` and `payload.parsedStatus`");
|
|
43929
|
+
lines.push("3. `payload.parsedLastAssistant`");
|
|
43930
|
+
lines.push("4. `payload.approval` / `payload.parsedActiveModal`");
|
|
43931
|
+
lines.push("5. `payload.rawPreview` only when control-sequence residue matters");
|
|
43932
|
+
lines.push("");
|
|
42543
43933
|
lines.push("The debug payload should be read in this priority order:");
|
|
42544
43934
|
lines.push("1. `screenText` / current visible state");
|
|
42545
43935
|
lines.push("2. parsed `status`, `messages`, `activeModal`");
|
|
42546
43936
|
lines.push("3. `rawBuffer` only for style/control-sequence cues");
|
|
42547
43937
|
lines.push("4. `buffer` only when the current screen is insufficient");
|
|
42548
43938
|
lines.push("");
|
|
42549
|
-
lines.push("
|
|
43939
|
+
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.");
|
|
43940
|
+
lines.push("Do NOT guess based only on the final chat bubble or a truncated UI preview.");
|
|
43941
|
+
lines.push("");
|
|
43942
|
+
lines.push("Extract the current `instanceId` from the exercise, launch, or status response and keep using it below.");
|
|
42550
43943
|
lines.push("");
|
|
42551
|
-
lines.push("### 3.
|
|
43944
|
+
lines.push("### 3. Manual fallback only: send a realistic approval-triggering prompt");
|
|
42552
43945
|
lines.push("```bash");
|
|
42553
43946
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/send \\`);
|
|
42554
43947
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
42555
43948
|
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
43949
|
lines.push("```");
|
|
42557
43950
|
lines.push("");
|
|
42558
|
-
lines.push("### 4.
|
|
43951
|
+
lines.push("### 4. Manual fallback only: if approval appears, resolve it until the CLI reaches idle");
|
|
42559
43952
|
lines.push("```bash");
|
|
42560
43953
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/resolve \\`);
|
|
42561
43954
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
@@ -42565,10 +43958,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42565
43958
|
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>","keys":"1"}'`);
|
|
42566
43959
|
lines.push("```");
|
|
42567
43960
|
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.");
|
|
43961
|
+
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
43962
|
lines.push("");
|
|
42570
43963
|
lines.push("### Patch Discipline");
|
|
42571
43964
|
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.");
|
|
43965
|
+
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.");
|
|
43966
|
+
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.");
|
|
43967
|
+
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.");
|
|
43968
|
+
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
43969
|
lines.push("");
|
|
42573
43970
|
lines.push("### 5. Verify the side effects outside the CLI");
|
|
42574
43971
|
lines.push("```bash");
|
|
@@ -42593,6 +43990,8 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42593
43990
|
lines.push("7. Re-run the debug endpoints after edits. Do NOT finish until the parsed result looks correct.");
|
|
42594
43991
|
lines.push("8. Confirm the parser still works after a redraw or scroll change without duplicating transcript history.");
|
|
42595
43992
|
lines.push("9. Confirm the implementation prefers current-screen signals over stale history when both are present.");
|
|
43993
|
+
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.");
|
|
43994
|
+
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
43995
|
lines.push("");
|
|
42597
43996
|
if (userComment) {
|
|
42598
43997
|
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
@@ -42601,10 +44000,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42601
44000
|
lines.push(userComment);
|
|
42602
44001
|
lines.push("");
|
|
42603
44002
|
}
|
|
42604
|
-
lines.push("Start NOW. Launch the CLI, inspect PTY state, edit the scripts, and verify via the CLI debug endpoints.");
|
|
44003
|
+
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
44004
|
return lines.join("\n");
|
|
42606
44005
|
}
|
|
42607
44006
|
function handleAutoImplSSE(ctx, type, req, res) {
|
|
44007
|
+
clearStaleAutoImplState(ctx, "SSE connection opened");
|
|
42608
44008
|
res.writeHead(200, {
|
|
42609
44009
|
"Content-Type": "text/event-stream",
|
|
42610
44010
|
"Cache-Control": "no-cache",
|
|
@@ -42626,6 +44026,7 @@ data: ${JSON.stringify(p.data)}
|
|
|
42626
44026
|
});
|
|
42627
44027
|
}
|
|
42628
44028
|
function handleAutoImplCancel(ctx, _type, _req, res) {
|
|
44029
|
+
clearStaleAutoImplState(ctx, "cancel request");
|
|
42629
44030
|
if (ctx.autoImplProcess) {
|
|
42630
44031
|
ctx.autoImplProcess.kill("SIGTERM");
|
|
42631
44032
|
setTimeout(() => {
|
|
@@ -42653,25 +44054,26 @@ data: ${JSON.stringify(msg.data)}
|
|
|
42653
44054
|
}
|
|
42654
44055
|
}
|
|
42655
44056
|
}
|
|
42656
|
-
var
|
|
44057
|
+
var fs14, path17, os18;
|
|
42657
44058
|
var init_dev_auto_implement = __esm({
|
|
42658
44059
|
"../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts"() {
|
|
42659
44060
|
"use strict";
|
|
42660
|
-
|
|
42661
|
-
|
|
44061
|
+
fs14 = __toESM(require("fs"));
|
|
44062
|
+
path17 = __toESM(require("path"));
|
|
42662
44063
|
os18 = __toESM(require("os"));
|
|
42663
44064
|
init_dev_server();
|
|
44065
|
+
init_dev_cli_debug();
|
|
42664
44066
|
}
|
|
42665
44067
|
});
|
|
42666
44068
|
|
|
42667
44069
|
// ../../oss/packages/daemon-core/src/daemon/dev-server.ts
|
|
42668
|
-
var http2,
|
|
44070
|
+
var http2, fs15, path18, DEV_SERVER_PORT, DevServer;
|
|
42669
44071
|
var init_dev_server = __esm({
|
|
42670
44072
|
"../../oss/packages/daemon-core/src/daemon/dev-server.ts"() {
|
|
42671
44073
|
"use strict";
|
|
42672
44074
|
http2 = __toESM(require("http"));
|
|
42673
|
-
|
|
42674
|
-
|
|
44075
|
+
fs15 = __toESM(require("fs"));
|
|
44076
|
+
path18 = __toESM(require("path"));
|
|
42675
44077
|
init_scaffold_template();
|
|
42676
44078
|
init_version_archive();
|
|
42677
44079
|
init_logger();
|
|
@@ -42732,11 +44134,16 @@ var init_dev_server = __esm({
|
|
|
42732
44134
|
{ method: "GET", pattern: "/api/cli/status", handler: (q2, s15) => this.handleCliStatus(q2, s15) },
|
|
42733
44135
|
{ method: "POST", pattern: "/api/cli/launch", handler: (q2, s15) => this.handleCliLaunch(q2, s15) },
|
|
42734
44136
|
{ method: "POST", pattern: "/api/cli/send", handler: (q2, s15) => this.handleCliSend(q2, s15) },
|
|
44137
|
+
{ method: "POST", pattern: "/api/cli/exercise", handler: (q2, s15) => this.handleCliExercise(q2, s15) },
|
|
44138
|
+
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q2, s15) => this.handleCliFixtureCapture(q2, s15) },
|
|
44139
|
+
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q2, s15) => this.handleCliFixtureReplay(q2, s15) },
|
|
42735
44140
|
{ method: "POST", pattern: "/api/cli/resolve", handler: (q2, s15) => this.handleCliResolve(q2, s15) },
|
|
42736
44141
|
{ method: "POST", pattern: "/api/cli/raw", handler: (q2, s15) => this.handleCliRaw(q2, s15) },
|
|
42737
44142
|
{ method: "POST", pattern: "/api/cli/stop", handler: (q2, s15) => this.handleCliStop(q2, s15) },
|
|
42738
44143
|
{ method: "GET", pattern: "/api/cli/events", handler: (q2, s15) => this.handleCliSSE(q2, s15) },
|
|
42739
44144
|
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliDebug(p[0], q2, s15) },
|
|
44145
|
+
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliTrace(p[0], q2, s15) },
|
|
44146
|
+
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliFixtureList(p[0], q2, s15) },
|
|
42740
44147
|
// Dynamic routes (provider :type param)
|
|
42741
44148
|
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q2, s15, p) => this.handleRunScript(p[0], q2, s15) },
|
|
42742
44149
|
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q2, s15, p) => this.handleListFiles(p[0], q2, s15) },
|
|
@@ -42770,8 +44177,8 @@ var init_dev_server = __esm({
|
|
|
42770
44177
|
}
|
|
42771
44178
|
getEndpointList() {
|
|
42772
44179
|
return this.routes.map((r) => {
|
|
42773
|
-
const
|
|
42774
|
-
return `${r.method.padEnd(5)} ${
|
|
44180
|
+
const path23 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
44181
|
+
return `${r.method.padEnd(5)} ${path23}`;
|
|
42775
44182
|
});
|
|
42776
44183
|
}
|
|
42777
44184
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -43053,12 +44460,12 @@ var init_dev_server = __esm({
|
|
|
43053
44460
|
// ─── DevConsole SPA ───
|
|
43054
44461
|
getConsoleDistDir() {
|
|
43055
44462
|
const candidates = [
|
|
43056
|
-
|
|
43057
|
-
|
|
43058
|
-
|
|
44463
|
+
path18.resolve(__dirname, "../../web-devconsole/dist"),
|
|
44464
|
+
path18.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
44465
|
+
path18.join(process.cwd(), "packages/web-devconsole/dist")
|
|
43059
44466
|
];
|
|
43060
44467
|
for (const dir of candidates) {
|
|
43061
|
-
if (
|
|
44468
|
+
if (fs15.existsSync(path18.join(dir, "index.html"))) return dir;
|
|
43062
44469
|
}
|
|
43063
44470
|
return null;
|
|
43064
44471
|
}
|
|
@@ -43068,9 +44475,9 @@ var init_dev_server = __esm({
|
|
|
43068
44475
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
43069
44476
|
return;
|
|
43070
44477
|
}
|
|
43071
|
-
const htmlPath =
|
|
44478
|
+
const htmlPath = path18.join(distDir, "index.html");
|
|
43072
44479
|
try {
|
|
43073
|
-
const html =
|
|
44480
|
+
const html = fs15.readFileSync(htmlPath, "utf-8");
|
|
43074
44481
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
43075
44482
|
res.end(html);
|
|
43076
44483
|
} catch (e) {
|
|
@@ -43093,15 +44500,15 @@ var init_dev_server = __esm({
|
|
|
43093
44500
|
this.json(res, 404, { error: "Not found" });
|
|
43094
44501
|
return;
|
|
43095
44502
|
}
|
|
43096
|
-
const safePath =
|
|
43097
|
-
const filePath =
|
|
44503
|
+
const safePath = path18.normalize(pathname).replace(/^\.\.\//, "");
|
|
44504
|
+
const filePath = path18.join(distDir, safePath);
|
|
43098
44505
|
if (!filePath.startsWith(distDir)) {
|
|
43099
44506
|
this.json(res, 403, { error: "Forbidden" });
|
|
43100
44507
|
return;
|
|
43101
44508
|
}
|
|
43102
44509
|
try {
|
|
43103
|
-
const content =
|
|
43104
|
-
const ext =
|
|
44510
|
+
const content = fs15.readFileSync(filePath);
|
|
44511
|
+
const ext = path18.extname(filePath);
|
|
43105
44512
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
43106
44513
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
43107
44514
|
res.end(content);
|
|
@@ -43209,14 +44616,14 @@ var init_dev_server = __esm({
|
|
|
43209
44616
|
const files = [];
|
|
43210
44617
|
const scan = (d, prefix) => {
|
|
43211
44618
|
try {
|
|
43212
|
-
for (const entry of
|
|
44619
|
+
for (const entry of fs15.readdirSync(d, { withFileTypes: true })) {
|
|
43213
44620
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
43214
44621
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
43215
44622
|
if (entry.isDirectory()) {
|
|
43216
44623
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
43217
|
-
scan(
|
|
44624
|
+
scan(path18.join(d, entry.name), rel);
|
|
43218
44625
|
} else {
|
|
43219
|
-
const stat4 =
|
|
44626
|
+
const stat4 = fs15.statSync(path18.join(d, entry.name));
|
|
43220
44627
|
files.push({ path: rel, size: stat4.size, type: "file" });
|
|
43221
44628
|
}
|
|
43222
44629
|
}
|
|
@@ -43239,16 +44646,16 @@ var init_dev_server = __esm({
|
|
|
43239
44646
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
43240
44647
|
return;
|
|
43241
44648
|
}
|
|
43242
|
-
const fullPath =
|
|
44649
|
+
const fullPath = path18.resolve(dir, path18.normalize(filePath));
|
|
43243
44650
|
if (!fullPath.startsWith(dir)) {
|
|
43244
44651
|
this.json(res, 403, { error: "Forbidden" });
|
|
43245
44652
|
return;
|
|
43246
44653
|
}
|
|
43247
|
-
if (!
|
|
44654
|
+
if (!fs15.existsSync(fullPath) || fs15.statSync(fullPath).isDirectory()) {
|
|
43248
44655
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
43249
44656
|
return;
|
|
43250
44657
|
}
|
|
43251
|
-
const content =
|
|
44658
|
+
const content = fs15.readFileSync(fullPath, "utf-8");
|
|
43252
44659
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
43253
44660
|
}
|
|
43254
44661
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -43264,15 +44671,15 @@ var init_dev_server = __esm({
|
|
|
43264
44671
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
43265
44672
|
return;
|
|
43266
44673
|
}
|
|
43267
|
-
const fullPath =
|
|
44674
|
+
const fullPath = path18.resolve(dir, path18.normalize(filePath));
|
|
43268
44675
|
if (!fullPath.startsWith(dir)) {
|
|
43269
44676
|
this.json(res, 403, { error: "Forbidden" });
|
|
43270
44677
|
return;
|
|
43271
44678
|
}
|
|
43272
44679
|
try {
|
|
43273
|
-
if (
|
|
43274
|
-
|
|
43275
|
-
|
|
44680
|
+
if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
|
|
44681
|
+
fs15.mkdirSync(path18.dirname(fullPath), { recursive: true });
|
|
44682
|
+
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
43276
44683
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
43277
44684
|
this.providerLoader.reload();
|
|
43278
44685
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -43288,9 +44695,9 @@ var init_dev_server = __esm({
|
|
|
43288
44695
|
return;
|
|
43289
44696
|
}
|
|
43290
44697
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
43291
|
-
const p =
|
|
43292
|
-
if (
|
|
43293
|
-
const source =
|
|
44698
|
+
const p = path18.join(dir, name);
|
|
44699
|
+
if (fs15.existsSync(p)) {
|
|
44700
|
+
const source = fs15.readFileSync(p, "utf-8");
|
|
43294
44701
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
43295
44702
|
return;
|
|
43296
44703
|
}
|
|
@@ -43309,11 +44716,11 @@ var init_dev_server = __esm({
|
|
|
43309
44716
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
43310
44717
|
return;
|
|
43311
44718
|
}
|
|
43312
|
-
const target =
|
|
43313
|
-
const targetPath =
|
|
44719
|
+
const target = fs15.existsSync(path18.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
44720
|
+
const targetPath = path18.join(dir, target);
|
|
43314
44721
|
try {
|
|
43315
|
-
if (
|
|
43316
|
-
|
|
44722
|
+
if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
|
|
44723
|
+
fs15.writeFileSync(targetPath, source, "utf-8");
|
|
43317
44724
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
43318
44725
|
this.providerLoader.reload();
|
|
43319
44726
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -43470,21 +44877,21 @@ var init_dev_server = __esm({
|
|
|
43470
44877
|
}
|
|
43471
44878
|
let targetDir;
|
|
43472
44879
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
43473
|
-
const jsonPath =
|
|
43474
|
-
if (
|
|
44880
|
+
const jsonPath = path18.join(targetDir, "provider.json");
|
|
44881
|
+
if (fs15.existsSync(jsonPath)) {
|
|
43475
44882
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
43476
44883
|
return;
|
|
43477
44884
|
}
|
|
43478
44885
|
try {
|
|
43479
44886
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2, osPaths, processNames });
|
|
43480
|
-
|
|
43481
|
-
|
|
44887
|
+
fs15.mkdirSync(targetDir, { recursive: true });
|
|
44888
|
+
fs15.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
43482
44889
|
const createdFiles = ["provider.json"];
|
|
43483
44890
|
if (result.files) {
|
|
43484
44891
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
43485
|
-
const fullPath =
|
|
43486
|
-
|
|
43487
|
-
|
|
44892
|
+
const fullPath = path18.join(targetDir, relPath);
|
|
44893
|
+
fs15.mkdirSync(path18.dirname(fullPath), { recursive: true });
|
|
44894
|
+
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
43488
44895
|
createdFiles.push(relPath);
|
|
43489
44896
|
}
|
|
43490
44897
|
}
|
|
@@ -43533,45 +44940,45 @@ var init_dev_server = __esm({
|
|
|
43533
44940
|
}
|
|
43534
44941
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
43535
44942
|
getLatestScriptVersionDir(scriptsDir) {
|
|
43536
|
-
if (!
|
|
43537
|
-
const versions =
|
|
44943
|
+
if (!fs15.existsSync(scriptsDir)) return null;
|
|
44944
|
+
const versions = fs15.readdirSync(scriptsDir).filter((d) => {
|
|
43538
44945
|
try {
|
|
43539
|
-
return
|
|
44946
|
+
return fs15.statSync(path18.join(scriptsDir, d)).isDirectory();
|
|
43540
44947
|
} catch {
|
|
43541
44948
|
return false;
|
|
43542
44949
|
}
|
|
43543
44950
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
43544
44951
|
if (versions.length === 0) return null;
|
|
43545
|
-
return
|
|
44952
|
+
return path18.join(scriptsDir, versions[0]);
|
|
43546
44953
|
}
|
|
43547
44954
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
43548
|
-
const canonicalUserDir =
|
|
43549
|
-
const desiredDir = requestedDir ?
|
|
43550
|
-
const upstreamRoot =
|
|
43551
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
44955
|
+
const canonicalUserDir = path18.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
44956
|
+
const desiredDir = requestedDir ? path18.resolve(requestedDir) : canonicalUserDir;
|
|
44957
|
+
const upstreamRoot = path18.resolve(this.providerLoader.getUpstreamDir());
|
|
44958
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path18.sep}`)) {
|
|
43552
44959
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
43553
44960
|
}
|
|
43554
|
-
if (
|
|
44961
|
+
if (path18.basename(desiredDir) !== type) {
|
|
43555
44962
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
43556
44963
|
}
|
|
43557
44964
|
const sourceDir = this.findProviderDir(type);
|
|
43558
44965
|
if (!sourceDir) {
|
|
43559
44966
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
43560
44967
|
}
|
|
43561
|
-
if (!
|
|
43562
|
-
|
|
43563
|
-
|
|
44968
|
+
if (!fs15.existsSync(desiredDir)) {
|
|
44969
|
+
fs15.mkdirSync(path18.dirname(desiredDir), { recursive: true });
|
|
44970
|
+
fs15.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
43564
44971
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
43565
44972
|
}
|
|
43566
|
-
const providerJson =
|
|
43567
|
-
if (!
|
|
44973
|
+
const providerJson = path18.join(desiredDir, "provider.json");
|
|
44974
|
+
if (!fs15.existsSync(providerJson)) {
|
|
43568
44975
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
43569
44976
|
}
|
|
43570
44977
|
try {
|
|
43571
|
-
const providerData = JSON.parse(
|
|
44978
|
+
const providerData = JSON.parse(fs15.readFileSync(providerJson, "utf-8"));
|
|
43572
44979
|
if (providerData.disableUpstream !== true) {
|
|
43573
44980
|
providerData.disableUpstream = true;
|
|
43574
|
-
|
|
44981
|
+
fs15.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
43575
44982
|
}
|
|
43576
44983
|
} catch (error48) {
|
|
43577
44984
|
return {
|
|
@@ -43611,7 +45018,7 @@ var init_dev_server = __esm({
|
|
|
43611
45018
|
setMode: "set_mode.js"
|
|
43612
45019
|
};
|
|
43613
45020
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
43614
|
-
const scriptsDir =
|
|
45021
|
+
const scriptsDir = path18.join(providerDir, "scripts");
|
|
43615
45022
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
43616
45023
|
if (latestScriptsDir) {
|
|
43617
45024
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -43619,10 +45026,10 @@ var init_dev_server = __esm({
|
|
|
43619
45026
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
43620
45027
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
43621
45028
|
lines.push("");
|
|
43622
|
-
for (const file2 of
|
|
45029
|
+
for (const file2 of fs15.readdirSync(latestScriptsDir)) {
|
|
43623
45030
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
43624
45031
|
try {
|
|
43625
|
-
const content =
|
|
45032
|
+
const content = fs15.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
|
|
43626
45033
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
43627
45034
|
lines.push("```javascript");
|
|
43628
45035
|
lines.push(content);
|
|
@@ -43632,14 +45039,14 @@ var init_dev_server = __esm({
|
|
|
43632
45039
|
}
|
|
43633
45040
|
}
|
|
43634
45041
|
}
|
|
43635
|
-
const refFiles =
|
|
45042
|
+
const refFiles = fs15.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
43636
45043
|
if (refFiles.length > 0) {
|
|
43637
45044
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
43638
45045
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
43639
45046
|
lines.push("");
|
|
43640
45047
|
for (const file2 of refFiles) {
|
|
43641
45048
|
try {
|
|
43642
|
-
const content =
|
|
45049
|
+
const content = fs15.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
|
|
43643
45050
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
43644
45051
|
lines.push("```javascript");
|
|
43645
45052
|
lines.push(content);
|
|
@@ -43680,11 +45087,11 @@ var init_dev_server = __esm({
|
|
|
43680
45087
|
lines.push("");
|
|
43681
45088
|
}
|
|
43682
45089
|
}
|
|
43683
|
-
const docsDir =
|
|
45090
|
+
const docsDir = path18.join(providerDir, "../../docs");
|
|
43684
45091
|
const loadGuide = (name) => {
|
|
43685
45092
|
try {
|
|
43686
|
-
const p =
|
|
43687
|
-
if (
|
|
45093
|
+
const p = path18.join(docsDir, name);
|
|
45094
|
+
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
43688
45095
|
} catch {
|
|
43689
45096
|
}
|
|
43690
45097
|
return null;
|
|
@@ -43857,7 +45264,7 @@ var init_dev_server = __esm({
|
|
|
43857
45264
|
parseApproval: "parse_approval.js"
|
|
43858
45265
|
};
|
|
43859
45266
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
43860
|
-
const scriptsDir =
|
|
45267
|
+
const scriptsDir = path18.join(providerDir, "scripts");
|
|
43861
45268
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
43862
45269
|
if (latestScriptsDir) {
|
|
43863
45270
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -43865,11 +45272,11 @@ var init_dev_server = __esm({
|
|
|
43865
45272
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
43866
45273
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
43867
45274
|
lines.push("");
|
|
43868
|
-
for (const file2 of
|
|
45275
|
+
for (const file2 of fs15.readdirSync(latestScriptsDir)) {
|
|
43869
45276
|
if (!file2.endsWith(".js")) continue;
|
|
43870
45277
|
if (!targetFileNames.has(file2)) continue;
|
|
43871
45278
|
try {
|
|
43872
|
-
const content =
|
|
45279
|
+
const content = fs15.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
|
|
43873
45280
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
43874
45281
|
lines.push("```javascript");
|
|
43875
45282
|
lines.push(content);
|
|
@@ -43878,14 +45285,14 @@ var init_dev_server = __esm({
|
|
|
43878
45285
|
} catch {
|
|
43879
45286
|
}
|
|
43880
45287
|
}
|
|
43881
|
-
const refFiles =
|
|
45288
|
+
const refFiles = fs15.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
43882
45289
|
if (refFiles.length > 0) {
|
|
43883
45290
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
43884
45291
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
43885
45292
|
lines.push("");
|
|
43886
45293
|
for (const file2 of refFiles) {
|
|
43887
45294
|
try {
|
|
43888
|
-
const content =
|
|
45295
|
+
const content = fs15.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
|
|
43889
45296
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
43890
45297
|
lines.push("```javascript");
|
|
43891
45298
|
lines.push(content);
|
|
@@ -43918,11 +45325,11 @@ var init_dev_server = __esm({
|
|
|
43918
45325
|
lines.push("");
|
|
43919
45326
|
}
|
|
43920
45327
|
}
|
|
43921
|
-
const docsDir =
|
|
45328
|
+
const docsDir = path18.join(providerDir, "../../docs");
|
|
43922
45329
|
const loadGuide = (name) => {
|
|
43923
45330
|
try {
|
|
43924
|
-
const p =
|
|
43925
|
-
if (
|
|
45331
|
+
const p = path18.join(docsDir, name);
|
|
45332
|
+
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
43926
45333
|
} catch {
|
|
43927
45334
|
}
|
|
43928
45335
|
return null;
|
|
@@ -43987,6 +45394,7 @@ var init_dev_server = __esm({
|
|
|
43987
45394
|
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
43988
45395
|
lines.push("```bash");
|
|
43989
45396
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
45397
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/trace/${type}`);
|
|
43990
45398
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
43991
45399
|
lines.push("```");
|
|
43992
45400
|
lines.push("");
|
|
@@ -44121,6 +45529,16 @@ data: ${JSON.stringify(msg.data)}
|
|
|
44121
45529
|
async handleCliSend(req, res) {
|
|
44122
45530
|
return handleCliSend(this, req, res);
|
|
44123
45531
|
}
|
|
45532
|
+
/** POST /api/cli/exercise — launch/send/approve/wait helper for provider-fix loops */
|
|
45533
|
+
async handleCliExercise(req, res) {
|
|
45534
|
+
return handleCliExercise(this, req, res);
|
|
45535
|
+
}
|
|
45536
|
+
async handleCliFixtureCapture(req, res) {
|
|
45537
|
+
return handleCliFixtureCapture(this, req, res);
|
|
45538
|
+
}
|
|
45539
|
+
async handleCliFixtureReplay(req, res) {
|
|
45540
|
+
return handleCliFixtureReplay(this, req, res);
|
|
45541
|
+
}
|
|
44124
45542
|
/** POST /api/cli/stop — stop a running CLI { type } */
|
|
44125
45543
|
async handleCliStop(req, res) {
|
|
44126
45544
|
return handleCliStop(this, req, res);
|
|
@@ -44144,6 +45562,13 @@ data: ${JSON.stringify(msg.data)}
|
|
|
44144
45562
|
async handleCliDebug(type, _req, res) {
|
|
44145
45563
|
return handleCliDebug(this, type, _req, res);
|
|
44146
45564
|
}
|
|
45565
|
+
/** GET /api/cli/trace/:type — recent CLI trace timeline plus current debug snapshot */
|
|
45566
|
+
async handleCliTrace(type, _req, res) {
|
|
45567
|
+
return handleCliTrace(this, type, _req, res);
|
|
45568
|
+
}
|
|
45569
|
+
async handleCliFixtureList(type, _req, res) {
|
|
45570
|
+
return handleCliFixtureList(this, type, _req, res);
|
|
45571
|
+
}
|
|
44147
45572
|
/** POST /api/cli/resolve — resolve an approval modal { type, buttonIndex } */
|
|
44148
45573
|
async handleCliResolve(req, res) {
|
|
44149
45574
|
return handleCliResolve(this, req, res);
|
|
@@ -44451,7 +45876,18 @@ var init_session_host_transport = __esm({
|
|
|
44451
45876
|
});
|
|
44452
45877
|
}
|
|
44453
45878
|
async boot() {
|
|
44454
|
-
|
|
45879
|
+
if (typeof this.options.ensureReady === "function") {
|
|
45880
|
+
await this.options.ensureReady();
|
|
45881
|
+
}
|
|
45882
|
+
try {
|
|
45883
|
+
await this.client.connect();
|
|
45884
|
+
} catch (error48) {
|
|
45885
|
+
if (typeof this.options.ensureReady !== "function") {
|
|
45886
|
+
throw error48;
|
|
45887
|
+
}
|
|
45888
|
+
await this.options.ensureReady();
|
|
45889
|
+
await this.client.connect();
|
|
45890
|
+
}
|
|
44455
45891
|
this.unsubscribe = this.client.onEvent((event) => this.handleEvent(event));
|
|
44456
45892
|
let record2 = null;
|
|
44457
45893
|
if (this.options.attachExisting) {
|
|
@@ -44764,8 +46200,8 @@ async function installExtension(ide, extension) {
|
|
|
44764
46200
|
const res = await fetch(extension.vsixUrl);
|
|
44765
46201
|
if (res.ok) {
|
|
44766
46202
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
44767
|
-
const
|
|
44768
|
-
|
|
46203
|
+
const fs19 = await import("fs");
|
|
46204
|
+
fs19.writeFileSync(vsixPath, buffer);
|
|
44769
46205
|
return new Promise((resolve13) => {
|
|
44770
46206
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
44771
46207
|
(0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
|
|
@@ -45604,17 +47040,17 @@ function canPeerUsePrivilegedShareCommand(commandType, permission) {
|
|
|
45604
47040
|
return false;
|
|
45605
47041
|
}
|
|
45606
47042
|
}
|
|
45607
|
-
var
|
|
47043
|
+
var fs16, path19, os20, import_node_module2, esmRequire, logFile, log, logDebug, DaemonP2PSender;
|
|
45608
47044
|
var init_daemon_p2p = __esm({
|
|
45609
47045
|
"src/daemon-p2p.ts"() {
|
|
45610
47046
|
"use strict";
|
|
45611
|
-
|
|
47047
|
+
fs16 = __toESM(require("fs"));
|
|
45612
47048
|
init_src();
|
|
45613
|
-
|
|
47049
|
+
path19 = __toESM(require("path"));
|
|
45614
47050
|
os20 = __toESM(require("os"));
|
|
45615
47051
|
import_node_module2 = require("module");
|
|
45616
47052
|
esmRequire = (0, import_node_module2.createRequire)(__filename);
|
|
45617
|
-
logFile =
|
|
47053
|
+
logFile = path19.join(os20.tmpdir(), "adhdev_daemon_p2p.log");
|
|
45618
47054
|
log = (msg) => {
|
|
45619
47055
|
LOG.info("P2P", `[${(/* @__PURE__ */ new Date()).toISOString()}] [P2P] ${msg}`);
|
|
45620
47056
|
};
|
|
@@ -45682,17 +47118,17 @@ ${e?.stack || ""}`);
|
|
|
45682
47118
|
const prebuildKey = `${platform11}-${arch3}`;
|
|
45683
47119
|
try {
|
|
45684
47120
|
const candidates = [
|
|
45685
|
-
|
|
45686
|
-
|
|
45687
|
-
|
|
47121
|
+
path19.join(__dirname, "node_modules", "node-datachannel"),
|
|
47122
|
+
path19.join(__dirname, "..", "node_modules", "node-datachannel"),
|
|
47123
|
+
path19.join(__dirname, "..", "..", "node_modules", "node-datachannel")
|
|
45688
47124
|
];
|
|
45689
47125
|
for (const candidate of candidates) {
|
|
45690
|
-
const prebuildPath =
|
|
45691
|
-
if (
|
|
45692
|
-
const targetDir =
|
|
45693
|
-
const targetPath =
|
|
45694
|
-
|
|
45695
|
-
|
|
47126
|
+
const prebuildPath = path19.join(candidate, "prebuilds", prebuildKey, "node_datachannel.node");
|
|
47127
|
+
if (fs16.existsSync(prebuildPath)) {
|
|
47128
|
+
const targetDir = path19.join(candidate, "build", "Release");
|
|
47129
|
+
const targetPath = path19.join(targetDir, "node_datachannel.node");
|
|
47130
|
+
fs16.mkdirSync(targetDir, { recursive: true });
|
|
47131
|
+
fs16.copyFileSync(prebuildPath, targetPath);
|
|
45696
47132
|
try {
|
|
45697
47133
|
delete esmRequire.cache[esmRequire.resolve("node-datachannel")];
|
|
45698
47134
|
} catch {
|
|
@@ -46592,20 +48028,34 @@ __export(session_host_exports, {
|
|
|
46592
48028
|
listHostedCliRuntimes: () => listHostedCliRuntimes2,
|
|
46593
48029
|
stopSessionHost: () => stopSessionHost
|
|
46594
48030
|
});
|
|
48031
|
+
function buildSessionHostEnv(baseEnv) {
|
|
48032
|
+
const env = {};
|
|
48033
|
+
for (const [key, value] of Object.entries(baseEnv)) {
|
|
48034
|
+
if (typeof value !== "string") continue;
|
|
48035
|
+
env[key] = value;
|
|
48036
|
+
}
|
|
48037
|
+
for (const key of Object.keys(env)) {
|
|
48038
|
+
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_")) {
|
|
48039
|
+
delete env[key];
|
|
48040
|
+
}
|
|
48041
|
+
}
|
|
48042
|
+
env.ADHDEV_SESSION_HOST_NAME = SESSION_HOST_APP_NAME;
|
|
48043
|
+
return env;
|
|
48044
|
+
}
|
|
46595
48045
|
function resolveSessionHostEntry() {
|
|
46596
48046
|
const packagedCandidates = [
|
|
46597
|
-
|
|
46598
|
-
|
|
48047
|
+
path20.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
|
|
48048
|
+
path20.resolve(__dirname, "../../vendor/session-host-daemon/index.js")
|
|
46599
48049
|
];
|
|
46600
48050
|
for (const candidate of packagedCandidates) {
|
|
46601
|
-
if (
|
|
48051
|
+
if (fs17.existsSync(candidate)) {
|
|
46602
48052
|
return candidate;
|
|
46603
48053
|
}
|
|
46604
48054
|
}
|
|
46605
48055
|
return require.resolve("@adhdev/session-host-daemon");
|
|
46606
48056
|
}
|
|
46607
48057
|
function getSessionHostPidFile() {
|
|
46608
|
-
return
|
|
48058
|
+
return path20.join(os21.homedir(), ".adhdev", `${SESSION_HOST_APP_NAME}-session-host.pid`);
|
|
46609
48059
|
}
|
|
46610
48060
|
function killPid2(pid) {
|
|
46611
48061
|
try {
|
|
@@ -46623,8 +48073,8 @@ function stopSessionHost() {
|
|
|
46623
48073
|
let stopped = false;
|
|
46624
48074
|
const pidFile = getSessionHostPidFile();
|
|
46625
48075
|
try {
|
|
46626
|
-
if (
|
|
46627
|
-
const pid = Number.parseInt(
|
|
48076
|
+
if (fs17.existsSync(pidFile)) {
|
|
48077
|
+
const pid = Number.parseInt(fs17.readFileSync(pidFile, "utf8").trim(), 10);
|
|
46628
48078
|
if (Number.isFinite(pid)) {
|
|
46629
48079
|
stopped = killPid2(pid) || stopped;
|
|
46630
48080
|
}
|
|
@@ -46632,7 +48082,7 @@ function stopSessionHost() {
|
|
|
46632
48082
|
} catch {
|
|
46633
48083
|
} finally {
|
|
46634
48084
|
try {
|
|
46635
|
-
|
|
48085
|
+
fs17.unlinkSync(pidFile);
|
|
46636
48086
|
} catch {
|
|
46637
48087
|
}
|
|
46638
48088
|
}
|
|
@@ -46651,36 +48101,49 @@ function stopSessionHost() {
|
|
|
46651
48101
|
return stopped;
|
|
46652
48102
|
}
|
|
46653
48103
|
async function ensureSessionHostReady2() {
|
|
46654
|
-
|
|
46655
|
-
|
|
46656
|
-
|
|
46657
|
-
|
|
46658
|
-
|
|
46659
|
-
|
|
46660
|
-
|
|
46661
|
-
|
|
46662
|
-
|
|
46663
|
-
|
|
46664
|
-
|
|
46665
|
-
|
|
46666
|
-
|
|
46667
|
-
|
|
46668
|
-
|
|
46669
|
-
|
|
48104
|
+
const spawnHost = () => {
|
|
48105
|
+
const entry = resolveSessionHostEntry();
|
|
48106
|
+
const child = (0, import_child_process11.spawn)(process.execPath, [entry], {
|
|
48107
|
+
detached: true,
|
|
48108
|
+
stdio: "ignore",
|
|
48109
|
+
windowsHide: true,
|
|
48110
|
+
env: buildSessionHostEnv(process.env)
|
|
48111
|
+
});
|
|
48112
|
+
child.unref();
|
|
48113
|
+
};
|
|
48114
|
+
try {
|
|
48115
|
+
return await ensureSessionHostReady({
|
|
48116
|
+
appName: SESSION_HOST_APP_NAME,
|
|
48117
|
+
spawnHost,
|
|
48118
|
+
timeoutMs: SESSION_HOST_START_TIMEOUT_MS
|
|
48119
|
+
});
|
|
48120
|
+
} catch (error48) {
|
|
48121
|
+
stopSessionHost();
|
|
48122
|
+
return ensureSessionHostReady({
|
|
48123
|
+
appName: SESSION_HOST_APP_NAME,
|
|
48124
|
+
spawnHost,
|
|
48125
|
+
timeoutMs: SESSION_HOST_START_TIMEOUT_MS
|
|
48126
|
+
}).catch((retryError) => {
|
|
48127
|
+
const initialMessage = error48 instanceof Error ? error48.message : String(error48);
|
|
48128
|
+
const retryMessage = retryError instanceof Error ? retryError.message : String(retryError);
|
|
48129
|
+
throw new Error(`Session host failed to start after retry (${initialMessage}; retry: ${retryMessage})`);
|
|
48130
|
+
});
|
|
48131
|
+
}
|
|
46670
48132
|
}
|
|
46671
48133
|
async function listHostedCliRuntimes2(endpoint) {
|
|
46672
48134
|
return listHostedCliRuntimes(endpoint);
|
|
46673
48135
|
}
|
|
46674
|
-
var import_child_process11,
|
|
48136
|
+
var import_child_process11, fs17, os21, path20, SESSION_HOST_APP_NAME, SESSION_HOST_START_TIMEOUT_MS;
|
|
46675
48137
|
var init_session_host = __esm({
|
|
46676
48138
|
"src/session-host.ts"() {
|
|
46677
48139
|
"use strict";
|
|
46678
48140
|
import_child_process11 = require("child_process");
|
|
46679
|
-
|
|
48141
|
+
fs17 = __toESM(require("fs"));
|
|
46680
48142
|
os21 = __toESM(require("os"));
|
|
46681
|
-
|
|
48143
|
+
path20 = __toESM(require("path"));
|
|
46682
48144
|
init_src();
|
|
46683
48145
|
SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
|
|
48146
|
+
SESSION_HOST_START_TIMEOUT_MS = 15e3;
|
|
46684
48147
|
}
|
|
46685
48148
|
});
|
|
46686
48149
|
|
|
@@ -46692,24 +48155,24 @@ __export(adhdev_daemon_exports, {
|
|
|
46692
48155
|
stopDaemon: () => stopDaemon
|
|
46693
48156
|
});
|
|
46694
48157
|
function getDaemonPidFile() {
|
|
46695
|
-
const dir =
|
|
46696
|
-
if (!
|
|
46697
|
-
return
|
|
48158
|
+
const dir = path21.join(os22.homedir(), ".adhdev");
|
|
48159
|
+
if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
|
|
48160
|
+
return path21.join(dir, "daemon.pid");
|
|
46698
48161
|
}
|
|
46699
48162
|
function writeDaemonPid(pid) {
|
|
46700
|
-
|
|
48163
|
+
fs18.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
|
|
46701
48164
|
}
|
|
46702
48165
|
function removeDaemonPid() {
|
|
46703
48166
|
try {
|
|
46704
|
-
|
|
48167
|
+
fs18.unlinkSync(getDaemonPidFile());
|
|
46705
48168
|
} catch (e) {
|
|
46706
48169
|
}
|
|
46707
48170
|
}
|
|
46708
48171
|
function isDaemonRunning() {
|
|
46709
48172
|
const pidFile = getDaemonPidFile();
|
|
46710
48173
|
try {
|
|
46711
|
-
if (!
|
|
46712
|
-
const pid = parseInt(
|
|
48174
|
+
if (!fs18.existsSync(pidFile)) return false;
|
|
48175
|
+
const pid = parseInt(fs18.readFileSync(pidFile, "utf-8").trim());
|
|
46713
48176
|
process.kill(pid, 0);
|
|
46714
48177
|
return true;
|
|
46715
48178
|
} catch {
|
|
@@ -46720,8 +48183,8 @@ function isDaemonRunning() {
|
|
|
46720
48183
|
function stopDaemon() {
|
|
46721
48184
|
const pidFile = getDaemonPidFile();
|
|
46722
48185
|
try {
|
|
46723
|
-
if (!
|
|
46724
|
-
const pid = parseInt(
|
|
48186
|
+
if (!fs18.existsSync(pidFile)) return false;
|
|
48187
|
+
const pid = parseInt(fs18.readFileSync(pidFile, "utf-8").trim());
|
|
46725
48188
|
process.kill(pid, "SIGTERM");
|
|
46726
48189
|
removeDaemonPid();
|
|
46727
48190
|
return true;
|
|
@@ -46730,7 +48193,7 @@ function stopDaemon() {
|
|
|
46730
48193
|
return false;
|
|
46731
48194
|
}
|
|
46732
48195
|
}
|
|
46733
|
-
var os22,
|
|
48196
|
+
var os22, fs18, path21, import_chalk2, pkgVersion, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
46734
48197
|
var init_adhdev_daemon = __esm({
|
|
46735
48198
|
"src/adhdev-daemon.ts"() {
|
|
46736
48199
|
"use strict";
|
|
@@ -46741,19 +48204,19 @@ var init_adhdev_daemon = __esm({
|
|
|
46741
48204
|
init_session_host();
|
|
46742
48205
|
init_dist();
|
|
46743
48206
|
os22 = __toESM(require("os"));
|
|
46744
|
-
|
|
46745
|
-
|
|
48207
|
+
fs18 = __toESM(require("fs"));
|
|
48208
|
+
path21 = __toESM(require("path"));
|
|
46746
48209
|
import_chalk2 = __toESM(require("chalk"));
|
|
46747
|
-
pkgVersion = "0.
|
|
48210
|
+
pkgVersion = "0.8.0";
|
|
46748
48211
|
if (pkgVersion === "unknown") {
|
|
46749
48212
|
try {
|
|
46750
48213
|
const possiblePaths = [
|
|
46751
|
-
|
|
46752
|
-
|
|
48214
|
+
path21.join(__dirname, "..", "package.json"),
|
|
48215
|
+
path21.join(__dirname, "package.json")
|
|
46753
48216
|
];
|
|
46754
48217
|
for (const p of possiblePaths) {
|
|
46755
48218
|
try {
|
|
46756
|
-
const data = JSON.parse(
|
|
48219
|
+
const data = JSON.parse(fs18.readFileSync(p, "utf-8"));
|
|
46757
48220
|
if (data.version) {
|
|
46758
48221
|
pkgVersion = data.version;
|
|
46759
48222
|
break;
|
|
@@ -46851,6 +48314,10 @@ ${err?.stack || ""}`);
|
|
|
46851
48314
|
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
46852
48315
|
createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, providerSessionId, attachExisting }) => new SessionHostPtyTransportFactory({
|
|
46853
48316
|
endpoint: sessionHostEndpoint,
|
|
48317
|
+
ensureReady: async () => {
|
|
48318
|
+
const activeEndpoint = await ensureSessionHostReady2();
|
|
48319
|
+
this.sessionHostEndpoint = activeEndpoint;
|
|
48320
|
+
},
|
|
46854
48321
|
clientId: `daemon_${config2.machineId}`,
|
|
46855
48322
|
runtimeId,
|
|
46856
48323
|
providerType,
|
|
@@ -47446,8 +48913,8 @@ async function startDaemonFlow() {
|
|
|
47446
48913
|
const daemon = new AdhdevDaemon2();
|
|
47447
48914
|
const { execSync: execSync7 } = await import("child_process");
|
|
47448
48915
|
const os23 = await import("os");
|
|
47449
|
-
const
|
|
47450
|
-
const logPath =
|
|
48916
|
+
const path23 = await import("path");
|
|
48917
|
+
const logPath = path23.join(os23.homedir(), ".adhdev", "daemon.log");
|
|
47451
48918
|
const platform11 = os23.platform();
|
|
47452
48919
|
try {
|
|
47453
48920
|
if (platform11 === "win32") {
|
|
@@ -48437,35 +49904,35 @@ function registerProviderCommands(program2) {
|
|
|
48437
49904
|
let osPaths = {};
|
|
48438
49905
|
let processNames = {};
|
|
48439
49906
|
if (category === "ide") {
|
|
48440
|
-
const
|
|
48441
|
-
const
|
|
49907
|
+
const fs19 = await import("fs");
|
|
49908
|
+
const path23 = await import("path");
|
|
48442
49909
|
const os23 = await import("os");
|
|
48443
49910
|
if (os23.platform() === "darwin") {
|
|
48444
49911
|
while (true) {
|
|
48445
49912
|
const p = (await rl.question(`macOS Application Path (e.g. /Applications/${defaultName}.app): `)).trim() || `/Applications/${defaultName}.app`;
|
|
48446
49913
|
if (p === "skip") break;
|
|
48447
|
-
if (!
|
|
49914
|
+
if (!fs19.existsSync(p)) {
|
|
48448
49915
|
console.log(import_chalk6.default.red(` \u2717 Path not found: ${p}`));
|
|
48449
49916
|
console.log(import_chalk6.default.gray(` (Please provide the exact absolute path to the .app or binary, or type 'skip')`));
|
|
48450
49917
|
continue;
|
|
48451
49918
|
}
|
|
48452
49919
|
console.log(import_chalk6.default.green(` \u2713 Path verified: ${p}`));
|
|
48453
49920
|
osPaths["darwin"] = [p];
|
|
48454
|
-
processNames["darwin"] =
|
|
49921
|
+
processNames["darwin"] = path23.basename(p, ".app");
|
|
48455
49922
|
break;
|
|
48456
49923
|
}
|
|
48457
49924
|
} else if (os23.platform() === "win32") {
|
|
48458
49925
|
while (true) {
|
|
48459
49926
|
const p = (await rl.question(`Windows Executable Path (e.g. C:\\Program Files\\${defaultName}\\${defaultName}.exe): `)).trim();
|
|
48460
49927
|
if (!p || p === "skip") break;
|
|
48461
|
-
if (!
|
|
49928
|
+
if (!fs19.existsSync(p)) {
|
|
48462
49929
|
console.log(import_chalk6.default.red(` \u2717 Path not found: ${p}`));
|
|
48463
49930
|
console.log(import_chalk6.default.gray(` (Please provide the exact absolute path, or type 'skip')`));
|
|
48464
49931
|
continue;
|
|
48465
49932
|
}
|
|
48466
49933
|
console.log(import_chalk6.default.green(` \u2713 Path verified: ${p}`));
|
|
48467
49934
|
osPaths["win32"] = [p];
|
|
48468
|
-
processNames["win32"] =
|
|
49935
|
+
processNames["win32"] = path23.basename(p, ".exe");
|
|
48469
49936
|
break;
|
|
48470
49937
|
}
|
|
48471
49938
|
}
|
|
@@ -49141,8 +50608,8 @@ function registerCdpCommands(program2) {
|
|
|
49141
50608
|
}
|
|
49142
50609
|
const output = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
49143
50610
|
if (options.output) {
|
|
49144
|
-
const
|
|
49145
|
-
|
|
50611
|
+
const fs19 = await import("fs");
|
|
50612
|
+
fs19.writeFileSync(options.output, output, "utf-8");
|
|
49146
50613
|
console.log(import_chalk6.default.green(`
|
|
49147
50614
|
\u2713 Saved to ${options.output} (${output.length} chars)
|
|
49148
50615
|
`));
|
|
@@ -49245,8 +50712,8 @@ function registerCdpCommands(program2) {
|
|
|
49245
50712
|
ws2.on("message", async (data) => {
|
|
49246
50713
|
const msg = JSON.parse(data.toString());
|
|
49247
50714
|
if (msg.id === 1 && msg.result?.data) {
|
|
49248
|
-
const
|
|
49249
|
-
|
|
50715
|
+
const fs19 = await import("fs");
|
|
50716
|
+
fs19.writeFileSync(options.output, Buffer.from(msg.result.data, "base64"));
|
|
49250
50717
|
console.log(import_chalk6.default.green(`
|
|
49251
50718
|
\u2713 Screenshot saved to ${options.output}
|
|
49252
50719
|
`));
|