adhdev 0.7.46 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1924 -420
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1960 -416
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/session-host-daemon/index.js +14 -3
- package/vendor/session-host-daemon/index.js.map +1 -1
- package/vendor/session-host-daemon/index.mjs +14 -3
- package/vendor/session-host-daemon/index.mjs.map +1 -1
package/dist/index.js
CHANGED
|
@@ -569,18 +569,18 @@ function checkPathExists(paths) {
|
|
|
569
569
|
return null;
|
|
570
570
|
}
|
|
571
571
|
async function detectIDEs() {
|
|
572
|
-
const
|
|
572
|
+
const os22 = (0, import_os2.platform)();
|
|
573
573
|
const results = [];
|
|
574
574
|
for (const def of getMergedDefinitions()) {
|
|
575
575
|
const cliPath = findCliCommand(def.cli);
|
|
576
|
-
const appPath = checkPathExists(def.paths[
|
|
576
|
+
const appPath = checkPathExists(def.paths[os22] || []);
|
|
577
577
|
const installed = !!(cliPath || appPath);
|
|
578
578
|
let resolvedCli = cliPath;
|
|
579
|
-
if (!resolvedCli && appPath &&
|
|
579
|
+
if (!resolvedCli && appPath && os22 === "darwin") {
|
|
580
580
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
581
581
|
if ((0, import_fs2.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
582
582
|
}
|
|
583
|
-
if (!resolvedCli && appPath &&
|
|
583
|
+
if (!resolvedCli && appPath && os22 === "win32") {
|
|
584
584
|
const { dirname: dirname9 } = await import("path");
|
|
585
585
|
const appDir = dirname9(appPath);
|
|
586
586
|
const candidates = [
|
|
@@ -2687,6 +2687,7 @@ var init_chat_history = __esm({
|
|
|
2687
2687
|
role: msg.role,
|
|
2688
2688
|
content: msg.content || "",
|
|
2689
2689
|
kind: typeof msg.kind === "string" ? msg.kind : void 0,
|
|
2690
|
+
senderName: typeof msg.senderName === "string" ? msg.senderName : void 0,
|
|
2690
2691
|
agent: agentType,
|
|
2691
2692
|
instanceId,
|
|
2692
2693
|
historySessionId: effectiveHistoryKey,
|
|
@@ -2725,6 +2726,7 @@ var init_chat_history = __esm({
|
|
|
2725
2726
|
kind: "system",
|
|
2726
2727
|
content,
|
|
2727
2728
|
receivedAt: options.receivedAt,
|
|
2729
|
+
senderName: options.senderName,
|
|
2728
2730
|
historyDedupKey: options.dedupKey
|
|
2729
2731
|
}],
|
|
2730
2732
|
options.sessionTitle,
|
|
@@ -3847,6 +3849,12 @@ function getCurrentManagerKey(h) {
|
|
|
3847
3849
|
function getTargetedCliAdapter(h, args, providerType) {
|
|
3848
3850
|
return h.getCliAdapter(args?.targetSessionId || providerType || h.currentSession?.providerType || h.currentManagerKey);
|
|
3849
3851
|
}
|
|
3852
|
+
function getTargetInstance(h, args) {
|
|
3853
|
+
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
3854
|
+
const sessionId = targetSessionId || h.currentSession?.sessionId || "";
|
|
3855
|
+
if (!sessionId) return null;
|
|
3856
|
+
return h.ctx.instanceManager?.getInstance(sessionId);
|
|
3857
|
+
}
|
|
3850
3858
|
function getTargetTransport(h, provider) {
|
|
3851
3859
|
if (h.currentSession?.transport) return h.currentSession.transport;
|
|
3852
3860
|
switch (provider?.category) {
|
|
@@ -4589,6 +4597,7 @@ async function handleResolveAction(h, args) {
|
|
|
4589
4597
|
adapter.writeRaw?.(keys);
|
|
4590
4598
|
}
|
|
4591
4599
|
LOG.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
|
|
4600
|
+
getTargetInstance(h, args)?.recordApprovalSelection?.(buttons[buttonIndex] ?? button);
|
|
4592
4601
|
return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
|
|
4593
4602
|
}
|
|
4594
4603
|
if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
|
|
@@ -15163,10 +15172,10 @@ __export(provider_cli_adapter_exports, {
|
|
|
15163
15172
|
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
15164
15173
|
});
|
|
15165
15174
|
function stripAnsi(str) {
|
|
15166
|
-
return str.replace(/\x1B\[
|
|
15175
|
+
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, " ");
|
|
15167
15176
|
}
|
|
15168
15177
|
function stripTerminalNoise(str) {
|
|
15169
|
-
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, " ");
|
|
15178
|
+
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, " ");
|
|
15170
15179
|
}
|
|
15171
15180
|
function sanitizeTerminalText(str) {
|
|
15172
15181
|
return stripTerminalNoise(stripAnsi(str));
|
|
@@ -15209,12 +15218,12 @@ function findBinary(name) {
|
|
|
15209
15218
|
function isScriptBinary(binaryPath) {
|
|
15210
15219
|
if (!path7.isAbsolute(binaryPath)) return false;
|
|
15211
15220
|
try {
|
|
15212
|
-
const
|
|
15213
|
-
const resolved =
|
|
15221
|
+
const fs18 = require("fs");
|
|
15222
|
+
const resolved = fs18.realpathSync(binaryPath);
|
|
15214
15223
|
const head = Buffer.alloc(8);
|
|
15215
|
-
const fd =
|
|
15216
|
-
|
|
15217
|
-
|
|
15224
|
+
const fd = fs18.openSync(resolved, "r");
|
|
15225
|
+
fs18.readSync(fd, head, 0, 8, 0);
|
|
15226
|
+
fs18.closeSync(fd);
|
|
15218
15227
|
let i = 0;
|
|
15219
15228
|
if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
|
|
15220
15229
|
return head[i] === 35 && head[i + 1] === 33;
|
|
@@ -15225,12 +15234,12 @@ function isScriptBinary(binaryPath) {
|
|
|
15225
15234
|
function looksLikeMachOOrElf(filePath) {
|
|
15226
15235
|
if (!path7.isAbsolute(filePath)) return false;
|
|
15227
15236
|
try {
|
|
15228
|
-
const
|
|
15229
|
-
const resolved =
|
|
15237
|
+
const fs18 = require("fs");
|
|
15238
|
+
const resolved = fs18.realpathSync(filePath);
|
|
15230
15239
|
const buf = Buffer.alloc(8);
|
|
15231
|
-
const fd =
|
|
15232
|
-
|
|
15233
|
-
|
|
15240
|
+
const fd = fs18.openSync(resolved, "r");
|
|
15241
|
+
fs18.readSync(fd, buf, 0, 8, 0);
|
|
15242
|
+
fs18.closeSync(fd);
|
|
15234
15243
|
let i = 0;
|
|
15235
15244
|
if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
|
|
15236
15245
|
const b2 = buf.subarray(i);
|
|
@@ -15283,6 +15292,9 @@ function promptLikelyVisible(screenText, promptSnippet) {
|
|
|
15283
15292
|
).length;
|
|
15284
15293
|
return matched >= required2;
|
|
15285
15294
|
}
|
|
15295
|
+
function normalizeScreenSnapshot(text) {
|
|
15296
|
+
return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
|
|
15297
|
+
}
|
|
15286
15298
|
function parsePatternEntry(x) {
|
|
15287
15299
|
if (x instanceof RegExp) return x;
|
|
15288
15300
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -15321,14 +15333,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
15321
15333
|
pty2 = require("node-pty");
|
|
15322
15334
|
if (os9.platform() !== "win32") {
|
|
15323
15335
|
try {
|
|
15324
|
-
const
|
|
15336
|
+
const fs18 = require("fs");
|
|
15325
15337
|
const ptyDir = path7.resolve(path7.dirname(require.resolve("node-pty")), "..");
|
|
15326
15338
|
const platformArch = `${os9.platform()}-${os9.arch()}`;
|
|
15327
15339
|
const helper = path7.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
|
|
15328
|
-
if (
|
|
15329
|
-
const stat4 =
|
|
15340
|
+
if (fs18.existsSync(helper)) {
|
|
15341
|
+
const stat4 = fs18.statSync(helper);
|
|
15330
15342
|
if (!(stat4.mode & 73)) {
|
|
15331
|
-
|
|
15343
|
+
fs18.chmodSync(helper, stat4.mode | 493);
|
|
15332
15344
|
LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
|
|
15333
15345
|
}
|
|
15334
15346
|
}
|
|
@@ -15362,10 +15374,25 @@ var init_provider_cli_adapter = __esm({
|
|
|
15362
15374
|
this.sendDelayMs = typeof provider.sendDelayMs === "number" ? Math.max(0, provider.sendDelayMs) : 0;
|
|
15363
15375
|
this.sendKey = typeof provider.sendKey === "string" && provider.sendKey.length > 0 ? provider.sendKey : "\r";
|
|
15364
15376
|
this.submitStrategy = provider.submitStrategy === "immediate" ? "immediate" : "wait_for_echo";
|
|
15377
|
+
this.providerResolutionMeta = {
|
|
15378
|
+
type: provider.type,
|
|
15379
|
+
name: provider.name,
|
|
15380
|
+
resolvedVersion: provider._resolvedVersion || null,
|
|
15381
|
+
resolvedOs: provider._resolvedOs || null,
|
|
15382
|
+
providerDir: provider._resolvedProviderDir || null,
|
|
15383
|
+
scriptDir: provider._resolvedScriptDir || null,
|
|
15384
|
+
scriptsPath: provider._resolvedScriptsPath || null,
|
|
15385
|
+
scriptsSource: provider._resolvedScriptsSource || null,
|
|
15386
|
+
versionWarning: provider._versionWarning || null
|
|
15387
|
+
};
|
|
15365
15388
|
this.cliScripts = provider.scripts || {};
|
|
15366
15389
|
const scriptNames = Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function");
|
|
15367
15390
|
if (scriptNames.length > 0) {
|
|
15368
15391
|
LOG.info("CLI", `[${this.cliType}] CLI scripts: [${scriptNames.join(", ")}]`);
|
|
15392
|
+
LOG.info(
|
|
15393
|
+
"CLI",
|
|
15394
|
+
`[${this.cliType}] Provider resolution: providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"} source=${this.providerResolutionMeta.scriptsSource || "-"} version=${this.providerResolutionMeta.resolvedVersion || "-"}`
|
|
15395
|
+
);
|
|
15369
15396
|
} else {
|
|
15370
15397
|
LOG.warn("CLI", `[${this.cliType}] \u26A0 No CLI scripts loaded! Provider needs scripts/{version}/scripts.js`);
|
|
15371
15398
|
}
|
|
@@ -15398,6 +15425,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
15398
15425
|
ptyOutputBuffer = "";
|
|
15399
15426
|
ptyOutputFlushTimer = null;
|
|
15400
15427
|
pendingTerminalQueryTail = "";
|
|
15428
|
+
lastOutputAt = 0;
|
|
15429
|
+
lastNonEmptyOutputAt = 0;
|
|
15430
|
+
lastScreenChangeAt = 0;
|
|
15431
|
+
lastScreenSnapshot = "";
|
|
15401
15432
|
// Server log forwarding
|
|
15402
15433
|
serverConn = null;
|
|
15403
15434
|
logBuffer = [];
|
|
@@ -15418,6 +15449,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15418
15449
|
submitRetryTimer = null;
|
|
15419
15450
|
submitRetryUsed = false;
|
|
15420
15451
|
submitRetryPromptSnippet = "";
|
|
15452
|
+
idleFinishCandidate = null;
|
|
15421
15453
|
// Resize redraw suppression
|
|
15422
15454
|
resizeSuppressUntil = 0;
|
|
15423
15455
|
// Debug: status transition history
|
|
@@ -15433,6 +15465,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
15433
15465
|
/** Max accumulated buffer size (last 50KB) */
|
|
15434
15466
|
static MAX_ACCUMULATED_BUFFER = 5e4;
|
|
15435
15467
|
currentTurnScope = null;
|
|
15468
|
+
traceEntries = [];
|
|
15469
|
+
traceSeq = 0;
|
|
15470
|
+
traceSessionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
15471
|
+
static MAX_TRACE_ENTRIES = 250;
|
|
15472
|
+
providerResolutionMeta;
|
|
15473
|
+
static IDLE_FINISH_CONFIRM_MS = 900;
|
|
15436
15474
|
syncMessageViews() {
|
|
15437
15475
|
this.messages = [...this.committedMessages];
|
|
15438
15476
|
this.structuredMessages = [...this.committedMessages];
|
|
@@ -15468,8 +15506,89 @@ var init_provider_cli_adapter = __esm({
|
|
|
15468
15506
|
this.currentStatus = status;
|
|
15469
15507
|
this.statusHistory.push({ status, at: Date.now(), trigger });
|
|
15470
15508
|
if (this.statusHistory.length > 50) this.statusHistory.shift();
|
|
15509
|
+
this.recordTrace("status", {
|
|
15510
|
+
previousStatus: prev,
|
|
15511
|
+
trigger: trigger || null
|
|
15512
|
+
});
|
|
15471
15513
|
LOG.info("CLI", `[${this.cliType}] status: ${prev} \u2192 ${status}${trigger ? ` (${trigger})` : ""}`);
|
|
15472
15514
|
}
|
|
15515
|
+
clearIdleFinishCandidate(reason) {
|
|
15516
|
+
if (!this.idleFinishCandidate) return;
|
|
15517
|
+
this.recordTrace("idle_candidate_reset", {
|
|
15518
|
+
reason,
|
|
15519
|
+
candidate: this.idleFinishCandidate
|
|
15520
|
+
});
|
|
15521
|
+
this.idleFinishCandidate = null;
|
|
15522
|
+
}
|
|
15523
|
+
armIdleFinishCandidate(assistantLength) {
|
|
15524
|
+
const now = Date.now();
|
|
15525
|
+
this.idleFinishCandidate = {
|
|
15526
|
+
armedAt: now,
|
|
15527
|
+
lastOutputAt: this.lastOutputAt,
|
|
15528
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
15529
|
+
responseEpoch: this.responseEpoch,
|
|
15530
|
+
assistantLength
|
|
15531
|
+
};
|
|
15532
|
+
this.recordTrace("idle_candidate_armed", {
|
|
15533
|
+
confirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
|
|
15534
|
+
candidate: this.idleFinishCandidate,
|
|
15535
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
15536
|
+
});
|
|
15537
|
+
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
15538
|
+
this.settleTimer = setTimeout(() => {
|
|
15539
|
+
this.settleTimer = null;
|
|
15540
|
+
this.settledBuffer = this.recentOutputBuffer;
|
|
15541
|
+
this.evaluateSettled();
|
|
15542
|
+
}, _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS);
|
|
15543
|
+
}
|
|
15544
|
+
summarizeTraceText(text, max = 800) {
|
|
15545
|
+
const value = sanitizeTerminalText(String(text || ""));
|
|
15546
|
+
if (value.length <= max) return value;
|
|
15547
|
+
return `\u2026${value.slice(-max)}`;
|
|
15548
|
+
}
|
|
15549
|
+
summarizeTraceMessages(messages, limit = 3) {
|
|
15550
|
+
return messages.slice(-limit).map((message) => ({
|
|
15551
|
+
role: message.role,
|
|
15552
|
+
content: this.summarizeTraceText(message.content, 240),
|
|
15553
|
+
timestamp: message.timestamp
|
|
15554
|
+
}));
|
|
15555
|
+
}
|
|
15556
|
+
buildTraceParseSnapshot(scope, partialResponse = "") {
|
|
15557
|
+
const scopedBuffer = scope ? this.sliceFromOffset(this.accumulatedBuffer, scope.bufferStart) || this.accumulatedBuffer : this.accumulatedBuffer;
|
|
15558
|
+
const scopedRawBuffer = scope ? this.sliceFromOffset(this.accumulatedRawBuffer, scope.rawBufferStart) || this.accumulatedRawBuffer : this.accumulatedRawBuffer;
|
|
15559
|
+
return {
|
|
15560
|
+
currentTurnScope: scope || null,
|
|
15561
|
+
responseBuffer: this.summarizeTraceText(this.responseBuffer, 1200),
|
|
15562
|
+
partialResponse: this.summarizeTraceText(partialResponse || this.responseBuffer, 1200),
|
|
15563
|
+
turnBuffer: this.summarizeTraceText(scopedBuffer, 1600),
|
|
15564
|
+
turnRawPreview: this.summarizeTraceText(scopedRawBuffer, 1600),
|
|
15565
|
+
turnSanitizedRawPreview: this.summarizeTraceText(sanitizeTerminalText(scopedRawBuffer), 1600)
|
|
15566
|
+
};
|
|
15567
|
+
}
|
|
15568
|
+
recordTrace(type, payload = {}) {
|
|
15569
|
+
const entry = {
|
|
15570
|
+
id: ++this.traceSeq,
|
|
15571
|
+
at: Date.now(),
|
|
15572
|
+
type,
|
|
15573
|
+
status: this.currentStatus,
|
|
15574
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
15575
|
+
activeModal: this.activeModal ? { message: this.activeModal.message, buttons: [...this.activeModal.buttons] } : null,
|
|
15576
|
+
payload
|
|
15577
|
+
};
|
|
15578
|
+
this.traceEntries.push(entry);
|
|
15579
|
+
if (this.traceEntries.length > _ProviderCliAdapter.MAX_TRACE_ENTRIES) {
|
|
15580
|
+
this.traceEntries.splice(0, this.traceEntries.length - _ProviderCliAdapter.MAX_TRACE_ENTRIES);
|
|
15581
|
+
}
|
|
15582
|
+
}
|
|
15583
|
+
resetTraceSession() {
|
|
15584
|
+
this.traceEntries = [];
|
|
15585
|
+
this.traceSeq = 0;
|
|
15586
|
+
this.traceSessionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
15587
|
+
this.recordTrace("session_start", {
|
|
15588
|
+
providerType: this.cliType,
|
|
15589
|
+
workingDir: this.workingDir
|
|
15590
|
+
});
|
|
15591
|
+
}
|
|
15473
15592
|
// Resolved timeouts
|
|
15474
15593
|
timeouts;
|
|
15475
15594
|
// Provider approval key mapping
|
|
@@ -15515,6 +15634,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15515
15634
|
const isWin = os9.platform() === "win32";
|
|
15516
15635
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
15517
15636
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
15637
|
+
this.resetTraceSession();
|
|
15518
15638
|
let shellCmd;
|
|
15519
15639
|
let shellArgs;
|
|
15520
15640
|
const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
@@ -15540,6 +15660,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
15540
15660
|
cwd: this.workingDir,
|
|
15541
15661
|
env: buildCliSpawnEnv(process.env, spawnConfig.env)
|
|
15542
15662
|
};
|
|
15663
|
+
this.recordTrace("spawn", {
|
|
15664
|
+
shellCommand: shellCmd,
|
|
15665
|
+
shellArgs,
|
|
15666
|
+
cwd: ptyOpts.cwd,
|
|
15667
|
+
cols: ptyOpts.cols,
|
|
15668
|
+
rows: ptyOpts.rows,
|
|
15669
|
+
providerResolution: this.providerResolutionMeta
|
|
15670
|
+
});
|
|
15543
15671
|
try {
|
|
15544
15672
|
this.ptyProcess = this.transportFactory.spawn(shellCmd, shellArgs, ptyOpts);
|
|
15545
15673
|
} catch (err) {
|
|
@@ -15582,6 +15710,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15582
15710
|
this.ptyProcess.onExit(({ exitCode }) => {
|
|
15583
15711
|
LOG.info("CLI", `[${this.cliType}] Exit code ${exitCode}`);
|
|
15584
15712
|
this.flushPendingOutputParse();
|
|
15713
|
+
this.recordTrace("exit", { exitCode });
|
|
15585
15714
|
this.ptyProcess = null;
|
|
15586
15715
|
this.setStatus("stopped", "pty_exit");
|
|
15587
15716
|
this.ready = false;
|
|
@@ -15597,6 +15726,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
15597
15726
|
this.currentTurnScope = null;
|
|
15598
15727
|
this.ready = false;
|
|
15599
15728
|
await this.ptyProcess.ready;
|
|
15729
|
+
this.recordTrace("ready", {
|
|
15730
|
+
runtimeMeta: this.getRuntimeMetadata()
|
|
15731
|
+
});
|
|
15600
15732
|
this.setStatus("idle", "pty_ready");
|
|
15601
15733
|
this.onStatusChange?.();
|
|
15602
15734
|
}
|
|
@@ -15604,6 +15736,24 @@ var init_provider_cli_adapter = __esm({
|
|
|
15604
15736
|
handleOutput(rawData) {
|
|
15605
15737
|
this.terminalScreen.write(rawData);
|
|
15606
15738
|
const cleanData = sanitizeTerminalText(rawData);
|
|
15739
|
+
const now = Date.now();
|
|
15740
|
+
const normalizedScreenSnapshot = normalizeScreenSnapshot(this.terminalScreen.getText());
|
|
15741
|
+
this.lastOutputAt = now;
|
|
15742
|
+
if (cleanData.trim()) this.lastNonEmptyOutputAt = now;
|
|
15743
|
+
if (normalizedScreenSnapshot !== this.lastScreenSnapshot) {
|
|
15744
|
+
this.lastScreenSnapshot = normalizedScreenSnapshot;
|
|
15745
|
+
this.lastScreenChangeAt = now;
|
|
15746
|
+
}
|
|
15747
|
+
if (this.idleFinishCandidate && (rawData.length > 0 || cleanData.length > 0)) {
|
|
15748
|
+
this.clearIdleFinishCandidate("new_output");
|
|
15749
|
+
}
|
|
15750
|
+
this.recordTrace("output", {
|
|
15751
|
+
rawLength: rawData.length,
|
|
15752
|
+
cleanLength: cleanData.length,
|
|
15753
|
+
rawPreview: this.summarizeTraceText(rawData, 300),
|
|
15754
|
+
cleanPreview: this.summarizeTraceText(cleanData, 300),
|
|
15755
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 1200)
|
|
15756
|
+
});
|
|
15607
15757
|
if (this.isWaitingForResponse && cleanData) {
|
|
15608
15758
|
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
|
|
15609
15759
|
}
|
|
@@ -15621,11 +15771,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
15621
15771
|
this.startupBuffer += cleanData;
|
|
15622
15772
|
const elapsed = Date.now() - this.spawnAt;
|
|
15623
15773
|
const scriptStatus = this.runDetectStatus(this.startupBuffer);
|
|
15624
|
-
const
|
|
15774
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
15775
|
+
const hasInteractivePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
15776
|
+
const startupStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
15777
|
+
const isReady = (scriptStatus === "idle" || scriptStatus === "waiting_approval") && hasInteractivePrompt && startupStableMs >= 700 || elapsed > 8e3 || this.startupBuffer.length > 12e3;
|
|
15625
15778
|
if (isReady) {
|
|
15626
15779
|
this.startupParseGate = false;
|
|
15627
15780
|
this.ready = true;
|
|
15628
|
-
LOG.info(
|
|
15781
|
+
LOG.info(
|
|
15782
|
+
"CLI",
|
|
15783
|
+
`[${this.cliType}] Startup ready (${elapsed}ms, scriptStatus=${scriptStatus}, prompt=${hasInteractivePrompt}, stableMs=${startupStableMs}) providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
15784
|
+
);
|
|
15629
15785
|
this.onStatusChange?.();
|
|
15630
15786
|
}
|
|
15631
15787
|
}
|
|
@@ -15670,6 +15826,41 @@ var init_provider_cli_adapter = __esm({
|
|
|
15670
15826
|
if (!text.trim()) return false;
|
|
15671
15827
|
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);
|
|
15672
15828
|
}
|
|
15829
|
+
async waitForInteractivePrompt(maxWaitMs = 5e3) {
|
|
15830
|
+
const startedAt = Date.now();
|
|
15831
|
+
let loggedWait = false;
|
|
15832
|
+
while (Date.now() - startedAt < maxWaitMs) {
|
|
15833
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
15834
|
+
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
15835
|
+
const stableMs = this.lastScreenChangeAt ? Date.now() - this.lastScreenChangeAt : 0;
|
|
15836
|
+
const recentlyOutput = this.lastNonEmptyOutputAt ? Date.now() - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
15837
|
+
const status = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
|
|
15838
|
+
const startupLikelyActive = /Welcome back|Tips for getting|Recent activity|Claude Code v\d/i.test(screenText);
|
|
15839
|
+
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "starting" && status !== "generating";
|
|
15840
|
+
if (interactiveReady) {
|
|
15841
|
+
if (loggedWait) {
|
|
15842
|
+
LOG.info(
|
|
15843
|
+
"CLI",
|
|
15844
|
+
`[${this.cliType}] Interactive prompt ready after ${Date.now() - startedAt}ms (stableMs=${stableMs}, recentOutputMs=${recentlyOutput}, startup=${startupLikelyActive})`
|
|
15845
|
+
);
|
|
15846
|
+
}
|
|
15847
|
+
return;
|
|
15848
|
+
}
|
|
15849
|
+
if (!loggedWait && Date.now() - startedAt >= 400) {
|
|
15850
|
+
loggedWait = true;
|
|
15851
|
+
LOG.info(
|
|
15852
|
+
"CLI",
|
|
15853
|
+
`[${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)}`
|
|
15854
|
+
);
|
|
15855
|
+
}
|
|
15856
|
+
await new Promise((resolve13) => setTimeout(resolve13, 50));
|
|
15857
|
+
}
|
|
15858
|
+
const finalScreenText = this.terminalScreen.getText() || "";
|
|
15859
|
+
LOG.warn(
|
|
15860
|
+
"CLI",
|
|
15861
|
+
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(this.summarizeTraceText(finalScreenText, 240)).slice(0, 280)}`
|
|
15862
|
+
);
|
|
15863
|
+
}
|
|
15673
15864
|
evaluateSettled() {
|
|
15674
15865
|
const now = Date.now();
|
|
15675
15866
|
if (this.submitPendingUntil > now || this.responseSettleIgnoreUntil > now) {
|
|
@@ -15687,6 +15878,30 @@ var init_provider_cli_adapter = __esm({
|
|
|
15687
15878
|
const modal = this.runParseApproval(tail);
|
|
15688
15879
|
const rawScriptStatus = this.runDetectStatus(tail);
|
|
15689
15880
|
const scriptStatus = rawScriptStatus;
|
|
15881
|
+
const parsedTranscript = this.parseCurrentTranscript(
|
|
15882
|
+
this.committedMessages,
|
|
15883
|
+
this.responseBuffer,
|
|
15884
|
+
this.currentTurnScope
|
|
15885
|
+
);
|
|
15886
|
+
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? this.normalizeParsedMessages(parsedTranscript.messages) : [];
|
|
15887
|
+
const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
|
|
15888
|
+
this.recordTrace("settled", {
|
|
15889
|
+
tail: this.summarizeTraceText(tail, 500),
|
|
15890
|
+
screenText: this.summarizeTraceText(screenText, 1200),
|
|
15891
|
+
detectStatus: scriptStatus,
|
|
15892
|
+
parsedStatus: parsedTranscript?.status || null,
|
|
15893
|
+
parsedMessageCount: parsedMessages.length,
|
|
15894
|
+
parsedLastAssistant: lastParsedAssistant ? this.summarizeTraceText(lastParsedAssistant.content, 280) : "",
|
|
15895
|
+
parsedActiveModal: parsedTranscript?.activeModal ?? null,
|
|
15896
|
+
approval: modal,
|
|
15897
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
15898
|
+
});
|
|
15899
|
+
if (this.currentTurnScope && !lastParsedAssistant) {
|
|
15900
|
+
LOG.info(
|
|
15901
|
+
"CLI",
|
|
15902
|
+
`[${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 || "-"}`
|
|
15903
|
+
);
|
|
15904
|
+
}
|
|
15690
15905
|
if (!scriptStatus) return;
|
|
15691
15906
|
const prevStatus = this.currentStatus;
|
|
15692
15907
|
const clearPendingScriptStatus = () => {
|
|
@@ -15722,6 +15937,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15722
15937
|
clearPendingScriptStatus();
|
|
15723
15938
|
}
|
|
15724
15939
|
if (scriptStatus === "waiting_approval") {
|
|
15940
|
+
this.clearIdleFinishCandidate("waiting_approval");
|
|
15725
15941
|
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
15726
15942
|
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
15727
15943
|
if ((inCooldown || visibleIdlePrompt) && !modal) {
|
|
@@ -15755,6 +15971,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
15755
15971
|
}
|
|
15756
15972
|
}
|
|
15757
15973
|
if (scriptStatus === "generating") {
|
|
15974
|
+
this.clearIdleFinishCandidate("generating");
|
|
15758
15975
|
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
15759
15976
|
const noActiveTurn = !this.currentTurnScope;
|
|
15760
15977
|
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));
|
|
@@ -15791,13 +16008,58 @@ var init_provider_cli_adapter = __esm({
|
|
|
15791
16008
|
this.lastApprovalResolvedAt = Date.now();
|
|
15792
16009
|
}
|
|
15793
16010
|
if (this.isWaitingForResponse) {
|
|
16011
|
+
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
16012
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
16013
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
16014
|
+
const hasAssistantTurn = !!lastParsedAssistant;
|
|
16015
|
+
const assistantLength = lastParsedAssistant?.content?.length || 0;
|
|
16016
|
+
const idleQuietThresholdMs = Math.max(220, this.timeouts.outputSettle);
|
|
16017
|
+
const idleStableThresholdMs = Math.max(120, Math.min(220, this.timeouts.outputSettle));
|
|
16018
|
+
const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
|
|
16019
|
+
const candidate = this.idleFinishCandidate;
|
|
16020
|
+
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;
|
|
16021
|
+
const canFinishImmediately = idleReady && candidateQuiet;
|
|
16022
|
+
this.recordTrace("idle_decision", {
|
|
16023
|
+
visibleIdlePrompt,
|
|
16024
|
+
quietForMs,
|
|
16025
|
+
screenStableMs,
|
|
16026
|
+
hasAssistantTurn,
|
|
16027
|
+
assistantLength,
|
|
16028
|
+
hasModal: !!modal,
|
|
16029
|
+
idleQuietThresholdMs,
|
|
16030
|
+
idleStableThresholdMs,
|
|
16031
|
+
idleReady,
|
|
16032
|
+
idleFinishConfirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
|
|
16033
|
+
idleFinishCandidate: candidate,
|
|
16034
|
+
candidateQuiet,
|
|
16035
|
+
canFinishImmediately,
|
|
16036
|
+
submitPendingUntil: this.submitPendingUntil,
|
|
16037
|
+
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
16038
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
16039
|
+
});
|
|
16040
|
+
if (canFinishImmediately) {
|
|
16041
|
+
this.clearIdleFinishCandidate("finish_response");
|
|
16042
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
16043
|
+
this.finishResponse();
|
|
16044
|
+
return;
|
|
16045
|
+
}
|
|
16046
|
+
if (idleReady) {
|
|
16047
|
+
if (!candidate) {
|
|
16048
|
+
this.armIdleFinishCandidate(assistantLength);
|
|
16049
|
+
return;
|
|
16050
|
+
}
|
|
16051
|
+
} else {
|
|
16052
|
+
this.clearIdleFinishCandidate("idle_not_ready");
|
|
16053
|
+
}
|
|
15794
16054
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
15795
16055
|
this.idleTimeout = setTimeout(() => {
|
|
15796
16056
|
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
16057
|
+
this.clearIdleFinishCandidate("idle_timeout_finish");
|
|
15797
16058
|
this.finishResponse();
|
|
15798
16059
|
}
|
|
15799
16060
|
}, this.timeouts.idleFinish);
|
|
15800
16061
|
} else if (prevStatus !== "idle") {
|
|
16062
|
+
this.clearIdleFinishCandidate("idle_without_response");
|
|
15801
16063
|
this.setStatus("idle", "script_detect");
|
|
15802
16064
|
this.onStatusChange?.();
|
|
15803
16065
|
}
|
|
@@ -15806,6 +16068,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
15806
16068
|
finishResponse() {
|
|
15807
16069
|
if (this.submitPendingUntil > Date.now()) return;
|
|
15808
16070
|
if (this.responseSettleIgnoreUntil > Date.now()) return;
|
|
16071
|
+
this.clearIdleFinishCandidate("finish_response_enter");
|
|
16072
|
+
this.recordTrace("finish_response", {
|
|
16073
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
16074
|
+
});
|
|
15809
16075
|
this.commitCurrentTranscript();
|
|
15810
16076
|
if (this.responseTimeout) {
|
|
15811
16077
|
clearTimeout(this.responseTimeout);
|
|
@@ -15842,6 +16108,20 @@ var init_provider_cli_adapter = __esm({
|
|
|
15842
16108
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
15843
16109
|
this.committedMessages = this.normalizeParsedMessages(parsed.messages);
|
|
15844
16110
|
this.syncMessageViews();
|
|
16111
|
+
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
16112
|
+
this.recordTrace("commit_transcript", {
|
|
16113
|
+
parsedStatus: parsed.status || null,
|
|
16114
|
+
messageCount: this.committedMessages.length,
|
|
16115
|
+
lastAssistant: lastAssistant ? this.summarizeTraceText(lastAssistant.content, 320) : "",
|
|
16116
|
+
messages: this.summarizeTraceMessages(this.committedMessages),
|
|
16117
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
16118
|
+
});
|
|
16119
|
+
if (!lastAssistant && this.currentTurnScope) {
|
|
16120
|
+
LOG.warn(
|
|
16121
|
+
"CLI",
|
|
16122
|
+
`[${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 || "-"}`
|
|
16123
|
+
);
|
|
16124
|
+
}
|
|
15845
16125
|
}
|
|
15846
16126
|
}
|
|
15847
16127
|
// ─── Script Execution ──────────────────────────
|
|
@@ -15965,16 +16245,23 @@ ${data.message || ""}`.trim();
|
|
|
15965
16245
|
}
|
|
15966
16246
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
15967
16247
|
if (this.isWaitingForResponse) return;
|
|
16248
|
+
await this.waitForInteractivePrompt();
|
|
15968
16249
|
this.committedMessages.push({ role: "user", content: text, timestamp: Date.now() });
|
|
15969
16250
|
this.syncMessageViews();
|
|
15970
16251
|
this.isWaitingForResponse = true;
|
|
15971
16252
|
this.responseBuffer = "";
|
|
16253
|
+
this.clearIdleFinishCandidate("send_message");
|
|
15972
16254
|
this.currentTurnScope = {
|
|
15973
16255
|
prompt: text,
|
|
15974
16256
|
startedAt: Date.now(),
|
|
15975
16257
|
bufferStart: this.accumulatedBuffer.length,
|
|
15976
16258
|
rawBufferStart: this.accumulatedRawBuffer.length
|
|
15977
16259
|
};
|
|
16260
|
+
this.recordTrace("send_message", {
|
|
16261
|
+
text: this.summarizeTraceText(text, 500),
|
|
16262
|
+
estimatedLines: estimatePromptDisplayLines(text),
|
|
16263
|
+
turnScope: this.currentTurnScope
|
|
16264
|
+
});
|
|
15978
16265
|
LOG.info("CLI", `[${this.cliType}] sendMessage turn scope buffer=${this.currentTurnScope.bufferStart} raw=${this.currentTurnScope.rawBufferStart} prompt=${JSON.stringify(text).slice(0, 120)}`);
|
|
15979
16266
|
this.submitRetryUsed = false;
|
|
15980
16267
|
this.submitRetryPromptSnippet = extractPromptRetrySnippet(text);
|
|
@@ -16004,6 +16291,11 @@ ${data.message || ""}`.trim();
|
|
|
16004
16291
|
const submit = () => {
|
|
16005
16292
|
if (!this.ptyProcess) return;
|
|
16006
16293
|
this.submitPendingUntil = 0;
|
|
16294
|
+
this.recordTrace("submit_write", {
|
|
16295
|
+
mode: "submit_key",
|
|
16296
|
+
sendKey: this.sendKey,
|
|
16297
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 500)
|
|
16298
|
+
});
|
|
16007
16299
|
this.ptyProcess.write(this.sendKey);
|
|
16008
16300
|
const retrySubmitIfStuck = (attempt) => {
|
|
16009
16301
|
this.submitRetryTimer = null;
|
|
@@ -16015,6 +16307,12 @@ ${data.message || ""}`.trim();
|
|
|
16015
16307
|
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;
|
|
16016
16308
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
16017
16309
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
16310
|
+
this.recordTrace("submit_write", {
|
|
16311
|
+
mode: "submit_retry",
|
|
16312
|
+
attempt,
|
|
16313
|
+
sendKey: this.sendKey,
|
|
16314
|
+
screenText: this.summarizeTraceText(screenText, 500)
|
|
16315
|
+
});
|
|
16018
16316
|
this.ptyProcess.write(this.sendKey);
|
|
16019
16317
|
if (attempt >= 3) {
|
|
16020
16318
|
this.submitRetryUsed = true;
|
|
@@ -16027,6 +16325,12 @@ ${data.message || ""}`.trim();
|
|
|
16027
16325
|
};
|
|
16028
16326
|
if (this.submitStrategy === "immediate") {
|
|
16029
16327
|
this.submitPendingUntil = 0;
|
|
16328
|
+
this.recordTrace("submit_write", {
|
|
16329
|
+
mode: "immediate",
|
|
16330
|
+
text: this.summarizeTraceText(text, 500),
|
|
16331
|
+
sendKey: this.sendKey,
|
|
16332
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 500)
|
|
16333
|
+
});
|
|
16030
16334
|
this.ptyProcess.write(text + this.sendKey);
|
|
16031
16335
|
this.submitRetryTimer = setTimeout(() => {
|
|
16032
16336
|
this.submitRetryTimer = null;
|
|
@@ -16037,6 +16341,12 @@ ${data.message || ""}`.trim();
|
|
|
16037
16341
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
16038
16342
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
16039
16343
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
16344
|
+
this.recordTrace("submit_write", {
|
|
16345
|
+
mode: "immediate_retry",
|
|
16346
|
+
attempt: 1,
|
|
16347
|
+
sendKey: this.sendKey,
|
|
16348
|
+
screenText: this.summarizeTraceText(screenText, 500)
|
|
16349
|
+
});
|
|
16040
16350
|
this.ptyProcess.write(this.sendKey);
|
|
16041
16351
|
this.submitRetryUsed = true;
|
|
16042
16352
|
}, retryDelayMs);
|
|
@@ -16047,6 +16357,12 @@ ${data.message || ""}`.trim();
|
|
|
16047
16357
|
this.submitPendingUntil = Date.now() + submitDelayMs;
|
|
16048
16358
|
}
|
|
16049
16359
|
this.ptyProcess.write(text);
|
|
16360
|
+
this.recordTrace("submit_write", {
|
|
16361
|
+
mode: "type_then_submit",
|
|
16362
|
+
text: this.summarizeTraceText(text, 500),
|
|
16363
|
+
sendKey: this.sendKey,
|
|
16364
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 500)
|
|
16365
|
+
});
|
|
16050
16366
|
const submitStartedAt = Date.now();
|
|
16051
16367
|
let lastNormalizedScreen = "";
|
|
16052
16368
|
let lastScreenChangeAt = submitStartedAt;
|
|
@@ -16147,6 +16463,7 @@ ${data.message || ""}`.trim();
|
|
|
16147
16463
|
});
|
|
16148
16464
|
}
|
|
16149
16465
|
shutdown() {
|
|
16466
|
+
this.clearIdleFinishCandidate("shutdown");
|
|
16150
16467
|
if (this.settleTimer) {
|
|
16151
16468
|
clearTimeout(this.settleTimer);
|
|
16152
16469
|
this.settleTimer = null;
|
|
@@ -16187,6 +16504,7 @@ ${data.message || ""}`.trim();
|
|
|
16187
16504
|
}
|
|
16188
16505
|
}
|
|
16189
16506
|
detach() {
|
|
16507
|
+
this.clearIdleFinishCandidate("detach");
|
|
16190
16508
|
if (this.settleTimer) {
|
|
16191
16509
|
clearTimeout(this.settleTimer);
|
|
16192
16510
|
this.settleTimer = null;
|
|
@@ -16227,6 +16545,7 @@ ${data.message || ""}`.trim();
|
|
|
16227
16545
|
this.onStatusChange?.();
|
|
16228
16546
|
}
|
|
16229
16547
|
clearHistory() {
|
|
16548
|
+
this.clearIdleFinishCandidate("clear_history");
|
|
16230
16549
|
this.committedMessages = [];
|
|
16231
16550
|
this.syncMessageViews();
|
|
16232
16551
|
this.accumulatedBuffer = "";
|
|
@@ -16256,10 +16575,19 @@ ${data.message || ""}`.trim();
|
|
|
16256
16575
|
return this.ready;
|
|
16257
16576
|
}
|
|
16258
16577
|
writeRaw(data) {
|
|
16578
|
+
this.recordTrace("write_raw", {
|
|
16579
|
+
keys: JSON.stringify(data),
|
|
16580
|
+
length: data.length
|
|
16581
|
+
});
|
|
16259
16582
|
this.ptyProcess?.write(data);
|
|
16260
16583
|
}
|
|
16261
16584
|
resolveModal(buttonIndex) {
|
|
16262
16585
|
if (!this.ptyProcess || this.currentStatus !== "waiting_approval" && !this.activeModal) return;
|
|
16586
|
+
this.clearIdleFinishCandidate("resolve_modal");
|
|
16587
|
+
this.recordTrace("resolve_modal", {
|
|
16588
|
+
buttonIndex,
|
|
16589
|
+
activeModal: this.activeModal
|
|
16590
|
+
});
|
|
16263
16591
|
this.activeModal = null;
|
|
16264
16592
|
this.lastApprovalResolvedAt = Date.now();
|
|
16265
16593
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
@@ -16291,6 +16619,7 @@ ${data.message || ""}`.trim();
|
|
|
16291
16619
|
return {
|
|
16292
16620
|
type: this.cliType,
|
|
16293
16621
|
name: this.cliName,
|
|
16622
|
+
providerResolution: this.providerResolutionMeta,
|
|
16294
16623
|
status: this.currentStatus,
|
|
16295
16624
|
ready: this.ready,
|
|
16296
16625
|
startupParseGate: this.startupParseGate,
|
|
@@ -16310,6 +16639,10 @@ ${data.message || ""}`.trim();
|
|
|
16310
16639
|
rawBufferPreview: this.accumulatedRawBuffer.slice(-1e3),
|
|
16311
16640
|
sanitizedRawPreview: sanitizeTerminalText(this.accumulatedRawBuffer).slice(-1e3),
|
|
16312
16641
|
responseBuffer: this.responseBuffer.slice(-1e3),
|
|
16642
|
+
lastOutputAt: this.lastOutputAt,
|
|
16643
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
16644
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
16645
|
+
lastScreenSnapshot: this.lastScreenSnapshot.slice(-500),
|
|
16313
16646
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
16314
16647
|
activeModal: this.activeModal,
|
|
16315
16648
|
lastApprovalResolvedAt: this.lastApprovalResolvedAt,
|
|
@@ -16321,6 +16654,8 @@ ${data.message || ""}`.trim();
|
|
|
16321
16654
|
resizeSuppressUntil: this.resizeSuppressUntil,
|
|
16322
16655
|
hasCliScripts: this.hasCliScripts(),
|
|
16323
16656
|
scriptNames: Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function"),
|
|
16657
|
+
traceSessionId: this.traceSessionId,
|
|
16658
|
+
traceEntryCount: this.traceEntries.length,
|
|
16324
16659
|
statusHistory: this.statusHistory.slice(-30),
|
|
16325
16660
|
timeouts: this.timeouts,
|
|
16326
16661
|
pendingOutputParseBufferLength: this.pendingOutputParseBuffer.length,
|
|
@@ -16328,6 +16663,25 @@ ${data.message || ""}`.trim();
|
|
|
16328
16663
|
ptyAlive: !!this.ptyProcess
|
|
16329
16664
|
};
|
|
16330
16665
|
}
|
|
16666
|
+
getTraceState(limit = 120) {
|
|
16667
|
+
const cappedLimit = Math.max(1, Math.min(500, Number.isFinite(limit) ? Math.floor(limit) : 120));
|
|
16668
|
+
return {
|
|
16669
|
+
sessionId: this.traceSessionId,
|
|
16670
|
+
providerResolution: this.providerResolutionMeta,
|
|
16671
|
+
entryCount: this.traceEntries.length,
|
|
16672
|
+
entries: this.traceEntries.slice(-cappedLimit),
|
|
16673
|
+
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 4e3),
|
|
16674
|
+
recentOutputBuffer: this.summarizeTraceText(this.recentOutputBuffer, 1e3),
|
|
16675
|
+
responseBuffer: this.summarizeTraceText(this.responseBuffer, 1200),
|
|
16676
|
+
status: this.currentStatus,
|
|
16677
|
+
activeModal: this.activeModal,
|
|
16678
|
+
currentTurnScope: this.currentTurnScope,
|
|
16679
|
+
messages: this.summarizeTraceMessages(this.committedMessages, 5)
|
|
16680
|
+
};
|
|
16681
|
+
}
|
|
16682
|
+
getProviderResolutionMeta() {
|
|
16683
|
+
return { ...this.providerResolutionMeta };
|
|
16684
|
+
}
|
|
16331
16685
|
respondToTerminalQueries(data) {
|
|
16332
16686
|
if (!this.ptyProcess || !data) return;
|
|
16333
16687
|
const combined = this.pendingTerminalQueryTail + data;
|
|
@@ -16399,6 +16753,7 @@ var init_cli_provider_instance = __esm({
|
|
|
16399
16753
|
generatingDebouncePending = null;
|
|
16400
16754
|
lastApprovalEventAt = 0;
|
|
16401
16755
|
historyWriter;
|
|
16756
|
+
runtimeMessages = [];
|
|
16402
16757
|
instanceId;
|
|
16403
16758
|
presentationMode;
|
|
16404
16759
|
providerSessionId;
|
|
@@ -16461,6 +16816,7 @@ var init_cli_provider_instance = __esm({
|
|
|
16461
16816
|
}
|
|
16462
16817
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
16463
16818
|
const parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
|
|
16819
|
+
const mergedMessages = this.mergeConversationMessages(parsedMessages);
|
|
16464
16820
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
16465
16821
|
if (parsedMessages.length > 0) {
|
|
16466
16822
|
let messagesToSave = parsedMessages;
|
|
@@ -16490,7 +16846,7 @@ var init_cli_provider_instance = __esm({
|
|
|
16490
16846
|
id: `${this.type}_${this.workingDir}`,
|
|
16491
16847
|
title: parsedStatus?.title || dirName,
|
|
16492
16848
|
status: parsedStatus?.status || adapterStatus.status,
|
|
16493
|
-
messages:
|
|
16849
|
+
messages: mergedMessages,
|
|
16494
16850
|
activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
|
|
16495
16851
|
inputContent: ""
|
|
16496
16852
|
},
|
|
@@ -16589,6 +16945,11 @@ var init_cli_provider_instance = __esm({
|
|
|
16589
16945
|
const approvalCooldown = 5e3;
|
|
16590
16946
|
if (this.lastStatus !== "waiting_approval" && (!this.lastApprovalEventAt || now - this.lastApprovalEventAt > approvalCooldown)) {
|
|
16591
16947
|
this.lastApprovalEventAt = now;
|
|
16948
|
+
this.appendRuntimeSystemMessage(
|
|
16949
|
+
this.formatApprovalRequestMessage(modal?.message, modal?.buttons),
|
|
16950
|
+
`approval_request:${now}`,
|
|
16951
|
+
now
|
|
16952
|
+
);
|
|
16592
16953
|
this.pushEvent({
|
|
16593
16954
|
event: "agent:waiting_approval",
|
|
16594
16955
|
chatTitle,
|
|
@@ -16660,11 +17021,71 @@ var init_cli_provider_instance = __esm({
|
|
|
16660
17021
|
get cliName() {
|
|
16661
17022
|
return this.provider.name;
|
|
16662
17023
|
}
|
|
17024
|
+
recordApprovalSelection(buttonText) {
|
|
17025
|
+
const cleanButton = String(buttonText || "").trim();
|
|
17026
|
+
if (!cleanButton) return;
|
|
17027
|
+
const now = Date.now();
|
|
17028
|
+
this.appendRuntimeSystemMessage(
|
|
17029
|
+
`Approval selected: ${cleanButton}`,
|
|
17030
|
+
`approval_selection:${now}:${cleanButton}`,
|
|
17031
|
+
now
|
|
17032
|
+
);
|
|
17033
|
+
}
|
|
16663
17034
|
formatMarkerTimestamp(timestamp) {
|
|
16664
17035
|
const date5 = new Date(timestamp);
|
|
16665
17036
|
const pad = (value) => String(value).padStart(2, "0");
|
|
16666
17037
|
return `${date5.getFullYear()}-${pad(date5.getMonth() + 1)}-${pad(date5.getDate())} ${pad(date5.getHours())}:${pad(date5.getMinutes())}:${pad(date5.getSeconds())}`;
|
|
16667
17038
|
}
|
|
17039
|
+
appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
|
|
17040
|
+
const normalizedContent = String(content || "").trim();
|
|
17041
|
+
if (!normalizedContent) return;
|
|
17042
|
+
if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
|
|
17043
|
+
this.runtimeMessages.push({
|
|
17044
|
+
key: dedupKey,
|
|
17045
|
+
message: {
|
|
17046
|
+
role: "system",
|
|
17047
|
+
senderName: "System",
|
|
17048
|
+
content: normalizedContent,
|
|
17049
|
+
receivedAt,
|
|
17050
|
+
timestamp: receivedAt
|
|
17051
|
+
}
|
|
17052
|
+
});
|
|
17053
|
+
if (this.runtimeMessages.length > 50) {
|
|
17054
|
+
this.runtimeMessages = this.runtimeMessages.slice(-50);
|
|
17055
|
+
}
|
|
17056
|
+
this.historyWriter.appendNewMessages(
|
|
17057
|
+
this.type,
|
|
17058
|
+
[{
|
|
17059
|
+
role: "system",
|
|
17060
|
+
senderName: "System",
|
|
17061
|
+
content: normalizedContent,
|
|
17062
|
+
receivedAt,
|
|
17063
|
+
historyDedupKey: dedupKey
|
|
17064
|
+
}],
|
|
17065
|
+
this.adapter.getScriptParsedStatus?.()?.title || this.workingDir.split("/").filter(Boolean).pop() || "session",
|
|
17066
|
+
this.instanceId,
|
|
17067
|
+
this.providerSessionId
|
|
17068
|
+
);
|
|
17069
|
+
}
|
|
17070
|
+
mergeConversationMessages(parsedMessages) {
|
|
17071
|
+
if (this.runtimeMessages.length === 0) return parsedMessages;
|
|
17072
|
+
return [...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
|
|
17073
|
+
const aTime = a.message.receivedAt || a.message.timestamp || 0;
|
|
17074
|
+
const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
|
|
17075
|
+
if (aTime !== bTime) return aTime - bTime;
|
|
17076
|
+
return a.index - b2.index;
|
|
17077
|
+
}).map((entry) => entry.message);
|
|
17078
|
+
}
|
|
17079
|
+
formatApprovalRequestMessage(modalMessage, buttons) {
|
|
17080
|
+
const lines = ["Approval requested"];
|
|
17081
|
+
const cleanMessage = String(modalMessage || "").trim();
|
|
17082
|
+
if (cleanMessage) lines.push(cleanMessage);
|
|
17083
|
+
const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
|
|
17084
|
+
if (labels.length > 0) {
|
|
17085
|
+
lines.push(labels.map((label) => `[${label}]`).join(" "));
|
|
17086
|
+
}
|
|
17087
|
+
return lines.join("\n");
|
|
17088
|
+
}
|
|
16668
17089
|
promoteProviderSessionId(sessionId) {
|
|
16669
17090
|
const nextSessionId = String(sessionId || "").trim();
|
|
16670
17091
|
if (!nextSessionId || nextSessionId === this.providerSessionId) return;
|
|
@@ -17001,10 +17422,10 @@ function mergeDefs(...defs) {
|
|
|
17001
17422
|
function cloneDef(schema) {
|
|
17002
17423
|
return mergeDefs(schema._zod.def);
|
|
17003
17424
|
}
|
|
17004
|
-
function getElementAtPath(obj,
|
|
17005
|
-
if (!
|
|
17425
|
+
function getElementAtPath(obj, path21) {
|
|
17426
|
+
if (!path21)
|
|
17006
17427
|
return obj;
|
|
17007
|
-
return
|
|
17428
|
+
return path21.reduce((acc, key) => acc?.[key], obj);
|
|
17008
17429
|
}
|
|
17009
17430
|
function promiseAllObject(promisesObj) {
|
|
17010
17431
|
const keys = Object.keys(promisesObj);
|
|
@@ -17316,11 +17737,11 @@ function aborted(x, startIndex = 0) {
|
|
|
17316
17737
|
}
|
|
17317
17738
|
return false;
|
|
17318
17739
|
}
|
|
17319
|
-
function prefixIssues(
|
|
17740
|
+
function prefixIssues(path21, issues) {
|
|
17320
17741
|
return issues.map((iss) => {
|
|
17321
17742
|
var _a2;
|
|
17322
17743
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
17323
|
-
iss.path.unshift(
|
|
17744
|
+
iss.path.unshift(path21);
|
|
17324
17745
|
return iss;
|
|
17325
17746
|
});
|
|
17326
17747
|
}
|
|
@@ -17563,7 +17984,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
|
|
|
17563
17984
|
}
|
|
17564
17985
|
function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
17565
17986
|
const result = { errors: [] };
|
|
17566
|
-
const processError = (error49,
|
|
17987
|
+
const processError = (error49, path21 = []) => {
|
|
17567
17988
|
var _a2, _b;
|
|
17568
17989
|
for (const issue2 of error49.issues) {
|
|
17569
17990
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -17573,7 +17994,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
17573
17994
|
} else if (issue2.code === "invalid_element") {
|
|
17574
17995
|
processError({ issues: issue2.issues }, issue2.path);
|
|
17575
17996
|
} else {
|
|
17576
|
-
const fullpath = [...
|
|
17997
|
+
const fullpath = [...path21, ...issue2.path];
|
|
17577
17998
|
if (fullpath.length === 0) {
|
|
17578
17999
|
result.errors.push(mapper(issue2));
|
|
17579
18000
|
continue;
|
|
@@ -17605,8 +18026,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
17605
18026
|
}
|
|
17606
18027
|
function toDotPath(_path) {
|
|
17607
18028
|
const segs = [];
|
|
17608
|
-
const
|
|
17609
|
-
for (const seg of
|
|
18029
|
+
const path21 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
18030
|
+
for (const seg of path21) {
|
|
17610
18031
|
if (typeof seg === "number")
|
|
17611
18032
|
segs.push(`[${seg}]`);
|
|
17612
18033
|
else if (typeof seg === "symbol")
|
|
@@ -30370,13 +30791,13 @@ function resolveRef(ref, ctx) {
|
|
|
30370
30791
|
if (!ref.startsWith("#")) {
|
|
30371
30792
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
30372
30793
|
}
|
|
30373
|
-
const
|
|
30374
|
-
if (
|
|
30794
|
+
const path21 = ref.slice(1).split("/").filter(Boolean);
|
|
30795
|
+
if (path21.length === 0) {
|
|
30375
30796
|
return ctx.rootSchema;
|
|
30376
30797
|
}
|
|
30377
30798
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
30378
|
-
if (
|
|
30379
|
-
const key =
|
|
30799
|
+
if (path21[0] === defsKey) {
|
|
30800
|
+
const key = path21[1];
|
|
30380
30801
|
if (!key || !ctx.defs[key]) {
|
|
30381
30802
|
throw new Error(`Reference not found: ${ref}`);
|
|
30382
30803
|
}
|
|
@@ -34764,7 +35185,7 @@ var init_readdirp = __esm({
|
|
|
34764
35185
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
34765
35186
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
34766
35187
|
if (wantBigintFsStats) {
|
|
34767
|
-
this._stat = (
|
|
35188
|
+
this._stat = (path21) => statMethod(path21, { bigint: true });
|
|
34768
35189
|
} else {
|
|
34769
35190
|
this._stat = statMethod;
|
|
34770
35191
|
}
|
|
@@ -34789,8 +35210,8 @@ var init_readdirp = __esm({
|
|
|
34789
35210
|
const par = this.parent;
|
|
34790
35211
|
const fil = par && par.files;
|
|
34791
35212
|
if (fil && fil.length > 0) {
|
|
34792
|
-
const { path:
|
|
34793
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
35213
|
+
const { path: path21, depth } = par;
|
|
35214
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path21));
|
|
34794
35215
|
const awaited = await Promise.all(slice);
|
|
34795
35216
|
for (const entry of awaited) {
|
|
34796
35217
|
if (!entry)
|
|
@@ -34830,20 +35251,20 @@ var init_readdirp = __esm({
|
|
|
34830
35251
|
this.reading = false;
|
|
34831
35252
|
}
|
|
34832
35253
|
}
|
|
34833
|
-
async _exploreDir(
|
|
35254
|
+
async _exploreDir(path21, depth) {
|
|
34834
35255
|
let files;
|
|
34835
35256
|
try {
|
|
34836
|
-
files = await (0, import_promises.readdir)(
|
|
35257
|
+
files = await (0, import_promises.readdir)(path21, this._rdOptions);
|
|
34837
35258
|
} catch (error48) {
|
|
34838
35259
|
this._onError(error48);
|
|
34839
35260
|
}
|
|
34840
|
-
return { files, depth, path:
|
|
35261
|
+
return { files, depth, path: path21 };
|
|
34841
35262
|
}
|
|
34842
|
-
async _formatEntry(dirent,
|
|
35263
|
+
async _formatEntry(dirent, path21) {
|
|
34843
35264
|
let entry;
|
|
34844
35265
|
const basename7 = this._isDirent ? dirent.name : dirent;
|
|
34845
35266
|
try {
|
|
34846
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
35267
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path21, basename7));
|
|
34847
35268
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename7 };
|
|
34848
35269
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
34849
35270
|
} catch (err) {
|
|
@@ -34900,16 +35321,16 @@ var init_readdirp = __esm({
|
|
|
34900
35321
|
});
|
|
34901
35322
|
|
|
34902
35323
|
// ../../oss/packages/daemon-core/node_modules/chokidar/handler.js
|
|
34903
|
-
function createFsWatchInstance(
|
|
35324
|
+
function createFsWatchInstance(path21, options, listener, errHandler, emitRaw) {
|
|
34904
35325
|
const handleEvent = (rawEvent, evPath) => {
|
|
34905
|
-
listener(
|
|
34906
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
34907
|
-
if (evPath &&
|
|
34908
|
-
fsWatchBroadcast(sp.resolve(
|
|
35326
|
+
listener(path21);
|
|
35327
|
+
emitRaw(rawEvent, evPath, { watchedPath: path21 });
|
|
35328
|
+
if (evPath && path21 !== evPath) {
|
|
35329
|
+
fsWatchBroadcast(sp.resolve(path21, evPath), KEY_LISTENERS, sp.join(path21, evPath));
|
|
34909
35330
|
}
|
|
34910
35331
|
};
|
|
34911
35332
|
try {
|
|
34912
|
-
return (0, import_node_fs.watch)(
|
|
35333
|
+
return (0, import_node_fs.watch)(path21, {
|
|
34913
35334
|
persistent: options.persistent
|
|
34914
35335
|
}, handleEvent);
|
|
34915
35336
|
} catch (error48) {
|
|
@@ -35258,12 +35679,12 @@ var init_handler2 = __esm({
|
|
|
35258
35679
|
listener(val1, val2, val3);
|
|
35259
35680
|
});
|
|
35260
35681
|
};
|
|
35261
|
-
setFsWatchListener = (
|
|
35682
|
+
setFsWatchListener = (path21, fullPath, options, handlers) => {
|
|
35262
35683
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
35263
35684
|
let cont = FsWatchInstances.get(fullPath);
|
|
35264
35685
|
let watcher;
|
|
35265
35686
|
if (!options.persistent) {
|
|
35266
|
-
watcher = createFsWatchInstance(
|
|
35687
|
+
watcher = createFsWatchInstance(path21, options, listener, errHandler, rawEmitter);
|
|
35267
35688
|
if (!watcher)
|
|
35268
35689
|
return;
|
|
35269
35690
|
return watcher.close.bind(watcher);
|
|
@@ -35274,7 +35695,7 @@ var init_handler2 = __esm({
|
|
|
35274
35695
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
35275
35696
|
} else {
|
|
35276
35697
|
watcher = createFsWatchInstance(
|
|
35277
|
-
|
|
35698
|
+
path21,
|
|
35278
35699
|
options,
|
|
35279
35700
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
35280
35701
|
errHandler,
|
|
@@ -35289,7 +35710,7 @@ var init_handler2 = __esm({
|
|
|
35289
35710
|
cont.watcherUnusable = true;
|
|
35290
35711
|
if (isWindows && error48.code === "EPERM") {
|
|
35291
35712
|
try {
|
|
35292
|
-
const fd = await (0, import_promises2.open)(
|
|
35713
|
+
const fd = await (0, import_promises2.open)(path21, "r");
|
|
35293
35714
|
await fd.close();
|
|
35294
35715
|
broadcastErr(error48);
|
|
35295
35716
|
} catch (err) {
|
|
@@ -35320,7 +35741,7 @@ var init_handler2 = __esm({
|
|
|
35320
35741
|
};
|
|
35321
35742
|
};
|
|
35322
35743
|
FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
35323
|
-
setFsWatchFileListener = (
|
|
35744
|
+
setFsWatchFileListener = (path21, fullPath, options, handlers) => {
|
|
35324
35745
|
const { listener, rawEmitter } = handlers;
|
|
35325
35746
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
35326
35747
|
const copts = cont && cont.options;
|
|
@@ -35342,7 +35763,7 @@ var init_handler2 = __esm({
|
|
|
35342
35763
|
});
|
|
35343
35764
|
const currmtime = curr.mtimeMs;
|
|
35344
35765
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
35345
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
35766
|
+
foreach(cont.listeners, (listener2) => listener2(path21, curr));
|
|
35346
35767
|
}
|
|
35347
35768
|
})
|
|
35348
35769
|
};
|
|
@@ -35372,13 +35793,13 @@ var init_handler2 = __esm({
|
|
|
35372
35793
|
* @param listener on fs change
|
|
35373
35794
|
* @returns closer for the watcher instance
|
|
35374
35795
|
*/
|
|
35375
|
-
_watchWithNodeFs(
|
|
35796
|
+
_watchWithNodeFs(path21, listener) {
|
|
35376
35797
|
const opts = this.fsw.options;
|
|
35377
|
-
const directory = sp.dirname(
|
|
35378
|
-
const basename7 = sp.basename(
|
|
35798
|
+
const directory = sp.dirname(path21);
|
|
35799
|
+
const basename7 = sp.basename(path21);
|
|
35379
35800
|
const parent = this.fsw._getWatchedDir(directory);
|
|
35380
35801
|
parent.add(basename7);
|
|
35381
|
-
const absolutePath = sp.resolve(
|
|
35802
|
+
const absolutePath = sp.resolve(path21);
|
|
35382
35803
|
const options = {
|
|
35383
35804
|
persistent: opts.persistent
|
|
35384
35805
|
};
|
|
@@ -35388,12 +35809,12 @@ var init_handler2 = __esm({
|
|
|
35388
35809
|
if (opts.usePolling) {
|
|
35389
35810
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
35390
35811
|
options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
|
|
35391
|
-
closer = setFsWatchFileListener(
|
|
35812
|
+
closer = setFsWatchFileListener(path21, absolutePath, options, {
|
|
35392
35813
|
listener,
|
|
35393
35814
|
rawEmitter: this.fsw._emitRaw
|
|
35394
35815
|
});
|
|
35395
35816
|
} else {
|
|
35396
|
-
closer = setFsWatchListener(
|
|
35817
|
+
closer = setFsWatchListener(path21, absolutePath, options, {
|
|
35397
35818
|
listener,
|
|
35398
35819
|
errHandler: this._boundHandleError,
|
|
35399
35820
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -35415,7 +35836,7 @@ var init_handler2 = __esm({
|
|
|
35415
35836
|
let prevStats = stats;
|
|
35416
35837
|
if (parent.has(basename7))
|
|
35417
35838
|
return;
|
|
35418
|
-
const listener = async (
|
|
35839
|
+
const listener = async (path21, newStats) => {
|
|
35419
35840
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
|
|
35420
35841
|
return;
|
|
35421
35842
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -35429,11 +35850,11 @@ var init_handler2 = __esm({
|
|
|
35429
35850
|
this.fsw._emit(EV.CHANGE, file2, newStats2);
|
|
35430
35851
|
}
|
|
35431
35852
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
35432
|
-
this.fsw._closeFile(
|
|
35853
|
+
this.fsw._closeFile(path21);
|
|
35433
35854
|
prevStats = newStats2;
|
|
35434
35855
|
const closer2 = this._watchWithNodeFs(file2, listener);
|
|
35435
35856
|
if (closer2)
|
|
35436
|
-
this.fsw._addPathCloser(
|
|
35857
|
+
this.fsw._addPathCloser(path21, closer2);
|
|
35437
35858
|
} else {
|
|
35438
35859
|
prevStats = newStats2;
|
|
35439
35860
|
}
|
|
@@ -35465,7 +35886,7 @@ var init_handler2 = __esm({
|
|
|
35465
35886
|
* @param item basename of this item
|
|
35466
35887
|
* @returns true if no more processing is needed for this entry.
|
|
35467
35888
|
*/
|
|
35468
|
-
async _handleSymlink(entry, directory,
|
|
35889
|
+
async _handleSymlink(entry, directory, path21, item) {
|
|
35469
35890
|
if (this.fsw.closed) {
|
|
35470
35891
|
return;
|
|
35471
35892
|
}
|
|
@@ -35475,7 +35896,7 @@ var init_handler2 = __esm({
|
|
|
35475
35896
|
this.fsw._incrReadyCount();
|
|
35476
35897
|
let linkPath;
|
|
35477
35898
|
try {
|
|
35478
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
35899
|
+
linkPath = await (0, import_promises2.realpath)(path21);
|
|
35479
35900
|
} catch (e) {
|
|
35480
35901
|
this.fsw._emitReady();
|
|
35481
35902
|
return true;
|
|
@@ -35485,12 +35906,12 @@ var init_handler2 = __esm({
|
|
|
35485
35906
|
if (dir.has(item)) {
|
|
35486
35907
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
35487
35908
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
35488
|
-
this.fsw._emit(EV.CHANGE,
|
|
35909
|
+
this.fsw._emit(EV.CHANGE, path21, entry.stats);
|
|
35489
35910
|
}
|
|
35490
35911
|
} else {
|
|
35491
35912
|
dir.add(item);
|
|
35492
35913
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
35493
|
-
this.fsw._emit(EV.ADD,
|
|
35914
|
+
this.fsw._emit(EV.ADD, path21, entry.stats);
|
|
35494
35915
|
}
|
|
35495
35916
|
this.fsw._emitReady();
|
|
35496
35917
|
return true;
|
|
@@ -35520,9 +35941,9 @@ var init_handler2 = __esm({
|
|
|
35520
35941
|
return;
|
|
35521
35942
|
}
|
|
35522
35943
|
const item = entry.path;
|
|
35523
|
-
let
|
|
35944
|
+
let path21 = sp.join(directory, item);
|
|
35524
35945
|
current.add(item);
|
|
35525
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
35946
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path21, item)) {
|
|
35526
35947
|
return;
|
|
35527
35948
|
}
|
|
35528
35949
|
if (this.fsw.closed) {
|
|
@@ -35531,8 +35952,8 @@ var init_handler2 = __esm({
|
|
|
35531
35952
|
}
|
|
35532
35953
|
if (item === target || !target && !previous.has(item)) {
|
|
35533
35954
|
this.fsw._incrReadyCount();
|
|
35534
|
-
|
|
35535
|
-
this._addToNodeFs(
|
|
35955
|
+
path21 = sp.join(dir, sp.relative(dir, path21));
|
|
35956
|
+
this._addToNodeFs(path21, initialAdd, wh, depth + 1);
|
|
35536
35957
|
}
|
|
35537
35958
|
}).on(EV.ERROR, this._boundHandleError);
|
|
35538
35959
|
return new Promise((resolve13, reject) => {
|
|
@@ -35601,13 +36022,13 @@ var init_handler2 = __esm({
|
|
|
35601
36022
|
* @param depth Child path actually targeted for watch
|
|
35602
36023
|
* @param target Child path actually targeted for watch
|
|
35603
36024
|
*/
|
|
35604
|
-
async _addToNodeFs(
|
|
36025
|
+
async _addToNodeFs(path21, initialAdd, priorWh, depth, target) {
|
|
35605
36026
|
const ready = this.fsw._emitReady;
|
|
35606
|
-
if (this.fsw._isIgnored(
|
|
36027
|
+
if (this.fsw._isIgnored(path21) || this.fsw.closed) {
|
|
35607
36028
|
ready();
|
|
35608
36029
|
return false;
|
|
35609
36030
|
}
|
|
35610
|
-
const wh = this.fsw._getWatchHelpers(
|
|
36031
|
+
const wh = this.fsw._getWatchHelpers(path21);
|
|
35611
36032
|
if (priorWh) {
|
|
35612
36033
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
35613
36034
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -35623,8 +36044,8 @@ var init_handler2 = __esm({
|
|
|
35623
36044
|
const follow = this.fsw.options.followSymlinks;
|
|
35624
36045
|
let closer;
|
|
35625
36046
|
if (stats.isDirectory()) {
|
|
35626
|
-
const absPath = sp.resolve(
|
|
35627
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
36047
|
+
const absPath = sp.resolve(path21);
|
|
36048
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path21) : path21;
|
|
35628
36049
|
if (this.fsw.closed)
|
|
35629
36050
|
return;
|
|
35630
36051
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -35634,29 +36055,29 @@ var init_handler2 = __esm({
|
|
|
35634
36055
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
35635
36056
|
}
|
|
35636
36057
|
} else if (stats.isSymbolicLink()) {
|
|
35637
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
36058
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path21) : path21;
|
|
35638
36059
|
if (this.fsw.closed)
|
|
35639
36060
|
return;
|
|
35640
36061
|
const parent = sp.dirname(wh.watchPath);
|
|
35641
36062
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
35642
36063
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
35643
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
36064
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path21, wh, targetPath);
|
|
35644
36065
|
if (this.fsw.closed)
|
|
35645
36066
|
return;
|
|
35646
36067
|
if (targetPath !== void 0) {
|
|
35647
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
36068
|
+
this.fsw._symlinkPaths.set(sp.resolve(path21), targetPath);
|
|
35648
36069
|
}
|
|
35649
36070
|
} else {
|
|
35650
36071
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
35651
36072
|
}
|
|
35652
36073
|
ready();
|
|
35653
36074
|
if (closer)
|
|
35654
|
-
this.fsw._addPathCloser(
|
|
36075
|
+
this.fsw._addPathCloser(path21, closer);
|
|
35655
36076
|
return false;
|
|
35656
36077
|
} catch (error48) {
|
|
35657
36078
|
if (this.fsw._handleError(error48)) {
|
|
35658
36079
|
ready();
|
|
35659
|
-
return
|
|
36080
|
+
return path21;
|
|
35660
36081
|
}
|
|
35661
36082
|
}
|
|
35662
36083
|
}
|
|
@@ -35691,24 +36112,24 @@ function createPattern(matcher) {
|
|
|
35691
36112
|
}
|
|
35692
36113
|
return () => false;
|
|
35693
36114
|
}
|
|
35694
|
-
function normalizePath(
|
|
35695
|
-
if (typeof
|
|
36115
|
+
function normalizePath(path21) {
|
|
36116
|
+
if (typeof path21 !== "string")
|
|
35696
36117
|
throw new Error("string expected");
|
|
35697
|
-
|
|
35698
|
-
|
|
36118
|
+
path21 = sp2.normalize(path21);
|
|
36119
|
+
path21 = path21.replace(/\\/g, "/");
|
|
35699
36120
|
let prepend = false;
|
|
35700
|
-
if (
|
|
36121
|
+
if (path21.startsWith("//"))
|
|
35701
36122
|
prepend = true;
|
|
35702
|
-
|
|
36123
|
+
path21 = path21.replace(DOUBLE_SLASH_RE, "/");
|
|
35703
36124
|
if (prepend)
|
|
35704
|
-
|
|
35705
|
-
return
|
|
36125
|
+
path21 = "/" + path21;
|
|
36126
|
+
return path21;
|
|
35706
36127
|
}
|
|
35707
36128
|
function matchPatterns(patterns, testString, stats) {
|
|
35708
|
-
const
|
|
36129
|
+
const path21 = normalizePath(testString);
|
|
35709
36130
|
for (let index = 0; index < patterns.length; index++) {
|
|
35710
36131
|
const pattern = patterns[index];
|
|
35711
|
-
if (pattern(
|
|
36132
|
+
if (pattern(path21, stats)) {
|
|
35712
36133
|
return true;
|
|
35713
36134
|
}
|
|
35714
36135
|
}
|
|
@@ -35771,19 +36192,19 @@ var init_chokidar = __esm({
|
|
|
35771
36192
|
}
|
|
35772
36193
|
return str;
|
|
35773
36194
|
};
|
|
35774
|
-
normalizePathToUnix = (
|
|
35775
|
-
normalizeIgnored = (cwd = "") => (
|
|
35776
|
-
if (typeof
|
|
35777
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
36195
|
+
normalizePathToUnix = (path21) => toUnix(sp2.normalize(toUnix(path21)));
|
|
36196
|
+
normalizeIgnored = (cwd = "") => (path21) => {
|
|
36197
|
+
if (typeof path21 === "string") {
|
|
36198
|
+
return normalizePathToUnix(sp2.isAbsolute(path21) ? path21 : sp2.join(cwd, path21));
|
|
35778
36199
|
} else {
|
|
35779
|
-
return
|
|
36200
|
+
return path21;
|
|
35780
36201
|
}
|
|
35781
36202
|
};
|
|
35782
|
-
getAbsolutePath = (
|
|
35783
|
-
if (sp2.isAbsolute(
|
|
35784
|
-
return
|
|
36203
|
+
getAbsolutePath = (path21, cwd) => {
|
|
36204
|
+
if (sp2.isAbsolute(path21)) {
|
|
36205
|
+
return path21;
|
|
35785
36206
|
}
|
|
35786
|
-
return sp2.join(cwd,
|
|
36207
|
+
return sp2.join(cwd, path21);
|
|
35787
36208
|
};
|
|
35788
36209
|
EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
35789
36210
|
DirEntry = class {
|
|
@@ -35848,10 +36269,10 @@ var init_chokidar = __esm({
|
|
|
35848
36269
|
dirParts;
|
|
35849
36270
|
followSymlinks;
|
|
35850
36271
|
statMethod;
|
|
35851
|
-
constructor(
|
|
36272
|
+
constructor(path21, follow, fsw) {
|
|
35852
36273
|
this.fsw = fsw;
|
|
35853
|
-
const watchPath =
|
|
35854
|
-
this.path =
|
|
36274
|
+
const watchPath = path21;
|
|
36275
|
+
this.path = path21 = path21.replace(REPLACER_RE, "");
|
|
35855
36276
|
this.watchPath = watchPath;
|
|
35856
36277
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
35857
36278
|
this.dirParts = [];
|
|
@@ -35991,20 +36412,20 @@ var init_chokidar = __esm({
|
|
|
35991
36412
|
this._closePromise = void 0;
|
|
35992
36413
|
let paths = unifyPaths(paths_);
|
|
35993
36414
|
if (cwd) {
|
|
35994
|
-
paths = paths.map((
|
|
35995
|
-
const absPath = getAbsolutePath(
|
|
36415
|
+
paths = paths.map((path21) => {
|
|
36416
|
+
const absPath = getAbsolutePath(path21, cwd);
|
|
35996
36417
|
return absPath;
|
|
35997
36418
|
});
|
|
35998
36419
|
}
|
|
35999
|
-
paths.forEach((
|
|
36000
|
-
this._removeIgnoredPath(
|
|
36420
|
+
paths.forEach((path21) => {
|
|
36421
|
+
this._removeIgnoredPath(path21);
|
|
36001
36422
|
});
|
|
36002
36423
|
this._userIgnored = void 0;
|
|
36003
36424
|
if (!this._readyCount)
|
|
36004
36425
|
this._readyCount = 0;
|
|
36005
36426
|
this._readyCount += paths.length;
|
|
36006
|
-
Promise.all(paths.map(async (
|
|
36007
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
36427
|
+
Promise.all(paths.map(async (path21) => {
|
|
36428
|
+
const res = await this._nodeFsHandler._addToNodeFs(path21, !_internal, void 0, 0, _origAdd);
|
|
36008
36429
|
if (res)
|
|
36009
36430
|
this._emitReady();
|
|
36010
36431
|
return res;
|
|
@@ -36026,17 +36447,17 @@ var init_chokidar = __esm({
|
|
|
36026
36447
|
return this;
|
|
36027
36448
|
const paths = unifyPaths(paths_);
|
|
36028
36449
|
const { cwd } = this.options;
|
|
36029
|
-
paths.forEach((
|
|
36030
|
-
if (!sp2.isAbsolute(
|
|
36450
|
+
paths.forEach((path21) => {
|
|
36451
|
+
if (!sp2.isAbsolute(path21) && !this._closers.has(path21)) {
|
|
36031
36452
|
if (cwd)
|
|
36032
|
-
|
|
36033
|
-
|
|
36453
|
+
path21 = sp2.join(cwd, path21);
|
|
36454
|
+
path21 = sp2.resolve(path21);
|
|
36034
36455
|
}
|
|
36035
|
-
this._closePath(
|
|
36036
|
-
this._addIgnoredPath(
|
|
36037
|
-
if (this._watched.has(
|
|
36456
|
+
this._closePath(path21);
|
|
36457
|
+
this._addIgnoredPath(path21);
|
|
36458
|
+
if (this._watched.has(path21)) {
|
|
36038
36459
|
this._addIgnoredPath({
|
|
36039
|
-
path:
|
|
36460
|
+
path: path21,
|
|
36040
36461
|
recursive: true
|
|
36041
36462
|
});
|
|
36042
36463
|
}
|
|
@@ -36100,38 +36521,38 @@ var init_chokidar = __esm({
|
|
|
36100
36521
|
* @param stats arguments to be passed with event
|
|
36101
36522
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
36102
36523
|
*/
|
|
36103
|
-
async _emit(event,
|
|
36524
|
+
async _emit(event, path21, stats) {
|
|
36104
36525
|
if (this.closed)
|
|
36105
36526
|
return;
|
|
36106
36527
|
const opts = this.options;
|
|
36107
36528
|
if (isWindows)
|
|
36108
|
-
|
|
36529
|
+
path21 = sp2.normalize(path21);
|
|
36109
36530
|
if (opts.cwd)
|
|
36110
|
-
|
|
36111
|
-
const args = [
|
|
36531
|
+
path21 = sp2.relative(opts.cwd, path21);
|
|
36532
|
+
const args = [path21];
|
|
36112
36533
|
if (stats != null)
|
|
36113
36534
|
args.push(stats);
|
|
36114
36535
|
const awf = opts.awaitWriteFinish;
|
|
36115
36536
|
let pw;
|
|
36116
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
36537
|
+
if (awf && (pw = this._pendingWrites.get(path21))) {
|
|
36117
36538
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
36118
36539
|
return this;
|
|
36119
36540
|
}
|
|
36120
36541
|
if (opts.atomic) {
|
|
36121
36542
|
if (event === EVENTS.UNLINK) {
|
|
36122
|
-
this._pendingUnlinks.set(
|
|
36543
|
+
this._pendingUnlinks.set(path21, [event, ...args]);
|
|
36123
36544
|
setTimeout(() => {
|
|
36124
|
-
this._pendingUnlinks.forEach((entry,
|
|
36545
|
+
this._pendingUnlinks.forEach((entry, path23) => {
|
|
36125
36546
|
this.emit(...entry);
|
|
36126
36547
|
this.emit(EVENTS.ALL, ...entry);
|
|
36127
|
-
this._pendingUnlinks.delete(
|
|
36548
|
+
this._pendingUnlinks.delete(path23);
|
|
36128
36549
|
});
|
|
36129
36550
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
36130
36551
|
return this;
|
|
36131
36552
|
}
|
|
36132
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
36553
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path21)) {
|
|
36133
36554
|
event = EVENTS.CHANGE;
|
|
36134
|
-
this._pendingUnlinks.delete(
|
|
36555
|
+
this._pendingUnlinks.delete(path21);
|
|
36135
36556
|
}
|
|
36136
36557
|
}
|
|
36137
36558
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -36149,16 +36570,16 @@ var init_chokidar = __esm({
|
|
|
36149
36570
|
this.emitWithAll(event, args);
|
|
36150
36571
|
}
|
|
36151
36572
|
};
|
|
36152
|
-
this._awaitWriteFinish(
|
|
36573
|
+
this._awaitWriteFinish(path21, awf.stabilityThreshold, event, awfEmit);
|
|
36153
36574
|
return this;
|
|
36154
36575
|
}
|
|
36155
36576
|
if (event === EVENTS.CHANGE) {
|
|
36156
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
36577
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path21, 50);
|
|
36157
36578
|
if (isThrottled)
|
|
36158
36579
|
return this;
|
|
36159
36580
|
}
|
|
36160
36581
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
36161
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
36582
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path21) : path21;
|
|
36162
36583
|
let stats2;
|
|
36163
36584
|
try {
|
|
36164
36585
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -36189,23 +36610,23 @@ var init_chokidar = __esm({
|
|
|
36189
36610
|
* @param timeout duration of time to suppress duplicate actions
|
|
36190
36611
|
* @returns tracking object or false if action should be suppressed
|
|
36191
36612
|
*/
|
|
36192
|
-
_throttle(actionType,
|
|
36613
|
+
_throttle(actionType, path21, timeout) {
|
|
36193
36614
|
if (!this._throttled.has(actionType)) {
|
|
36194
36615
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
36195
36616
|
}
|
|
36196
36617
|
const action = this._throttled.get(actionType);
|
|
36197
36618
|
if (!action)
|
|
36198
36619
|
throw new Error("invalid throttle");
|
|
36199
|
-
const actionPath = action.get(
|
|
36620
|
+
const actionPath = action.get(path21);
|
|
36200
36621
|
if (actionPath) {
|
|
36201
36622
|
actionPath.count++;
|
|
36202
36623
|
return false;
|
|
36203
36624
|
}
|
|
36204
36625
|
let timeoutObject;
|
|
36205
36626
|
const clear = () => {
|
|
36206
|
-
const item = action.get(
|
|
36627
|
+
const item = action.get(path21);
|
|
36207
36628
|
const count = item ? item.count : 0;
|
|
36208
|
-
action.delete(
|
|
36629
|
+
action.delete(path21);
|
|
36209
36630
|
clearTimeout(timeoutObject);
|
|
36210
36631
|
if (item)
|
|
36211
36632
|
clearTimeout(item.timeoutObject);
|
|
@@ -36213,7 +36634,7 @@ var init_chokidar = __esm({
|
|
|
36213
36634
|
};
|
|
36214
36635
|
timeoutObject = setTimeout(clear, timeout);
|
|
36215
36636
|
const thr = { timeoutObject, clear, count: 0 };
|
|
36216
|
-
action.set(
|
|
36637
|
+
action.set(path21, thr);
|
|
36217
36638
|
return thr;
|
|
36218
36639
|
}
|
|
36219
36640
|
_incrReadyCount() {
|
|
@@ -36227,44 +36648,44 @@ var init_chokidar = __esm({
|
|
|
36227
36648
|
* @param event
|
|
36228
36649
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
36229
36650
|
*/
|
|
36230
|
-
_awaitWriteFinish(
|
|
36651
|
+
_awaitWriteFinish(path21, threshold, event, awfEmit) {
|
|
36231
36652
|
const awf = this.options.awaitWriteFinish;
|
|
36232
36653
|
if (typeof awf !== "object")
|
|
36233
36654
|
return;
|
|
36234
36655
|
const pollInterval = awf.pollInterval;
|
|
36235
36656
|
let timeoutHandler;
|
|
36236
|
-
let fullPath =
|
|
36237
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
36238
|
-
fullPath = sp2.join(this.options.cwd,
|
|
36657
|
+
let fullPath = path21;
|
|
36658
|
+
if (this.options.cwd && !sp2.isAbsolute(path21)) {
|
|
36659
|
+
fullPath = sp2.join(this.options.cwd, path21);
|
|
36239
36660
|
}
|
|
36240
36661
|
const now = /* @__PURE__ */ new Date();
|
|
36241
36662
|
const writes = this._pendingWrites;
|
|
36242
36663
|
function awaitWriteFinishFn(prevStat) {
|
|
36243
36664
|
(0, import_node_fs2.stat)(fullPath, (err, curStat) => {
|
|
36244
|
-
if (err || !writes.has(
|
|
36665
|
+
if (err || !writes.has(path21)) {
|
|
36245
36666
|
if (err && err.code !== "ENOENT")
|
|
36246
36667
|
awfEmit(err);
|
|
36247
36668
|
return;
|
|
36248
36669
|
}
|
|
36249
36670
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
36250
36671
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
36251
|
-
writes.get(
|
|
36672
|
+
writes.get(path21).lastChange = now2;
|
|
36252
36673
|
}
|
|
36253
|
-
const pw = writes.get(
|
|
36674
|
+
const pw = writes.get(path21);
|
|
36254
36675
|
const df = now2 - pw.lastChange;
|
|
36255
36676
|
if (df >= threshold) {
|
|
36256
|
-
writes.delete(
|
|
36677
|
+
writes.delete(path21);
|
|
36257
36678
|
awfEmit(void 0, curStat);
|
|
36258
36679
|
} else {
|
|
36259
36680
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
36260
36681
|
}
|
|
36261
36682
|
});
|
|
36262
36683
|
}
|
|
36263
|
-
if (!writes.has(
|
|
36264
|
-
writes.set(
|
|
36684
|
+
if (!writes.has(path21)) {
|
|
36685
|
+
writes.set(path21, {
|
|
36265
36686
|
lastChange: now,
|
|
36266
36687
|
cancelWait: () => {
|
|
36267
|
-
writes.delete(
|
|
36688
|
+
writes.delete(path21);
|
|
36268
36689
|
clearTimeout(timeoutHandler);
|
|
36269
36690
|
return event;
|
|
36270
36691
|
}
|
|
@@ -36275,8 +36696,8 @@ var init_chokidar = __esm({
|
|
|
36275
36696
|
/**
|
|
36276
36697
|
* Determines whether user has asked to ignore this path.
|
|
36277
36698
|
*/
|
|
36278
|
-
_isIgnored(
|
|
36279
|
-
if (this.options.atomic && DOT_RE.test(
|
|
36699
|
+
_isIgnored(path21, stats) {
|
|
36700
|
+
if (this.options.atomic && DOT_RE.test(path21))
|
|
36280
36701
|
return true;
|
|
36281
36702
|
if (!this._userIgnored) {
|
|
36282
36703
|
const { cwd } = this.options;
|
|
@@ -36286,17 +36707,17 @@ var init_chokidar = __esm({
|
|
|
36286
36707
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
36287
36708
|
this._userIgnored = anymatch(list, void 0);
|
|
36288
36709
|
}
|
|
36289
|
-
return this._userIgnored(
|
|
36710
|
+
return this._userIgnored(path21, stats);
|
|
36290
36711
|
}
|
|
36291
|
-
_isntIgnored(
|
|
36292
|
-
return !this._isIgnored(
|
|
36712
|
+
_isntIgnored(path21, stat4) {
|
|
36713
|
+
return !this._isIgnored(path21, stat4);
|
|
36293
36714
|
}
|
|
36294
36715
|
/**
|
|
36295
36716
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
36296
36717
|
* @param path file or directory pattern being watched
|
|
36297
36718
|
*/
|
|
36298
|
-
_getWatchHelpers(
|
|
36299
|
-
return new WatchHelper(
|
|
36719
|
+
_getWatchHelpers(path21) {
|
|
36720
|
+
return new WatchHelper(path21, this.options.followSymlinks, this);
|
|
36300
36721
|
}
|
|
36301
36722
|
// Directory helpers
|
|
36302
36723
|
// -----------------
|
|
@@ -36328,63 +36749,63 @@ var init_chokidar = __esm({
|
|
|
36328
36749
|
* @param item base path of item/directory
|
|
36329
36750
|
*/
|
|
36330
36751
|
_remove(directory, item, isDirectory) {
|
|
36331
|
-
const
|
|
36332
|
-
const fullPath = sp2.resolve(
|
|
36333
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
36334
|
-
if (!this._throttle("remove",
|
|
36752
|
+
const path21 = sp2.join(directory, item);
|
|
36753
|
+
const fullPath = sp2.resolve(path21);
|
|
36754
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path21) || this._watched.has(fullPath);
|
|
36755
|
+
if (!this._throttle("remove", path21, 100))
|
|
36335
36756
|
return;
|
|
36336
36757
|
if (!isDirectory && this._watched.size === 1) {
|
|
36337
36758
|
this.add(directory, item, true);
|
|
36338
36759
|
}
|
|
36339
|
-
const wp = this._getWatchedDir(
|
|
36760
|
+
const wp = this._getWatchedDir(path21);
|
|
36340
36761
|
const nestedDirectoryChildren = wp.getChildren();
|
|
36341
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
36762
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path21, nested));
|
|
36342
36763
|
const parent = this._getWatchedDir(directory);
|
|
36343
36764
|
const wasTracked = parent.has(item);
|
|
36344
36765
|
parent.remove(item);
|
|
36345
36766
|
if (this._symlinkPaths.has(fullPath)) {
|
|
36346
36767
|
this._symlinkPaths.delete(fullPath);
|
|
36347
36768
|
}
|
|
36348
|
-
let relPath =
|
|
36769
|
+
let relPath = path21;
|
|
36349
36770
|
if (this.options.cwd)
|
|
36350
|
-
relPath = sp2.relative(this.options.cwd,
|
|
36771
|
+
relPath = sp2.relative(this.options.cwd, path21);
|
|
36351
36772
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
36352
36773
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
36353
36774
|
if (event === EVENTS.ADD)
|
|
36354
36775
|
return;
|
|
36355
36776
|
}
|
|
36356
|
-
this._watched.delete(
|
|
36777
|
+
this._watched.delete(path21);
|
|
36357
36778
|
this._watched.delete(fullPath);
|
|
36358
36779
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
36359
|
-
if (wasTracked && !this._isIgnored(
|
|
36360
|
-
this._emit(eventName,
|
|
36361
|
-
this._closePath(
|
|
36780
|
+
if (wasTracked && !this._isIgnored(path21))
|
|
36781
|
+
this._emit(eventName, path21);
|
|
36782
|
+
this._closePath(path21);
|
|
36362
36783
|
}
|
|
36363
36784
|
/**
|
|
36364
36785
|
* Closes all watchers for a path
|
|
36365
36786
|
*/
|
|
36366
|
-
_closePath(
|
|
36367
|
-
this._closeFile(
|
|
36368
|
-
const dir = sp2.dirname(
|
|
36369
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
36787
|
+
_closePath(path21) {
|
|
36788
|
+
this._closeFile(path21);
|
|
36789
|
+
const dir = sp2.dirname(path21);
|
|
36790
|
+
this._getWatchedDir(dir).remove(sp2.basename(path21));
|
|
36370
36791
|
}
|
|
36371
36792
|
/**
|
|
36372
36793
|
* Closes only file-specific watchers
|
|
36373
36794
|
*/
|
|
36374
|
-
_closeFile(
|
|
36375
|
-
const closers = this._closers.get(
|
|
36795
|
+
_closeFile(path21) {
|
|
36796
|
+
const closers = this._closers.get(path21);
|
|
36376
36797
|
if (!closers)
|
|
36377
36798
|
return;
|
|
36378
36799
|
closers.forEach((closer) => closer());
|
|
36379
|
-
this._closers.delete(
|
|
36800
|
+
this._closers.delete(path21);
|
|
36380
36801
|
}
|
|
36381
|
-
_addPathCloser(
|
|
36802
|
+
_addPathCloser(path21, closer) {
|
|
36382
36803
|
if (!closer)
|
|
36383
36804
|
return;
|
|
36384
|
-
let list = this._closers.get(
|
|
36805
|
+
let list = this._closers.get(path21);
|
|
36385
36806
|
if (!list) {
|
|
36386
36807
|
list = [];
|
|
36387
|
-
this._closers.set(
|
|
36808
|
+
this._closers.set(path21, list);
|
|
36388
36809
|
}
|
|
36389
36810
|
list.push(closer);
|
|
36390
36811
|
}
|
|
@@ -36760,6 +37181,7 @@ var init_provider_loader = __esm({
|
|
|
36760
37181
|
resolve(type, context) {
|
|
36761
37182
|
const base = this.providers.get(type);
|
|
36762
37183
|
if (!base) return void 0;
|
|
37184
|
+
const providerDir = this.findProviderDirInternal(type) || void 0;
|
|
36763
37185
|
const currentOs = context?.os || process.platform;
|
|
36764
37186
|
const currentVersion = context?.version ?? this.versionArchive?.getLatest(type) ?? void 0;
|
|
36765
37187
|
const resolved = JSON.parse(JSON.stringify(base));
|
|
@@ -36769,6 +37191,9 @@ var init_provider_loader = __esm({
|
|
|
36769
37191
|
if (base.scripts) {
|
|
36770
37192
|
resolved.scripts = { ...base.scripts };
|
|
36771
37193
|
}
|
|
37194
|
+
if (providerDir) {
|
|
37195
|
+
resolved._resolvedProviderDir = providerDir;
|
|
37196
|
+
}
|
|
36772
37197
|
if (base.os?.[currentOs]) {
|
|
36773
37198
|
const osOverride = base.os[currentOs];
|
|
36774
37199
|
if (osOverride.scripts) {
|
|
@@ -36789,6 +37214,12 @@ var init_provider_loader = __esm({
|
|
|
36789
37214
|
if (loaded) {
|
|
36790
37215
|
resolved.scripts = loaded;
|
|
36791
37216
|
this.log(` [compatibility] ${type} v${currentVersion} \u2192 ${entry.scriptDir}`);
|
|
37217
|
+
resolved._resolvedScriptDir = entry.scriptDir;
|
|
37218
|
+
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
37219
|
+
if (providerDir) {
|
|
37220
|
+
const fullDir = path10.join(providerDir, entry.scriptDir);
|
|
37221
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
|
|
37222
|
+
}
|
|
36792
37223
|
matched = true;
|
|
36793
37224
|
}
|
|
36794
37225
|
break;
|
|
@@ -36799,6 +37230,12 @@ var init_provider_loader = __esm({
|
|
|
36799
37230
|
if (loaded) {
|
|
36800
37231
|
resolved.scripts = loaded;
|
|
36801
37232
|
this.log(` [compatibility] ${type} v${currentVersion} \u2192 default: ${base.defaultScriptDir}`);
|
|
37233
|
+
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
37234
|
+
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
37235
|
+
if (providerDir) {
|
|
37236
|
+
const fullDir = path10.join(providerDir, base.defaultScriptDir);
|
|
37237
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
|
|
37238
|
+
}
|
|
36802
37239
|
}
|
|
36803
37240
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
36804
37241
|
}
|
|
@@ -36811,6 +37248,12 @@ var init_provider_loader = __esm({
|
|
|
36811
37248
|
if (loaded) {
|
|
36812
37249
|
resolved.scripts = loaded;
|
|
36813
37250
|
this.log(` [version override] ${type} ${range} \u2192 ${dirOverride}`);
|
|
37251
|
+
resolved._resolvedScriptDir = dirOverride;
|
|
37252
|
+
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
37253
|
+
if (providerDir) {
|
|
37254
|
+
const fullDir = path10.join(providerDir, dirOverride);
|
|
37255
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
|
|
37256
|
+
}
|
|
36814
37257
|
}
|
|
36815
37258
|
} else if (override.scripts) {
|
|
36816
37259
|
resolved.scripts = { ...resolved.scripts, ...override.scripts };
|
|
@@ -36822,6 +37265,12 @@ var init_provider_loader = __esm({
|
|
|
36822
37265
|
if (loaded) {
|
|
36823
37266
|
resolved.scripts = loaded;
|
|
36824
37267
|
this.log(` [compatibility] ${type} no version detected \u2192 default: ${base.defaultScriptDir}`);
|
|
37268
|
+
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
37269
|
+
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
37270
|
+
if (providerDir) {
|
|
37271
|
+
const fullDir = path10.join(providerDir, base.defaultScriptDir);
|
|
37272
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
|
|
37273
|
+
}
|
|
36825
37274
|
}
|
|
36826
37275
|
}
|
|
36827
37276
|
if (base.overrides) {
|
|
@@ -36890,6 +37339,9 @@ var init_provider_loader = __esm({
|
|
|
36890
37339
|
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
|
|
36891
37340
|
});
|
|
36892
37341
|
const handleChange = (filePath) => {
|
|
37342
|
+
if (/[\/\\]fixtures[\/\\]/.test(filePath)) {
|
|
37343
|
+
return;
|
|
37344
|
+
}
|
|
36893
37345
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
36894
37346
|
this.log(`File changed: ${path10.basename(filePath)}, reloading...`);
|
|
36895
37347
|
this.reload();
|
|
@@ -37583,7 +38035,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
37583
38035
|
}
|
|
37584
38036
|
} else if (plat === "win32") {
|
|
37585
38037
|
try {
|
|
37586
|
-
const
|
|
38038
|
+
const fs18 = require("fs");
|
|
37587
38039
|
const appNameMap = getMacAppIdentifiers();
|
|
37588
38040
|
const appName = appNameMap[ideId];
|
|
37589
38041
|
if (appName) {
|
|
@@ -37592,8 +38044,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
37592
38044
|
appName,
|
|
37593
38045
|
"storage.json"
|
|
37594
38046
|
);
|
|
37595
|
-
if (
|
|
37596
|
-
const data = JSON.parse(
|
|
38047
|
+
if (fs18.existsSync(storagePath)) {
|
|
38048
|
+
const data = JSON.parse(fs18.readFileSync(storagePath, "utf-8"));
|
|
37597
38049
|
const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
|
|
37598
38050
|
if (workspaces.length > 0) {
|
|
37599
38051
|
const recent = workspaces[0];
|
|
@@ -39216,6 +39668,15 @@ var init_poller = __esm({
|
|
|
39216
39668
|
cdpManagerKey: ideType,
|
|
39217
39669
|
instanceKey: `ide:${ideType}`
|
|
39218
39670
|
});
|
|
39671
|
+
const activeSessionId2 = agentStreamManager.getActiveSessionId(parentSessionId);
|
|
39672
|
+
if (!activeSessionId2 || enabledExtTypes.size === 1) {
|
|
39673
|
+
await agentStreamManager.setActiveSession(
|
|
39674
|
+
cdp,
|
|
39675
|
+
parentSessionId,
|
|
39676
|
+
extInstance.getInstanceId()
|
|
39677
|
+
);
|
|
39678
|
+
LOG.info("AgentStream", `Auto-activated enabled extension: ${extType} (${ideType})`);
|
|
39679
|
+
}
|
|
39219
39680
|
}
|
|
39220
39681
|
LOG.info("AgentStream", `Extension added: ${extType} (enabled for ${ideType})`);
|
|
39221
39682
|
}
|
|
@@ -41051,6 +41512,160 @@ var init_dev_cdp_handlers = __esm({
|
|
|
41051
41512
|
});
|
|
41052
41513
|
|
|
41053
41514
|
// ../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts
|
|
41515
|
+
function slugifyFixtureName(value) {
|
|
41516
|
+
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
41517
|
+
return normalized || `fixture-${Date.now()}`;
|
|
41518
|
+
}
|
|
41519
|
+
function getCliFixtureDir(ctx, type) {
|
|
41520
|
+
const providerDir = ctx.providerLoader.findProviderDir(type);
|
|
41521
|
+
if (!providerDir) {
|
|
41522
|
+
throw new Error(`Provider directory not found for '${type}'`);
|
|
41523
|
+
}
|
|
41524
|
+
return path15.join(providerDir, "fixtures");
|
|
41525
|
+
}
|
|
41526
|
+
function readCliFixture(ctx, type, name) {
|
|
41527
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
41528
|
+
const filePath = path15.join(fixtureDir, `${name}.json`);
|
|
41529
|
+
if (!fs12.existsSync(filePath)) {
|
|
41530
|
+
throw new Error(`Fixture not found: ${filePath}`);
|
|
41531
|
+
}
|
|
41532
|
+
return JSON.parse(fs12.readFileSync(filePath, "utf-8"));
|
|
41533
|
+
}
|
|
41534
|
+
function getExerciseTranscriptText(result) {
|
|
41535
|
+
const parts = [];
|
|
41536
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41537
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41538
|
+
for (const message of [...debugMessages, ...traceMessages]) {
|
|
41539
|
+
if (!message || typeof message.content !== "string") continue;
|
|
41540
|
+
parts.push(message.content);
|
|
41541
|
+
}
|
|
41542
|
+
if (typeof result?.debug?.partialResponse === "string") parts.push(result.debug.partialResponse);
|
|
41543
|
+
if (typeof result?.trace?.responseBuffer === "string") parts.push(result.trace.responseBuffer);
|
|
41544
|
+
return parts.join("\n");
|
|
41545
|
+
}
|
|
41546
|
+
function getExerciseLastAssistant(result) {
|
|
41547
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41548
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41549
|
+
for (const messages of [debugMessages, traceMessages]) {
|
|
41550
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
41551
|
+
const message = messages[i];
|
|
41552
|
+
if (message?.role === "assistant" && typeof message.content === "string" && message.content.trim()) {
|
|
41553
|
+
return message.content;
|
|
41554
|
+
}
|
|
41555
|
+
}
|
|
41556
|
+
}
|
|
41557
|
+
return "";
|
|
41558
|
+
}
|
|
41559
|
+
function getExerciseMessageCount(result) {
|
|
41560
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41561
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41562
|
+
return Math.max(debugMessages.length, traceMessages.length);
|
|
41563
|
+
}
|
|
41564
|
+
function compileFixtureRegex(source) {
|
|
41565
|
+
const value = String(source || "").trim();
|
|
41566
|
+
if (!value) return null;
|
|
41567
|
+
const delimited = value.match(/^\/([\s\S]+)\/([dgimsuvy]*)$/);
|
|
41568
|
+
try {
|
|
41569
|
+
if (delimited) {
|
|
41570
|
+
return new RegExp(delimited[1], delimited[2]);
|
|
41571
|
+
}
|
|
41572
|
+
return new RegExp(value, "m");
|
|
41573
|
+
} catch {
|
|
41574
|
+
return null;
|
|
41575
|
+
}
|
|
41576
|
+
}
|
|
41577
|
+
function statusesContainSequence(actual, expected) {
|
|
41578
|
+
if (!expected.length) return true;
|
|
41579
|
+
let index = 0;
|
|
41580
|
+
for (const status of actual) {
|
|
41581
|
+
if (status === expected[index]) index += 1;
|
|
41582
|
+
if (index >= expected.length) return true;
|
|
41583
|
+
}
|
|
41584
|
+
return false;
|
|
41585
|
+
}
|
|
41586
|
+
function validateCliFixtureResult(result, assertions) {
|
|
41587
|
+
const failures = [];
|
|
41588
|
+
const transcriptText = getExerciseTranscriptText(result);
|
|
41589
|
+
const lastAssistant = getExerciseLastAssistant(result);
|
|
41590
|
+
const mustContainAny = assertions.mustContainAny || [];
|
|
41591
|
+
const mustNotContainAny = assertions.mustNotContainAny || [];
|
|
41592
|
+
const mustMatchAny = assertions.mustMatchAny || [];
|
|
41593
|
+
const mustNotMatchAny = assertions.mustNotMatchAny || [];
|
|
41594
|
+
const lastAssistantMustContainAny = assertions.lastAssistantMustContainAny || [];
|
|
41595
|
+
const lastAssistantMustNotContainAny = assertions.lastAssistantMustNotContainAny || [];
|
|
41596
|
+
const lastAssistantMustMatchAny = assertions.lastAssistantMustMatchAny || [];
|
|
41597
|
+
const lastAssistantMustNotMatchAny = assertions.lastAssistantMustNotMatchAny || [];
|
|
41598
|
+
const statusesSeen = Array.isArray(result?.statusesSeen) ? result.statusesSeen.map((value) => String(value)) : [];
|
|
41599
|
+
if (assertions.requireNotTimedOut !== false && result?.timedOut) {
|
|
41600
|
+
failures.push("Exercise timed out");
|
|
41601
|
+
}
|
|
41602
|
+
const missingRequired = mustContainAny.filter((value) => !transcriptText.includes(value));
|
|
41603
|
+
if (missingRequired.length > 0) {
|
|
41604
|
+
failures.push(`Missing required substrings: ${missingRequired.join(", ")}`);
|
|
41605
|
+
}
|
|
41606
|
+
const presentBanned = mustNotContainAny.filter((value) => transcriptText.includes(value));
|
|
41607
|
+
if (presentBanned.length > 0) {
|
|
41608
|
+
failures.push(`Found banned substrings: ${presentBanned.join(", ")}`);
|
|
41609
|
+
}
|
|
41610
|
+
const missingRegex = mustMatchAny.filter((value) => {
|
|
41611
|
+
const regex = compileFixtureRegex(value);
|
|
41612
|
+
return !regex || !regex.test(transcriptText);
|
|
41613
|
+
});
|
|
41614
|
+
if (missingRegex.length > 0) {
|
|
41615
|
+
failures.push(`Missing required regex matches: ${missingRegex.join(", ")}`);
|
|
41616
|
+
}
|
|
41617
|
+
const presentBannedRegex = mustNotMatchAny.filter((value) => {
|
|
41618
|
+
const regex = compileFixtureRegex(value);
|
|
41619
|
+
return !!regex && regex.test(transcriptText);
|
|
41620
|
+
});
|
|
41621
|
+
if (presentBannedRegex.length > 0) {
|
|
41622
|
+
failures.push(`Found banned regex matches: ${presentBannedRegex.join(", ")}`);
|
|
41623
|
+
}
|
|
41624
|
+
const missingLastAssistant = lastAssistantMustContainAny.filter((value) => !lastAssistant.includes(value));
|
|
41625
|
+
if (missingLastAssistant.length > 0) {
|
|
41626
|
+
failures.push(`Missing required lastAssistant substrings: ${missingLastAssistant.join(", ")}`);
|
|
41627
|
+
}
|
|
41628
|
+
const presentBannedLastAssistant = lastAssistantMustNotContainAny.filter((value) => lastAssistant.includes(value));
|
|
41629
|
+
if (presentBannedLastAssistant.length > 0) {
|
|
41630
|
+
failures.push(`Found banned lastAssistant substrings: ${presentBannedLastAssistant.join(", ")}`);
|
|
41631
|
+
}
|
|
41632
|
+
const missingLastAssistantRegex = lastAssistantMustMatchAny.filter((value) => {
|
|
41633
|
+
const regex = compileFixtureRegex(value);
|
|
41634
|
+
return !regex || !regex.test(lastAssistant);
|
|
41635
|
+
});
|
|
41636
|
+
if (missingLastAssistantRegex.length > 0) {
|
|
41637
|
+
failures.push(`Missing required lastAssistant regex matches: ${missingLastAssistantRegex.join(", ")}`);
|
|
41638
|
+
}
|
|
41639
|
+
const presentBannedLastAssistantRegex = lastAssistantMustNotMatchAny.filter((value) => {
|
|
41640
|
+
const regex = compileFixtureRegex(value);
|
|
41641
|
+
return !!regex && regex.test(lastAssistant);
|
|
41642
|
+
});
|
|
41643
|
+
if (presentBannedLastAssistantRegex.length > 0) {
|
|
41644
|
+
failures.push(`Found banned lastAssistant regex matches: ${presentBannedLastAssistantRegex.join(", ")}`);
|
|
41645
|
+
}
|
|
41646
|
+
if (assertions.statusesSeen?.length && !statusesContainSequence(statusesSeen, assertions.statusesSeen)) {
|
|
41647
|
+
failures.push(`Expected statuses sequence not observed: ${assertions.statusesSeen.join(" -> ")}`);
|
|
41648
|
+
}
|
|
41649
|
+
if (result && typeof result === "object") {
|
|
41650
|
+
result.lastAssistant = lastAssistant;
|
|
41651
|
+
}
|
|
41652
|
+
return failures;
|
|
41653
|
+
}
|
|
41654
|
+
function getCliProviderResolutionMeta(ctx, type, adapter) {
|
|
41655
|
+
const adapterMeta = typeof adapter?.getProviderResolutionMeta === "function" ? adapter.getProviderResolutionMeta() : adapter?.getDebugState?.()?.providerResolution || null;
|
|
41656
|
+
const resolvedProvider = ctx.providerLoader.resolve(type);
|
|
41657
|
+
if (!adapterMeta && !resolvedProvider) return null;
|
|
41658
|
+
return {
|
|
41659
|
+
type,
|
|
41660
|
+
providerDir: adapterMeta?.providerDir || resolvedProvider?._resolvedProviderDir || ctx.providerLoader.findProviderDir(type),
|
|
41661
|
+
scriptDir: adapterMeta?.scriptDir || resolvedProvider?._resolvedScriptDir || null,
|
|
41662
|
+
scriptsPath: adapterMeta?.scriptsPath || resolvedProvider?._resolvedScriptsPath || null,
|
|
41663
|
+
scriptsSource: adapterMeta?.scriptsSource || resolvedProvider?._resolvedScriptsSource || null,
|
|
41664
|
+
resolvedVersion: adapterMeta?.resolvedVersion || resolvedProvider?._resolvedVersion || null,
|
|
41665
|
+
resolvedOs: adapterMeta?.resolvedOs || resolvedProvider?._resolvedOs || null,
|
|
41666
|
+
versionWarning: adapterMeta?.versionWarning || resolvedProvider?._versionWarning || null
|
|
41667
|
+
};
|
|
41668
|
+
}
|
|
41054
41669
|
function findCliTarget(ctx, type, instanceId) {
|
|
41055
41670
|
if (!ctx.instanceManager) return null;
|
|
41056
41671
|
const cliStates = ctx.instanceManager.collectAllStates().filter((s15) => s15.category === "cli" || s15.category === "acp");
|
|
@@ -41059,6 +41674,331 @@ function findCliTarget(ctx, type, instanceId) {
|
|
|
41059
41674
|
const matches = cliStates.filter((s15) => s15.type === type);
|
|
41060
41675
|
return matches[matches.length - 1] || null;
|
|
41061
41676
|
}
|
|
41677
|
+
function getCliTargetBundle(ctx, type, instanceId) {
|
|
41678
|
+
if (!ctx.instanceManager) return null;
|
|
41679
|
+
const target = findCliTarget(ctx, type, instanceId);
|
|
41680
|
+
if (!target) return null;
|
|
41681
|
+
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
41682
|
+
if (!instance) return null;
|
|
41683
|
+
const adapter = instance.getAdapter?.() || instance.adapter;
|
|
41684
|
+
if (!adapter) return null;
|
|
41685
|
+
return { target, instance, adapter };
|
|
41686
|
+
}
|
|
41687
|
+
function sleep(ms2) {
|
|
41688
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms2));
|
|
41689
|
+
}
|
|
41690
|
+
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
41691
|
+
const startedAt = Date.now();
|
|
41692
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
41693
|
+
const bundle = getCliTargetBundle(ctx, type, instanceId);
|
|
41694
|
+
if (bundle) {
|
|
41695
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
41696
|
+
const startupParseGate = !!debug?.startupParseGate;
|
|
41697
|
+
const adapterReady = !!debug?.ready;
|
|
41698
|
+
const visibleStatusReady = bundle.target.status === "generating" || bundle.target.status === "waiting_approval";
|
|
41699
|
+
const idleReady = bundle.target.status === "idle" && !startupParseGate;
|
|
41700
|
+
if (adapterReady || visibleStatusReady || idleReady) {
|
|
41701
|
+
return bundle;
|
|
41702
|
+
}
|
|
41703
|
+
}
|
|
41704
|
+
await sleep(100);
|
|
41705
|
+
}
|
|
41706
|
+
return getCliTargetBundle(ctx, type, instanceId);
|
|
41707
|
+
}
|
|
41708
|
+
async function runCliExerciseInternal(ctx, body) {
|
|
41709
|
+
if (!ctx.cliManager) {
|
|
41710
|
+
throw new Error("CliManager not available");
|
|
41711
|
+
}
|
|
41712
|
+
if (!ctx.instanceManager) {
|
|
41713
|
+
throw new Error("InstanceManager not available");
|
|
41714
|
+
}
|
|
41715
|
+
const {
|
|
41716
|
+
type,
|
|
41717
|
+
text,
|
|
41718
|
+
instanceId: requestedInstanceId,
|
|
41719
|
+
workingDir,
|
|
41720
|
+
args,
|
|
41721
|
+
autoLaunch = true,
|
|
41722
|
+
freshSession = true,
|
|
41723
|
+
autoResolveApprovals = true,
|
|
41724
|
+
approvalButtonIndex = 0,
|
|
41725
|
+
timeoutMs = 45e3,
|
|
41726
|
+
readyTimeoutMs = 15e3,
|
|
41727
|
+
idleSettledMs = 1200,
|
|
41728
|
+
traceLimit = 160,
|
|
41729
|
+
stopWhenDone = false
|
|
41730
|
+
} = body || {};
|
|
41731
|
+
if (!type) {
|
|
41732
|
+
throw new Error("type required (e.g. claude-cli, codex-cli)");
|
|
41733
|
+
}
|
|
41734
|
+
if (!text || typeof text !== "string") {
|
|
41735
|
+
throw new Error("text required (prompt to send to the CLI)");
|
|
41736
|
+
}
|
|
41737
|
+
let resolvedInstanceId = requestedInstanceId;
|
|
41738
|
+
if (freshSession) {
|
|
41739
|
+
const staleTargets = ctx.instanceManager.collectAllStates().filter((state) => (state.category === "cli" || state.category === "acp") && state.type === type).map((state) => state.instanceId);
|
|
41740
|
+
for (const staleId of staleTargets) {
|
|
41741
|
+
ctx.instanceManager.removeInstance(staleId);
|
|
41742
|
+
}
|
|
41743
|
+
resolvedInstanceId = void 0;
|
|
41744
|
+
}
|
|
41745
|
+
let bundle = getCliTargetBundle(ctx, type, resolvedInstanceId);
|
|
41746
|
+
if (!bundle && autoLaunch) {
|
|
41747
|
+
const launchArgs = [type, workingDir || process.cwd(), Array.isArray(args) ? args : []];
|
|
41748
|
+
let launched = null;
|
|
41749
|
+
let lastLaunchError = null;
|
|
41750
|
+
for (let attempt = 1; attempt <= 2; attempt += 1) {
|
|
41751
|
+
try {
|
|
41752
|
+
launched = await ctx.cliManager.startSession(...launchArgs);
|
|
41753
|
+
lastLaunchError = null;
|
|
41754
|
+
break;
|
|
41755
|
+
} catch (error48) {
|
|
41756
|
+
lastLaunchError = error48 instanceof Error ? error48 : new Error(String(error48?.message || error48));
|
|
41757
|
+
const message = String(lastLaunchError.message || "");
|
|
41758
|
+
const retryable = /ECONNREFUSED|session-host|Session host/i.test(message);
|
|
41759
|
+
if (!retryable || attempt === 2) break;
|
|
41760
|
+
await sleep(1e3);
|
|
41761
|
+
}
|
|
41762
|
+
}
|
|
41763
|
+
if (!launched) {
|
|
41764
|
+
throw lastLaunchError || new Error(`Failed to start ${type}`);
|
|
41765
|
+
}
|
|
41766
|
+
resolvedInstanceId = launched.runtimeSessionId;
|
|
41767
|
+
bundle = await waitForCliReady(ctx, type, resolvedInstanceId, Math.max(1e3, readyTimeoutMs));
|
|
41768
|
+
}
|
|
41769
|
+
if (!bundle) {
|
|
41770
|
+
throw new Error(`No running instance found for: ${resolvedInstanceId || type}`);
|
|
41771
|
+
}
|
|
41772
|
+
const initialDebug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
41773
|
+
const initialTrace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
41774
|
+
const providerResolution = getCliProviderResolutionMeta(ctx, bundle.target.type, bundle.adapter);
|
|
41775
|
+
const preTraceCount = Number(initialTrace?.entryCount || 0);
|
|
41776
|
+
const startAt = Date.now();
|
|
41777
|
+
const statusesSeen = [];
|
|
41778
|
+
const approvalsResolved = [];
|
|
41779
|
+
let lastStatus = "";
|
|
41780
|
+
let lastModalKey = "";
|
|
41781
|
+
let idleSince = 0;
|
|
41782
|
+
let sawBusy = false;
|
|
41783
|
+
ctx.instanceManager.sendEvent(bundle.target.instanceId, "send_message", { text });
|
|
41784
|
+
while (Date.now() - startAt < Math.max(1e3, timeoutMs)) {
|
|
41785
|
+
await sleep(150);
|
|
41786
|
+
bundle = getCliTargetBundle(ctx, type, bundle.target.instanceId);
|
|
41787
|
+
if (!bundle) {
|
|
41788
|
+
throw new Error("CLI instance disappeared during exercise");
|
|
41789
|
+
}
|
|
41790
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
41791
|
+
const trace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
41792
|
+
const status = String(debug?.status || bundle.target.status || "unknown");
|
|
41793
|
+
const traceEntries = Array.isArray(trace?.entries) ? trace.entries : [];
|
|
41794
|
+
const sawSendMessage = traceEntries.some((entry) => entry?.type === "send_message");
|
|
41795
|
+
const sawSubmitWrite = traceEntries.some((entry) => entry?.type === "submit_write");
|
|
41796
|
+
const hasTurnStarted = sawSendMessage || sawSubmitWrite || !!debug?.currentTurnScope;
|
|
41797
|
+
if (status !== lastStatus) {
|
|
41798
|
+
statusesSeen.push(status);
|
|
41799
|
+
lastStatus = status;
|
|
41800
|
+
}
|
|
41801
|
+
if (status === "generating" || status === "waiting_approval") {
|
|
41802
|
+
sawBusy = true;
|
|
41803
|
+
idleSince = 0;
|
|
41804
|
+
}
|
|
41805
|
+
const modal = debug?.activeModal || trace?.activeModal || null;
|
|
41806
|
+
if (autoResolveApprovals && status === "waiting_approval" && modal && Array.isArray(modal.buttons) && modal.buttons.length > 0) {
|
|
41807
|
+
const clampedIndex = Math.max(0, Math.min(Number(approvalButtonIndex) || 0, modal.buttons.length - 1));
|
|
41808
|
+
const modalKey = JSON.stringify({
|
|
41809
|
+
message: modal.message || "",
|
|
41810
|
+
buttons: modal.buttons,
|
|
41811
|
+
index: clampedIndex
|
|
41812
|
+
});
|
|
41813
|
+
if (modalKey !== lastModalKey && typeof bundle.adapter.resolveModal === "function") {
|
|
41814
|
+
lastModalKey = modalKey;
|
|
41815
|
+
approvalsResolved.push({
|
|
41816
|
+
at: Date.now(),
|
|
41817
|
+
buttonIndex: clampedIndex,
|
|
41818
|
+
label: modal.buttons[clampedIndex] || null
|
|
41819
|
+
});
|
|
41820
|
+
bundle.adapter.resolveModal(clampedIndex);
|
|
41821
|
+
continue;
|
|
41822
|
+
}
|
|
41823
|
+
}
|
|
41824
|
+
const traceCount = Number(trace?.entryCount || 0);
|
|
41825
|
+
const hasProgress = hasTurnStarted && (traceCount > preTraceCount || statusesSeen.length > 1 || approvalsResolved.length > 0);
|
|
41826
|
+
if (status === "idle" && hasProgress && sawBusy) {
|
|
41827
|
+
if (!idleSince) idleSince = Date.now();
|
|
41828
|
+
if (Date.now() - idleSince >= Math.max(200, idleSettledMs)) {
|
|
41829
|
+
const payload2 = {
|
|
41830
|
+
exercised: true,
|
|
41831
|
+
instanceId: bundle.target.instanceId,
|
|
41832
|
+
providerState: {
|
|
41833
|
+
type: bundle.target.type,
|
|
41834
|
+
name: bundle.target.name,
|
|
41835
|
+
status: bundle.target.status,
|
|
41836
|
+
mode: "mode" in bundle.target ? bundle.target.mode : void 0
|
|
41837
|
+
},
|
|
41838
|
+
providerResolution,
|
|
41839
|
+
initialDebug,
|
|
41840
|
+
initialTrace,
|
|
41841
|
+
debug,
|
|
41842
|
+
trace,
|
|
41843
|
+
statusesSeen,
|
|
41844
|
+
approvalsResolved,
|
|
41845
|
+
elapsedMs: Date.now() - startAt,
|
|
41846
|
+
timedOut: false
|
|
41847
|
+
};
|
|
41848
|
+
payload2.lastAssistant = getExerciseLastAssistant(payload2);
|
|
41849
|
+
payload2.messageCount = getExerciseMessageCount(payload2);
|
|
41850
|
+
if (stopWhenDone) {
|
|
41851
|
+
ctx.instanceManager.removeInstance(bundle.target.instanceId);
|
|
41852
|
+
}
|
|
41853
|
+
return payload2;
|
|
41854
|
+
}
|
|
41855
|
+
} else if (status === "idle" && hasProgress) {
|
|
41856
|
+
if (!idleSince) idleSince = Date.now();
|
|
41857
|
+
if (Date.now() - idleSince >= Math.max(500, idleSettledMs) && Date.now() - startAt >= 750) {
|
|
41858
|
+
const payload2 = {
|
|
41859
|
+
exercised: true,
|
|
41860
|
+
instanceId: bundle.target.instanceId,
|
|
41861
|
+
providerState: {
|
|
41862
|
+
type: bundle.target.type,
|
|
41863
|
+
name: bundle.target.name,
|
|
41864
|
+
status: bundle.target.status,
|
|
41865
|
+
mode: "mode" in bundle.target ? bundle.target.mode : void 0
|
|
41866
|
+
},
|
|
41867
|
+
providerResolution,
|
|
41868
|
+
initialDebug,
|
|
41869
|
+
initialTrace,
|
|
41870
|
+
debug,
|
|
41871
|
+
trace,
|
|
41872
|
+
statusesSeen,
|
|
41873
|
+
approvalsResolved,
|
|
41874
|
+
elapsedMs: Date.now() - startAt,
|
|
41875
|
+
timedOut: false
|
|
41876
|
+
};
|
|
41877
|
+
payload2.lastAssistant = getExerciseLastAssistant(payload2);
|
|
41878
|
+
payload2.messageCount = getExerciseMessageCount(payload2);
|
|
41879
|
+
if (stopWhenDone) {
|
|
41880
|
+
ctx.instanceManager.removeInstance(bundle.target.instanceId);
|
|
41881
|
+
}
|
|
41882
|
+
return payload2;
|
|
41883
|
+
}
|
|
41884
|
+
} else {
|
|
41885
|
+
idleSince = 0;
|
|
41886
|
+
}
|
|
41887
|
+
}
|
|
41888
|
+
const finalBundle = getCliTargetBundle(ctx, type, bundle.target.instanceId) || bundle;
|
|
41889
|
+
const finalDebug = typeof finalBundle.adapter.getDebugState === "function" ? finalBundle.adapter.getDebugState() : null;
|
|
41890
|
+
const finalTrace = typeof finalBundle.adapter.getTraceState === "function" ? finalBundle.adapter.getTraceState(traceLimit) : null;
|
|
41891
|
+
if (stopWhenDone) {
|
|
41892
|
+
ctx.instanceManager.removeInstance(finalBundle.target.instanceId);
|
|
41893
|
+
}
|
|
41894
|
+
const payload = {
|
|
41895
|
+
exercised: true,
|
|
41896
|
+
instanceId: finalBundle.target.instanceId,
|
|
41897
|
+
providerState: {
|
|
41898
|
+
type: finalBundle.target.type,
|
|
41899
|
+
name: finalBundle.target.name,
|
|
41900
|
+
status: finalBundle.target.status,
|
|
41901
|
+
mode: "mode" in finalBundle.target ? finalBundle.target.mode : void 0
|
|
41902
|
+
},
|
|
41903
|
+
providerResolution: getCliProviderResolutionMeta(ctx, finalBundle.target.type, finalBundle.adapter),
|
|
41904
|
+
initialDebug,
|
|
41905
|
+
initialTrace,
|
|
41906
|
+
debug: finalDebug,
|
|
41907
|
+
trace: finalTrace,
|
|
41908
|
+
statusesSeen,
|
|
41909
|
+
approvalsResolved,
|
|
41910
|
+
elapsedMs: Date.now() - startAt,
|
|
41911
|
+
timedOut: true
|
|
41912
|
+
};
|
|
41913
|
+
payload.lastAssistant = getExerciseLastAssistant(payload);
|
|
41914
|
+
payload.messageCount = getExerciseMessageCount(payload);
|
|
41915
|
+
return payload;
|
|
41916
|
+
}
|
|
41917
|
+
async function runCliAutoImplVerification(ctx, type, verification) {
|
|
41918
|
+
const assertions = {
|
|
41919
|
+
mustContainAny: verification?.mustContainAny || [],
|
|
41920
|
+
mustNotContainAny: verification?.mustNotContainAny || [],
|
|
41921
|
+
mustMatchAny: verification?.mustMatchAny || [],
|
|
41922
|
+
mustNotMatchAny: verification?.mustNotMatchAny || [],
|
|
41923
|
+
lastAssistantMustContainAny: verification?.lastAssistantMustContainAny || [],
|
|
41924
|
+
lastAssistantMustNotContainAny: verification?.lastAssistantMustNotContainAny || [],
|
|
41925
|
+
lastAssistantMustMatchAny: verification?.lastAssistantMustMatchAny || [],
|
|
41926
|
+
lastAssistantMustNotMatchAny: verification?.lastAssistantMustNotMatchAny || [],
|
|
41927
|
+
requireNotTimedOut: true
|
|
41928
|
+
};
|
|
41929
|
+
const rawFixtureNames = Array.isArray(verification?.fixtureNames) ? verification.fixtureNames.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
41930
|
+
if (rawFixtureNames.length > 0) {
|
|
41931
|
+
const results = [];
|
|
41932
|
+
for (const rawFixtureName2 of rawFixtureNames) {
|
|
41933
|
+
const name = slugifyFixtureName(rawFixtureName2);
|
|
41934
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
41935
|
+
const mergedAssertions = {
|
|
41936
|
+
...fixture.assertions,
|
|
41937
|
+
...assertions
|
|
41938
|
+
};
|
|
41939
|
+
const result2 = await runCliExerciseInternal(ctx, {
|
|
41940
|
+
...fixture.request,
|
|
41941
|
+
type
|
|
41942
|
+
});
|
|
41943
|
+
const failures2 = validateCliFixtureResult(result2, mergedAssertions);
|
|
41944
|
+
results.push({
|
|
41945
|
+
fixtureName: name,
|
|
41946
|
+
pass: failures2.length === 0,
|
|
41947
|
+
failures: failures2,
|
|
41948
|
+
result: result2,
|
|
41949
|
+
assertions: mergedAssertions,
|
|
41950
|
+
fixture
|
|
41951
|
+
});
|
|
41952
|
+
}
|
|
41953
|
+
const firstFailure = results.find((item) => !item.pass) || results[results.length - 1];
|
|
41954
|
+
return {
|
|
41955
|
+
mode: "fixture_replay_suite",
|
|
41956
|
+
pass: results.every((item) => item.pass),
|
|
41957
|
+
failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
|
|
41958
|
+
result: firstFailure.result,
|
|
41959
|
+
assertions: firstFailure.assertions,
|
|
41960
|
+
fixture: firstFailure.fixture,
|
|
41961
|
+
results
|
|
41962
|
+
};
|
|
41963
|
+
}
|
|
41964
|
+
const rawFixtureName = String(verification?.fixtureName || "").trim();
|
|
41965
|
+
if (rawFixtureName) {
|
|
41966
|
+
const name = slugifyFixtureName(rawFixtureName);
|
|
41967
|
+
try {
|
|
41968
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
41969
|
+
const mergedAssertions = {
|
|
41970
|
+
...fixture.assertions,
|
|
41971
|
+
...assertions
|
|
41972
|
+
};
|
|
41973
|
+
const result2 = await runCliExerciseInternal(ctx, {
|
|
41974
|
+
...fixture.request,
|
|
41975
|
+
type
|
|
41976
|
+
});
|
|
41977
|
+
const failures2 = validateCliFixtureResult(result2, mergedAssertions);
|
|
41978
|
+
return {
|
|
41979
|
+
mode: "fixture_replay",
|
|
41980
|
+
pass: failures2.length === 0,
|
|
41981
|
+
failures: failures2,
|
|
41982
|
+
result: result2,
|
|
41983
|
+
assertions: mergedAssertions,
|
|
41984
|
+
fixture
|
|
41985
|
+
};
|
|
41986
|
+
} catch {
|
|
41987
|
+
}
|
|
41988
|
+
}
|
|
41989
|
+
const result = await runCliExerciseInternal(ctx, {
|
|
41990
|
+
...verification?.request || {},
|
|
41991
|
+
type
|
|
41992
|
+
});
|
|
41993
|
+
const failures = validateCliFixtureResult(result, assertions);
|
|
41994
|
+
return {
|
|
41995
|
+
mode: "exercise",
|
|
41996
|
+
pass: failures.length === 0,
|
|
41997
|
+
failures,
|
|
41998
|
+
result,
|
|
41999
|
+
assertions
|
|
42000
|
+
};
|
|
42001
|
+
}
|
|
41062
42002
|
async function handleCliStatus(ctx, _req, res) {
|
|
41063
42003
|
if (!ctx.instanceManager) {
|
|
41064
42004
|
ctx.json(res, 503, { error: "InstanceManager not available (daemon not fully initialized)" });
|
|
@@ -41197,12 +42137,14 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
41197
42137
|
status: target.status,
|
|
41198
42138
|
mode: "mode" in target ? target.mode : void 0
|
|
41199
42139
|
},
|
|
42140
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
41200
42141
|
debug: debugState
|
|
41201
42142
|
});
|
|
41202
42143
|
} else {
|
|
41203
42144
|
ctx.json(res, 200, {
|
|
41204
42145
|
instanceId: target.instanceId,
|
|
41205
42146
|
providerState: target,
|
|
42147
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
41206
42148
|
debug: null,
|
|
41207
42149
|
message: "No debug state available (adapter.getDebugState not found)"
|
|
41208
42150
|
});
|
|
@@ -41211,6 +42153,191 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
41211
42153
|
ctx.json(res, 500, { error: `Debug state failed: ${e.message}` });
|
|
41212
42154
|
}
|
|
41213
42155
|
}
|
|
42156
|
+
async function handleCliTrace(ctx, type, req, res) {
|
|
42157
|
+
if (!ctx.instanceManager) {
|
|
42158
|
+
ctx.json(res, 503, { error: "InstanceManager not available" });
|
|
42159
|
+
return;
|
|
42160
|
+
}
|
|
42161
|
+
const target = findCliTarget(ctx, type);
|
|
42162
|
+
if (!target) {
|
|
42163
|
+
const allStates = ctx.instanceManager.collectAllStates();
|
|
42164
|
+
ctx.json(res, 404, {
|
|
42165
|
+
error: `No running instance for: ${type}`,
|
|
42166
|
+
available: allStates.filter((s15) => s15.category === "cli" || s15.category === "acp").map((s15) => s15.type)
|
|
42167
|
+
});
|
|
42168
|
+
return;
|
|
42169
|
+
}
|
|
42170
|
+
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
42171
|
+
if (!instance) {
|
|
42172
|
+
ctx.json(res, 404, { error: `Instance not found: ${target.instanceId}` });
|
|
42173
|
+
return;
|
|
42174
|
+
}
|
|
42175
|
+
try {
|
|
42176
|
+
const adapter = instance.getAdapter?.() || instance.adapter;
|
|
42177
|
+
const url2 = new URL(req.url || "/", "http://127.0.0.1");
|
|
42178
|
+
const limit = parseInt(url2.searchParams.get("limit") || "120", 10);
|
|
42179
|
+
if (adapter && typeof adapter.getTraceState === "function") {
|
|
42180
|
+
const trace = adapter.getTraceState(limit);
|
|
42181
|
+
const debug = typeof adapter.getDebugState === "function" ? adapter.getDebugState() : null;
|
|
42182
|
+
ctx.json(res, 200, {
|
|
42183
|
+
instanceId: target.instanceId,
|
|
42184
|
+
providerState: {
|
|
42185
|
+
type: target.type,
|
|
42186
|
+
name: target.name,
|
|
42187
|
+
status: target.status,
|
|
42188
|
+
mode: "mode" in target ? target.mode : void 0
|
|
42189
|
+
},
|
|
42190
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
42191
|
+
debug,
|
|
42192
|
+
trace
|
|
42193
|
+
});
|
|
42194
|
+
} else {
|
|
42195
|
+
ctx.json(res, 200, {
|
|
42196
|
+
instanceId: target.instanceId,
|
|
42197
|
+
providerState: target,
|
|
42198
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
42199
|
+
debug: typeof adapter?.getDebugState === "function" ? adapter.getDebugState() : null,
|
|
42200
|
+
trace: null,
|
|
42201
|
+
message: "No trace state available (adapter.getTraceState not found)"
|
|
42202
|
+
});
|
|
42203
|
+
}
|
|
42204
|
+
} catch (e) {
|
|
42205
|
+
ctx.json(res, 500, { error: `Trace state failed: ${e.message}` });
|
|
42206
|
+
}
|
|
42207
|
+
}
|
|
42208
|
+
async function handleCliExercise(ctx, req, res) {
|
|
42209
|
+
try {
|
|
42210
|
+
const body = await ctx.readBody(req);
|
|
42211
|
+
const result = await runCliExerciseInternal(ctx, body || {});
|
|
42212
|
+
ctx.json(res, 200, result);
|
|
42213
|
+
} catch (e) {
|
|
42214
|
+
ctx.json(res, 500, { error: `Exercise failed: ${e.message}` });
|
|
42215
|
+
}
|
|
42216
|
+
}
|
|
42217
|
+
async function handleCliFixtureCapture(ctx, req, res) {
|
|
42218
|
+
try {
|
|
42219
|
+
const body = await ctx.readBody(req);
|
|
42220
|
+
const type = String(body?.type || "");
|
|
42221
|
+
const request = body?.request || {};
|
|
42222
|
+
if (!type) {
|
|
42223
|
+
ctx.json(res, 400, { error: "type required" });
|
|
42224
|
+
return;
|
|
42225
|
+
}
|
|
42226
|
+
if (!request?.text) {
|
|
42227
|
+
ctx.json(res, 400, { error: "request.text required" });
|
|
42228
|
+
return;
|
|
42229
|
+
}
|
|
42230
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
42231
|
+
fs12.mkdirSync(fixtureDir, { recursive: true });
|
|
42232
|
+
const name = slugifyFixtureName(String(body?.name || `${type}-${Date.now()}`));
|
|
42233
|
+
const result = await runCliExerciseInternal(ctx, { ...request, type });
|
|
42234
|
+
const fixture = {
|
|
42235
|
+
version: 1,
|
|
42236
|
+
kind: "cli-exercise-fixture",
|
|
42237
|
+
name,
|
|
42238
|
+
type,
|
|
42239
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
42240
|
+
providerDir: ctx.providerLoader.findProviderDir(type),
|
|
42241
|
+
providerResolution: result?.providerResolution || null,
|
|
42242
|
+
request: { ...request, type },
|
|
42243
|
+
result,
|
|
42244
|
+
assertions: {
|
|
42245
|
+
mustContainAny: Array.isArray(body?.assertions?.mustContainAny) ? body.assertions.mustContainAny : [],
|
|
42246
|
+
mustNotContainAny: Array.isArray(body?.assertions?.mustNotContainAny) ? body.assertions.mustNotContainAny : [],
|
|
42247
|
+
mustMatchAny: Array.isArray(body?.assertions?.mustMatchAny) ? body.assertions.mustMatchAny : [],
|
|
42248
|
+
mustNotMatchAny: Array.isArray(body?.assertions?.mustNotMatchAny) ? body.assertions.mustNotMatchAny : [],
|
|
42249
|
+
lastAssistantMustContainAny: Array.isArray(body?.assertions?.lastAssistantMustContainAny) ? body.assertions.lastAssistantMustContainAny : [],
|
|
42250
|
+
lastAssistantMustNotContainAny: Array.isArray(body?.assertions?.lastAssistantMustNotContainAny) ? body.assertions.lastAssistantMustNotContainAny : [],
|
|
42251
|
+
lastAssistantMustMatchAny: Array.isArray(body?.assertions?.lastAssistantMustMatchAny) ? body.assertions.lastAssistantMustMatchAny : [],
|
|
42252
|
+
lastAssistantMustNotMatchAny: Array.isArray(body?.assertions?.lastAssistantMustNotMatchAny) ? body.assertions.lastAssistantMustNotMatchAny : [],
|
|
42253
|
+
statusesSeen: Array.isArray(body?.assertions?.statusesSeen) ? body.assertions.statusesSeen : void 0,
|
|
42254
|
+
requireNotTimedOut: body?.assertions?.requireNotTimedOut !== false
|
|
42255
|
+
},
|
|
42256
|
+
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
42257
|
+
};
|
|
42258
|
+
const filePath = path15.join(fixtureDir, `${name}.json`);
|
|
42259
|
+
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
42260
|
+
ctx.json(res, 200, {
|
|
42261
|
+
saved: true,
|
|
42262
|
+
name,
|
|
42263
|
+
path: filePath,
|
|
42264
|
+
fixture,
|
|
42265
|
+
verification: {
|
|
42266
|
+
pass: validateCliFixtureResult(result, fixture.assertions).length === 0,
|
|
42267
|
+
failures: validateCliFixtureResult(result, fixture.assertions)
|
|
42268
|
+
}
|
|
42269
|
+
});
|
|
42270
|
+
} catch (e) {
|
|
42271
|
+
ctx.json(res, 500, { error: `Fixture capture failed: ${e.message}` });
|
|
42272
|
+
}
|
|
42273
|
+
}
|
|
42274
|
+
async function handleCliFixtureList(ctx, type, _req, res) {
|
|
42275
|
+
try {
|
|
42276
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
42277
|
+
if (!fs12.existsSync(fixtureDir)) {
|
|
42278
|
+
ctx.json(res, 200, { fixtures: [], count: 0 });
|
|
42279
|
+
return;
|
|
42280
|
+
}
|
|
42281
|
+
const fixtures = fs12.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
|
|
42282
|
+
const fullPath = path15.join(fixtureDir, file2);
|
|
42283
|
+
try {
|
|
42284
|
+
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
42285
|
+
return {
|
|
42286
|
+
name: raw.name || file2.replace(/\.json$/i, ""),
|
|
42287
|
+
path: fullPath,
|
|
42288
|
+
createdAt: raw.createdAt || null,
|
|
42289
|
+
notes: raw.notes || null,
|
|
42290
|
+
requestText: raw.request?.text || "",
|
|
42291
|
+
assertions: raw.assertions || {}
|
|
42292
|
+
};
|
|
42293
|
+
} catch {
|
|
42294
|
+
return {
|
|
42295
|
+
name: file2.replace(/\.json$/i, ""),
|
|
42296
|
+
path: fullPath,
|
|
42297
|
+
createdAt: null,
|
|
42298
|
+
notes: "Unreadable fixture",
|
|
42299
|
+
requestText: "",
|
|
42300
|
+
assertions: {}
|
|
42301
|
+
};
|
|
42302
|
+
}
|
|
42303
|
+
});
|
|
42304
|
+
ctx.json(res, 200, { fixtures, count: fixtures.length });
|
|
42305
|
+
} catch (e) {
|
|
42306
|
+
ctx.json(res, 500, { error: `Fixture list failed: ${e.message}` });
|
|
42307
|
+
}
|
|
42308
|
+
}
|
|
42309
|
+
async function handleCliFixtureReplay(ctx, req, res) {
|
|
42310
|
+
try {
|
|
42311
|
+
const body = await ctx.readBody(req);
|
|
42312
|
+
const type = String(body?.type || "");
|
|
42313
|
+
const rawName = String(body?.name || "").trim();
|
|
42314
|
+
if (!type || !rawName) {
|
|
42315
|
+
ctx.json(res, 400, { error: "type and name required" });
|
|
42316
|
+
return;
|
|
42317
|
+
}
|
|
42318
|
+
const name = slugifyFixtureName(rawName);
|
|
42319
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
42320
|
+
const result = await runCliExerciseInternal(ctx, {
|
|
42321
|
+
...fixture.request,
|
|
42322
|
+
type
|
|
42323
|
+
});
|
|
42324
|
+
const assertions = {
|
|
42325
|
+
...fixture.assertions,
|
|
42326
|
+
...body?.assertions || {}
|
|
42327
|
+
};
|
|
42328
|
+
const failures = validateCliFixtureResult(result, assertions);
|
|
42329
|
+
ctx.json(res, 200, {
|
|
42330
|
+
replayed: true,
|
|
42331
|
+
pass: failures.length === 0,
|
|
42332
|
+
failures,
|
|
42333
|
+
fixture,
|
|
42334
|
+
result,
|
|
42335
|
+
assertions
|
|
42336
|
+
});
|
|
42337
|
+
} catch (e) {
|
|
42338
|
+
ctx.json(res, 500, { error: `Fixture replay failed: ${e.message}` });
|
|
42339
|
+
}
|
|
42340
|
+
}
|
|
41214
42341
|
async function handleCliResolve(ctx, req, res) {
|
|
41215
42342
|
const body = await ctx.readBody(req);
|
|
41216
42343
|
const { type, buttonIndex, instanceId } = body;
|
|
@@ -41285,13 +42412,36 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
41285
42412
|
ctx.json(res, 500, { error: `Raw send failed: ${e.message}` });
|
|
41286
42413
|
}
|
|
41287
42414
|
}
|
|
42415
|
+
var fs12, path15;
|
|
41288
42416
|
var init_dev_cli_debug = __esm({
|
|
41289
42417
|
"../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts"() {
|
|
41290
42418
|
"use strict";
|
|
42419
|
+
fs12 = __toESM(require("fs"));
|
|
42420
|
+
path15 = __toESM(require("path"));
|
|
41291
42421
|
}
|
|
41292
42422
|
});
|
|
41293
42423
|
|
|
41294
42424
|
// ../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts
|
|
42425
|
+
function getAutoImplPid(ctx) {
|
|
42426
|
+
const proc = ctx.autoImplProcess;
|
|
42427
|
+
return proc && typeof proc.pid === "number" && proc.pid > 0 ? proc.pid : null;
|
|
42428
|
+
}
|
|
42429
|
+
function isPidAlive(pid) {
|
|
42430
|
+
try {
|
|
42431
|
+
process.kill(pid, 0);
|
|
42432
|
+
return true;
|
|
42433
|
+
} catch (error48) {
|
|
42434
|
+
return error48?.code === "EPERM";
|
|
42435
|
+
}
|
|
42436
|
+
}
|
|
42437
|
+
function clearStaleAutoImplState(ctx, reason) {
|
|
42438
|
+
if (!ctx.autoImplStatus.running && !ctx.autoImplProcess) return;
|
|
42439
|
+
const pid = getAutoImplPid(ctx);
|
|
42440
|
+
if (pid && isPidAlive(pid)) return;
|
|
42441
|
+
ctx.log(`Clearing stale auto-implement state: ${reason}${pid ? ` (pid ${pid})` : ""}`);
|
|
42442
|
+
ctx.autoImplProcess = null;
|
|
42443
|
+
ctx.autoImplStatus.running = false;
|
|
42444
|
+
}
|
|
41295
42445
|
function getDefaultAutoImplReference(ctx, category, type) {
|
|
41296
42446
|
if (category === "cli") {
|
|
41297
42447
|
return type === "codex-cli" ? "claude-cli" : "codex-cli";
|
|
@@ -41307,45 +42457,45 @@ function resolveAutoImplReference(ctx, category, requestedReference, targetType)
|
|
|
41307
42457
|
return fallback?.type || null;
|
|
41308
42458
|
}
|
|
41309
42459
|
function getLatestScriptVersionDir(scriptsDir) {
|
|
41310
|
-
if (!
|
|
41311
|
-
const versions =
|
|
42460
|
+
if (!fs13.existsSync(scriptsDir)) return null;
|
|
42461
|
+
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
41312
42462
|
try {
|
|
41313
|
-
return
|
|
42463
|
+
return fs13.statSync(path16.join(scriptsDir, d)).isDirectory();
|
|
41314
42464
|
} catch {
|
|
41315
42465
|
return false;
|
|
41316
42466
|
}
|
|
41317
42467
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
41318
42468
|
if (versions.length === 0) return null;
|
|
41319
|
-
return
|
|
42469
|
+
return path16.join(scriptsDir, versions[0]);
|
|
41320
42470
|
}
|
|
41321
42471
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
41322
|
-
const canonicalUserDir =
|
|
41323
|
-
const desiredDir = requestedDir ?
|
|
41324
|
-
const upstreamRoot =
|
|
41325
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
42472
|
+
const canonicalUserDir = path16.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
42473
|
+
const desiredDir = requestedDir ? path16.resolve(requestedDir) : canonicalUserDir;
|
|
42474
|
+
const upstreamRoot = path16.resolve(ctx.providerLoader.getUpstreamDir());
|
|
42475
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path16.sep}`)) {
|
|
41326
42476
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
41327
42477
|
}
|
|
41328
|
-
if (
|
|
42478
|
+
if (path16.basename(desiredDir) !== type) {
|
|
41329
42479
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
41330
42480
|
}
|
|
41331
42481
|
const sourceDir = ctx.findProviderDir(type);
|
|
41332
42482
|
if (!sourceDir) {
|
|
41333
42483
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
41334
42484
|
}
|
|
41335
|
-
if (!
|
|
41336
|
-
|
|
41337
|
-
|
|
42485
|
+
if (!fs13.existsSync(desiredDir)) {
|
|
42486
|
+
fs13.mkdirSync(path16.dirname(desiredDir), { recursive: true });
|
|
42487
|
+
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
41338
42488
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
41339
42489
|
}
|
|
41340
|
-
const providerJson =
|
|
41341
|
-
if (!
|
|
42490
|
+
const providerJson = path16.join(desiredDir, "provider.json");
|
|
42491
|
+
if (!fs13.existsSync(providerJson)) {
|
|
41342
42492
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
41343
42493
|
}
|
|
41344
42494
|
try {
|
|
41345
|
-
const providerData = JSON.parse(
|
|
42495
|
+
const providerData = JSON.parse(fs13.readFileSync(providerJson, "utf-8"));
|
|
41346
42496
|
if (providerData.disableUpstream !== true) {
|
|
41347
42497
|
providerData.disableUpstream = true;
|
|
41348
|
-
|
|
42498
|
+
fs13.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
41349
42499
|
}
|
|
41350
42500
|
} catch (error48) {
|
|
41351
42501
|
return {
|
|
@@ -41358,15 +42508,15 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
41358
42508
|
function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
41359
42509
|
if (!referenceType) return {};
|
|
41360
42510
|
const refDir = ctx.findProviderDir(referenceType);
|
|
41361
|
-
if (!refDir || !
|
|
42511
|
+
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
41362
42512
|
const referenceScripts = {};
|
|
41363
|
-
const scriptsDir =
|
|
42513
|
+
const scriptsDir = path16.join(refDir, "scripts");
|
|
41364
42514
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
41365
42515
|
if (!latestDir) return referenceScripts;
|
|
41366
|
-
for (const file2 of
|
|
42516
|
+
for (const file2 of fs13.readdirSync(latestDir)) {
|
|
41367
42517
|
if (!file2.endsWith(".js")) continue;
|
|
41368
42518
|
try {
|
|
41369
|
-
referenceScripts[file2] =
|
|
42519
|
+
referenceScripts[file2] = fs13.readFileSync(path16.join(latestDir, file2), "utf-8");
|
|
41370
42520
|
} catch {
|
|
41371
42521
|
}
|
|
41372
42522
|
}
|
|
@@ -41374,11 +42524,20 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
41374
42524
|
}
|
|
41375
42525
|
async function handleAutoImplement(ctx, type, req, res) {
|
|
41376
42526
|
const body = await ctx.readBody(req);
|
|
41377
|
-
const {
|
|
42527
|
+
const {
|
|
42528
|
+
agent = "claude-cli",
|
|
42529
|
+
functions,
|
|
42530
|
+
reference,
|
|
42531
|
+
model,
|
|
42532
|
+
comment,
|
|
42533
|
+
providerDir: requestedProviderDir,
|
|
42534
|
+
verification
|
|
42535
|
+
} = body;
|
|
41378
42536
|
if (!functions || !Array.isArray(functions) || functions.length === 0) {
|
|
41379
42537
|
ctx.json(res, 400, { error: 'functions[] is required (e.g. ["readChat", "sendMessage"])' });
|
|
41380
42538
|
return;
|
|
41381
42539
|
}
|
|
42540
|
+
clearStaleAutoImplState(ctx, "new auto-implement request");
|
|
41382
42541
|
if (ctx.autoImplStatus.running) {
|
|
41383
42542
|
ctx.json(res, 409, { error: "Auto-implement already in progress", type: ctx.autoImplStatus.type });
|
|
41384
42543
|
return;
|
|
@@ -41396,7 +42555,55 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41396
42555
|
return;
|
|
41397
42556
|
}
|
|
41398
42557
|
const providerDir = writableProvider.dir;
|
|
42558
|
+
ctx.autoImplStatus = { running: false, type, progress: [] };
|
|
42559
|
+
if (provider.category === "cli" && verification && (verification.fixtureName || verification.fixtureNames && verification.fixtureNames.length > 0)) {
|
|
42560
|
+
sendAutoImplSSE(ctx, {
|
|
42561
|
+
event: "progress",
|
|
42562
|
+
data: {
|
|
42563
|
+
function: "_preflight",
|
|
42564
|
+
status: "verifying",
|
|
42565
|
+
message: "Running preflight verification before spawning agent..."
|
|
42566
|
+
}
|
|
42567
|
+
});
|
|
42568
|
+
try {
|
|
42569
|
+
const preflight = await runCliAutoImplVerification(ctx, type, verification);
|
|
42570
|
+
sendAutoImplSSE(ctx, { event: "verification", data: preflight });
|
|
42571
|
+
if (preflight.pass) {
|
|
42572
|
+
sendAutoImplSSE(ctx, {
|
|
42573
|
+
event: "complete",
|
|
42574
|
+
data: {
|
|
42575
|
+
success: true,
|
|
42576
|
+
exitCode: 0,
|
|
42577
|
+
functions,
|
|
42578
|
+
message: `\u2705 No-op: exact ${preflight.mode} already passes`,
|
|
42579
|
+
verification: preflight,
|
|
42580
|
+
skipped: true
|
|
42581
|
+
}
|
|
42582
|
+
});
|
|
42583
|
+
ctx.json(res, 200, {
|
|
42584
|
+
started: false,
|
|
42585
|
+
skipped: true,
|
|
42586
|
+
type,
|
|
42587
|
+
functions,
|
|
42588
|
+
providerDir,
|
|
42589
|
+
verification: preflight,
|
|
42590
|
+
message: "Preflight verification already passes. No auto-implement run needed."
|
|
42591
|
+
});
|
|
42592
|
+
return;
|
|
42593
|
+
}
|
|
42594
|
+
} catch (error48) {
|
|
42595
|
+
sendAutoImplSSE(ctx, {
|
|
42596
|
+
event: "progress",
|
|
42597
|
+
data: {
|
|
42598
|
+
function: "_preflight",
|
|
42599
|
+
status: "verify_failed",
|
|
42600
|
+
message: `Preflight verification errored, continuing to agent run: ${error48?.message || error48}`
|
|
42601
|
+
}
|
|
42602
|
+
});
|
|
42603
|
+
}
|
|
42604
|
+
}
|
|
41399
42605
|
try {
|
|
42606
|
+
ctx.autoImplStatus = { running: true, type, progress: ctx.autoImplStatus.progress };
|
|
41400
42607
|
const resolvedReference = resolveAutoImplReference(ctx, provider.category, reference, type);
|
|
41401
42608
|
sendAutoImplSSE(ctx, {
|
|
41402
42609
|
event: "progress",
|
|
@@ -41416,17 +42623,17 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41416
42623
|
}
|
|
41417
42624
|
});
|
|
41418
42625
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
41419
|
-
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
|
|
41420
|
-
const tmpDir =
|
|
41421
|
-
if (!
|
|
41422
|
-
const promptFile =
|
|
41423
|
-
|
|
42626
|
+
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
42627
|
+
const tmpDir = path16.join(os17.tmpdir(), "adhdev-autoimpl");
|
|
42628
|
+
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
42629
|
+
const promptFile = path16.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
42630
|
+
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
41424
42631
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
41425
42632
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
41426
42633
|
const spawn5 = agentProvider?.spawn;
|
|
41427
42634
|
if (!spawn5?.command) {
|
|
41428
42635
|
try {
|
|
41429
|
-
|
|
42636
|
+
fs13.unlinkSync(promptFile);
|
|
41430
42637
|
} catch {
|
|
41431
42638
|
}
|
|
41432
42639
|
ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -41435,7 +42642,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41435
42642
|
const agentCategory = agentProvider?.category;
|
|
41436
42643
|
if (agentCategory === "acp") {
|
|
41437
42644
|
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn5.command} ${(spawn5.args || []).join(" ")}` } });
|
|
41438
|
-
ctx.autoImplStatus =
|
|
42645
|
+
ctx.autoImplStatus.running = true;
|
|
42646
|
+
ctx.autoImplStatus.type = type;
|
|
41439
42647
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
41440
42648
|
const { Readable: Readable3, Writable: Writable2 } = await import("stream");
|
|
41441
42649
|
const { spawn: spawnFn2 } = await import("child_process");
|
|
@@ -41527,7 +42735,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41527
42735
|
} catch {
|
|
41528
42736
|
}
|
|
41529
42737
|
try {
|
|
41530
|
-
|
|
42738
|
+
fs13.unlinkSync(promptFile);
|
|
41531
42739
|
} catch {
|
|
41532
42740
|
}
|
|
41533
42741
|
ctx.log(`Auto-implement (ACP) ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -41605,7 +42813,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41605
42813
|
}
|
|
41606
42814
|
}
|
|
41607
42815
|
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning agent: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
|
|
41608
|
-
ctx.autoImplStatus =
|
|
42816
|
+
ctx.autoImplStatus.running = true;
|
|
42817
|
+
ctx.autoImplStatus.type = type;
|
|
41609
42818
|
const spawnedAt = Date.now();
|
|
41610
42819
|
let child;
|
|
41611
42820
|
let isPty = false;
|
|
@@ -41648,6 +42857,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41648
42857
|
let approvalKeys = { 0: "y\r" };
|
|
41649
42858
|
let approvalBuffer = "";
|
|
41650
42859
|
let lastApprovalTime = 0;
|
|
42860
|
+
let completionSignalSeen = false;
|
|
41651
42861
|
try {
|
|
41652
42862
|
const { normalizeCliProviderForRuntime: normalizeCliProviderForRuntime2 } = await Promise.resolve().then(() => (init_provider_cli_adapter(), provider_cli_adapter_exports));
|
|
41653
42863
|
const normalized = normalizeCliProviderForRuntime2(agentProvider);
|
|
@@ -41661,6 +42871,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41661
42871
|
approvalBuffer = (approvalBuffer + cleanData).slice(-1500);
|
|
41662
42872
|
const elapsed = Date.now() - spawnedAt;
|
|
41663
42873
|
if (elapsed > 15e3 && cleanData.includes("_PIPELINE_COMPLETE_SIGNAL_")) {
|
|
42874
|
+
completionSignalSeen = true;
|
|
41664
42875
|
ctx.log(`Agent finished task after ${Math.round(elapsed / 1e3)}s. Terminating interactive CLI session to unblock pipeline.`);
|
|
41665
42876
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: `
|
|
41666
42877
|
[\u{1F916} ADHDev Pipeline] Completion token detected. Proceeding...
|
|
@@ -41684,6 +42895,55 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41684
42895
|
lastApprovalTime = Date.now();
|
|
41685
42896
|
}
|
|
41686
42897
|
};
|
|
42898
|
+
const finalizeCliAutoImpl = async (code) => {
|
|
42899
|
+
ctx.autoImplProcess = null;
|
|
42900
|
+
let success2 = completionSignalSeen || code === 0;
|
|
42901
|
+
let message = success2 ? completionSignalSeen && code !== 0 ? "\u2705 Auto-implement complete (completion signal)" : "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`;
|
|
42902
|
+
let verificationSummary = null;
|
|
42903
|
+
try {
|
|
42904
|
+
ctx.providerLoader.reload();
|
|
42905
|
+
} catch {
|
|
42906
|
+
}
|
|
42907
|
+
if (provider.category === "cli" && verification) {
|
|
42908
|
+
sendAutoImplSSE(ctx, {
|
|
42909
|
+
event: "progress",
|
|
42910
|
+
data: {
|
|
42911
|
+
function: "_verify",
|
|
42912
|
+
status: "running",
|
|
42913
|
+
message: "Running exact post-patch verification..."
|
|
42914
|
+
}
|
|
42915
|
+
});
|
|
42916
|
+
try {
|
|
42917
|
+
verificationSummary = await runCliAutoImplVerification(ctx, type, verification);
|
|
42918
|
+
sendAutoImplSSE(ctx, { event: "verification", data: verificationSummary });
|
|
42919
|
+
success2 = verificationSummary.pass;
|
|
42920
|
+
message = verificationSummary.pass ? `\u2705 Auto-implement complete (${verificationSummary.mode})` : `\u274C Post-patch verification failed (${verificationSummary.mode}): ${verificationSummary.failures.join("; ") || "unknown failure"}`;
|
|
42921
|
+
} catch (error48) {
|
|
42922
|
+
success2 = false;
|
|
42923
|
+
message = `\u274C Post-patch verification error: ${error48?.message || error48}`;
|
|
42924
|
+
sendAutoImplSSE(ctx, {
|
|
42925
|
+
event: "verification",
|
|
42926
|
+
data: { pass: false, error: error48?.message || String(error48) }
|
|
42927
|
+
});
|
|
42928
|
+
}
|
|
42929
|
+
}
|
|
42930
|
+
ctx.autoImplStatus.running = false;
|
|
42931
|
+
sendAutoImplSSE(ctx, {
|
|
42932
|
+
event: "complete",
|
|
42933
|
+
data: {
|
|
42934
|
+
success: success2,
|
|
42935
|
+
exitCode: code,
|
|
42936
|
+
functions,
|
|
42937
|
+
message,
|
|
42938
|
+
verification: verificationSummary
|
|
42939
|
+
}
|
|
42940
|
+
});
|
|
42941
|
+
try {
|
|
42942
|
+
fs13.unlinkSync(promptFile);
|
|
42943
|
+
} catch {
|
|
42944
|
+
}
|
|
42945
|
+
ctx.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})${verificationSummary ? ` verify=${verificationSummary.pass ? "pass" : "fail"}` : ""}`);
|
|
42946
|
+
};
|
|
41687
42947
|
if (isPty) {
|
|
41688
42948
|
child.onData((data) => {
|
|
41689
42949
|
stdout += data;
|
|
@@ -41695,21 +42955,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41695
42955
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
|
|
41696
42956
|
});
|
|
41697
42957
|
child.onExit(({ exitCode: code }) => {
|
|
41698
|
-
|
|
41699
|
-
ctx.autoImplStatus.running = false;
|
|
41700
|
-
const success2 = code === 0;
|
|
41701
|
-
sendAutoImplSSE(ctx, {
|
|
41702
|
-
event: "complete",
|
|
41703
|
-
data: { success: success2, exitCode: code, functions, message: success2 ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})` }
|
|
41704
|
-
});
|
|
41705
|
-
try {
|
|
41706
|
-
ctx.providerLoader.reload();
|
|
41707
|
-
} catch {
|
|
41708
|
-
}
|
|
41709
|
-
try {
|
|
41710
|
-
fs12.unlinkSync(promptFile);
|
|
41711
|
-
} catch {
|
|
41712
|
-
}
|
|
42958
|
+
void finalizeCliAutoImpl(code);
|
|
41713
42959
|
});
|
|
41714
42960
|
} else {
|
|
41715
42961
|
child.stdout?.on("data", (d) => {
|
|
@@ -41726,27 +42972,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41726
42972
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
|
|
41727
42973
|
});
|
|
41728
42974
|
child.on("exit", (code) => {
|
|
41729
|
-
|
|
41730
|
-
ctx.autoImplStatus.running = false;
|
|
41731
|
-
const success2 = code === 0;
|
|
41732
|
-
sendAutoImplSSE(ctx, {
|
|
41733
|
-
event: "complete",
|
|
41734
|
-
data: {
|
|
41735
|
-
success: success2,
|
|
41736
|
-
exitCode: code,
|
|
41737
|
-
functions,
|
|
41738
|
-
message: success2 ? "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`
|
|
41739
|
-
}
|
|
41740
|
-
});
|
|
41741
|
-
try {
|
|
41742
|
-
ctx.providerLoader.reload();
|
|
41743
|
-
} catch {
|
|
41744
|
-
}
|
|
41745
|
-
try {
|
|
41746
|
-
fs12.unlinkSync(promptFile);
|
|
41747
|
-
} catch {
|
|
41748
|
-
}
|
|
41749
|
-
ctx.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
42975
|
+
void finalizeCliAutoImpl(code);
|
|
41750
42976
|
});
|
|
41751
42977
|
}
|
|
41752
42978
|
ctx.json(res, 202, {
|
|
@@ -41763,9 +42989,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41763
42989
|
ctx.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
|
|
41764
42990
|
}
|
|
41765
42991
|
}
|
|
41766
|
-
function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType) {
|
|
42992
|
+
function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType, verification) {
|
|
41767
42993
|
if (provider.category === "cli") {
|
|
41768
|
-
return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType);
|
|
42994
|
+
return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification);
|
|
41769
42995
|
}
|
|
41770
42996
|
const lines = [];
|
|
41771
42997
|
lines.push("You are implementing browser automation scripts for an IDE provider.");
|
|
@@ -41790,7 +43016,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
41790
43016
|
setMode: "set_mode.js"
|
|
41791
43017
|
};
|
|
41792
43018
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
41793
|
-
const scriptsDir =
|
|
43019
|
+
const scriptsDir = path16.join(providerDir, "scripts");
|
|
41794
43020
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
41795
43021
|
if (latestScriptsDir) {
|
|
41796
43022
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -41798,10 +43024,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
41798
43024
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
41799
43025
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
41800
43026
|
lines.push("");
|
|
41801
|
-
for (const file2 of
|
|
43027
|
+
for (const file2 of fs13.readdirSync(latestScriptsDir)) {
|
|
41802
43028
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
41803
43029
|
try {
|
|
41804
|
-
const content =
|
|
43030
|
+
const content = fs13.readFileSync(path16.join(latestScriptsDir, file2), "utf-8");
|
|
41805
43031
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
41806
43032
|
lines.push("```javascript");
|
|
41807
43033
|
lines.push(content);
|
|
@@ -41811,14 +43037,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
41811
43037
|
}
|
|
41812
43038
|
}
|
|
41813
43039
|
}
|
|
41814
|
-
const refFiles =
|
|
43040
|
+
const refFiles = fs13.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
41815
43041
|
if (refFiles.length > 0) {
|
|
41816
43042
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
41817
43043
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
41818
43044
|
lines.push("");
|
|
41819
43045
|
for (const file2 of refFiles) {
|
|
41820
43046
|
try {
|
|
41821
|
-
const content =
|
|
43047
|
+
const content = fs13.readFileSync(path16.join(latestScriptsDir, file2), "utf-8");
|
|
41822
43048
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
41823
43049
|
lines.push("```javascript");
|
|
41824
43050
|
lines.push(content);
|
|
@@ -41859,11 +43085,11 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
41859
43085
|
lines.push("");
|
|
41860
43086
|
}
|
|
41861
43087
|
}
|
|
41862
|
-
const docsDir =
|
|
43088
|
+
const docsDir = path16.join(providerDir, "../../docs");
|
|
41863
43089
|
const loadGuide = (name) => {
|
|
41864
43090
|
try {
|
|
41865
|
-
const p =
|
|
41866
|
-
if (
|
|
43091
|
+
const p = path16.join(docsDir, name);
|
|
43092
|
+
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
41867
43093
|
} catch {
|
|
41868
43094
|
}
|
|
41869
43095
|
return null;
|
|
@@ -42021,8 +43247,69 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42021
43247
|
lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
|
|
42022
43248
|
return lines.join("\n");
|
|
42023
43249
|
}
|
|
42024
|
-
function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType) {
|
|
43250
|
+
function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification) {
|
|
42025
43251
|
const lines = [];
|
|
43252
|
+
const defaultExercisePayload = {
|
|
43253
|
+
type,
|
|
43254
|
+
workingDir: providerDir,
|
|
43255
|
+
freshSession: true,
|
|
43256
|
+
autoLaunch: true,
|
|
43257
|
+
autoResolveApprovals: true,
|
|
43258
|
+
approvalButtonIndex: 0,
|
|
43259
|
+
timeoutMs: 45e3,
|
|
43260
|
+
traceLimit: 200,
|
|
43261
|
+
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."
|
|
43262
|
+
};
|
|
43263
|
+
const exercisePayload = {
|
|
43264
|
+
...defaultExercisePayload,
|
|
43265
|
+
...verification?.request || {},
|
|
43266
|
+
type,
|
|
43267
|
+
workingDir: providerDir
|
|
43268
|
+
};
|
|
43269
|
+
const exerciseJson = JSON.stringify(exercisePayload).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43270
|
+
const verificationInspectFields = verification?.inspectFields?.length ? verification.inspectFields : [
|
|
43271
|
+
"debug.messages",
|
|
43272
|
+
"trace.entries[].payload.parsedLastAssistant",
|
|
43273
|
+
"trace.entries[].payload.lastAssistant"
|
|
43274
|
+
];
|
|
43275
|
+
const verificationMustContainAny = verification?.mustContainAny || [];
|
|
43276
|
+
const verificationMustNotContainAny = verification?.mustNotContainAny || [];
|
|
43277
|
+
const verificationMustMatchAny = verification?.mustMatchAny || [];
|
|
43278
|
+
const verificationMustNotMatchAny = verification?.mustNotMatchAny || [];
|
|
43279
|
+
const verificationLastAssistantMustContainAny = verification?.lastAssistantMustContainAny || [];
|
|
43280
|
+
const verificationLastAssistantMustNotContainAny = verification?.lastAssistantMustNotContainAny || [];
|
|
43281
|
+
const verificationLastAssistantMustMatchAny = verification?.lastAssistantMustMatchAny || [];
|
|
43282
|
+
const verificationLastAssistantMustNotMatchAny = verification?.lastAssistantMustNotMatchAny || [];
|
|
43283
|
+
const quotedMustContain = verificationMustContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43284
|
+
const quotedMustNotContain = verificationMustNotContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43285
|
+
const quotedMustMatch = verificationMustMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43286
|
+
const quotedMustNotMatch = verificationMustNotMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43287
|
+
const quotedLastAssistantMustContain = verificationLastAssistantMustContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43288
|
+
const quotedLastAssistantMustNotContain = verificationLastAssistantMustNotContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43289
|
+
const quotedLastAssistantMustMatch = verificationLastAssistantMustMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43290
|
+
const quotedLastAssistantMustNotMatch = verificationLastAssistantMustNotMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43291
|
+
const fixtureName = verification?.fixtureName || `${type}-provider-fix`;
|
|
43292
|
+
const fixtureNames = Array.isArray(verification?.fixtureNames) ? verification.fixtureNames.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
43293
|
+
const fixtureCaptureJson = JSON.stringify({
|
|
43294
|
+
type,
|
|
43295
|
+
name: fixtureName,
|
|
43296
|
+
request: exercisePayload,
|
|
43297
|
+
assertions: {
|
|
43298
|
+
mustContainAny: verificationMustContainAny,
|
|
43299
|
+
mustNotContainAny: verificationMustNotContainAny,
|
|
43300
|
+
mustMatchAny: verificationMustMatchAny,
|
|
43301
|
+
mustNotMatchAny: verificationMustNotMatchAny,
|
|
43302
|
+
lastAssistantMustContainAny: verificationLastAssistantMustContainAny,
|
|
43303
|
+
lastAssistantMustNotContainAny: verificationLastAssistantMustNotContainAny,
|
|
43304
|
+
lastAssistantMustMatchAny: verificationLastAssistantMustMatchAny,
|
|
43305
|
+
lastAssistantMustNotMatchAny: verificationLastAssistantMustNotMatchAny,
|
|
43306
|
+
requireNotTimedOut: true
|
|
43307
|
+
}
|
|
43308
|
+
}).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43309
|
+
const fixtureReplayJson = JSON.stringify({
|
|
43310
|
+
type,
|
|
43311
|
+
name: fixtureName
|
|
43312
|
+
}).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
42026
43313
|
lines.push("You are implementing PTY parsing scripts for a CLI provider.");
|
|
42027
43314
|
lines.push("Be concise. Do NOT explain your reasoning. Edit files directly and verify with the local DevServer.");
|
|
42028
43315
|
lines.push("");
|
|
@@ -42036,7 +43323,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42036
43323
|
parseApproval: "parse_approval.js"
|
|
42037
43324
|
};
|
|
42038
43325
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
42039
|
-
const scriptsDir =
|
|
43326
|
+
const scriptsDir = path16.join(providerDir, "scripts");
|
|
42040
43327
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
42041
43328
|
if (latestScriptsDir) {
|
|
42042
43329
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -42044,11 +43331,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42044
43331
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
42045
43332
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
42046
43333
|
lines.push("");
|
|
42047
|
-
for (const file2 of
|
|
43334
|
+
for (const file2 of fs13.readdirSync(latestScriptsDir)) {
|
|
42048
43335
|
if (!file2.endsWith(".js")) continue;
|
|
42049
43336
|
if (!targetFileNames.has(file2)) continue;
|
|
42050
43337
|
try {
|
|
42051
|
-
const content =
|
|
43338
|
+
const content = fs13.readFileSync(path16.join(latestScriptsDir, file2), "utf-8");
|
|
42052
43339
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
42053
43340
|
lines.push("```javascript");
|
|
42054
43341
|
lines.push(content);
|
|
@@ -42057,14 +43344,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42057
43344
|
} catch {
|
|
42058
43345
|
}
|
|
42059
43346
|
}
|
|
42060
|
-
const refFiles =
|
|
43347
|
+
const refFiles = fs13.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
42061
43348
|
if (refFiles.length > 0) {
|
|
42062
43349
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
42063
43350
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
42064
43351
|
lines.push("");
|
|
42065
43352
|
for (const file2 of refFiles) {
|
|
42066
43353
|
try {
|
|
42067
|
-
const content =
|
|
43354
|
+
const content = fs13.readFileSync(path16.join(latestScriptsDir, file2), "utf-8");
|
|
42068
43355
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
42069
43356
|
lines.push("```javascript");
|
|
42070
43357
|
lines.push(content);
|
|
@@ -42097,17 +43384,17 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42097
43384
|
lines.push("");
|
|
42098
43385
|
}
|
|
42099
43386
|
}
|
|
42100
|
-
const docsDir =
|
|
43387
|
+
const docsDir = path16.join(providerDir, "../../docs");
|
|
42101
43388
|
const loadGuide = (name) => {
|
|
42102
43389
|
try {
|
|
42103
|
-
const p =
|
|
42104
|
-
if (
|
|
43390
|
+
const p = path16.join(docsDir, name);
|
|
43391
|
+
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
42105
43392
|
} catch {
|
|
42106
43393
|
}
|
|
42107
43394
|
return null;
|
|
42108
43395
|
};
|
|
42109
43396
|
const providerGuide = loadGuide("PROVIDER_GUIDE.md");
|
|
42110
|
-
if (providerGuide) {
|
|
43397
|
+
if (providerGuide && provider.category !== "cli") {
|
|
42111
43398
|
lines.push("## Documentation: PROVIDER_GUIDE.md");
|
|
42112
43399
|
lines.push("```markdown");
|
|
42113
43400
|
lines.push(providerGuide);
|
|
@@ -42149,6 +43436,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42149
43436
|
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.");
|
|
42150
43437
|
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.");
|
|
42151
43438
|
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.");
|
|
43439
|
+
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.');
|
|
43440
|
+
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.");
|
|
43441
|
+
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.');
|
|
43442
|
+
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.");
|
|
43443
|
+
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.");
|
|
42152
43444
|
lines.push("");
|
|
42153
43445
|
lines.push("## Task");
|
|
42154
43446
|
lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(", ")}**`);
|
|
@@ -42156,35 +43448,145 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42156
43448
|
lines.push("## Verification API");
|
|
42157
43449
|
lines.push("Use the DevServer CLI debug endpoints, not DOM/CDP routes.");
|
|
42158
43450
|
lines.push("");
|
|
42159
|
-
lines.push("### 1.
|
|
43451
|
+
lines.push("### 1. Preferred: run a full autonomous repro");
|
|
43452
|
+
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.");
|
|
42160
43453
|
lines.push("```bash");
|
|
42161
|
-
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/
|
|
43454
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/exercise \\`);
|
|
42162
43455
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
42163
|
-
lines.push(` -d '
|
|
43456
|
+
lines.push(` -d '${exerciseJson}'`);
|
|
42164
43457
|
lines.push("```");
|
|
42165
43458
|
lines.push("");
|
|
43459
|
+
if (verification?.description) {
|
|
43460
|
+
lines.push("Verification intent:");
|
|
43461
|
+
lines.push(verification.description);
|
|
43462
|
+
lines.push("");
|
|
43463
|
+
}
|
|
43464
|
+
lines.push("Read the JSON response carefully. It already includes:");
|
|
43465
|
+
lines.push("1. `instanceId`");
|
|
43466
|
+
lines.push("2. `statusesSeen` and `approvalsResolved`");
|
|
43467
|
+
lines.push("3. `debug` for the final settled state");
|
|
43468
|
+
lines.push("4. `trace.entries` for the repro turn");
|
|
43469
|
+
lines.push("");
|
|
43470
|
+
lines.push("Save the response to a temp file and inspect the exact parsed transcript fields before editing:");
|
|
43471
|
+
lines.push("```bash");
|
|
43472
|
+
lines.push(`EXERCISE_JSON=$(mktemp)`);
|
|
43473
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/exercise \\`);
|
|
43474
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43475
|
+
lines.push(` -d '${exerciseJson}' > "$EXERCISE_JSON"`);
|
|
43476
|
+
lines.push(`jq '{timedOut,statusesSeen,approvalsResolved,inspect:{${verificationInspectFields.map((field, index) => `f${index + 1}: .${field}`).join(", ")}}}' "$EXERCISE_JSON"`);
|
|
43477
|
+
lines.push("```");
|
|
43478
|
+
lines.push("");
|
|
43479
|
+
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) {
|
|
43480
|
+
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.");
|
|
43481
|
+
lines.push("```bash");
|
|
43482
|
+
if (verificationMustContainAny.length > 0) {
|
|
43483
|
+
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"`);
|
|
43484
|
+
}
|
|
43485
|
+
if (verificationMustNotContainAny.length > 0) {
|
|
43486
|
+
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"`);
|
|
43487
|
+
}
|
|
43488
|
+
if (verificationMustMatchAny.length > 0) {
|
|
43489
|
+
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"`);
|
|
43490
|
+
}
|
|
43491
|
+
if (verificationMustNotMatchAny.length > 0) {
|
|
43492
|
+
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"`);
|
|
43493
|
+
}
|
|
43494
|
+
if (verificationLastAssistantMustContainAny.length > 0) {
|
|
43495
|
+
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"`);
|
|
43496
|
+
}
|
|
43497
|
+
if (verificationLastAssistantMustNotContainAny.length > 0) {
|
|
43498
|
+
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"`);
|
|
43499
|
+
}
|
|
43500
|
+
if (verificationLastAssistantMustMatchAny.length > 0) {
|
|
43501
|
+
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"`);
|
|
43502
|
+
}
|
|
43503
|
+
if (verificationLastAssistantMustNotMatchAny.length > 0) {
|
|
43504
|
+
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"`);
|
|
43505
|
+
}
|
|
43506
|
+
lines.push("```");
|
|
43507
|
+
lines.push("");
|
|
43508
|
+
}
|
|
43509
|
+
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.");
|
|
43510
|
+
lines.push("");
|
|
43511
|
+
lines.push("### 1b. Persist or replay the exact repro as a reusable fixture");
|
|
43512
|
+
if (fixtureNames.length > 0) {
|
|
43513
|
+
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(", ")}.`);
|
|
43514
|
+
for (const name of fixtureNames) {
|
|
43515
|
+
const replayJson = JSON.stringify({ type, name }).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43516
|
+
lines.push("```bash");
|
|
43517
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43518
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43519
|
+
lines.push(` -d '${replayJson}'`);
|
|
43520
|
+
lines.push("```");
|
|
43521
|
+
lines.push("");
|
|
43522
|
+
}
|
|
43523
|
+
lines.push("Do not create new fixtures unless one of the listed fixtures is missing or stale.");
|
|
43524
|
+
} else if (verification?.fixtureName) {
|
|
43525
|
+
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.`);
|
|
43526
|
+
lines.push("```bash");
|
|
43527
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43528
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43529
|
+
lines.push(` -d '${fixtureReplayJson}'`);
|
|
43530
|
+
lines.push("```");
|
|
43531
|
+
lines.push("");
|
|
43532
|
+
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.");
|
|
43533
|
+
lines.push("```bash");
|
|
43534
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/capture \\`);
|
|
43535
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43536
|
+
lines.push(` -d '${fixtureCaptureJson}'`);
|
|
43537
|
+
lines.push("```");
|
|
43538
|
+
} else {
|
|
43539
|
+
lines.push("Capture the exact exercise once before editing. After patching, replay THIS fixture and do not declare success unless replay passes.");
|
|
43540
|
+
lines.push("```bash");
|
|
43541
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/capture \\`);
|
|
43542
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43543
|
+
lines.push(` -d '${fixtureCaptureJson}'`);
|
|
43544
|
+
lines.push("");
|
|
43545
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43546
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43547
|
+
lines.push(` -d '${fixtureReplayJson}'`);
|
|
43548
|
+
lines.push("```");
|
|
43549
|
+
}
|
|
43550
|
+
lines.push("");
|
|
43551
|
+
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.");
|
|
43552
|
+
lines.push("");
|
|
42166
43553
|
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
42167
43554
|
lines.push("```bash");
|
|
43555
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/launch \\`);
|
|
43556
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43557
|
+
lines.push(` -d '{"type":"${type}","workingDir":"${providerDir.replace(/\\/g, "\\\\")}"}'`);
|
|
42168
43558
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
43559
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/trace/${type}`);
|
|
42169
43560
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
42170
43561
|
lines.push("```");
|
|
42171
43562
|
lines.push("");
|
|
43563
|
+
lines.push("The CLI trace endpoint is the primary debugging source. Read it BEFORE editing any parser code.");
|
|
43564
|
+
lines.push("Use the trace timeline to find the latest `settled` or `commit_transcript` frame for the repro turn and inspect these fields first:");
|
|
43565
|
+
lines.push("1. `payload.screenText`");
|
|
43566
|
+
lines.push("2. `payload.detectStatus` and `payload.parsedStatus`");
|
|
43567
|
+
lines.push("3. `payload.parsedLastAssistant`");
|
|
43568
|
+
lines.push("4. `payload.approval` / `payload.parsedActiveModal`");
|
|
43569
|
+
lines.push("5. `payload.rawPreview` only when control-sequence residue matters");
|
|
43570
|
+
lines.push("");
|
|
42172
43571
|
lines.push("The debug payload should be read in this priority order:");
|
|
42173
43572
|
lines.push("1. `screenText` / current visible state");
|
|
42174
43573
|
lines.push("2. parsed `status`, `messages`, `activeModal`");
|
|
42175
43574
|
lines.push("3. `rawBuffer` only for style/control-sequence cues");
|
|
42176
43575
|
lines.push("4. `buffer` only when the current screen is insufficient");
|
|
42177
43576
|
lines.push("");
|
|
42178
|
-
lines.push("
|
|
43577
|
+
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.");
|
|
43578
|
+
lines.push("Do NOT guess based only on the final chat bubble or a truncated UI preview.");
|
|
42179
43579
|
lines.push("");
|
|
42180
|
-
lines.push("
|
|
43580
|
+
lines.push("Extract the current `instanceId` from the exercise, launch, or status response and keep using it below.");
|
|
43581
|
+
lines.push("");
|
|
43582
|
+
lines.push("### 3. Manual fallback only: send a realistic approval-triggering prompt");
|
|
42181
43583
|
lines.push("```bash");
|
|
42182
43584
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/send \\`);
|
|
42183
43585
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
42184
43586
|
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."}'`);
|
|
42185
43587
|
lines.push("```");
|
|
42186
43588
|
lines.push("");
|
|
42187
|
-
lines.push("### 4.
|
|
43589
|
+
lines.push("### 4. Manual fallback only: if approval appears, resolve it until the CLI reaches idle");
|
|
42188
43590
|
lines.push("```bash");
|
|
42189
43591
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/resolve \\`);
|
|
42190
43592
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
@@ -42194,10 +43596,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42194
43596
|
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>","keys":"1"}'`);
|
|
42195
43597
|
lines.push("```");
|
|
42196
43598
|
lines.push("");
|
|
42197
|
-
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.");
|
|
43599
|
+
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.");
|
|
42198
43600
|
lines.push("");
|
|
42199
43601
|
lines.push("### Patch Discipline");
|
|
42200
43602
|
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.");
|
|
43603
|
+
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.");
|
|
43604
|
+
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.");
|
|
43605
|
+
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.");
|
|
43606
|
+
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.');
|
|
42201
43607
|
lines.push("");
|
|
42202
43608
|
lines.push("### 5. Verify the side effects outside the CLI");
|
|
42203
43609
|
lines.push("```bash");
|
|
@@ -42222,6 +43628,8 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42222
43628
|
lines.push("7. Re-run the debug endpoints after edits. Do NOT finish until the parsed result looks correct.");
|
|
42223
43629
|
lines.push("8. Confirm the parser still works after a redraw or scroll change without duplicating transcript history.");
|
|
42224
43630
|
lines.push("9. Confirm the implementation prefers current-screen signals over stale history when both are present.");
|
|
43631
|
+
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.");
|
|
43632
|
+
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.");
|
|
42225
43633
|
lines.push("");
|
|
42226
43634
|
if (userComment) {
|
|
42227
43635
|
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
@@ -42230,10 +43638,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42230
43638
|
lines.push(userComment);
|
|
42231
43639
|
lines.push("");
|
|
42232
43640
|
}
|
|
42233
|
-
lines.push("Start NOW. Launch the CLI, inspect PTY state, edit the scripts, and verify via the CLI debug endpoints.");
|
|
43641
|
+
lines.push("Start NOW. Launch the CLI, inspect the trace and PTY state, edit the scripts, and verify via the CLI debug + trace endpoints.");
|
|
42234
43642
|
return lines.join("\n");
|
|
42235
43643
|
}
|
|
42236
43644
|
function handleAutoImplSSE(ctx, type, req, res) {
|
|
43645
|
+
clearStaleAutoImplState(ctx, "SSE connection opened");
|
|
42237
43646
|
res.writeHead(200, {
|
|
42238
43647
|
"Content-Type": "text/event-stream",
|
|
42239
43648
|
"Cache-Control": "no-cache",
|
|
@@ -42255,6 +43664,7 @@ data: ${JSON.stringify(p.data)}
|
|
|
42255
43664
|
});
|
|
42256
43665
|
}
|
|
42257
43666
|
function handleAutoImplCancel(ctx, _type, _req, res) {
|
|
43667
|
+
clearStaleAutoImplState(ctx, "cancel request");
|
|
42258
43668
|
if (ctx.autoImplProcess) {
|
|
42259
43669
|
ctx.autoImplProcess.kill("SIGTERM");
|
|
42260
43670
|
setTimeout(() => {
|
|
@@ -42282,25 +43692,26 @@ data: ${JSON.stringify(msg.data)}
|
|
|
42282
43692
|
}
|
|
42283
43693
|
}
|
|
42284
43694
|
}
|
|
42285
|
-
var
|
|
43695
|
+
var fs13, path16, os17;
|
|
42286
43696
|
var init_dev_auto_implement = __esm({
|
|
42287
43697
|
"../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts"() {
|
|
42288
43698
|
"use strict";
|
|
42289
|
-
|
|
42290
|
-
|
|
43699
|
+
fs13 = __toESM(require("fs"));
|
|
43700
|
+
path16 = __toESM(require("path"));
|
|
42291
43701
|
os17 = __toESM(require("os"));
|
|
42292
43702
|
init_dev_server();
|
|
43703
|
+
init_dev_cli_debug();
|
|
42293
43704
|
}
|
|
42294
43705
|
});
|
|
42295
43706
|
|
|
42296
43707
|
// ../../oss/packages/daemon-core/src/daemon/dev-server.ts
|
|
42297
|
-
var http2,
|
|
43708
|
+
var http2, fs14, path17, DEV_SERVER_PORT, DevServer;
|
|
42298
43709
|
var init_dev_server = __esm({
|
|
42299
43710
|
"../../oss/packages/daemon-core/src/daemon/dev-server.ts"() {
|
|
42300
43711
|
"use strict";
|
|
42301
43712
|
http2 = __toESM(require("http"));
|
|
42302
|
-
|
|
42303
|
-
|
|
43713
|
+
fs14 = __toESM(require("fs"));
|
|
43714
|
+
path17 = __toESM(require("path"));
|
|
42304
43715
|
init_scaffold_template();
|
|
42305
43716
|
init_version_archive();
|
|
42306
43717
|
init_logger();
|
|
@@ -42361,11 +43772,16 @@ var init_dev_server = __esm({
|
|
|
42361
43772
|
{ method: "GET", pattern: "/api/cli/status", handler: (q2, s15) => this.handleCliStatus(q2, s15) },
|
|
42362
43773
|
{ method: "POST", pattern: "/api/cli/launch", handler: (q2, s15) => this.handleCliLaunch(q2, s15) },
|
|
42363
43774
|
{ method: "POST", pattern: "/api/cli/send", handler: (q2, s15) => this.handleCliSend(q2, s15) },
|
|
43775
|
+
{ method: "POST", pattern: "/api/cli/exercise", handler: (q2, s15) => this.handleCliExercise(q2, s15) },
|
|
43776
|
+
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q2, s15) => this.handleCliFixtureCapture(q2, s15) },
|
|
43777
|
+
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q2, s15) => this.handleCliFixtureReplay(q2, s15) },
|
|
42364
43778
|
{ method: "POST", pattern: "/api/cli/resolve", handler: (q2, s15) => this.handleCliResolve(q2, s15) },
|
|
42365
43779
|
{ method: "POST", pattern: "/api/cli/raw", handler: (q2, s15) => this.handleCliRaw(q2, s15) },
|
|
42366
43780
|
{ method: "POST", pattern: "/api/cli/stop", handler: (q2, s15) => this.handleCliStop(q2, s15) },
|
|
42367
43781
|
{ method: "GET", pattern: "/api/cli/events", handler: (q2, s15) => this.handleCliSSE(q2, s15) },
|
|
42368
43782
|
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliDebug(p[0], q2, s15) },
|
|
43783
|
+
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliTrace(p[0], q2, s15) },
|
|
43784
|
+
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliFixtureList(p[0], q2, s15) },
|
|
42369
43785
|
// Dynamic routes (provider :type param)
|
|
42370
43786
|
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q2, s15, p) => this.handleRunScript(p[0], q2, s15) },
|
|
42371
43787
|
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q2, s15, p) => this.handleListFiles(p[0], q2, s15) },
|
|
@@ -42399,8 +43815,8 @@ var init_dev_server = __esm({
|
|
|
42399
43815
|
}
|
|
42400
43816
|
getEndpointList() {
|
|
42401
43817
|
return this.routes.map((r) => {
|
|
42402
|
-
const
|
|
42403
|
-
return `${r.method.padEnd(5)} ${
|
|
43818
|
+
const path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
43819
|
+
return `${r.method.padEnd(5)} ${path21}`;
|
|
42404
43820
|
});
|
|
42405
43821
|
}
|
|
42406
43822
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -42682,12 +44098,12 @@ var init_dev_server = __esm({
|
|
|
42682
44098
|
// ─── DevConsole SPA ───
|
|
42683
44099
|
getConsoleDistDir() {
|
|
42684
44100
|
const candidates = [
|
|
42685
|
-
|
|
42686
|
-
|
|
42687
|
-
|
|
44101
|
+
path17.resolve(__dirname, "../../web-devconsole/dist"),
|
|
44102
|
+
path17.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
44103
|
+
path17.join(process.cwd(), "packages/web-devconsole/dist")
|
|
42688
44104
|
];
|
|
42689
44105
|
for (const dir of candidates) {
|
|
42690
|
-
if (
|
|
44106
|
+
if (fs14.existsSync(path17.join(dir, "index.html"))) return dir;
|
|
42691
44107
|
}
|
|
42692
44108
|
return null;
|
|
42693
44109
|
}
|
|
@@ -42697,9 +44113,9 @@ var init_dev_server = __esm({
|
|
|
42697
44113
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
42698
44114
|
return;
|
|
42699
44115
|
}
|
|
42700
|
-
const htmlPath =
|
|
44116
|
+
const htmlPath = path17.join(distDir, "index.html");
|
|
42701
44117
|
try {
|
|
42702
|
-
const html =
|
|
44118
|
+
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
42703
44119
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
42704
44120
|
res.end(html);
|
|
42705
44121
|
} catch (e) {
|
|
@@ -42722,15 +44138,15 @@ var init_dev_server = __esm({
|
|
|
42722
44138
|
this.json(res, 404, { error: "Not found" });
|
|
42723
44139
|
return;
|
|
42724
44140
|
}
|
|
42725
|
-
const safePath =
|
|
42726
|
-
const filePath =
|
|
44141
|
+
const safePath = path17.normalize(pathname).replace(/^\.\.\//, "");
|
|
44142
|
+
const filePath = path17.join(distDir, safePath);
|
|
42727
44143
|
if (!filePath.startsWith(distDir)) {
|
|
42728
44144
|
this.json(res, 403, { error: "Forbidden" });
|
|
42729
44145
|
return;
|
|
42730
44146
|
}
|
|
42731
44147
|
try {
|
|
42732
|
-
const content =
|
|
42733
|
-
const ext =
|
|
44148
|
+
const content = fs14.readFileSync(filePath);
|
|
44149
|
+
const ext = path17.extname(filePath);
|
|
42734
44150
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
42735
44151
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
42736
44152
|
res.end(content);
|
|
@@ -42838,14 +44254,14 @@ var init_dev_server = __esm({
|
|
|
42838
44254
|
const files = [];
|
|
42839
44255
|
const scan = (d, prefix) => {
|
|
42840
44256
|
try {
|
|
42841
|
-
for (const entry of
|
|
44257
|
+
for (const entry of fs14.readdirSync(d, { withFileTypes: true })) {
|
|
42842
44258
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
42843
44259
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
42844
44260
|
if (entry.isDirectory()) {
|
|
42845
44261
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
42846
|
-
scan(
|
|
44262
|
+
scan(path17.join(d, entry.name), rel);
|
|
42847
44263
|
} else {
|
|
42848
|
-
const stat4 =
|
|
44264
|
+
const stat4 = fs14.statSync(path17.join(d, entry.name));
|
|
42849
44265
|
files.push({ path: rel, size: stat4.size, type: "file" });
|
|
42850
44266
|
}
|
|
42851
44267
|
}
|
|
@@ -42868,16 +44284,16 @@ var init_dev_server = __esm({
|
|
|
42868
44284
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
42869
44285
|
return;
|
|
42870
44286
|
}
|
|
42871
|
-
const fullPath =
|
|
44287
|
+
const fullPath = path17.resolve(dir, path17.normalize(filePath));
|
|
42872
44288
|
if (!fullPath.startsWith(dir)) {
|
|
42873
44289
|
this.json(res, 403, { error: "Forbidden" });
|
|
42874
44290
|
return;
|
|
42875
44291
|
}
|
|
42876
|
-
if (!
|
|
44292
|
+
if (!fs14.existsSync(fullPath) || fs14.statSync(fullPath).isDirectory()) {
|
|
42877
44293
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
42878
44294
|
return;
|
|
42879
44295
|
}
|
|
42880
|
-
const content =
|
|
44296
|
+
const content = fs14.readFileSync(fullPath, "utf-8");
|
|
42881
44297
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
42882
44298
|
}
|
|
42883
44299
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -42893,15 +44309,15 @@ var init_dev_server = __esm({
|
|
|
42893
44309
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
42894
44310
|
return;
|
|
42895
44311
|
}
|
|
42896
|
-
const fullPath =
|
|
44312
|
+
const fullPath = path17.resolve(dir, path17.normalize(filePath));
|
|
42897
44313
|
if (!fullPath.startsWith(dir)) {
|
|
42898
44314
|
this.json(res, 403, { error: "Forbidden" });
|
|
42899
44315
|
return;
|
|
42900
44316
|
}
|
|
42901
44317
|
try {
|
|
42902
|
-
if (
|
|
42903
|
-
|
|
42904
|
-
|
|
44318
|
+
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
44319
|
+
fs14.mkdirSync(path17.dirname(fullPath), { recursive: true });
|
|
44320
|
+
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
42905
44321
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
42906
44322
|
this.providerLoader.reload();
|
|
42907
44323
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -42917,9 +44333,9 @@ var init_dev_server = __esm({
|
|
|
42917
44333
|
return;
|
|
42918
44334
|
}
|
|
42919
44335
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
42920
|
-
const p =
|
|
42921
|
-
if (
|
|
42922
|
-
const source =
|
|
44336
|
+
const p = path17.join(dir, name);
|
|
44337
|
+
if (fs14.existsSync(p)) {
|
|
44338
|
+
const source = fs14.readFileSync(p, "utf-8");
|
|
42923
44339
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
42924
44340
|
return;
|
|
42925
44341
|
}
|
|
@@ -42938,11 +44354,11 @@ var init_dev_server = __esm({
|
|
|
42938
44354
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
42939
44355
|
return;
|
|
42940
44356
|
}
|
|
42941
|
-
const target =
|
|
42942
|
-
const targetPath =
|
|
44357
|
+
const target = fs14.existsSync(path17.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
44358
|
+
const targetPath = path17.join(dir, target);
|
|
42943
44359
|
try {
|
|
42944
|
-
if (
|
|
42945
|
-
|
|
44360
|
+
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
44361
|
+
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
42946
44362
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
42947
44363
|
this.providerLoader.reload();
|
|
42948
44364
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -43099,21 +44515,21 @@ var init_dev_server = __esm({
|
|
|
43099
44515
|
}
|
|
43100
44516
|
let targetDir;
|
|
43101
44517
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
43102
|
-
const jsonPath =
|
|
43103
|
-
if (
|
|
44518
|
+
const jsonPath = path17.join(targetDir, "provider.json");
|
|
44519
|
+
if (fs14.existsSync(jsonPath)) {
|
|
43104
44520
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
43105
44521
|
return;
|
|
43106
44522
|
}
|
|
43107
44523
|
try {
|
|
43108
44524
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2, osPaths, processNames });
|
|
43109
|
-
|
|
43110
|
-
|
|
44525
|
+
fs14.mkdirSync(targetDir, { recursive: true });
|
|
44526
|
+
fs14.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
43111
44527
|
const createdFiles = ["provider.json"];
|
|
43112
44528
|
if (result.files) {
|
|
43113
44529
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
43114
|
-
const fullPath =
|
|
43115
|
-
|
|
43116
|
-
|
|
44530
|
+
const fullPath = path17.join(targetDir, relPath);
|
|
44531
|
+
fs14.mkdirSync(path17.dirname(fullPath), { recursive: true });
|
|
44532
|
+
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
43117
44533
|
createdFiles.push(relPath);
|
|
43118
44534
|
}
|
|
43119
44535
|
}
|
|
@@ -43162,45 +44578,45 @@ var init_dev_server = __esm({
|
|
|
43162
44578
|
}
|
|
43163
44579
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
43164
44580
|
getLatestScriptVersionDir(scriptsDir) {
|
|
43165
|
-
if (!
|
|
43166
|
-
const versions =
|
|
44581
|
+
if (!fs14.existsSync(scriptsDir)) return null;
|
|
44582
|
+
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
43167
44583
|
try {
|
|
43168
|
-
return
|
|
44584
|
+
return fs14.statSync(path17.join(scriptsDir, d)).isDirectory();
|
|
43169
44585
|
} catch {
|
|
43170
44586
|
return false;
|
|
43171
44587
|
}
|
|
43172
44588
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
43173
44589
|
if (versions.length === 0) return null;
|
|
43174
|
-
return
|
|
44590
|
+
return path17.join(scriptsDir, versions[0]);
|
|
43175
44591
|
}
|
|
43176
44592
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
43177
|
-
const canonicalUserDir =
|
|
43178
|
-
const desiredDir = requestedDir ?
|
|
43179
|
-
const upstreamRoot =
|
|
43180
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
44593
|
+
const canonicalUserDir = path17.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
44594
|
+
const desiredDir = requestedDir ? path17.resolve(requestedDir) : canonicalUserDir;
|
|
44595
|
+
const upstreamRoot = path17.resolve(this.providerLoader.getUpstreamDir());
|
|
44596
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path17.sep}`)) {
|
|
43181
44597
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
43182
44598
|
}
|
|
43183
|
-
if (
|
|
44599
|
+
if (path17.basename(desiredDir) !== type) {
|
|
43184
44600
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
43185
44601
|
}
|
|
43186
44602
|
const sourceDir = this.findProviderDir(type);
|
|
43187
44603
|
if (!sourceDir) {
|
|
43188
44604
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
43189
44605
|
}
|
|
43190
|
-
if (!
|
|
43191
|
-
|
|
43192
|
-
|
|
44606
|
+
if (!fs14.existsSync(desiredDir)) {
|
|
44607
|
+
fs14.mkdirSync(path17.dirname(desiredDir), { recursive: true });
|
|
44608
|
+
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
43193
44609
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
43194
44610
|
}
|
|
43195
|
-
const providerJson =
|
|
43196
|
-
if (!
|
|
44611
|
+
const providerJson = path17.join(desiredDir, "provider.json");
|
|
44612
|
+
if (!fs14.existsSync(providerJson)) {
|
|
43197
44613
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
43198
44614
|
}
|
|
43199
44615
|
try {
|
|
43200
|
-
const providerData = JSON.parse(
|
|
44616
|
+
const providerData = JSON.parse(fs14.readFileSync(providerJson, "utf-8"));
|
|
43201
44617
|
if (providerData.disableUpstream !== true) {
|
|
43202
44618
|
providerData.disableUpstream = true;
|
|
43203
|
-
|
|
44619
|
+
fs14.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
43204
44620
|
}
|
|
43205
44621
|
} catch (error48) {
|
|
43206
44622
|
return {
|
|
@@ -43240,7 +44656,7 @@ var init_dev_server = __esm({
|
|
|
43240
44656
|
setMode: "set_mode.js"
|
|
43241
44657
|
};
|
|
43242
44658
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
43243
|
-
const scriptsDir =
|
|
44659
|
+
const scriptsDir = path17.join(providerDir, "scripts");
|
|
43244
44660
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
43245
44661
|
if (latestScriptsDir) {
|
|
43246
44662
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -43248,10 +44664,10 @@ var init_dev_server = __esm({
|
|
|
43248
44664
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
43249
44665
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
43250
44666
|
lines.push("");
|
|
43251
|
-
for (const file2 of
|
|
44667
|
+
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
43252
44668
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
43253
44669
|
try {
|
|
43254
|
-
const content =
|
|
44670
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
43255
44671
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
43256
44672
|
lines.push("```javascript");
|
|
43257
44673
|
lines.push(content);
|
|
@@ -43261,14 +44677,14 @@ var init_dev_server = __esm({
|
|
|
43261
44677
|
}
|
|
43262
44678
|
}
|
|
43263
44679
|
}
|
|
43264
|
-
const refFiles =
|
|
44680
|
+
const refFiles = fs14.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
43265
44681
|
if (refFiles.length > 0) {
|
|
43266
44682
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
43267
44683
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
43268
44684
|
lines.push("");
|
|
43269
44685
|
for (const file2 of refFiles) {
|
|
43270
44686
|
try {
|
|
43271
|
-
const content =
|
|
44687
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
43272
44688
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
43273
44689
|
lines.push("```javascript");
|
|
43274
44690
|
lines.push(content);
|
|
@@ -43309,11 +44725,11 @@ var init_dev_server = __esm({
|
|
|
43309
44725
|
lines.push("");
|
|
43310
44726
|
}
|
|
43311
44727
|
}
|
|
43312
|
-
const docsDir =
|
|
44728
|
+
const docsDir = path17.join(providerDir, "../../docs");
|
|
43313
44729
|
const loadGuide = (name) => {
|
|
43314
44730
|
try {
|
|
43315
|
-
const p =
|
|
43316
|
-
if (
|
|
44731
|
+
const p = path17.join(docsDir, name);
|
|
44732
|
+
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
43317
44733
|
} catch {
|
|
43318
44734
|
}
|
|
43319
44735
|
return null;
|
|
@@ -43486,7 +44902,7 @@ var init_dev_server = __esm({
|
|
|
43486
44902
|
parseApproval: "parse_approval.js"
|
|
43487
44903
|
};
|
|
43488
44904
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
43489
|
-
const scriptsDir =
|
|
44905
|
+
const scriptsDir = path17.join(providerDir, "scripts");
|
|
43490
44906
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
43491
44907
|
if (latestScriptsDir) {
|
|
43492
44908
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -43494,11 +44910,11 @@ var init_dev_server = __esm({
|
|
|
43494
44910
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
43495
44911
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
43496
44912
|
lines.push("");
|
|
43497
|
-
for (const file2 of
|
|
44913
|
+
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
43498
44914
|
if (!file2.endsWith(".js")) continue;
|
|
43499
44915
|
if (!targetFileNames.has(file2)) continue;
|
|
43500
44916
|
try {
|
|
43501
|
-
const content =
|
|
44917
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
43502
44918
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
43503
44919
|
lines.push("```javascript");
|
|
43504
44920
|
lines.push(content);
|
|
@@ -43507,14 +44923,14 @@ var init_dev_server = __esm({
|
|
|
43507
44923
|
} catch {
|
|
43508
44924
|
}
|
|
43509
44925
|
}
|
|
43510
|
-
const refFiles =
|
|
44926
|
+
const refFiles = fs14.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
43511
44927
|
if (refFiles.length > 0) {
|
|
43512
44928
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
43513
44929
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
43514
44930
|
lines.push("");
|
|
43515
44931
|
for (const file2 of refFiles) {
|
|
43516
44932
|
try {
|
|
43517
|
-
const content =
|
|
44933
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
43518
44934
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
43519
44935
|
lines.push("```javascript");
|
|
43520
44936
|
lines.push(content);
|
|
@@ -43547,11 +44963,11 @@ var init_dev_server = __esm({
|
|
|
43547
44963
|
lines.push("");
|
|
43548
44964
|
}
|
|
43549
44965
|
}
|
|
43550
|
-
const docsDir =
|
|
44966
|
+
const docsDir = path17.join(providerDir, "../../docs");
|
|
43551
44967
|
const loadGuide = (name) => {
|
|
43552
44968
|
try {
|
|
43553
|
-
const p =
|
|
43554
|
-
if (
|
|
44969
|
+
const p = path17.join(docsDir, name);
|
|
44970
|
+
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
43555
44971
|
} catch {
|
|
43556
44972
|
}
|
|
43557
44973
|
return null;
|
|
@@ -43616,6 +45032,7 @@ var init_dev_server = __esm({
|
|
|
43616
45032
|
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
43617
45033
|
lines.push("```bash");
|
|
43618
45034
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
45035
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/trace/${type}`);
|
|
43619
45036
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
43620
45037
|
lines.push("```");
|
|
43621
45038
|
lines.push("");
|
|
@@ -43750,6 +45167,16 @@ data: ${JSON.stringify(msg.data)}
|
|
|
43750
45167
|
async handleCliSend(req, res) {
|
|
43751
45168
|
return handleCliSend(this, req, res);
|
|
43752
45169
|
}
|
|
45170
|
+
/** POST /api/cli/exercise — launch/send/approve/wait helper for provider-fix loops */
|
|
45171
|
+
async handleCliExercise(req, res) {
|
|
45172
|
+
return handleCliExercise(this, req, res);
|
|
45173
|
+
}
|
|
45174
|
+
async handleCliFixtureCapture(req, res) {
|
|
45175
|
+
return handleCliFixtureCapture(this, req, res);
|
|
45176
|
+
}
|
|
45177
|
+
async handleCliFixtureReplay(req, res) {
|
|
45178
|
+
return handleCliFixtureReplay(this, req, res);
|
|
45179
|
+
}
|
|
43753
45180
|
/** POST /api/cli/stop — stop a running CLI { type } */
|
|
43754
45181
|
async handleCliStop(req, res) {
|
|
43755
45182
|
return handleCliStop(this, req, res);
|
|
@@ -43773,6 +45200,13 @@ data: ${JSON.stringify(msg.data)}
|
|
|
43773
45200
|
async handleCliDebug(type, _req, res) {
|
|
43774
45201
|
return handleCliDebug(this, type, _req, res);
|
|
43775
45202
|
}
|
|
45203
|
+
/** GET /api/cli/trace/:type — recent CLI trace timeline plus current debug snapshot */
|
|
45204
|
+
async handleCliTrace(type, _req, res) {
|
|
45205
|
+
return handleCliTrace(this, type, _req, res);
|
|
45206
|
+
}
|
|
45207
|
+
async handleCliFixtureList(type, _req, res) {
|
|
45208
|
+
return handleCliFixtureList(this, type, _req, res);
|
|
45209
|
+
}
|
|
43776
45210
|
/** POST /api/cli/resolve — resolve an approval modal { type, buttonIndex } */
|
|
43777
45211
|
async handleCliResolve(req, res) {
|
|
43778
45212
|
return handleCliResolve(this, req, res);
|
|
@@ -44080,7 +45514,18 @@ var init_session_host_transport = __esm({
|
|
|
44080
45514
|
});
|
|
44081
45515
|
}
|
|
44082
45516
|
async boot() {
|
|
44083
|
-
|
|
45517
|
+
if (typeof this.options.ensureReady === "function") {
|
|
45518
|
+
await this.options.ensureReady();
|
|
45519
|
+
}
|
|
45520
|
+
try {
|
|
45521
|
+
await this.client.connect();
|
|
45522
|
+
} catch (error48) {
|
|
45523
|
+
if (typeof this.options.ensureReady !== "function") {
|
|
45524
|
+
throw error48;
|
|
45525
|
+
}
|
|
45526
|
+
await this.options.ensureReady();
|
|
45527
|
+
await this.client.connect();
|
|
45528
|
+
}
|
|
44084
45529
|
this.unsubscribe = this.client.onEvent((event) => this.handleEvent(event));
|
|
44085
45530
|
let record2 = null;
|
|
44086
45531
|
if (this.options.attachExisting) {
|
|
@@ -44967,17 +46412,17 @@ function canPeerUsePrivilegedShareCommand(commandType, permission) {
|
|
|
44967
46412
|
return false;
|
|
44968
46413
|
}
|
|
44969
46414
|
}
|
|
44970
|
-
var
|
|
46415
|
+
var fs15, path18, os19, import_node_module2, esmRequire, logFile, log, logDebug, DaemonP2PSender;
|
|
44971
46416
|
var init_daemon_p2p = __esm({
|
|
44972
46417
|
"src/daemon-p2p.ts"() {
|
|
44973
46418
|
"use strict";
|
|
44974
|
-
|
|
46419
|
+
fs15 = __toESM(require("fs"));
|
|
44975
46420
|
init_src();
|
|
44976
|
-
|
|
46421
|
+
path18 = __toESM(require("path"));
|
|
44977
46422
|
os19 = __toESM(require("os"));
|
|
44978
46423
|
import_node_module2 = require("module");
|
|
44979
46424
|
esmRequire = (0, import_node_module2.createRequire)(__filename);
|
|
44980
|
-
logFile =
|
|
46425
|
+
logFile = path18.join(os19.tmpdir(), "adhdev_daemon_p2p.log");
|
|
44981
46426
|
log = (msg) => {
|
|
44982
46427
|
LOG.info("P2P", `[${(/* @__PURE__ */ new Date()).toISOString()}] [P2P] ${msg}`);
|
|
44983
46428
|
};
|
|
@@ -45045,17 +46490,17 @@ ${e?.stack || ""}`);
|
|
|
45045
46490
|
const prebuildKey = `${platform11}-${arch3}`;
|
|
45046
46491
|
try {
|
|
45047
46492
|
const candidates = [
|
|
45048
|
-
|
|
45049
|
-
|
|
45050
|
-
|
|
46493
|
+
path18.join(__dirname, "node_modules", "node-datachannel"),
|
|
46494
|
+
path18.join(__dirname, "..", "node_modules", "node-datachannel"),
|
|
46495
|
+
path18.join(__dirname, "..", "..", "node_modules", "node-datachannel")
|
|
45051
46496
|
];
|
|
45052
46497
|
for (const candidate of candidates) {
|
|
45053
|
-
const prebuildPath =
|
|
45054
|
-
if (
|
|
45055
|
-
const targetDir =
|
|
45056
|
-
const targetPath =
|
|
45057
|
-
|
|
45058
|
-
|
|
46498
|
+
const prebuildPath = path18.join(candidate, "prebuilds", prebuildKey, "node_datachannel.node");
|
|
46499
|
+
if (fs15.existsSync(prebuildPath)) {
|
|
46500
|
+
const targetDir = path18.join(candidate, "build", "Release");
|
|
46501
|
+
const targetPath = path18.join(targetDir, "node_datachannel.node");
|
|
46502
|
+
fs15.mkdirSync(targetDir, { recursive: true });
|
|
46503
|
+
fs15.copyFileSync(prebuildPath, targetPath);
|
|
45059
46504
|
try {
|
|
45060
46505
|
delete esmRequire.cache[esmRequire.resolve("node-datachannel")];
|
|
45061
46506
|
} catch {
|
|
@@ -45949,48 +47394,122 @@ var init_screenshot_controller = __esm({
|
|
|
45949
47394
|
});
|
|
45950
47395
|
|
|
45951
47396
|
// src/session-host.ts
|
|
47397
|
+
function buildSessionHostEnv(baseEnv) {
|
|
47398
|
+
const env = {};
|
|
47399
|
+
for (const [key, value] of Object.entries(baseEnv)) {
|
|
47400
|
+
if (typeof value !== "string") continue;
|
|
47401
|
+
env[key] = value;
|
|
47402
|
+
}
|
|
47403
|
+
for (const key of Object.keys(env)) {
|
|
47404
|
+
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_")) {
|
|
47405
|
+
delete env[key];
|
|
47406
|
+
}
|
|
47407
|
+
}
|
|
47408
|
+
env.ADHDEV_SESSION_HOST_NAME = SESSION_HOST_APP_NAME;
|
|
47409
|
+
return env;
|
|
47410
|
+
}
|
|
45952
47411
|
function resolveSessionHostEntry() {
|
|
45953
47412
|
const packagedCandidates = [
|
|
45954
|
-
|
|
45955
|
-
|
|
47413
|
+
path19.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
|
|
47414
|
+
path19.resolve(__dirname, "../../vendor/session-host-daemon/index.js")
|
|
45956
47415
|
];
|
|
45957
47416
|
for (const candidate of packagedCandidates) {
|
|
45958
|
-
if (
|
|
47417
|
+
if (fs16.existsSync(candidate)) {
|
|
45959
47418
|
return candidate;
|
|
45960
47419
|
}
|
|
45961
47420
|
}
|
|
45962
47421
|
return require.resolve("@adhdev/session-host-daemon");
|
|
45963
47422
|
}
|
|
45964
|
-
|
|
45965
|
-
return
|
|
45966
|
-
|
|
45967
|
-
|
|
45968
|
-
|
|
45969
|
-
|
|
45970
|
-
|
|
45971
|
-
|
|
45972
|
-
|
|
45973
|
-
|
|
45974
|
-
|
|
45975
|
-
|
|
47423
|
+
function getSessionHostPidFile() {
|
|
47424
|
+
return path19.join(os20.homedir(), ".adhdev", `${SESSION_HOST_APP_NAME}-session-host.pid`);
|
|
47425
|
+
}
|
|
47426
|
+
function killPid(pid) {
|
|
47427
|
+
try {
|
|
47428
|
+
if (process.platform === "win32") {
|
|
47429
|
+
(0, import_child_process9.execFileSync)("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore" });
|
|
47430
|
+
} else {
|
|
47431
|
+
process.kill(pid, "SIGTERM");
|
|
47432
|
+
}
|
|
47433
|
+
return true;
|
|
47434
|
+
} catch {
|
|
47435
|
+
return false;
|
|
47436
|
+
}
|
|
47437
|
+
}
|
|
47438
|
+
function stopSessionHost() {
|
|
47439
|
+
let stopped = false;
|
|
47440
|
+
const pidFile = getSessionHostPidFile();
|
|
47441
|
+
try {
|
|
47442
|
+
if (fs16.existsSync(pidFile)) {
|
|
47443
|
+
const pid = Number.parseInt(fs16.readFileSync(pidFile, "utf8").trim(), 10);
|
|
47444
|
+
if (Number.isFinite(pid)) {
|
|
47445
|
+
stopped = killPid(pid) || stopped;
|
|
47446
|
+
}
|
|
47447
|
+
}
|
|
47448
|
+
} catch {
|
|
47449
|
+
} finally {
|
|
47450
|
+
try {
|
|
47451
|
+
fs16.unlinkSync(pidFile);
|
|
47452
|
+
} catch {
|
|
47453
|
+
}
|
|
47454
|
+
}
|
|
47455
|
+
if (process.platform !== "win32") {
|
|
47456
|
+
try {
|
|
47457
|
+
const raw = (0, import_child_process9.execFileSync)("pgrep", ["-f", "session-host-daemon"], { encoding: "utf8" }).trim();
|
|
47458
|
+
for (const line of raw.split("\n")) {
|
|
47459
|
+
const pid = Number.parseInt(line.trim(), 10);
|
|
47460
|
+
if (Number.isFinite(pid)) {
|
|
47461
|
+
stopped = killPid(pid) || stopped;
|
|
45976
47462
|
}
|
|
45977
|
-
}
|
|
45978
|
-
|
|
47463
|
+
}
|
|
47464
|
+
} catch {
|
|
45979
47465
|
}
|
|
45980
|
-
}
|
|
47466
|
+
}
|
|
47467
|
+
return stopped;
|
|
47468
|
+
}
|
|
47469
|
+
async function ensureSessionHostReady2() {
|
|
47470
|
+
const spawnHost = () => {
|
|
47471
|
+
const entry = resolveSessionHostEntry();
|
|
47472
|
+
const child = (0, import_child_process9.spawn)(process.execPath, [entry], {
|
|
47473
|
+
detached: true,
|
|
47474
|
+
stdio: "ignore",
|
|
47475
|
+
windowsHide: true,
|
|
47476
|
+
env: buildSessionHostEnv(process.env)
|
|
47477
|
+
});
|
|
47478
|
+
child.unref();
|
|
47479
|
+
};
|
|
47480
|
+
try {
|
|
47481
|
+
return await ensureSessionHostReady({
|
|
47482
|
+
appName: SESSION_HOST_APP_NAME,
|
|
47483
|
+
spawnHost,
|
|
47484
|
+
timeoutMs: SESSION_HOST_START_TIMEOUT_MS
|
|
47485
|
+
});
|
|
47486
|
+
} catch (error48) {
|
|
47487
|
+
stopSessionHost();
|
|
47488
|
+
return ensureSessionHostReady({
|
|
47489
|
+
appName: SESSION_HOST_APP_NAME,
|
|
47490
|
+
spawnHost,
|
|
47491
|
+
timeoutMs: SESSION_HOST_START_TIMEOUT_MS
|
|
47492
|
+
}).catch((retryError) => {
|
|
47493
|
+
const initialMessage = error48 instanceof Error ? error48.message : String(error48);
|
|
47494
|
+
const retryMessage = retryError instanceof Error ? retryError.message : String(retryError);
|
|
47495
|
+
throw new Error(`Session host failed to start after retry (${initialMessage}; retry: ${retryMessage})`);
|
|
47496
|
+
});
|
|
47497
|
+
}
|
|
45981
47498
|
}
|
|
45982
47499
|
async function listHostedCliRuntimes2(endpoint) {
|
|
45983
47500
|
return listHostedCliRuntimes(endpoint);
|
|
45984
47501
|
}
|
|
45985
|
-
var import_child_process9,
|
|
47502
|
+
var import_child_process9, fs16, os20, path19, SESSION_HOST_APP_NAME, SESSION_HOST_START_TIMEOUT_MS;
|
|
45986
47503
|
var init_session_host = __esm({
|
|
45987
47504
|
"src/session-host.ts"() {
|
|
45988
47505
|
"use strict";
|
|
45989
47506
|
import_child_process9 = require("child_process");
|
|
45990
|
-
|
|
45991
|
-
|
|
47507
|
+
fs16 = __toESM(require("fs"));
|
|
47508
|
+
os20 = __toESM(require("os"));
|
|
47509
|
+
path19 = __toESM(require("path"));
|
|
45992
47510
|
init_src();
|
|
45993
47511
|
SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
|
|
47512
|
+
SESSION_HOST_START_TIMEOUT_MS = 15e3;
|
|
45994
47513
|
}
|
|
45995
47514
|
});
|
|
45996
47515
|
|
|
@@ -46002,24 +47521,24 @@ __export(adhdev_daemon_exports, {
|
|
|
46002
47521
|
stopDaemon: () => stopDaemon
|
|
46003
47522
|
});
|
|
46004
47523
|
function getDaemonPidFile() {
|
|
46005
|
-
const dir =
|
|
46006
|
-
if (!
|
|
46007
|
-
return
|
|
47524
|
+
const dir = path20.join(os21.homedir(), ".adhdev");
|
|
47525
|
+
if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
|
|
47526
|
+
return path20.join(dir, "daemon.pid");
|
|
46008
47527
|
}
|
|
46009
47528
|
function writeDaemonPid(pid) {
|
|
46010
|
-
|
|
47529
|
+
fs17.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
|
|
46011
47530
|
}
|
|
46012
47531
|
function removeDaemonPid() {
|
|
46013
47532
|
try {
|
|
46014
|
-
|
|
47533
|
+
fs17.unlinkSync(getDaemonPidFile());
|
|
46015
47534
|
} catch (e) {
|
|
46016
47535
|
}
|
|
46017
47536
|
}
|
|
46018
47537
|
function isDaemonRunning() {
|
|
46019
47538
|
const pidFile = getDaemonPidFile();
|
|
46020
47539
|
try {
|
|
46021
|
-
if (!
|
|
46022
|
-
const pid = parseInt(
|
|
47540
|
+
if (!fs17.existsSync(pidFile)) return false;
|
|
47541
|
+
const pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim());
|
|
46023
47542
|
process.kill(pid, 0);
|
|
46024
47543
|
return true;
|
|
46025
47544
|
} catch {
|
|
@@ -46030,8 +47549,8 @@ function isDaemonRunning() {
|
|
|
46030
47549
|
function stopDaemon() {
|
|
46031
47550
|
const pidFile = getDaemonPidFile();
|
|
46032
47551
|
try {
|
|
46033
|
-
if (!
|
|
46034
|
-
const pid = parseInt(
|
|
47552
|
+
if (!fs17.existsSync(pidFile)) return false;
|
|
47553
|
+
const pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim());
|
|
46035
47554
|
process.kill(pid, "SIGTERM");
|
|
46036
47555
|
removeDaemonPid();
|
|
46037
47556
|
return true;
|
|
@@ -46040,7 +47559,7 @@ function stopDaemon() {
|
|
|
46040
47559
|
return false;
|
|
46041
47560
|
}
|
|
46042
47561
|
}
|
|
46043
|
-
var
|
|
47562
|
+
var os21, fs17, path20, import_chalk2, pkgVersion, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
46044
47563
|
var init_adhdev_daemon = __esm({
|
|
46045
47564
|
"src/adhdev-daemon.ts"() {
|
|
46046
47565
|
"use strict";
|
|
@@ -46050,20 +47569,20 @@ var init_adhdev_daemon = __esm({
|
|
|
46050
47569
|
init_screenshot_controller();
|
|
46051
47570
|
init_session_host();
|
|
46052
47571
|
init_dist();
|
|
46053
|
-
|
|
46054
|
-
|
|
46055
|
-
|
|
47572
|
+
os21 = __toESM(require("os"));
|
|
47573
|
+
fs17 = __toESM(require("fs"));
|
|
47574
|
+
path20 = __toESM(require("path"));
|
|
46056
47575
|
import_chalk2 = __toESM(require("chalk"));
|
|
46057
|
-
pkgVersion = "0.
|
|
47576
|
+
pkgVersion = "0.8.1";
|
|
46058
47577
|
if (pkgVersion === "unknown") {
|
|
46059
47578
|
try {
|
|
46060
47579
|
const possiblePaths = [
|
|
46061
|
-
|
|
46062
|
-
|
|
47580
|
+
path20.join(__dirname, "..", "package.json"),
|
|
47581
|
+
path20.join(__dirname, "package.json")
|
|
46063
47582
|
];
|
|
46064
47583
|
for (const p of possiblePaths) {
|
|
46065
47584
|
try {
|
|
46066
|
-
const data = JSON.parse(
|
|
47585
|
+
const data = JSON.parse(fs17.readFileSync(p, "utf-8"));
|
|
46067
47586
|
if (data.version) {
|
|
46068
47587
|
pkgVersion = data.version;
|
|
46069
47588
|
break;
|
|
@@ -46161,6 +47680,10 @@ ${err?.stack || ""}`);
|
|
|
46161
47680
|
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
46162
47681
|
createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, providerSessionId, attachExisting }) => new SessionHostPtyTransportFactory({
|
|
46163
47682
|
endpoint: sessionHostEndpoint,
|
|
47683
|
+
ensureReady: async () => {
|
|
47684
|
+
const activeEndpoint = await ensureSessionHostReady2();
|
|
47685
|
+
this.sessionHostEndpoint = activeEndpoint;
|
|
47686
|
+
},
|
|
46164
47687
|
clientId: `daemon_${config2.machineId}`,
|
|
46165
47688
|
runtimeId,
|
|
46166
47689
|
providerType,
|
|
@@ -46206,8 +47729,8 @@ ${err?.stack || ""}`);
|
|
|
46206
47729
|
cliInfo: {
|
|
46207
47730
|
type: "adhdev-daemon",
|
|
46208
47731
|
version: pkgVersion,
|
|
46209
|
-
platform:
|
|
46210
|
-
hostname:
|
|
47732
|
+
platform: os21.platform(),
|
|
47733
|
+
hostname: os21.hostname(),
|
|
46211
47734
|
machineId: config2.machineId,
|
|
46212
47735
|
instanceId
|
|
46213
47736
|
}
|
|
@@ -46556,9 +48079,13 @@ ${import_chalk3.default.cyan("\u2551")} ${import_chalk3.default.gray("Agent Das
|
|
|
46556
48079
|
${import_chalk3.default.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")}
|
|
46557
48080
|
`;
|
|
46558
48081
|
var DIVIDER = import_chalk3.default.gray("\u2500".repeat(44));
|
|
48082
|
+
function hasCloudMachineAuth() {
|
|
48083
|
+
const config2 = loadConfig();
|
|
48084
|
+
return Boolean(config2.machineSecret && config2.machineSecret.trim());
|
|
48085
|
+
}
|
|
46559
48086
|
async function runWizard(options = {}) {
|
|
46560
48087
|
console.log(LOGO);
|
|
46561
|
-
if (isSetupComplete() && !options.force) {
|
|
48088
|
+
if (isSetupComplete() && hasCloudMachineAuth() && !options.force) {
|
|
46562
48089
|
const config2 = loadConfig();
|
|
46563
48090
|
console.log(import_chalk3.default.green("\u2713") + " ADHDev is already configured.");
|
|
46564
48091
|
console.log(import_chalk3.default.gray(` Account: ${config2.userEmail || "not logged in"}`));
|
|
@@ -46623,29 +48150,46 @@ async function checkForUpdate() {
|
|
|
46623
48150
|
async function quickSetup() {
|
|
46624
48151
|
console.log(import_chalk3.default.bold("\n\u{1F680} Quick Setup\n"));
|
|
46625
48152
|
const loginResult = await loginFlow();
|
|
48153
|
+
const setupDate = (/* @__PURE__ */ new Date()).toISOString();
|
|
46626
48154
|
if (!loginResult) {
|
|
46627
|
-
|
|
48155
|
+
updateConfig({
|
|
48156
|
+
selectedIde: "daemon",
|
|
48157
|
+
configuredIdes: ["daemon"],
|
|
48158
|
+
installedExtensions: ["adhdev"],
|
|
48159
|
+
setupCompleted: false,
|
|
48160
|
+
setupDate,
|
|
48161
|
+
userEmail: null,
|
|
48162
|
+
userName: null,
|
|
48163
|
+
machineSecret: null
|
|
48164
|
+
});
|
|
48165
|
+
console.log(import_chalk3.default.yellow("\u26A0 Setup is not complete without login. Run `adhdev setup` after signing in."));
|
|
46628
48166
|
}
|
|
46629
|
-
markSetupComplete(["daemon"], ["adhdev"]);
|
|
46630
48167
|
if (loginResult) {
|
|
48168
|
+
markSetupComplete(["daemon"], ["adhdev"]);
|
|
46631
48169
|
const configUpdate = {
|
|
46632
48170
|
machineSecret: loginResult.machineSecret,
|
|
46633
48171
|
userEmail: loginResult.email,
|
|
46634
48172
|
userName: loginResult.name,
|
|
48173
|
+
setupDate,
|
|
46635
48174
|
...loginResult.registeredMachineId ? { registeredMachineId: loginResult.registeredMachineId } : {}
|
|
46636
48175
|
};
|
|
46637
48176
|
updateConfig(configUpdate);
|
|
46638
48177
|
console.log(import_chalk3.default.green(` \u2713 Machine registered`));
|
|
46639
48178
|
}
|
|
46640
48179
|
await installCliOnly();
|
|
46641
|
-
|
|
48180
|
+
if (loginResult) {
|
|
48181
|
+
await startDaemonFlow();
|
|
48182
|
+
} else {
|
|
48183
|
+
console.log(import_chalk3.default.gray(" Start daemon after login: adhdev setup"));
|
|
48184
|
+
console.log();
|
|
48185
|
+
}
|
|
46642
48186
|
console.log(DIVIDER);
|
|
46643
48187
|
console.log(import_chalk3.default.bold("\n\u{1F389} Setup Complete!\n"));
|
|
46644
48188
|
console.log(` ${import_chalk3.default.bold("User:")} ${loginResult?.email || "not logged in"}`);
|
|
46645
|
-
console.log(` ${import_chalk3.default.bold("Status:")} ${import_chalk3.default.green("Ready to connect")}`);
|
|
48189
|
+
console.log(` ${import_chalk3.default.bold("Status:")} ${loginResult ? import_chalk3.default.green("Ready to connect") : import_chalk3.default.yellow("Login required")}`);
|
|
46646
48190
|
console.log();
|
|
46647
48191
|
console.log(import_chalk3.default.gray(" Next steps:"));
|
|
46648
|
-
console.log(import_chalk3.default.gray("
|
|
48192
|
+
console.log(import_chalk3.default.gray(` ${loginResult ? "adhdev daemon \u2014 Start the main daemon (required for all features)" : "adhdev setup \u2014 Sign in to finish setup and enable the daemon"}`));
|
|
46649
48193
|
console.log(import_chalk3.default.gray(" adhdev launch cursor \u2014 Launch Cursor IDE with remote control"));
|
|
46650
48194
|
console.log(import_chalk3.default.gray(" adhdev launch windsurf \u2014 Launch Windsurf IDE with remote control"));
|
|
46651
48195
|
console.log(import_chalk3.default.gray(" adhdev launch gemini \u2014 Start Gemini CLI agent via daemon"));
|
|
@@ -46672,16 +48216,16 @@ async function loginFlow() {
|
|
|
46672
48216
|
let verificationUrl;
|
|
46673
48217
|
try {
|
|
46674
48218
|
const config2 = loadConfig();
|
|
46675
|
-
const
|
|
48219
|
+
const os22 = await import("os");
|
|
46676
48220
|
const res = await fetch(`${SERVER_URL}/auth/cli/init`, {
|
|
46677
48221
|
method: "POST",
|
|
46678
48222
|
headers: { "Content-Type": "application/json" },
|
|
46679
48223
|
body: JSON.stringify({
|
|
46680
48224
|
clientMachineId: config2.machineId,
|
|
46681
48225
|
registeredMachineId: config2.registeredMachineId,
|
|
46682
|
-
hostname:
|
|
46683
|
-
platform:
|
|
46684
|
-
arch:
|
|
48226
|
+
hostname: os22.hostname(),
|
|
48227
|
+
platform: os22.platform(),
|
|
48228
|
+
arch: os22.arch()
|
|
46685
48229
|
})
|
|
46686
48230
|
});
|
|
46687
48231
|
if (!res.ok) {
|
|
@@ -46780,10 +48324,10 @@ async function startDaemonFlow() {
|
|
|
46780
48324
|
const { AdhdevDaemon: AdhdevDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
|
|
46781
48325
|
const daemon = new AdhdevDaemon2();
|
|
46782
48326
|
const { execSync: execSync6 } = await import("child_process");
|
|
46783
|
-
const
|
|
46784
|
-
const
|
|
46785
|
-
const logPath =
|
|
46786
|
-
const platform11 =
|
|
48327
|
+
const os22 = await import("os");
|
|
48328
|
+
const path21 = await import("path");
|
|
48329
|
+
const logPath = path21.join(os22.homedir(), ".adhdev", "daemon.log");
|
|
48330
|
+
const platform11 = os22.platform();
|
|
46787
48331
|
try {
|
|
46788
48332
|
if (platform11 === "win32") {
|
|
46789
48333
|
execSync6(`start /B adhdev daemon > "${logPath}" 2>&1`, {
|