adhdev 0.7.46 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1881 -414
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1924 -410
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/session-host-daemon/index.js +14 -3
- package/vendor/session-host-daemon/index.js.map +1 -1
- package/vendor/session-host-daemon/index.mjs +14 -3
- package/vendor/session-host-daemon/index.mjs.map +1 -1
package/dist/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];
|
|
@@ -41051,6 +41503,160 @@ var init_dev_cdp_handlers = __esm({
|
|
|
41051
41503
|
});
|
|
41052
41504
|
|
|
41053
41505
|
// ../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts
|
|
41506
|
+
function slugifyFixtureName(value) {
|
|
41507
|
+
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
41508
|
+
return normalized || `fixture-${Date.now()}`;
|
|
41509
|
+
}
|
|
41510
|
+
function getCliFixtureDir(ctx, type) {
|
|
41511
|
+
const providerDir = ctx.providerLoader.findProviderDir(type);
|
|
41512
|
+
if (!providerDir) {
|
|
41513
|
+
throw new Error(`Provider directory not found for '${type}'`);
|
|
41514
|
+
}
|
|
41515
|
+
return path15.join(providerDir, "fixtures");
|
|
41516
|
+
}
|
|
41517
|
+
function readCliFixture(ctx, type, name) {
|
|
41518
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
41519
|
+
const filePath = path15.join(fixtureDir, `${name}.json`);
|
|
41520
|
+
if (!fs12.existsSync(filePath)) {
|
|
41521
|
+
throw new Error(`Fixture not found: ${filePath}`);
|
|
41522
|
+
}
|
|
41523
|
+
return JSON.parse(fs12.readFileSync(filePath, "utf-8"));
|
|
41524
|
+
}
|
|
41525
|
+
function getExerciseTranscriptText(result) {
|
|
41526
|
+
const parts = [];
|
|
41527
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41528
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41529
|
+
for (const message of [...debugMessages, ...traceMessages]) {
|
|
41530
|
+
if (!message || typeof message.content !== "string") continue;
|
|
41531
|
+
parts.push(message.content);
|
|
41532
|
+
}
|
|
41533
|
+
if (typeof result?.debug?.partialResponse === "string") parts.push(result.debug.partialResponse);
|
|
41534
|
+
if (typeof result?.trace?.responseBuffer === "string") parts.push(result.trace.responseBuffer);
|
|
41535
|
+
return parts.join("\n");
|
|
41536
|
+
}
|
|
41537
|
+
function getExerciseLastAssistant(result) {
|
|
41538
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41539
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41540
|
+
for (const messages of [debugMessages, traceMessages]) {
|
|
41541
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
41542
|
+
const message = messages[i];
|
|
41543
|
+
if (message?.role === "assistant" && typeof message.content === "string" && message.content.trim()) {
|
|
41544
|
+
return message.content;
|
|
41545
|
+
}
|
|
41546
|
+
}
|
|
41547
|
+
}
|
|
41548
|
+
return "";
|
|
41549
|
+
}
|
|
41550
|
+
function getExerciseMessageCount(result) {
|
|
41551
|
+
const debugMessages = Array.isArray(result?.debug?.messages) ? result.debug.messages : [];
|
|
41552
|
+
const traceMessages = Array.isArray(result?.trace?.messages) ? result.trace.messages : [];
|
|
41553
|
+
return Math.max(debugMessages.length, traceMessages.length);
|
|
41554
|
+
}
|
|
41555
|
+
function compileFixtureRegex(source) {
|
|
41556
|
+
const value = String(source || "").trim();
|
|
41557
|
+
if (!value) return null;
|
|
41558
|
+
const delimited = value.match(/^\/([\s\S]+)\/([dgimsuvy]*)$/);
|
|
41559
|
+
try {
|
|
41560
|
+
if (delimited) {
|
|
41561
|
+
return new RegExp(delimited[1], delimited[2]);
|
|
41562
|
+
}
|
|
41563
|
+
return new RegExp(value, "m");
|
|
41564
|
+
} catch {
|
|
41565
|
+
return null;
|
|
41566
|
+
}
|
|
41567
|
+
}
|
|
41568
|
+
function statusesContainSequence(actual, expected) {
|
|
41569
|
+
if (!expected.length) return true;
|
|
41570
|
+
let index = 0;
|
|
41571
|
+
for (const status of actual) {
|
|
41572
|
+
if (status === expected[index]) index += 1;
|
|
41573
|
+
if (index >= expected.length) return true;
|
|
41574
|
+
}
|
|
41575
|
+
return false;
|
|
41576
|
+
}
|
|
41577
|
+
function validateCliFixtureResult(result, assertions) {
|
|
41578
|
+
const failures = [];
|
|
41579
|
+
const transcriptText = getExerciseTranscriptText(result);
|
|
41580
|
+
const lastAssistant = getExerciseLastAssistant(result);
|
|
41581
|
+
const mustContainAny = assertions.mustContainAny || [];
|
|
41582
|
+
const mustNotContainAny = assertions.mustNotContainAny || [];
|
|
41583
|
+
const mustMatchAny = assertions.mustMatchAny || [];
|
|
41584
|
+
const mustNotMatchAny = assertions.mustNotMatchAny || [];
|
|
41585
|
+
const lastAssistantMustContainAny = assertions.lastAssistantMustContainAny || [];
|
|
41586
|
+
const lastAssistantMustNotContainAny = assertions.lastAssistantMustNotContainAny || [];
|
|
41587
|
+
const lastAssistantMustMatchAny = assertions.lastAssistantMustMatchAny || [];
|
|
41588
|
+
const lastAssistantMustNotMatchAny = assertions.lastAssistantMustNotMatchAny || [];
|
|
41589
|
+
const statusesSeen = Array.isArray(result?.statusesSeen) ? result.statusesSeen.map((value) => String(value)) : [];
|
|
41590
|
+
if (assertions.requireNotTimedOut !== false && result?.timedOut) {
|
|
41591
|
+
failures.push("Exercise timed out");
|
|
41592
|
+
}
|
|
41593
|
+
const missingRequired = mustContainAny.filter((value) => !transcriptText.includes(value));
|
|
41594
|
+
if (missingRequired.length > 0) {
|
|
41595
|
+
failures.push(`Missing required substrings: ${missingRequired.join(", ")}`);
|
|
41596
|
+
}
|
|
41597
|
+
const presentBanned = mustNotContainAny.filter((value) => transcriptText.includes(value));
|
|
41598
|
+
if (presentBanned.length > 0) {
|
|
41599
|
+
failures.push(`Found banned substrings: ${presentBanned.join(", ")}`);
|
|
41600
|
+
}
|
|
41601
|
+
const missingRegex = mustMatchAny.filter((value) => {
|
|
41602
|
+
const regex = compileFixtureRegex(value);
|
|
41603
|
+
return !regex || !regex.test(transcriptText);
|
|
41604
|
+
});
|
|
41605
|
+
if (missingRegex.length > 0) {
|
|
41606
|
+
failures.push(`Missing required regex matches: ${missingRegex.join(", ")}`);
|
|
41607
|
+
}
|
|
41608
|
+
const presentBannedRegex = mustNotMatchAny.filter((value) => {
|
|
41609
|
+
const regex = compileFixtureRegex(value);
|
|
41610
|
+
return !!regex && regex.test(transcriptText);
|
|
41611
|
+
});
|
|
41612
|
+
if (presentBannedRegex.length > 0) {
|
|
41613
|
+
failures.push(`Found banned regex matches: ${presentBannedRegex.join(", ")}`);
|
|
41614
|
+
}
|
|
41615
|
+
const missingLastAssistant = lastAssistantMustContainAny.filter((value) => !lastAssistant.includes(value));
|
|
41616
|
+
if (missingLastAssistant.length > 0) {
|
|
41617
|
+
failures.push(`Missing required lastAssistant substrings: ${missingLastAssistant.join(", ")}`);
|
|
41618
|
+
}
|
|
41619
|
+
const presentBannedLastAssistant = lastAssistantMustNotContainAny.filter((value) => lastAssistant.includes(value));
|
|
41620
|
+
if (presentBannedLastAssistant.length > 0) {
|
|
41621
|
+
failures.push(`Found banned lastAssistant substrings: ${presentBannedLastAssistant.join(", ")}`);
|
|
41622
|
+
}
|
|
41623
|
+
const missingLastAssistantRegex = lastAssistantMustMatchAny.filter((value) => {
|
|
41624
|
+
const regex = compileFixtureRegex(value);
|
|
41625
|
+
return !regex || !regex.test(lastAssistant);
|
|
41626
|
+
});
|
|
41627
|
+
if (missingLastAssistantRegex.length > 0) {
|
|
41628
|
+
failures.push(`Missing required lastAssistant regex matches: ${missingLastAssistantRegex.join(", ")}`);
|
|
41629
|
+
}
|
|
41630
|
+
const presentBannedLastAssistantRegex = lastAssistantMustNotMatchAny.filter((value) => {
|
|
41631
|
+
const regex = compileFixtureRegex(value);
|
|
41632
|
+
return !!regex && regex.test(lastAssistant);
|
|
41633
|
+
});
|
|
41634
|
+
if (presentBannedLastAssistantRegex.length > 0) {
|
|
41635
|
+
failures.push(`Found banned lastAssistant regex matches: ${presentBannedLastAssistantRegex.join(", ")}`);
|
|
41636
|
+
}
|
|
41637
|
+
if (assertions.statusesSeen?.length && !statusesContainSequence(statusesSeen, assertions.statusesSeen)) {
|
|
41638
|
+
failures.push(`Expected statuses sequence not observed: ${assertions.statusesSeen.join(" -> ")}`);
|
|
41639
|
+
}
|
|
41640
|
+
if (result && typeof result === "object") {
|
|
41641
|
+
result.lastAssistant = lastAssistant;
|
|
41642
|
+
}
|
|
41643
|
+
return failures;
|
|
41644
|
+
}
|
|
41645
|
+
function getCliProviderResolutionMeta(ctx, type, adapter) {
|
|
41646
|
+
const adapterMeta = typeof adapter?.getProviderResolutionMeta === "function" ? adapter.getProviderResolutionMeta() : adapter?.getDebugState?.()?.providerResolution || null;
|
|
41647
|
+
const resolvedProvider = ctx.providerLoader.resolve(type);
|
|
41648
|
+
if (!adapterMeta && !resolvedProvider) return null;
|
|
41649
|
+
return {
|
|
41650
|
+
type,
|
|
41651
|
+
providerDir: adapterMeta?.providerDir || resolvedProvider?._resolvedProviderDir || ctx.providerLoader.findProviderDir(type),
|
|
41652
|
+
scriptDir: adapterMeta?.scriptDir || resolvedProvider?._resolvedScriptDir || null,
|
|
41653
|
+
scriptsPath: adapterMeta?.scriptsPath || resolvedProvider?._resolvedScriptsPath || null,
|
|
41654
|
+
scriptsSource: adapterMeta?.scriptsSource || resolvedProvider?._resolvedScriptsSource || null,
|
|
41655
|
+
resolvedVersion: adapterMeta?.resolvedVersion || resolvedProvider?._resolvedVersion || null,
|
|
41656
|
+
resolvedOs: adapterMeta?.resolvedOs || resolvedProvider?._resolvedOs || null,
|
|
41657
|
+
versionWarning: adapterMeta?.versionWarning || resolvedProvider?._versionWarning || null
|
|
41658
|
+
};
|
|
41659
|
+
}
|
|
41054
41660
|
function findCliTarget(ctx, type, instanceId) {
|
|
41055
41661
|
if (!ctx.instanceManager) return null;
|
|
41056
41662
|
const cliStates = ctx.instanceManager.collectAllStates().filter((s15) => s15.category === "cli" || s15.category === "acp");
|
|
@@ -41059,6 +41665,331 @@ function findCliTarget(ctx, type, instanceId) {
|
|
|
41059
41665
|
const matches = cliStates.filter((s15) => s15.type === type);
|
|
41060
41666
|
return matches[matches.length - 1] || null;
|
|
41061
41667
|
}
|
|
41668
|
+
function getCliTargetBundle(ctx, type, instanceId) {
|
|
41669
|
+
if (!ctx.instanceManager) return null;
|
|
41670
|
+
const target = findCliTarget(ctx, type, instanceId);
|
|
41671
|
+
if (!target) return null;
|
|
41672
|
+
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
41673
|
+
if (!instance) return null;
|
|
41674
|
+
const adapter = instance.getAdapter?.() || instance.adapter;
|
|
41675
|
+
if (!adapter) return null;
|
|
41676
|
+
return { target, instance, adapter };
|
|
41677
|
+
}
|
|
41678
|
+
function sleep(ms2) {
|
|
41679
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms2));
|
|
41680
|
+
}
|
|
41681
|
+
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
41682
|
+
const startedAt = Date.now();
|
|
41683
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
41684
|
+
const bundle = getCliTargetBundle(ctx, type, instanceId);
|
|
41685
|
+
if (bundle) {
|
|
41686
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
41687
|
+
const startupParseGate = !!debug?.startupParseGate;
|
|
41688
|
+
const adapterReady = !!debug?.ready;
|
|
41689
|
+
const visibleStatusReady = bundle.target.status === "generating" || bundle.target.status === "waiting_approval";
|
|
41690
|
+
const idleReady = bundle.target.status === "idle" && !startupParseGate;
|
|
41691
|
+
if (adapterReady || visibleStatusReady || idleReady) {
|
|
41692
|
+
return bundle;
|
|
41693
|
+
}
|
|
41694
|
+
}
|
|
41695
|
+
await sleep(100);
|
|
41696
|
+
}
|
|
41697
|
+
return getCliTargetBundle(ctx, type, instanceId);
|
|
41698
|
+
}
|
|
41699
|
+
async function runCliExerciseInternal(ctx, body) {
|
|
41700
|
+
if (!ctx.cliManager) {
|
|
41701
|
+
throw new Error("CliManager not available");
|
|
41702
|
+
}
|
|
41703
|
+
if (!ctx.instanceManager) {
|
|
41704
|
+
throw new Error("InstanceManager not available");
|
|
41705
|
+
}
|
|
41706
|
+
const {
|
|
41707
|
+
type,
|
|
41708
|
+
text,
|
|
41709
|
+
instanceId: requestedInstanceId,
|
|
41710
|
+
workingDir,
|
|
41711
|
+
args,
|
|
41712
|
+
autoLaunch = true,
|
|
41713
|
+
freshSession = true,
|
|
41714
|
+
autoResolveApprovals = true,
|
|
41715
|
+
approvalButtonIndex = 0,
|
|
41716
|
+
timeoutMs = 45e3,
|
|
41717
|
+
readyTimeoutMs = 15e3,
|
|
41718
|
+
idleSettledMs = 1200,
|
|
41719
|
+
traceLimit = 160,
|
|
41720
|
+
stopWhenDone = false
|
|
41721
|
+
} = body || {};
|
|
41722
|
+
if (!type) {
|
|
41723
|
+
throw new Error("type required (e.g. claude-cli, codex-cli)");
|
|
41724
|
+
}
|
|
41725
|
+
if (!text || typeof text !== "string") {
|
|
41726
|
+
throw new Error("text required (prompt to send to the CLI)");
|
|
41727
|
+
}
|
|
41728
|
+
let resolvedInstanceId = requestedInstanceId;
|
|
41729
|
+
if (freshSession) {
|
|
41730
|
+
const staleTargets = ctx.instanceManager.collectAllStates().filter((state) => (state.category === "cli" || state.category === "acp") && state.type === type).map((state) => state.instanceId);
|
|
41731
|
+
for (const staleId of staleTargets) {
|
|
41732
|
+
ctx.instanceManager.removeInstance(staleId);
|
|
41733
|
+
}
|
|
41734
|
+
resolvedInstanceId = void 0;
|
|
41735
|
+
}
|
|
41736
|
+
let bundle = getCliTargetBundle(ctx, type, resolvedInstanceId);
|
|
41737
|
+
if (!bundle && autoLaunch) {
|
|
41738
|
+
const launchArgs = [type, workingDir || process.cwd(), Array.isArray(args) ? args : []];
|
|
41739
|
+
let launched = null;
|
|
41740
|
+
let lastLaunchError = null;
|
|
41741
|
+
for (let attempt = 1; attempt <= 2; attempt += 1) {
|
|
41742
|
+
try {
|
|
41743
|
+
launched = await ctx.cliManager.startSession(...launchArgs);
|
|
41744
|
+
lastLaunchError = null;
|
|
41745
|
+
break;
|
|
41746
|
+
} catch (error48) {
|
|
41747
|
+
lastLaunchError = error48 instanceof Error ? error48 : new Error(String(error48?.message || error48));
|
|
41748
|
+
const message = String(lastLaunchError.message || "");
|
|
41749
|
+
const retryable = /ECONNREFUSED|session-host|Session host/i.test(message);
|
|
41750
|
+
if (!retryable || attempt === 2) break;
|
|
41751
|
+
await sleep(1e3);
|
|
41752
|
+
}
|
|
41753
|
+
}
|
|
41754
|
+
if (!launched) {
|
|
41755
|
+
throw lastLaunchError || new Error(`Failed to start ${type}`);
|
|
41756
|
+
}
|
|
41757
|
+
resolvedInstanceId = launched.runtimeSessionId;
|
|
41758
|
+
bundle = await waitForCliReady(ctx, type, resolvedInstanceId, Math.max(1e3, readyTimeoutMs));
|
|
41759
|
+
}
|
|
41760
|
+
if (!bundle) {
|
|
41761
|
+
throw new Error(`No running instance found for: ${resolvedInstanceId || type}`);
|
|
41762
|
+
}
|
|
41763
|
+
const initialDebug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
41764
|
+
const initialTrace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
41765
|
+
const providerResolution = getCliProviderResolutionMeta(ctx, bundle.target.type, bundle.adapter);
|
|
41766
|
+
const preTraceCount = Number(initialTrace?.entryCount || 0);
|
|
41767
|
+
const startAt = Date.now();
|
|
41768
|
+
const statusesSeen = [];
|
|
41769
|
+
const approvalsResolved = [];
|
|
41770
|
+
let lastStatus = "";
|
|
41771
|
+
let lastModalKey = "";
|
|
41772
|
+
let idleSince = 0;
|
|
41773
|
+
let sawBusy = false;
|
|
41774
|
+
ctx.instanceManager.sendEvent(bundle.target.instanceId, "send_message", { text });
|
|
41775
|
+
while (Date.now() - startAt < Math.max(1e3, timeoutMs)) {
|
|
41776
|
+
await sleep(150);
|
|
41777
|
+
bundle = getCliTargetBundle(ctx, type, bundle.target.instanceId);
|
|
41778
|
+
if (!bundle) {
|
|
41779
|
+
throw new Error("CLI instance disappeared during exercise");
|
|
41780
|
+
}
|
|
41781
|
+
const debug = typeof bundle.adapter.getDebugState === "function" ? bundle.adapter.getDebugState() : null;
|
|
41782
|
+
const trace = typeof bundle.adapter.getTraceState === "function" ? bundle.adapter.getTraceState(traceLimit) : null;
|
|
41783
|
+
const status = String(debug?.status || bundle.target.status || "unknown");
|
|
41784
|
+
const traceEntries = Array.isArray(trace?.entries) ? trace.entries : [];
|
|
41785
|
+
const sawSendMessage = traceEntries.some((entry) => entry?.type === "send_message");
|
|
41786
|
+
const sawSubmitWrite = traceEntries.some((entry) => entry?.type === "submit_write");
|
|
41787
|
+
const hasTurnStarted = sawSendMessage || sawSubmitWrite || !!debug?.currentTurnScope;
|
|
41788
|
+
if (status !== lastStatus) {
|
|
41789
|
+
statusesSeen.push(status);
|
|
41790
|
+
lastStatus = status;
|
|
41791
|
+
}
|
|
41792
|
+
if (status === "generating" || status === "waiting_approval") {
|
|
41793
|
+
sawBusy = true;
|
|
41794
|
+
idleSince = 0;
|
|
41795
|
+
}
|
|
41796
|
+
const modal = debug?.activeModal || trace?.activeModal || null;
|
|
41797
|
+
if (autoResolveApprovals && status === "waiting_approval" && modal && Array.isArray(modal.buttons) && modal.buttons.length > 0) {
|
|
41798
|
+
const clampedIndex = Math.max(0, Math.min(Number(approvalButtonIndex) || 0, modal.buttons.length - 1));
|
|
41799
|
+
const modalKey = JSON.stringify({
|
|
41800
|
+
message: modal.message || "",
|
|
41801
|
+
buttons: modal.buttons,
|
|
41802
|
+
index: clampedIndex
|
|
41803
|
+
});
|
|
41804
|
+
if (modalKey !== lastModalKey && typeof bundle.adapter.resolveModal === "function") {
|
|
41805
|
+
lastModalKey = modalKey;
|
|
41806
|
+
approvalsResolved.push({
|
|
41807
|
+
at: Date.now(),
|
|
41808
|
+
buttonIndex: clampedIndex,
|
|
41809
|
+
label: modal.buttons[clampedIndex] || null
|
|
41810
|
+
});
|
|
41811
|
+
bundle.adapter.resolveModal(clampedIndex);
|
|
41812
|
+
continue;
|
|
41813
|
+
}
|
|
41814
|
+
}
|
|
41815
|
+
const traceCount = Number(trace?.entryCount || 0);
|
|
41816
|
+
const hasProgress = hasTurnStarted && (traceCount > preTraceCount || statusesSeen.length > 1 || approvalsResolved.length > 0);
|
|
41817
|
+
if (status === "idle" && hasProgress && sawBusy) {
|
|
41818
|
+
if (!idleSince) idleSince = Date.now();
|
|
41819
|
+
if (Date.now() - idleSince >= Math.max(200, idleSettledMs)) {
|
|
41820
|
+
const payload2 = {
|
|
41821
|
+
exercised: true,
|
|
41822
|
+
instanceId: bundle.target.instanceId,
|
|
41823
|
+
providerState: {
|
|
41824
|
+
type: bundle.target.type,
|
|
41825
|
+
name: bundle.target.name,
|
|
41826
|
+
status: bundle.target.status,
|
|
41827
|
+
mode: "mode" in bundle.target ? bundle.target.mode : void 0
|
|
41828
|
+
},
|
|
41829
|
+
providerResolution,
|
|
41830
|
+
initialDebug,
|
|
41831
|
+
initialTrace,
|
|
41832
|
+
debug,
|
|
41833
|
+
trace,
|
|
41834
|
+
statusesSeen,
|
|
41835
|
+
approvalsResolved,
|
|
41836
|
+
elapsedMs: Date.now() - startAt,
|
|
41837
|
+
timedOut: false
|
|
41838
|
+
};
|
|
41839
|
+
payload2.lastAssistant = getExerciseLastAssistant(payload2);
|
|
41840
|
+
payload2.messageCount = getExerciseMessageCount(payload2);
|
|
41841
|
+
if (stopWhenDone) {
|
|
41842
|
+
ctx.instanceManager.removeInstance(bundle.target.instanceId);
|
|
41843
|
+
}
|
|
41844
|
+
return payload2;
|
|
41845
|
+
}
|
|
41846
|
+
} else if (status === "idle" && hasProgress) {
|
|
41847
|
+
if (!idleSince) idleSince = Date.now();
|
|
41848
|
+
if (Date.now() - idleSince >= Math.max(500, idleSettledMs) && Date.now() - startAt >= 750) {
|
|
41849
|
+
const payload2 = {
|
|
41850
|
+
exercised: true,
|
|
41851
|
+
instanceId: bundle.target.instanceId,
|
|
41852
|
+
providerState: {
|
|
41853
|
+
type: bundle.target.type,
|
|
41854
|
+
name: bundle.target.name,
|
|
41855
|
+
status: bundle.target.status,
|
|
41856
|
+
mode: "mode" in bundle.target ? bundle.target.mode : void 0
|
|
41857
|
+
},
|
|
41858
|
+
providerResolution,
|
|
41859
|
+
initialDebug,
|
|
41860
|
+
initialTrace,
|
|
41861
|
+
debug,
|
|
41862
|
+
trace,
|
|
41863
|
+
statusesSeen,
|
|
41864
|
+
approvalsResolved,
|
|
41865
|
+
elapsedMs: Date.now() - startAt,
|
|
41866
|
+
timedOut: false
|
|
41867
|
+
};
|
|
41868
|
+
payload2.lastAssistant = getExerciseLastAssistant(payload2);
|
|
41869
|
+
payload2.messageCount = getExerciseMessageCount(payload2);
|
|
41870
|
+
if (stopWhenDone) {
|
|
41871
|
+
ctx.instanceManager.removeInstance(bundle.target.instanceId);
|
|
41872
|
+
}
|
|
41873
|
+
return payload2;
|
|
41874
|
+
}
|
|
41875
|
+
} else {
|
|
41876
|
+
idleSince = 0;
|
|
41877
|
+
}
|
|
41878
|
+
}
|
|
41879
|
+
const finalBundle = getCliTargetBundle(ctx, type, bundle.target.instanceId) || bundle;
|
|
41880
|
+
const finalDebug = typeof finalBundle.adapter.getDebugState === "function" ? finalBundle.adapter.getDebugState() : null;
|
|
41881
|
+
const finalTrace = typeof finalBundle.adapter.getTraceState === "function" ? finalBundle.adapter.getTraceState(traceLimit) : null;
|
|
41882
|
+
if (stopWhenDone) {
|
|
41883
|
+
ctx.instanceManager.removeInstance(finalBundle.target.instanceId);
|
|
41884
|
+
}
|
|
41885
|
+
const payload = {
|
|
41886
|
+
exercised: true,
|
|
41887
|
+
instanceId: finalBundle.target.instanceId,
|
|
41888
|
+
providerState: {
|
|
41889
|
+
type: finalBundle.target.type,
|
|
41890
|
+
name: finalBundle.target.name,
|
|
41891
|
+
status: finalBundle.target.status,
|
|
41892
|
+
mode: "mode" in finalBundle.target ? finalBundle.target.mode : void 0
|
|
41893
|
+
},
|
|
41894
|
+
providerResolution: getCliProviderResolutionMeta(ctx, finalBundle.target.type, finalBundle.adapter),
|
|
41895
|
+
initialDebug,
|
|
41896
|
+
initialTrace,
|
|
41897
|
+
debug: finalDebug,
|
|
41898
|
+
trace: finalTrace,
|
|
41899
|
+
statusesSeen,
|
|
41900
|
+
approvalsResolved,
|
|
41901
|
+
elapsedMs: Date.now() - startAt,
|
|
41902
|
+
timedOut: true
|
|
41903
|
+
};
|
|
41904
|
+
payload.lastAssistant = getExerciseLastAssistant(payload);
|
|
41905
|
+
payload.messageCount = getExerciseMessageCount(payload);
|
|
41906
|
+
return payload;
|
|
41907
|
+
}
|
|
41908
|
+
async function runCliAutoImplVerification(ctx, type, verification) {
|
|
41909
|
+
const assertions = {
|
|
41910
|
+
mustContainAny: verification?.mustContainAny || [],
|
|
41911
|
+
mustNotContainAny: verification?.mustNotContainAny || [],
|
|
41912
|
+
mustMatchAny: verification?.mustMatchAny || [],
|
|
41913
|
+
mustNotMatchAny: verification?.mustNotMatchAny || [],
|
|
41914
|
+
lastAssistantMustContainAny: verification?.lastAssistantMustContainAny || [],
|
|
41915
|
+
lastAssistantMustNotContainAny: verification?.lastAssistantMustNotContainAny || [],
|
|
41916
|
+
lastAssistantMustMatchAny: verification?.lastAssistantMustMatchAny || [],
|
|
41917
|
+
lastAssistantMustNotMatchAny: verification?.lastAssistantMustNotMatchAny || [],
|
|
41918
|
+
requireNotTimedOut: true
|
|
41919
|
+
};
|
|
41920
|
+
const rawFixtureNames = Array.isArray(verification?.fixtureNames) ? verification.fixtureNames.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
41921
|
+
if (rawFixtureNames.length > 0) {
|
|
41922
|
+
const results = [];
|
|
41923
|
+
for (const rawFixtureName2 of rawFixtureNames) {
|
|
41924
|
+
const name = slugifyFixtureName(rawFixtureName2);
|
|
41925
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
41926
|
+
const mergedAssertions = {
|
|
41927
|
+
...fixture.assertions,
|
|
41928
|
+
...assertions
|
|
41929
|
+
};
|
|
41930
|
+
const result2 = await runCliExerciseInternal(ctx, {
|
|
41931
|
+
...fixture.request,
|
|
41932
|
+
type
|
|
41933
|
+
});
|
|
41934
|
+
const failures2 = validateCliFixtureResult(result2, mergedAssertions);
|
|
41935
|
+
results.push({
|
|
41936
|
+
fixtureName: name,
|
|
41937
|
+
pass: failures2.length === 0,
|
|
41938
|
+
failures: failures2,
|
|
41939
|
+
result: result2,
|
|
41940
|
+
assertions: mergedAssertions,
|
|
41941
|
+
fixture
|
|
41942
|
+
});
|
|
41943
|
+
}
|
|
41944
|
+
const firstFailure = results.find((item) => !item.pass) || results[results.length - 1];
|
|
41945
|
+
return {
|
|
41946
|
+
mode: "fixture_replay_suite",
|
|
41947
|
+
pass: results.every((item) => item.pass),
|
|
41948
|
+
failures: results.flatMap((item) => item.failures.map((failure) => `${item.fixtureName}: ${failure}`)),
|
|
41949
|
+
result: firstFailure.result,
|
|
41950
|
+
assertions: firstFailure.assertions,
|
|
41951
|
+
fixture: firstFailure.fixture,
|
|
41952
|
+
results
|
|
41953
|
+
};
|
|
41954
|
+
}
|
|
41955
|
+
const rawFixtureName = String(verification?.fixtureName || "").trim();
|
|
41956
|
+
if (rawFixtureName) {
|
|
41957
|
+
const name = slugifyFixtureName(rawFixtureName);
|
|
41958
|
+
try {
|
|
41959
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
41960
|
+
const mergedAssertions = {
|
|
41961
|
+
...fixture.assertions,
|
|
41962
|
+
...assertions
|
|
41963
|
+
};
|
|
41964
|
+
const result2 = await runCliExerciseInternal(ctx, {
|
|
41965
|
+
...fixture.request,
|
|
41966
|
+
type
|
|
41967
|
+
});
|
|
41968
|
+
const failures2 = validateCliFixtureResult(result2, mergedAssertions);
|
|
41969
|
+
return {
|
|
41970
|
+
mode: "fixture_replay",
|
|
41971
|
+
pass: failures2.length === 0,
|
|
41972
|
+
failures: failures2,
|
|
41973
|
+
result: result2,
|
|
41974
|
+
assertions: mergedAssertions,
|
|
41975
|
+
fixture
|
|
41976
|
+
};
|
|
41977
|
+
} catch {
|
|
41978
|
+
}
|
|
41979
|
+
}
|
|
41980
|
+
const result = await runCliExerciseInternal(ctx, {
|
|
41981
|
+
...verification?.request || {},
|
|
41982
|
+
type
|
|
41983
|
+
});
|
|
41984
|
+
const failures = validateCliFixtureResult(result, assertions);
|
|
41985
|
+
return {
|
|
41986
|
+
mode: "exercise",
|
|
41987
|
+
pass: failures.length === 0,
|
|
41988
|
+
failures,
|
|
41989
|
+
result,
|
|
41990
|
+
assertions
|
|
41991
|
+
};
|
|
41992
|
+
}
|
|
41062
41993
|
async function handleCliStatus(ctx, _req, res) {
|
|
41063
41994
|
if (!ctx.instanceManager) {
|
|
41064
41995
|
ctx.json(res, 503, { error: "InstanceManager not available (daemon not fully initialized)" });
|
|
@@ -41197,12 +42128,14 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
41197
42128
|
status: target.status,
|
|
41198
42129
|
mode: "mode" in target ? target.mode : void 0
|
|
41199
42130
|
},
|
|
42131
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
41200
42132
|
debug: debugState
|
|
41201
42133
|
});
|
|
41202
42134
|
} else {
|
|
41203
42135
|
ctx.json(res, 200, {
|
|
41204
42136
|
instanceId: target.instanceId,
|
|
41205
42137
|
providerState: target,
|
|
42138
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
41206
42139
|
debug: null,
|
|
41207
42140
|
message: "No debug state available (adapter.getDebugState not found)"
|
|
41208
42141
|
});
|
|
@@ -41211,6 +42144,191 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
41211
42144
|
ctx.json(res, 500, { error: `Debug state failed: ${e.message}` });
|
|
41212
42145
|
}
|
|
41213
42146
|
}
|
|
42147
|
+
async function handleCliTrace(ctx, type, req, res) {
|
|
42148
|
+
if (!ctx.instanceManager) {
|
|
42149
|
+
ctx.json(res, 503, { error: "InstanceManager not available" });
|
|
42150
|
+
return;
|
|
42151
|
+
}
|
|
42152
|
+
const target = findCliTarget(ctx, type);
|
|
42153
|
+
if (!target) {
|
|
42154
|
+
const allStates = ctx.instanceManager.collectAllStates();
|
|
42155
|
+
ctx.json(res, 404, {
|
|
42156
|
+
error: `No running instance for: ${type}`,
|
|
42157
|
+
available: allStates.filter((s15) => s15.category === "cli" || s15.category === "acp").map((s15) => s15.type)
|
|
42158
|
+
});
|
|
42159
|
+
return;
|
|
42160
|
+
}
|
|
42161
|
+
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
42162
|
+
if (!instance) {
|
|
42163
|
+
ctx.json(res, 404, { error: `Instance not found: ${target.instanceId}` });
|
|
42164
|
+
return;
|
|
42165
|
+
}
|
|
42166
|
+
try {
|
|
42167
|
+
const adapter = instance.getAdapter?.() || instance.adapter;
|
|
42168
|
+
const url2 = new URL(req.url || "/", "http://127.0.0.1");
|
|
42169
|
+
const limit = parseInt(url2.searchParams.get("limit") || "120", 10);
|
|
42170
|
+
if (adapter && typeof adapter.getTraceState === "function") {
|
|
42171
|
+
const trace = adapter.getTraceState(limit);
|
|
42172
|
+
const debug = typeof adapter.getDebugState === "function" ? adapter.getDebugState() : null;
|
|
42173
|
+
ctx.json(res, 200, {
|
|
42174
|
+
instanceId: target.instanceId,
|
|
42175
|
+
providerState: {
|
|
42176
|
+
type: target.type,
|
|
42177
|
+
name: target.name,
|
|
42178
|
+
status: target.status,
|
|
42179
|
+
mode: "mode" in target ? target.mode : void 0
|
|
42180
|
+
},
|
|
42181
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
42182
|
+
debug,
|
|
42183
|
+
trace
|
|
42184
|
+
});
|
|
42185
|
+
} else {
|
|
42186
|
+
ctx.json(res, 200, {
|
|
42187
|
+
instanceId: target.instanceId,
|
|
42188
|
+
providerState: target,
|
|
42189
|
+
providerResolution: getCliProviderResolutionMeta(ctx, target.type, adapter),
|
|
42190
|
+
debug: typeof adapter?.getDebugState === "function" ? adapter.getDebugState() : null,
|
|
42191
|
+
trace: null,
|
|
42192
|
+
message: "No trace state available (adapter.getTraceState not found)"
|
|
42193
|
+
});
|
|
42194
|
+
}
|
|
42195
|
+
} catch (e) {
|
|
42196
|
+
ctx.json(res, 500, { error: `Trace state failed: ${e.message}` });
|
|
42197
|
+
}
|
|
42198
|
+
}
|
|
42199
|
+
async function handleCliExercise(ctx, req, res) {
|
|
42200
|
+
try {
|
|
42201
|
+
const body = await ctx.readBody(req);
|
|
42202
|
+
const result = await runCliExerciseInternal(ctx, body || {});
|
|
42203
|
+
ctx.json(res, 200, result);
|
|
42204
|
+
} catch (e) {
|
|
42205
|
+
ctx.json(res, 500, { error: `Exercise failed: ${e.message}` });
|
|
42206
|
+
}
|
|
42207
|
+
}
|
|
42208
|
+
async function handleCliFixtureCapture(ctx, req, res) {
|
|
42209
|
+
try {
|
|
42210
|
+
const body = await ctx.readBody(req);
|
|
42211
|
+
const type = String(body?.type || "");
|
|
42212
|
+
const request = body?.request || {};
|
|
42213
|
+
if (!type) {
|
|
42214
|
+
ctx.json(res, 400, { error: "type required" });
|
|
42215
|
+
return;
|
|
42216
|
+
}
|
|
42217
|
+
if (!request?.text) {
|
|
42218
|
+
ctx.json(res, 400, { error: "request.text required" });
|
|
42219
|
+
return;
|
|
42220
|
+
}
|
|
42221
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
42222
|
+
fs12.mkdirSync(fixtureDir, { recursive: true });
|
|
42223
|
+
const name = slugifyFixtureName(String(body?.name || `${type}-${Date.now()}`));
|
|
42224
|
+
const result = await runCliExerciseInternal(ctx, { ...request, type });
|
|
42225
|
+
const fixture = {
|
|
42226
|
+
version: 1,
|
|
42227
|
+
kind: "cli-exercise-fixture",
|
|
42228
|
+
name,
|
|
42229
|
+
type,
|
|
42230
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
42231
|
+
providerDir: ctx.providerLoader.findProviderDir(type),
|
|
42232
|
+
providerResolution: result?.providerResolution || null,
|
|
42233
|
+
request: { ...request, type },
|
|
42234
|
+
result,
|
|
42235
|
+
assertions: {
|
|
42236
|
+
mustContainAny: Array.isArray(body?.assertions?.mustContainAny) ? body.assertions.mustContainAny : [],
|
|
42237
|
+
mustNotContainAny: Array.isArray(body?.assertions?.mustNotContainAny) ? body.assertions.mustNotContainAny : [],
|
|
42238
|
+
mustMatchAny: Array.isArray(body?.assertions?.mustMatchAny) ? body.assertions.mustMatchAny : [],
|
|
42239
|
+
mustNotMatchAny: Array.isArray(body?.assertions?.mustNotMatchAny) ? body.assertions.mustNotMatchAny : [],
|
|
42240
|
+
lastAssistantMustContainAny: Array.isArray(body?.assertions?.lastAssistantMustContainAny) ? body.assertions.lastAssistantMustContainAny : [],
|
|
42241
|
+
lastAssistantMustNotContainAny: Array.isArray(body?.assertions?.lastAssistantMustNotContainAny) ? body.assertions.lastAssistantMustNotContainAny : [],
|
|
42242
|
+
lastAssistantMustMatchAny: Array.isArray(body?.assertions?.lastAssistantMustMatchAny) ? body.assertions.lastAssistantMustMatchAny : [],
|
|
42243
|
+
lastAssistantMustNotMatchAny: Array.isArray(body?.assertions?.lastAssistantMustNotMatchAny) ? body.assertions.lastAssistantMustNotMatchAny : [],
|
|
42244
|
+
statusesSeen: Array.isArray(body?.assertions?.statusesSeen) ? body.assertions.statusesSeen : void 0,
|
|
42245
|
+
requireNotTimedOut: body?.assertions?.requireNotTimedOut !== false
|
|
42246
|
+
},
|
|
42247
|
+
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
42248
|
+
};
|
|
42249
|
+
const filePath = path15.join(fixtureDir, `${name}.json`);
|
|
42250
|
+
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
42251
|
+
ctx.json(res, 200, {
|
|
42252
|
+
saved: true,
|
|
42253
|
+
name,
|
|
42254
|
+
path: filePath,
|
|
42255
|
+
fixture,
|
|
42256
|
+
verification: {
|
|
42257
|
+
pass: validateCliFixtureResult(result, fixture.assertions).length === 0,
|
|
42258
|
+
failures: validateCliFixtureResult(result, fixture.assertions)
|
|
42259
|
+
}
|
|
42260
|
+
});
|
|
42261
|
+
} catch (e) {
|
|
42262
|
+
ctx.json(res, 500, { error: `Fixture capture failed: ${e.message}` });
|
|
42263
|
+
}
|
|
42264
|
+
}
|
|
42265
|
+
async function handleCliFixtureList(ctx, type, _req, res) {
|
|
42266
|
+
try {
|
|
42267
|
+
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
42268
|
+
if (!fs12.existsSync(fixtureDir)) {
|
|
42269
|
+
ctx.json(res, 200, { fixtures: [], count: 0 });
|
|
42270
|
+
return;
|
|
42271
|
+
}
|
|
42272
|
+
const fixtures = fs12.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
|
|
42273
|
+
const fullPath = path15.join(fixtureDir, file2);
|
|
42274
|
+
try {
|
|
42275
|
+
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
42276
|
+
return {
|
|
42277
|
+
name: raw.name || file2.replace(/\.json$/i, ""),
|
|
42278
|
+
path: fullPath,
|
|
42279
|
+
createdAt: raw.createdAt || null,
|
|
42280
|
+
notes: raw.notes || null,
|
|
42281
|
+
requestText: raw.request?.text || "",
|
|
42282
|
+
assertions: raw.assertions || {}
|
|
42283
|
+
};
|
|
42284
|
+
} catch {
|
|
42285
|
+
return {
|
|
42286
|
+
name: file2.replace(/\.json$/i, ""),
|
|
42287
|
+
path: fullPath,
|
|
42288
|
+
createdAt: null,
|
|
42289
|
+
notes: "Unreadable fixture",
|
|
42290
|
+
requestText: "",
|
|
42291
|
+
assertions: {}
|
|
42292
|
+
};
|
|
42293
|
+
}
|
|
42294
|
+
});
|
|
42295
|
+
ctx.json(res, 200, { fixtures, count: fixtures.length });
|
|
42296
|
+
} catch (e) {
|
|
42297
|
+
ctx.json(res, 500, { error: `Fixture list failed: ${e.message}` });
|
|
42298
|
+
}
|
|
42299
|
+
}
|
|
42300
|
+
async function handleCliFixtureReplay(ctx, req, res) {
|
|
42301
|
+
try {
|
|
42302
|
+
const body = await ctx.readBody(req);
|
|
42303
|
+
const type = String(body?.type || "");
|
|
42304
|
+
const rawName = String(body?.name || "").trim();
|
|
42305
|
+
if (!type || !rawName) {
|
|
42306
|
+
ctx.json(res, 400, { error: "type and name required" });
|
|
42307
|
+
return;
|
|
42308
|
+
}
|
|
42309
|
+
const name = slugifyFixtureName(rawName);
|
|
42310
|
+
const fixture = readCliFixture(ctx, type, name);
|
|
42311
|
+
const result = await runCliExerciseInternal(ctx, {
|
|
42312
|
+
...fixture.request,
|
|
42313
|
+
type
|
|
42314
|
+
});
|
|
42315
|
+
const assertions = {
|
|
42316
|
+
...fixture.assertions,
|
|
42317
|
+
...body?.assertions || {}
|
|
42318
|
+
};
|
|
42319
|
+
const failures = validateCliFixtureResult(result, assertions);
|
|
42320
|
+
ctx.json(res, 200, {
|
|
42321
|
+
replayed: true,
|
|
42322
|
+
pass: failures.length === 0,
|
|
42323
|
+
failures,
|
|
42324
|
+
fixture,
|
|
42325
|
+
result,
|
|
42326
|
+
assertions
|
|
42327
|
+
});
|
|
42328
|
+
} catch (e) {
|
|
42329
|
+
ctx.json(res, 500, { error: `Fixture replay failed: ${e.message}` });
|
|
42330
|
+
}
|
|
42331
|
+
}
|
|
41214
42332
|
async function handleCliResolve(ctx, req, res) {
|
|
41215
42333
|
const body = await ctx.readBody(req);
|
|
41216
42334
|
const { type, buttonIndex, instanceId } = body;
|
|
@@ -41285,13 +42403,36 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
41285
42403
|
ctx.json(res, 500, { error: `Raw send failed: ${e.message}` });
|
|
41286
42404
|
}
|
|
41287
42405
|
}
|
|
42406
|
+
var fs12, path15;
|
|
41288
42407
|
var init_dev_cli_debug = __esm({
|
|
41289
42408
|
"../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts"() {
|
|
41290
42409
|
"use strict";
|
|
42410
|
+
fs12 = __toESM(require("fs"));
|
|
42411
|
+
path15 = __toESM(require("path"));
|
|
41291
42412
|
}
|
|
41292
42413
|
});
|
|
41293
42414
|
|
|
41294
42415
|
// ../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts
|
|
42416
|
+
function getAutoImplPid(ctx) {
|
|
42417
|
+
const proc = ctx.autoImplProcess;
|
|
42418
|
+
return proc && typeof proc.pid === "number" && proc.pid > 0 ? proc.pid : null;
|
|
42419
|
+
}
|
|
42420
|
+
function isPidAlive(pid) {
|
|
42421
|
+
try {
|
|
42422
|
+
process.kill(pid, 0);
|
|
42423
|
+
return true;
|
|
42424
|
+
} catch (error48) {
|
|
42425
|
+
return error48?.code === "EPERM";
|
|
42426
|
+
}
|
|
42427
|
+
}
|
|
42428
|
+
function clearStaleAutoImplState(ctx, reason) {
|
|
42429
|
+
if (!ctx.autoImplStatus.running && !ctx.autoImplProcess) return;
|
|
42430
|
+
const pid = getAutoImplPid(ctx);
|
|
42431
|
+
if (pid && isPidAlive(pid)) return;
|
|
42432
|
+
ctx.log(`Clearing stale auto-implement state: ${reason}${pid ? ` (pid ${pid})` : ""}`);
|
|
42433
|
+
ctx.autoImplProcess = null;
|
|
42434
|
+
ctx.autoImplStatus.running = false;
|
|
42435
|
+
}
|
|
41295
42436
|
function getDefaultAutoImplReference(ctx, category, type) {
|
|
41296
42437
|
if (category === "cli") {
|
|
41297
42438
|
return type === "codex-cli" ? "claude-cli" : "codex-cli";
|
|
@@ -41307,45 +42448,45 @@ function resolveAutoImplReference(ctx, category, requestedReference, targetType)
|
|
|
41307
42448
|
return fallback?.type || null;
|
|
41308
42449
|
}
|
|
41309
42450
|
function getLatestScriptVersionDir(scriptsDir) {
|
|
41310
|
-
if (!
|
|
41311
|
-
const versions =
|
|
42451
|
+
if (!fs13.existsSync(scriptsDir)) return null;
|
|
42452
|
+
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
41312
42453
|
try {
|
|
41313
|
-
return
|
|
42454
|
+
return fs13.statSync(path16.join(scriptsDir, d)).isDirectory();
|
|
41314
42455
|
} catch {
|
|
41315
42456
|
return false;
|
|
41316
42457
|
}
|
|
41317
42458
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
41318
42459
|
if (versions.length === 0) return null;
|
|
41319
|
-
return
|
|
42460
|
+
return path16.join(scriptsDir, versions[0]);
|
|
41320
42461
|
}
|
|
41321
42462
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
41322
|
-
const canonicalUserDir =
|
|
41323
|
-
const desiredDir = requestedDir ?
|
|
41324
|
-
const upstreamRoot =
|
|
41325
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
42463
|
+
const canonicalUserDir = path16.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
42464
|
+
const desiredDir = requestedDir ? path16.resolve(requestedDir) : canonicalUserDir;
|
|
42465
|
+
const upstreamRoot = path16.resolve(ctx.providerLoader.getUpstreamDir());
|
|
42466
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path16.sep}`)) {
|
|
41326
42467
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
41327
42468
|
}
|
|
41328
|
-
if (
|
|
42469
|
+
if (path16.basename(desiredDir) !== type) {
|
|
41329
42470
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
41330
42471
|
}
|
|
41331
42472
|
const sourceDir = ctx.findProviderDir(type);
|
|
41332
42473
|
if (!sourceDir) {
|
|
41333
42474
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
41334
42475
|
}
|
|
41335
|
-
if (!
|
|
41336
|
-
|
|
41337
|
-
|
|
42476
|
+
if (!fs13.existsSync(desiredDir)) {
|
|
42477
|
+
fs13.mkdirSync(path16.dirname(desiredDir), { recursive: true });
|
|
42478
|
+
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
41338
42479
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
41339
42480
|
}
|
|
41340
|
-
const providerJson =
|
|
41341
|
-
if (!
|
|
42481
|
+
const providerJson = path16.join(desiredDir, "provider.json");
|
|
42482
|
+
if (!fs13.existsSync(providerJson)) {
|
|
41342
42483
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
41343
42484
|
}
|
|
41344
42485
|
try {
|
|
41345
|
-
const providerData = JSON.parse(
|
|
42486
|
+
const providerData = JSON.parse(fs13.readFileSync(providerJson, "utf-8"));
|
|
41346
42487
|
if (providerData.disableUpstream !== true) {
|
|
41347
42488
|
providerData.disableUpstream = true;
|
|
41348
|
-
|
|
42489
|
+
fs13.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
41349
42490
|
}
|
|
41350
42491
|
} catch (error48) {
|
|
41351
42492
|
return {
|
|
@@ -41358,15 +42499,15 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
41358
42499
|
function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
41359
42500
|
if (!referenceType) return {};
|
|
41360
42501
|
const refDir = ctx.findProviderDir(referenceType);
|
|
41361
|
-
if (!refDir || !
|
|
42502
|
+
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
41362
42503
|
const referenceScripts = {};
|
|
41363
|
-
const scriptsDir =
|
|
42504
|
+
const scriptsDir = path16.join(refDir, "scripts");
|
|
41364
42505
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
41365
42506
|
if (!latestDir) return referenceScripts;
|
|
41366
|
-
for (const file2 of
|
|
42507
|
+
for (const file2 of fs13.readdirSync(latestDir)) {
|
|
41367
42508
|
if (!file2.endsWith(".js")) continue;
|
|
41368
42509
|
try {
|
|
41369
|
-
referenceScripts[file2] =
|
|
42510
|
+
referenceScripts[file2] = fs13.readFileSync(path16.join(latestDir, file2), "utf-8");
|
|
41370
42511
|
} catch {
|
|
41371
42512
|
}
|
|
41372
42513
|
}
|
|
@@ -41374,11 +42515,20 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
41374
42515
|
}
|
|
41375
42516
|
async function handleAutoImplement(ctx, type, req, res) {
|
|
41376
42517
|
const body = await ctx.readBody(req);
|
|
41377
|
-
const {
|
|
42518
|
+
const {
|
|
42519
|
+
agent = "claude-cli",
|
|
42520
|
+
functions,
|
|
42521
|
+
reference,
|
|
42522
|
+
model,
|
|
42523
|
+
comment,
|
|
42524
|
+
providerDir: requestedProviderDir,
|
|
42525
|
+
verification
|
|
42526
|
+
} = body;
|
|
41378
42527
|
if (!functions || !Array.isArray(functions) || functions.length === 0) {
|
|
41379
42528
|
ctx.json(res, 400, { error: 'functions[] is required (e.g. ["readChat", "sendMessage"])' });
|
|
41380
42529
|
return;
|
|
41381
42530
|
}
|
|
42531
|
+
clearStaleAutoImplState(ctx, "new auto-implement request");
|
|
41382
42532
|
if (ctx.autoImplStatus.running) {
|
|
41383
42533
|
ctx.json(res, 409, { error: "Auto-implement already in progress", type: ctx.autoImplStatus.type });
|
|
41384
42534
|
return;
|
|
@@ -41396,7 +42546,55 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41396
42546
|
return;
|
|
41397
42547
|
}
|
|
41398
42548
|
const providerDir = writableProvider.dir;
|
|
42549
|
+
ctx.autoImplStatus = { running: false, type, progress: [] };
|
|
42550
|
+
if (provider.category === "cli" && verification && (verification.fixtureName || verification.fixtureNames && verification.fixtureNames.length > 0)) {
|
|
42551
|
+
sendAutoImplSSE(ctx, {
|
|
42552
|
+
event: "progress",
|
|
42553
|
+
data: {
|
|
42554
|
+
function: "_preflight",
|
|
42555
|
+
status: "verifying",
|
|
42556
|
+
message: "Running preflight verification before spawning agent..."
|
|
42557
|
+
}
|
|
42558
|
+
});
|
|
42559
|
+
try {
|
|
42560
|
+
const preflight = await runCliAutoImplVerification(ctx, type, verification);
|
|
42561
|
+
sendAutoImplSSE(ctx, { event: "verification", data: preflight });
|
|
42562
|
+
if (preflight.pass) {
|
|
42563
|
+
sendAutoImplSSE(ctx, {
|
|
42564
|
+
event: "complete",
|
|
42565
|
+
data: {
|
|
42566
|
+
success: true,
|
|
42567
|
+
exitCode: 0,
|
|
42568
|
+
functions,
|
|
42569
|
+
message: `\u2705 No-op: exact ${preflight.mode} already passes`,
|
|
42570
|
+
verification: preflight,
|
|
42571
|
+
skipped: true
|
|
42572
|
+
}
|
|
42573
|
+
});
|
|
42574
|
+
ctx.json(res, 200, {
|
|
42575
|
+
started: false,
|
|
42576
|
+
skipped: true,
|
|
42577
|
+
type,
|
|
42578
|
+
functions,
|
|
42579
|
+
providerDir,
|
|
42580
|
+
verification: preflight,
|
|
42581
|
+
message: "Preflight verification already passes. No auto-implement run needed."
|
|
42582
|
+
});
|
|
42583
|
+
return;
|
|
42584
|
+
}
|
|
42585
|
+
} catch (error48) {
|
|
42586
|
+
sendAutoImplSSE(ctx, {
|
|
42587
|
+
event: "progress",
|
|
42588
|
+
data: {
|
|
42589
|
+
function: "_preflight",
|
|
42590
|
+
status: "verify_failed",
|
|
42591
|
+
message: `Preflight verification errored, continuing to agent run: ${error48?.message || error48}`
|
|
42592
|
+
}
|
|
42593
|
+
});
|
|
42594
|
+
}
|
|
42595
|
+
}
|
|
41399
42596
|
try {
|
|
42597
|
+
ctx.autoImplStatus = { running: true, type, progress: ctx.autoImplStatus.progress };
|
|
41400
42598
|
const resolvedReference = resolveAutoImplReference(ctx, provider.category, reference, type);
|
|
41401
42599
|
sendAutoImplSSE(ctx, {
|
|
41402
42600
|
event: "progress",
|
|
@@ -41416,17 +42614,17 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41416
42614
|
}
|
|
41417
42615
|
});
|
|
41418
42616
|
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
|
-
|
|
42617
|
+
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
42618
|
+
const tmpDir = path16.join(os17.tmpdir(), "adhdev-autoimpl");
|
|
42619
|
+
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
42620
|
+
const promptFile = path16.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
42621
|
+
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
41424
42622
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
41425
42623
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
41426
42624
|
const spawn5 = agentProvider?.spawn;
|
|
41427
42625
|
if (!spawn5?.command) {
|
|
41428
42626
|
try {
|
|
41429
|
-
|
|
42627
|
+
fs13.unlinkSync(promptFile);
|
|
41430
42628
|
} catch {
|
|
41431
42629
|
}
|
|
41432
42630
|
ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -41435,7 +42633,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41435
42633
|
const agentCategory = agentProvider?.category;
|
|
41436
42634
|
if (agentCategory === "acp") {
|
|
41437
42635
|
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn5.command} ${(spawn5.args || []).join(" ")}` } });
|
|
41438
|
-
ctx.autoImplStatus =
|
|
42636
|
+
ctx.autoImplStatus.running = true;
|
|
42637
|
+
ctx.autoImplStatus.type = type;
|
|
41439
42638
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
41440
42639
|
const { Readable: Readable3, Writable: Writable2 } = await import("stream");
|
|
41441
42640
|
const { spawn: spawnFn2 } = await import("child_process");
|
|
@@ -41527,7 +42726,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41527
42726
|
} catch {
|
|
41528
42727
|
}
|
|
41529
42728
|
try {
|
|
41530
|
-
|
|
42729
|
+
fs13.unlinkSync(promptFile);
|
|
41531
42730
|
} catch {
|
|
41532
42731
|
}
|
|
41533
42732
|
ctx.log(`Auto-implement (ACP) ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -41605,7 +42804,8 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41605
42804
|
}
|
|
41606
42805
|
}
|
|
41607
42806
|
sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning agent: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
|
|
41608
|
-
ctx.autoImplStatus =
|
|
42807
|
+
ctx.autoImplStatus.running = true;
|
|
42808
|
+
ctx.autoImplStatus.type = type;
|
|
41609
42809
|
const spawnedAt = Date.now();
|
|
41610
42810
|
let child;
|
|
41611
42811
|
let isPty = false;
|
|
@@ -41648,6 +42848,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41648
42848
|
let approvalKeys = { 0: "y\r" };
|
|
41649
42849
|
let approvalBuffer = "";
|
|
41650
42850
|
let lastApprovalTime = 0;
|
|
42851
|
+
let completionSignalSeen = false;
|
|
41651
42852
|
try {
|
|
41652
42853
|
const { normalizeCliProviderForRuntime: normalizeCliProviderForRuntime2 } = await Promise.resolve().then(() => (init_provider_cli_adapter(), provider_cli_adapter_exports));
|
|
41653
42854
|
const normalized = normalizeCliProviderForRuntime2(agentProvider);
|
|
@@ -41661,6 +42862,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41661
42862
|
approvalBuffer = (approvalBuffer + cleanData).slice(-1500);
|
|
41662
42863
|
const elapsed = Date.now() - spawnedAt;
|
|
41663
42864
|
if (elapsed > 15e3 && cleanData.includes("_PIPELINE_COMPLETE_SIGNAL_")) {
|
|
42865
|
+
completionSignalSeen = true;
|
|
41664
42866
|
ctx.log(`Agent finished task after ${Math.round(elapsed / 1e3)}s. Terminating interactive CLI session to unblock pipeline.`);
|
|
41665
42867
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: `
|
|
41666
42868
|
[\u{1F916} ADHDev Pipeline] Completion token detected. Proceeding...
|
|
@@ -41684,6 +42886,55 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41684
42886
|
lastApprovalTime = Date.now();
|
|
41685
42887
|
}
|
|
41686
42888
|
};
|
|
42889
|
+
const finalizeCliAutoImpl = async (code) => {
|
|
42890
|
+
ctx.autoImplProcess = null;
|
|
42891
|
+
let success2 = completionSignalSeen || code === 0;
|
|
42892
|
+
let message = success2 ? completionSignalSeen && code !== 0 ? "\u2705 Auto-implement complete (completion signal)" : "\u2705 Auto-implement complete" : `\u274C Agent exited (code: ${code})`;
|
|
42893
|
+
let verificationSummary = null;
|
|
42894
|
+
try {
|
|
42895
|
+
ctx.providerLoader.reload();
|
|
42896
|
+
} catch {
|
|
42897
|
+
}
|
|
42898
|
+
if (provider.category === "cli" && verification) {
|
|
42899
|
+
sendAutoImplSSE(ctx, {
|
|
42900
|
+
event: "progress",
|
|
42901
|
+
data: {
|
|
42902
|
+
function: "_verify",
|
|
42903
|
+
status: "running",
|
|
42904
|
+
message: "Running exact post-patch verification..."
|
|
42905
|
+
}
|
|
42906
|
+
});
|
|
42907
|
+
try {
|
|
42908
|
+
verificationSummary = await runCliAutoImplVerification(ctx, type, verification);
|
|
42909
|
+
sendAutoImplSSE(ctx, { event: "verification", data: verificationSummary });
|
|
42910
|
+
success2 = verificationSummary.pass;
|
|
42911
|
+
message = verificationSummary.pass ? `\u2705 Auto-implement complete (${verificationSummary.mode})` : `\u274C Post-patch verification failed (${verificationSummary.mode}): ${verificationSummary.failures.join("; ") || "unknown failure"}`;
|
|
42912
|
+
} catch (error48) {
|
|
42913
|
+
success2 = false;
|
|
42914
|
+
message = `\u274C Post-patch verification error: ${error48?.message || error48}`;
|
|
42915
|
+
sendAutoImplSSE(ctx, {
|
|
42916
|
+
event: "verification",
|
|
42917
|
+
data: { pass: false, error: error48?.message || String(error48) }
|
|
42918
|
+
});
|
|
42919
|
+
}
|
|
42920
|
+
}
|
|
42921
|
+
ctx.autoImplStatus.running = false;
|
|
42922
|
+
sendAutoImplSSE(ctx, {
|
|
42923
|
+
event: "complete",
|
|
42924
|
+
data: {
|
|
42925
|
+
success: success2,
|
|
42926
|
+
exitCode: code,
|
|
42927
|
+
functions,
|
|
42928
|
+
message,
|
|
42929
|
+
verification: verificationSummary
|
|
42930
|
+
}
|
|
42931
|
+
});
|
|
42932
|
+
try {
|
|
42933
|
+
fs13.unlinkSync(promptFile);
|
|
42934
|
+
} catch {
|
|
42935
|
+
}
|
|
42936
|
+
ctx.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})${verificationSummary ? ` verify=${verificationSummary.pass ? "pass" : "fail"}` : ""}`);
|
|
42937
|
+
};
|
|
41687
42938
|
if (isPty) {
|
|
41688
42939
|
child.onData((data) => {
|
|
41689
42940
|
stdout += data;
|
|
@@ -41695,21 +42946,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41695
42946
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
|
|
41696
42947
|
});
|
|
41697
42948
|
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
|
-
}
|
|
42949
|
+
void finalizeCliAutoImpl(code);
|
|
41713
42950
|
});
|
|
41714
42951
|
} else {
|
|
41715
42952
|
child.stdout?.on("data", (d) => {
|
|
@@ -41726,27 +42963,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41726
42963
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
|
|
41727
42964
|
});
|
|
41728
42965
|
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})`);
|
|
42966
|
+
void finalizeCliAutoImpl(code);
|
|
41750
42967
|
});
|
|
41751
42968
|
}
|
|
41752
42969
|
ctx.json(res, 202, {
|
|
@@ -41763,9 +42980,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
41763
42980
|
ctx.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
|
|
41764
42981
|
}
|
|
41765
42982
|
}
|
|
41766
|
-
function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType) {
|
|
42983
|
+
function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, userComment, referenceType, verification) {
|
|
41767
42984
|
if (provider.category === "cli") {
|
|
41768
|
-
return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType);
|
|
42985
|
+
return buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification);
|
|
41769
42986
|
}
|
|
41770
42987
|
const lines = [];
|
|
41771
42988
|
lines.push("You are implementing browser automation scripts for an IDE provider.");
|
|
@@ -41790,7 +43007,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
41790
43007
|
setMode: "set_mode.js"
|
|
41791
43008
|
};
|
|
41792
43009
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
41793
|
-
const scriptsDir =
|
|
43010
|
+
const scriptsDir = path16.join(providerDir, "scripts");
|
|
41794
43011
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
41795
43012
|
if (latestScriptsDir) {
|
|
41796
43013
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -41798,10 +43015,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
41798
43015
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
41799
43016
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
41800
43017
|
lines.push("");
|
|
41801
|
-
for (const file2 of
|
|
43018
|
+
for (const file2 of fs13.readdirSync(latestScriptsDir)) {
|
|
41802
43019
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
41803
43020
|
try {
|
|
41804
|
-
const content =
|
|
43021
|
+
const content = fs13.readFileSync(path16.join(latestScriptsDir, file2), "utf-8");
|
|
41805
43022
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
41806
43023
|
lines.push("```javascript");
|
|
41807
43024
|
lines.push(content);
|
|
@@ -41811,14 +43028,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
41811
43028
|
}
|
|
41812
43029
|
}
|
|
41813
43030
|
}
|
|
41814
|
-
const refFiles =
|
|
43031
|
+
const refFiles = fs13.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
41815
43032
|
if (refFiles.length > 0) {
|
|
41816
43033
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
41817
43034
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
41818
43035
|
lines.push("");
|
|
41819
43036
|
for (const file2 of refFiles) {
|
|
41820
43037
|
try {
|
|
41821
|
-
const content =
|
|
43038
|
+
const content = fs13.readFileSync(path16.join(latestScriptsDir, file2), "utf-8");
|
|
41822
43039
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
41823
43040
|
lines.push("```javascript");
|
|
41824
43041
|
lines.push(content);
|
|
@@ -41859,11 +43076,11 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
41859
43076
|
lines.push("");
|
|
41860
43077
|
}
|
|
41861
43078
|
}
|
|
41862
|
-
const docsDir =
|
|
43079
|
+
const docsDir = path16.join(providerDir, "../../docs");
|
|
41863
43080
|
const loadGuide = (name) => {
|
|
41864
43081
|
try {
|
|
41865
|
-
const p =
|
|
41866
|
-
if (
|
|
43082
|
+
const p = path16.join(docsDir, name);
|
|
43083
|
+
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
41867
43084
|
} catch {
|
|
41868
43085
|
}
|
|
41869
43086
|
return null;
|
|
@@ -42021,8 +43238,69 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
42021
43238
|
lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
|
|
42022
43239
|
return lines.join("\n");
|
|
42023
43240
|
}
|
|
42024
|
-
function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType) {
|
|
43241
|
+
function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, referenceScripts, userComment, referenceType, verification) {
|
|
42025
43242
|
const lines = [];
|
|
43243
|
+
const defaultExercisePayload = {
|
|
43244
|
+
type,
|
|
43245
|
+
workingDir: providerDir,
|
|
43246
|
+
freshSession: true,
|
|
43247
|
+
autoLaunch: true,
|
|
43248
|
+
autoResolveApprovals: true,
|
|
43249
|
+
approvalButtonIndex: 0,
|
|
43250
|
+
timeoutMs: 45e3,
|
|
43251
|
+
traceLimit: 200,
|
|
43252
|
+
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."
|
|
43253
|
+
};
|
|
43254
|
+
const exercisePayload = {
|
|
43255
|
+
...defaultExercisePayload,
|
|
43256
|
+
...verification?.request || {},
|
|
43257
|
+
type,
|
|
43258
|
+
workingDir: providerDir
|
|
43259
|
+
};
|
|
43260
|
+
const exerciseJson = JSON.stringify(exercisePayload).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43261
|
+
const verificationInspectFields = verification?.inspectFields?.length ? verification.inspectFields : [
|
|
43262
|
+
"debug.messages",
|
|
43263
|
+
"trace.entries[].payload.parsedLastAssistant",
|
|
43264
|
+
"trace.entries[].payload.lastAssistant"
|
|
43265
|
+
];
|
|
43266
|
+
const verificationMustContainAny = verification?.mustContainAny || [];
|
|
43267
|
+
const verificationMustNotContainAny = verification?.mustNotContainAny || [];
|
|
43268
|
+
const verificationMustMatchAny = verification?.mustMatchAny || [];
|
|
43269
|
+
const verificationMustNotMatchAny = verification?.mustNotMatchAny || [];
|
|
43270
|
+
const verificationLastAssistantMustContainAny = verification?.lastAssistantMustContainAny || [];
|
|
43271
|
+
const verificationLastAssistantMustNotContainAny = verification?.lastAssistantMustNotContainAny || [];
|
|
43272
|
+
const verificationLastAssistantMustMatchAny = verification?.lastAssistantMustMatchAny || [];
|
|
43273
|
+
const verificationLastAssistantMustNotMatchAny = verification?.lastAssistantMustNotMatchAny || [];
|
|
43274
|
+
const quotedMustContain = verificationMustContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43275
|
+
const quotedMustNotContain = verificationMustNotContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43276
|
+
const quotedMustMatch = verificationMustMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43277
|
+
const quotedMustNotMatch = verificationMustNotMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43278
|
+
const quotedLastAssistantMustContain = verificationLastAssistantMustContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43279
|
+
const quotedLastAssistantMustNotContain = verificationLastAssistantMustNotContainAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43280
|
+
const quotedLastAssistantMustMatch = verificationLastAssistantMustMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43281
|
+
const quotedLastAssistantMustNotMatch = verificationLastAssistantMustNotMatchAny.map((value) => JSON.stringify(value)).join(", ");
|
|
43282
|
+
const fixtureName = verification?.fixtureName || `${type}-provider-fix`;
|
|
43283
|
+
const fixtureNames = Array.isArray(verification?.fixtureNames) ? verification.fixtureNames.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
43284
|
+
const fixtureCaptureJson = JSON.stringify({
|
|
43285
|
+
type,
|
|
43286
|
+
name: fixtureName,
|
|
43287
|
+
request: exercisePayload,
|
|
43288
|
+
assertions: {
|
|
43289
|
+
mustContainAny: verificationMustContainAny,
|
|
43290
|
+
mustNotContainAny: verificationMustNotContainAny,
|
|
43291
|
+
mustMatchAny: verificationMustMatchAny,
|
|
43292
|
+
mustNotMatchAny: verificationMustNotMatchAny,
|
|
43293
|
+
lastAssistantMustContainAny: verificationLastAssistantMustContainAny,
|
|
43294
|
+
lastAssistantMustNotContainAny: verificationLastAssistantMustNotContainAny,
|
|
43295
|
+
lastAssistantMustMatchAny: verificationLastAssistantMustMatchAny,
|
|
43296
|
+
lastAssistantMustNotMatchAny: verificationLastAssistantMustNotMatchAny,
|
|
43297
|
+
requireNotTimedOut: true
|
|
43298
|
+
}
|
|
43299
|
+
}).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43300
|
+
const fixtureReplayJson = JSON.stringify({
|
|
43301
|
+
type,
|
|
43302
|
+
name: fixtureName
|
|
43303
|
+
}).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
42026
43304
|
lines.push("You are implementing PTY parsing scripts for a CLI provider.");
|
|
42027
43305
|
lines.push("Be concise. Do NOT explain your reasoning. Edit files directly and verify with the local DevServer.");
|
|
42028
43306
|
lines.push("");
|
|
@@ -42036,7 +43314,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42036
43314
|
parseApproval: "parse_approval.js"
|
|
42037
43315
|
};
|
|
42038
43316
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
42039
|
-
const scriptsDir =
|
|
43317
|
+
const scriptsDir = path16.join(providerDir, "scripts");
|
|
42040
43318
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
42041
43319
|
if (latestScriptsDir) {
|
|
42042
43320
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -42044,11 +43322,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42044
43322
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
42045
43323
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
42046
43324
|
lines.push("");
|
|
42047
|
-
for (const file2 of
|
|
43325
|
+
for (const file2 of fs13.readdirSync(latestScriptsDir)) {
|
|
42048
43326
|
if (!file2.endsWith(".js")) continue;
|
|
42049
43327
|
if (!targetFileNames.has(file2)) continue;
|
|
42050
43328
|
try {
|
|
42051
|
-
const content =
|
|
43329
|
+
const content = fs13.readFileSync(path16.join(latestScriptsDir, file2), "utf-8");
|
|
42052
43330
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
42053
43331
|
lines.push("```javascript");
|
|
42054
43332
|
lines.push(content);
|
|
@@ -42057,14 +43335,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42057
43335
|
} catch {
|
|
42058
43336
|
}
|
|
42059
43337
|
}
|
|
42060
|
-
const refFiles =
|
|
43338
|
+
const refFiles = fs13.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
42061
43339
|
if (refFiles.length > 0) {
|
|
42062
43340
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
42063
43341
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
42064
43342
|
lines.push("");
|
|
42065
43343
|
for (const file2 of refFiles) {
|
|
42066
43344
|
try {
|
|
42067
|
-
const content =
|
|
43345
|
+
const content = fs13.readFileSync(path16.join(latestScriptsDir, file2), "utf-8");
|
|
42068
43346
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
42069
43347
|
lines.push("```javascript");
|
|
42070
43348
|
lines.push(content);
|
|
@@ -42097,17 +43375,17 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42097
43375
|
lines.push("");
|
|
42098
43376
|
}
|
|
42099
43377
|
}
|
|
42100
|
-
const docsDir =
|
|
43378
|
+
const docsDir = path16.join(providerDir, "../../docs");
|
|
42101
43379
|
const loadGuide = (name) => {
|
|
42102
43380
|
try {
|
|
42103
|
-
const p =
|
|
42104
|
-
if (
|
|
43381
|
+
const p = path16.join(docsDir, name);
|
|
43382
|
+
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
42105
43383
|
} catch {
|
|
42106
43384
|
}
|
|
42107
43385
|
return null;
|
|
42108
43386
|
};
|
|
42109
43387
|
const providerGuide = loadGuide("PROVIDER_GUIDE.md");
|
|
42110
|
-
if (providerGuide) {
|
|
43388
|
+
if (providerGuide && provider.category !== "cli") {
|
|
42111
43389
|
lines.push("## Documentation: PROVIDER_GUIDE.md");
|
|
42112
43390
|
lines.push("```markdown");
|
|
42113
43391
|
lines.push(providerGuide);
|
|
@@ -42149,6 +43427,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42149
43427
|
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
43428
|
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
43429
|
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.");
|
|
43430
|
+
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.');
|
|
43431
|
+
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.");
|
|
43432
|
+
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.');
|
|
43433
|
+
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.");
|
|
43434
|
+
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
43435
|
lines.push("");
|
|
42153
43436
|
lines.push("## Task");
|
|
42154
43437
|
lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(", ")}**`);
|
|
@@ -42156,35 +43439,145 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42156
43439
|
lines.push("## Verification API");
|
|
42157
43440
|
lines.push("Use the DevServer CLI debug endpoints, not DOM/CDP routes.");
|
|
42158
43441
|
lines.push("");
|
|
42159
|
-
lines.push("### 1.
|
|
43442
|
+
lines.push("### 1. Preferred: run a full autonomous repro");
|
|
43443
|
+
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
43444
|
lines.push("```bash");
|
|
42161
|
-
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/
|
|
43445
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/exercise \\`);
|
|
42162
43446
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
42163
|
-
lines.push(` -d '
|
|
43447
|
+
lines.push(` -d '${exerciseJson}'`);
|
|
42164
43448
|
lines.push("```");
|
|
42165
43449
|
lines.push("");
|
|
43450
|
+
if (verification?.description) {
|
|
43451
|
+
lines.push("Verification intent:");
|
|
43452
|
+
lines.push(verification.description);
|
|
43453
|
+
lines.push("");
|
|
43454
|
+
}
|
|
43455
|
+
lines.push("Read the JSON response carefully. It already includes:");
|
|
43456
|
+
lines.push("1. `instanceId`");
|
|
43457
|
+
lines.push("2. `statusesSeen` and `approvalsResolved`");
|
|
43458
|
+
lines.push("3. `debug` for the final settled state");
|
|
43459
|
+
lines.push("4. `trace.entries` for the repro turn");
|
|
43460
|
+
lines.push("");
|
|
43461
|
+
lines.push("Save the response to a temp file and inspect the exact parsed transcript fields before editing:");
|
|
43462
|
+
lines.push("```bash");
|
|
43463
|
+
lines.push(`EXERCISE_JSON=$(mktemp)`);
|
|
43464
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/exercise \\`);
|
|
43465
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43466
|
+
lines.push(` -d '${exerciseJson}' > "$EXERCISE_JSON"`);
|
|
43467
|
+
lines.push(`jq '{timedOut,statusesSeen,approvalsResolved,inspect:{${verificationInspectFields.map((field, index) => `f${index + 1}: .${field}`).join(", ")}}}' "$EXERCISE_JSON"`);
|
|
43468
|
+
lines.push("```");
|
|
43469
|
+
lines.push("");
|
|
43470
|
+
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) {
|
|
43471
|
+
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.");
|
|
43472
|
+
lines.push("```bash");
|
|
43473
|
+
if (verificationMustContainAny.length > 0) {
|
|
43474
|
+
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"`);
|
|
43475
|
+
}
|
|
43476
|
+
if (verificationMustNotContainAny.length > 0) {
|
|
43477
|
+
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"`);
|
|
43478
|
+
}
|
|
43479
|
+
if (verificationMustMatchAny.length > 0) {
|
|
43480
|
+
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"`);
|
|
43481
|
+
}
|
|
43482
|
+
if (verificationMustNotMatchAny.length > 0) {
|
|
43483
|
+
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"`);
|
|
43484
|
+
}
|
|
43485
|
+
if (verificationLastAssistantMustContainAny.length > 0) {
|
|
43486
|
+
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"`);
|
|
43487
|
+
}
|
|
43488
|
+
if (verificationLastAssistantMustNotContainAny.length > 0) {
|
|
43489
|
+
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"`);
|
|
43490
|
+
}
|
|
43491
|
+
if (verificationLastAssistantMustMatchAny.length > 0) {
|
|
43492
|
+
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"`);
|
|
43493
|
+
}
|
|
43494
|
+
if (verificationLastAssistantMustNotMatchAny.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 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"`);
|
|
43496
|
+
}
|
|
43497
|
+
lines.push("```");
|
|
43498
|
+
lines.push("");
|
|
43499
|
+
}
|
|
43500
|
+
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.");
|
|
43501
|
+
lines.push("");
|
|
43502
|
+
lines.push("### 1b. Persist or replay the exact repro as a reusable fixture");
|
|
43503
|
+
if (fixtureNames.length > 0) {
|
|
43504
|
+
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(", ")}.`);
|
|
43505
|
+
for (const name of fixtureNames) {
|
|
43506
|
+
const replayJson = JSON.stringify({ type, name }).replace(/\\/g, "\\\\").replace(/'/g, `'\\''`);
|
|
43507
|
+
lines.push("```bash");
|
|
43508
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43509
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43510
|
+
lines.push(` -d '${replayJson}'`);
|
|
43511
|
+
lines.push("```");
|
|
43512
|
+
lines.push("");
|
|
43513
|
+
}
|
|
43514
|
+
lines.push("Do not create new fixtures unless one of the listed fixtures is missing or stale.");
|
|
43515
|
+
} else if (verification?.fixtureName) {
|
|
43516
|
+
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.`);
|
|
43517
|
+
lines.push("```bash");
|
|
43518
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43519
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43520
|
+
lines.push(` -d '${fixtureReplayJson}'`);
|
|
43521
|
+
lines.push("```");
|
|
43522
|
+
lines.push("");
|
|
43523
|
+
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.");
|
|
43524
|
+
lines.push("```bash");
|
|
43525
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/capture \\`);
|
|
43526
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43527
|
+
lines.push(` -d '${fixtureCaptureJson}'`);
|
|
43528
|
+
lines.push("```");
|
|
43529
|
+
} else {
|
|
43530
|
+
lines.push("Capture the exact exercise once before editing. After patching, replay THIS fixture and do not declare success unless replay passes.");
|
|
43531
|
+
lines.push("```bash");
|
|
43532
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/capture \\`);
|
|
43533
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43534
|
+
lines.push(` -d '${fixtureCaptureJson}'`);
|
|
43535
|
+
lines.push("");
|
|
43536
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/fixture/replay \\`);
|
|
43537
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43538
|
+
lines.push(` -d '${fixtureReplayJson}'`);
|
|
43539
|
+
lines.push("```");
|
|
43540
|
+
}
|
|
43541
|
+
lines.push("");
|
|
43542
|
+
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.");
|
|
43543
|
+
lines.push("");
|
|
42166
43544
|
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
42167
43545
|
lines.push("```bash");
|
|
43546
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/launch \\`);
|
|
43547
|
+
lines.push(' -H "Content-Type: application/json" \\');
|
|
43548
|
+
lines.push(` -d '{"type":"${type}","workingDir":"${providerDir.replace(/\\/g, "\\\\")}"}'`);
|
|
42168
43549
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
43550
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/trace/${type}`);
|
|
42169
43551
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
42170
43552
|
lines.push("```");
|
|
42171
43553
|
lines.push("");
|
|
43554
|
+
lines.push("The CLI trace endpoint is the primary debugging source. Read it BEFORE editing any parser code.");
|
|
43555
|
+
lines.push("Use the trace timeline to find the latest `settled` or `commit_transcript` frame for the repro turn and inspect these fields first:");
|
|
43556
|
+
lines.push("1. `payload.screenText`");
|
|
43557
|
+
lines.push("2. `payload.detectStatus` and `payload.parsedStatus`");
|
|
43558
|
+
lines.push("3. `payload.parsedLastAssistant`");
|
|
43559
|
+
lines.push("4. `payload.approval` / `payload.parsedActiveModal`");
|
|
43560
|
+
lines.push("5. `payload.rawPreview` only when control-sequence residue matters");
|
|
43561
|
+
lines.push("");
|
|
42172
43562
|
lines.push("The debug payload should be read in this priority order:");
|
|
42173
43563
|
lines.push("1. `screenText` / current visible state");
|
|
42174
43564
|
lines.push("2. parsed `status`, `messages`, `activeModal`");
|
|
42175
43565
|
lines.push("3. `rawBuffer` only for style/control-sequence cues");
|
|
42176
43566
|
lines.push("4. `buffer` only when the current screen is insufficient");
|
|
42177
43567
|
lines.push("");
|
|
42178
|
-
lines.push("
|
|
43568
|
+
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.");
|
|
43569
|
+
lines.push("Do NOT guess based only on the final chat bubble or a truncated UI preview.");
|
|
43570
|
+
lines.push("");
|
|
43571
|
+
lines.push("Extract the current `instanceId` from the exercise, launch, or status response and keep using it below.");
|
|
42179
43572
|
lines.push("");
|
|
42180
|
-
lines.push("### 3.
|
|
43573
|
+
lines.push("### 3. Manual fallback only: send a realistic approval-triggering prompt");
|
|
42181
43574
|
lines.push("```bash");
|
|
42182
43575
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/send \\`);
|
|
42183
43576
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
42184
43577
|
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
43578
|
lines.push("```");
|
|
42186
43579
|
lines.push("");
|
|
42187
|
-
lines.push("### 4.
|
|
43580
|
+
lines.push("### 4. Manual fallback only: if approval appears, resolve it until the CLI reaches idle");
|
|
42188
43581
|
lines.push("```bash");
|
|
42189
43582
|
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/resolve \\`);
|
|
42190
43583
|
lines.push(' -H "Content-Type: application/json" \\');
|
|
@@ -42194,10 +43587,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42194
43587
|
lines.push(` -d '{"type":"${type}","instanceId":"<INSTANCE_ID>","keys":"1"}'`);
|
|
42195
43588
|
lines.push("```");
|
|
42196
43589
|
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.");
|
|
43590
|
+
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
43591
|
lines.push("");
|
|
42199
43592
|
lines.push("### Patch Discipline");
|
|
42200
43593
|
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.");
|
|
43594
|
+
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.");
|
|
43595
|
+
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.");
|
|
43596
|
+
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.");
|
|
43597
|
+
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
43598
|
lines.push("");
|
|
42202
43599
|
lines.push("### 5. Verify the side effects outside the CLI");
|
|
42203
43600
|
lines.push("```bash");
|
|
@@ -42222,6 +43619,8 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42222
43619
|
lines.push("7. Re-run the debug endpoints after edits. Do NOT finish until the parsed result looks correct.");
|
|
42223
43620
|
lines.push("8. Confirm the parser still works after a redraw or scroll change without duplicating transcript history.");
|
|
42224
43621
|
lines.push("9. Confirm the implementation prefers current-screen signals over stale history when both are present.");
|
|
43622
|
+
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.");
|
|
43623
|
+
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
43624
|
lines.push("");
|
|
42226
43625
|
if (userComment) {
|
|
42227
43626
|
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
@@ -42230,10 +43629,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
42230
43629
|
lines.push(userComment);
|
|
42231
43630
|
lines.push("");
|
|
42232
43631
|
}
|
|
42233
|
-
lines.push("Start NOW. Launch the CLI, inspect PTY state, edit the scripts, and verify via the CLI debug endpoints.");
|
|
43632
|
+
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
43633
|
return lines.join("\n");
|
|
42235
43634
|
}
|
|
42236
43635
|
function handleAutoImplSSE(ctx, type, req, res) {
|
|
43636
|
+
clearStaleAutoImplState(ctx, "SSE connection opened");
|
|
42237
43637
|
res.writeHead(200, {
|
|
42238
43638
|
"Content-Type": "text/event-stream",
|
|
42239
43639
|
"Cache-Control": "no-cache",
|
|
@@ -42255,6 +43655,7 @@ data: ${JSON.stringify(p.data)}
|
|
|
42255
43655
|
});
|
|
42256
43656
|
}
|
|
42257
43657
|
function handleAutoImplCancel(ctx, _type, _req, res) {
|
|
43658
|
+
clearStaleAutoImplState(ctx, "cancel request");
|
|
42258
43659
|
if (ctx.autoImplProcess) {
|
|
42259
43660
|
ctx.autoImplProcess.kill("SIGTERM");
|
|
42260
43661
|
setTimeout(() => {
|
|
@@ -42282,25 +43683,26 @@ data: ${JSON.stringify(msg.data)}
|
|
|
42282
43683
|
}
|
|
42283
43684
|
}
|
|
42284
43685
|
}
|
|
42285
|
-
var
|
|
43686
|
+
var fs13, path16, os17;
|
|
42286
43687
|
var init_dev_auto_implement = __esm({
|
|
42287
43688
|
"../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts"() {
|
|
42288
43689
|
"use strict";
|
|
42289
|
-
|
|
42290
|
-
|
|
43690
|
+
fs13 = __toESM(require("fs"));
|
|
43691
|
+
path16 = __toESM(require("path"));
|
|
42291
43692
|
os17 = __toESM(require("os"));
|
|
42292
43693
|
init_dev_server();
|
|
43694
|
+
init_dev_cli_debug();
|
|
42293
43695
|
}
|
|
42294
43696
|
});
|
|
42295
43697
|
|
|
42296
43698
|
// ../../oss/packages/daemon-core/src/daemon/dev-server.ts
|
|
42297
|
-
var http2,
|
|
43699
|
+
var http2, fs14, path17, DEV_SERVER_PORT, DevServer;
|
|
42298
43700
|
var init_dev_server = __esm({
|
|
42299
43701
|
"../../oss/packages/daemon-core/src/daemon/dev-server.ts"() {
|
|
42300
43702
|
"use strict";
|
|
42301
43703
|
http2 = __toESM(require("http"));
|
|
42302
|
-
|
|
42303
|
-
|
|
43704
|
+
fs14 = __toESM(require("fs"));
|
|
43705
|
+
path17 = __toESM(require("path"));
|
|
42304
43706
|
init_scaffold_template();
|
|
42305
43707
|
init_version_archive();
|
|
42306
43708
|
init_logger();
|
|
@@ -42361,11 +43763,16 @@ var init_dev_server = __esm({
|
|
|
42361
43763
|
{ method: "GET", pattern: "/api/cli/status", handler: (q2, s15) => this.handleCliStatus(q2, s15) },
|
|
42362
43764
|
{ method: "POST", pattern: "/api/cli/launch", handler: (q2, s15) => this.handleCliLaunch(q2, s15) },
|
|
42363
43765
|
{ method: "POST", pattern: "/api/cli/send", handler: (q2, s15) => this.handleCliSend(q2, s15) },
|
|
43766
|
+
{ method: "POST", pattern: "/api/cli/exercise", handler: (q2, s15) => this.handleCliExercise(q2, s15) },
|
|
43767
|
+
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q2, s15) => this.handleCliFixtureCapture(q2, s15) },
|
|
43768
|
+
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q2, s15) => this.handleCliFixtureReplay(q2, s15) },
|
|
42364
43769
|
{ method: "POST", pattern: "/api/cli/resolve", handler: (q2, s15) => this.handleCliResolve(q2, s15) },
|
|
42365
43770
|
{ method: "POST", pattern: "/api/cli/raw", handler: (q2, s15) => this.handleCliRaw(q2, s15) },
|
|
42366
43771
|
{ method: "POST", pattern: "/api/cli/stop", handler: (q2, s15) => this.handleCliStop(q2, s15) },
|
|
42367
43772
|
{ method: "GET", pattern: "/api/cli/events", handler: (q2, s15) => this.handleCliSSE(q2, s15) },
|
|
42368
43773
|
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliDebug(p[0], q2, s15) },
|
|
43774
|
+
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliTrace(p[0], q2, s15) },
|
|
43775
|
+
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q2, s15, p) => this.handleCliFixtureList(p[0], q2, s15) },
|
|
42369
43776
|
// Dynamic routes (provider :type param)
|
|
42370
43777
|
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q2, s15, p) => this.handleRunScript(p[0], q2, s15) },
|
|
42371
43778
|
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q2, s15, p) => this.handleListFiles(p[0], q2, s15) },
|
|
@@ -42399,8 +43806,8 @@ var init_dev_server = __esm({
|
|
|
42399
43806
|
}
|
|
42400
43807
|
getEndpointList() {
|
|
42401
43808
|
return this.routes.map((r) => {
|
|
42402
|
-
const
|
|
42403
|
-
return `${r.method.padEnd(5)} ${
|
|
43809
|
+
const path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
43810
|
+
return `${r.method.padEnd(5)} ${path21}`;
|
|
42404
43811
|
});
|
|
42405
43812
|
}
|
|
42406
43813
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -42682,12 +44089,12 @@ var init_dev_server = __esm({
|
|
|
42682
44089
|
// ─── DevConsole SPA ───
|
|
42683
44090
|
getConsoleDistDir() {
|
|
42684
44091
|
const candidates = [
|
|
42685
|
-
|
|
42686
|
-
|
|
42687
|
-
|
|
44092
|
+
path17.resolve(__dirname, "../../web-devconsole/dist"),
|
|
44093
|
+
path17.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
44094
|
+
path17.join(process.cwd(), "packages/web-devconsole/dist")
|
|
42688
44095
|
];
|
|
42689
44096
|
for (const dir of candidates) {
|
|
42690
|
-
if (
|
|
44097
|
+
if (fs14.existsSync(path17.join(dir, "index.html"))) return dir;
|
|
42691
44098
|
}
|
|
42692
44099
|
return null;
|
|
42693
44100
|
}
|
|
@@ -42697,9 +44104,9 @@ var init_dev_server = __esm({
|
|
|
42697
44104
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
42698
44105
|
return;
|
|
42699
44106
|
}
|
|
42700
|
-
const htmlPath =
|
|
44107
|
+
const htmlPath = path17.join(distDir, "index.html");
|
|
42701
44108
|
try {
|
|
42702
|
-
const html =
|
|
44109
|
+
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
42703
44110
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
42704
44111
|
res.end(html);
|
|
42705
44112
|
} catch (e) {
|
|
@@ -42722,15 +44129,15 @@ var init_dev_server = __esm({
|
|
|
42722
44129
|
this.json(res, 404, { error: "Not found" });
|
|
42723
44130
|
return;
|
|
42724
44131
|
}
|
|
42725
|
-
const safePath =
|
|
42726
|
-
const filePath =
|
|
44132
|
+
const safePath = path17.normalize(pathname).replace(/^\.\.\//, "");
|
|
44133
|
+
const filePath = path17.join(distDir, safePath);
|
|
42727
44134
|
if (!filePath.startsWith(distDir)) {
|
|
42728
44135
|
this.json(res, 403, { error: "Forbidden" });
|
|
42729
44136
|
return;
|
|
42730
44137
|
}
|
|
42731
44138
|
try {
|
|
42732
|
-
const content =
|
|
42733
|
-
const ext =
|
|
44139
|
+
const content = fs14.readFileSync(filePath);
|
|
44140
|
+
const ext = path17.extname(filePath);
|
|
42734
44141
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
42735
44142
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
42736
44143
|
res.end(content);
|
|
@@ -42838,14 +44245,14 @@ var init_dev_server = __esm({
|
|
|
42838
44245
|
const files = [];
|
|
42839
44246
|
const scan = (d, prefix) => {
|
|
42840
44247
|
try {
|
|
42841
|
-
for (const entry of
|
|
44248
|
+
for (const entry of fs14.readdirSync(d, { withFileTypes: true })) {
|
|
42842
44249
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
42843
44250
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
42844
44251
|
if (entry.isDirectory()) {
|
|
42845
44252
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
42846
|
-
scan(
|
|
44253
|
+
scan(path17.join(d, entry.name), rel);
|
|
42847
44254
|
} else {
|
|
42848
|
-
const stat4 =
|
|
44255
|
+
const stat4 = fs14.statSync(path17.join(d, entry.name));
|
|
42849
44256
|
files.push({ path: rel, size: stat4.size, type: "file" });
|
|
42850
44257
|
}
|
|
42851
44258
|
}
|
|
@@ -42868,16 +44275,16 @@ var init_dev_server = __esm({
|
|
|
42868
44275
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
42869
44276
|
return;
|
|
42870
44277
|
}
|
|
42871
|
-
const fullPath =
|
|
44278
|
+
const fullPath = path17.resolve(dir, path17.normalize(filePath));
|
|
42872
44279
|
if (!fullPath.startsWith(dir)) {
|
|
42873
44280
|
this.json(res, 403, { error: "Forbidden" });
|
|
42874
44281
|
return;
|
|
42875
44282
|
}
|
|
42876
|
-
if (!
|
|
44283
|
+
if (!fs14.existsSync(fullPath) || fs14.statSync(fullPath).isDirectory()) {
|
|
42877
44284
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
42878
44285
|
return;
|
|
42879
44286
|
}
|
|
42880
|
-
const content =
|
|
44287
|
+
const content = fs14.readFileSync(fullPath, "utf-8");
|
|
42881
44288
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
42882
44289
|
}
|
|
42883
44290
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -42893,15 +44300,15 @@ var init_dev_server = __esm({
|
|
|
42893
44300
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
42894
44301
|
return;
|
|
42895
44302
|
}
|
|
42896
|
-
const fullPath =
|
|
44303
|
+
const fullPath = path17.resolve(dir, path17.normalize(filePath));
|
|
42897
44304
|
if (!fullPath.startsWith(dir)) {
|
|
42898
44305
|
this.json(res, 403, { error: "Forbidden" });
|
|
42899
44306
|
return;
|
|
42900
44307
|
}
|
|
42901
44308
|
try {
|
|
42902
|
-
if (
|
|
42903
|
-
|
|
42904
|
-
|
|
44309
|
+
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
44310
|
+
fs14.mkdirSync(path17.dirname(fullPath), { recursive: true });
|
|
44311
|
+
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
42905
44312
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
42906
44313
|
this.providerLoader.reload();
|
|
42907
44314
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -42917,9 +44324,9 @@ var init_dev_server = __esm({
|
|
|
42917
44324
|
return;
|
|
42918
44325
|
}
|
|
42919
44326
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
42920
|
-
const p =
|
|
42921
|
-
if (
|
|
42922
|
-
const source =
|
|
44327
|
+
const p = path17.join(dir, name);
|
|
44328
|
+
if (fs14.existsSync(p)) {
|
|
44329
|
+
const source = fs14.readFileSync(p, "utf-8");
|
|
42923
44330
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
42924
44331
|
return;
|
|
42925
44332
|
}
|
|
@@ -42938,11 +44345,11 @@ var init_dev_server = __esm({
|
|
|
42938
44345
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
42939
44346
|
return;
|
|
42940
44347
|
}
|
|
42941
|
-
const target =
|
|
42942
|
-
const targetPath =
|
|
44348
|
+
const target = fs14.existsSync(path17.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
44349
|
+
const targetPath = path17.join(dir, target);
|
|
42943
44350
|
try {
|
|
42944
|
-
if (
|
|
42945
|
-
|
|
44351
|
+
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
44352
|
+
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
42946
44353
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
42947
44354
|
this.providerLoader.reload();
|
|
42948
44355
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -43099,21 +44506,21 @@ var init_dev_server = __esm({
|
|
|
43099
44506
|
}
|
|
43100
44507
|
let targetDir;
|
|
43101
44508
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
43102
|
-
const jsonPath =
|
|
43103
|
-
if (
|
|
44509
|
+
const jsonPath = path17.join(targetDir, "provider.json");
|
|
44510
|
+
if (fs14.existsSync(jsonPath)) {
|
|
43104
44511
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
43105
44512
|
return;
|
|
43106
44513
|
}
|
|
43107
44514
|
try {
|
|
43108
44515
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2, osPaths, processNames });
|
|
43109
|
-
|
|
43110
|
-
|
|
44516
|
+
fs14.mkdirSync(targetDir, { recursive: true });
|
|
44517
|
+
fs14.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
43111
44518
|
const createdFiles = ["provider.json"];
|
|
43112
44519
|
if (result.files) {
|
|
43113
44520
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
43114
|
-
const fullPath =
|
|
43115
|
-
|
|
43116
|
-
|
|
44521
|
+
const fullPath = path17.join(targetDir, relPath);
|
|
44522
|
+
fs14.mkdirSync(path17.dirname(fullPath), { recursive: true });
|
|
44523
|
+
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
43117
44524
|
createdFiles.push(relPath);
|
|
43118
44525
|
}
|
|
43119
44526
|
}
|
|
@@ -43162,45 +44569,45 @@ var init_dev_server = __esm({
|
|
|
43162
44569
|
}
|
|
43163
44570
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
43164
44571
|
getLatestScriptVersionDir(scriptsDir) {
|
|
43165
|
-
if (!
|
|
43166
|
-
const versions =
|
|
44572
|
+
if (!fs14.existsSync(scriptsDir)) return null;
|
|
44573
|
+
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
43167
44574
|
try {
|
|
43168
|
-
return
|
|
44575
|
+
return fs14.statSync(path17.join(scriptsDir, d)).isDirectory();
|
|
43169
44576
|
} catch {
|
|
43170
44577
|
return false;
|
|
43171
44578
|
}
|
|
43172
44579
|
}).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
43173
44580
|
if (versions.length === 0) return null;
|
|
43174
|
-
return
|
|
44581
|
+
return path17.join(scriptsDir, versions[0]);
|
|
43175
44582
|
}
|
|
43176
44583
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
43177
|
-
const canonicalUserDir =
|
|
43178
|
-
const desiredDir = requestedDir ?
|
|
43179
|
-
const upstreamRoot =
|
|
43180
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
44584
|
+
const canonicalUserDir = path17.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
44585
|
+
const desiredDir = requestedDir ? path17.resolve(requestedDir) : canonicalUserDir;
|
|
44586
|
+
const upstreamRoot = path17.resolve(this.providerLoader.getUpstreamDir());
|
|
44587
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path17.sep}`)) {
|
|
43181
44588
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
43182
44589
|
}
|
|
43183
|
-
if (
|
|
44590
|
+
if (path17.basename(desiredDir) !== type) {
|
|
43184
44591
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
43185
44592
|
}
|
|
43186
44593
|
const sourceDir = this.findProviderDir(type);
|
|
43187
44594
|
if (!sourceDir) {
|
|
43188
44595
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
43189
44596
|
}
|
|
43190
|
-
if (!
|
|
43191
|
-
|
|
43192
|
-
|
|
44597
|
+
if (!fs14.existsSync(desiredDir)) {
|
|
44598
|
+
fs14.mkdirSync(path17.dirname(desiredDir), { recursive: true });
|
|
44599
|
+
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
43193
44600
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
43194
44601
|
}
|
|
43195
|
-
const providerJson =
|
|
43196
|
-
if (!
|
|
44602
|
+
const providerJson = path17.join(desiredDir, "provider.json");
|
|
44603
|
+
if (!fs14.existsSync(providerJson)) {
|
|
43197
44604
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
43198
44605
|
}
|
|
43199
44606
|
try {
|
|
43200
|
-
const providerData = JSON.parse(
|
|
44607
|
+
const providerData = JSON.parse(fs14.readFileSync(providerJson, "utf-8"));
|
|
43201
44608
|
if (providerData.disableUpstream !== true) {
|
|
43202
44609
|
providerData.disableUpstream = true;
|
|
43203
|
-
|
|
44610
|
+
fs14.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
|
|
43204
44611
|
}
|
|
43205
44612
|
} catch (error48) {
|
|
43206
44613
|
return {
|
|
@@ -43240,7 +44647,7 @@ var init_dev_server = __esm({
|
|
|
43240
44647
|
setMode: "set_mode.js"
|
|
43241
44648
|
};
|
|
43242
44649
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
43243
|
-
const scriptsDir =
|
|
44650
|
+
const scriptsDir = path17.join(providerDir, "scripts");
|
|
43244
44651
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
43245
44652
|
if (latestScriptsDir) {
|
|
43246
44653
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -43248,10 +44655,10 @@ var init_dev_server = __esm({
|
|
|
43248
44655
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
43249
44656
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
43250
44657
|
lines.push("");
|
|
43251
|
-
for (const file2 of
|
|
44658
|
+
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
43252
44659
|
if (file2.endsWith(".js") && targetFileNames.has(file2)) {
|
|
43253
44660
|
try {
|
|
43254
|
-
const content =
|
|
44661
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
43255
44662
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
43256
44663
|
lines.push("```javascript");
|
|
43257
44664
|
lines.push(content);
|
|
@@ -43261,14 +44668,14 @@ var init_dev_server = __esm({
|
|
|
43261
44668
|
}
|
|
43262
44669
|
}
|
|
43263
44670
|
}
|
|
43264
|
-
const refFiles =
|
|
44671
|
+
const refFiles = fs14.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
43265
44672
|
if (refFiles.length > 0) {
|
|
43266
44673
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
43267
44674
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
43268
44675
|
lines.push("");
|
|
43269
44676
|
for (const file2 of refFiles) {
|
|
43270
44677
|
try {
|
|
43271
|
-
const content =
|
|
44678
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
43272
44679
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
43273
44680
|
lines.push("```javascript");
|
|
43274
44681
|
lines.push(content);
|
|
@@ -43309,11 +44716,11 @@ var init_dev_server = __esm({
|
|
|
43309
44716
|
lines.push("");
|
|
43310
44717
|
}
|
|
43311
44718
|
}
|
|
43312
|
-
const docsDir =
|
|
44719
|
+
const docsDir = path17.join(providerDir, "../../docs");
|
|
43313
44720
|
const loadGuide = (name) => {
|
|
43314
44721
|
try {
|
|
43315
|
-
const p =
|
|
43316
|
-
if (
|
|
44722
|
+
const p = path17.join(docsDir, name);
|
|
44723
|
+
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
43317
44724
|
} catch {
|
|
43318
44725
|
}
|
|
43319
44726
|
return null;
|
|
@@ -43486,7 +44893,7 @@ var init_dev_server = __esm({
|
|
|
43486
44893
|
parseApproval: "parse_approval.js"
|
|
43487
44894
|
};
|
|
43488
44895
|
const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
|
|
43489
|
-
const scriptsDir =
|
|
44896
|
+
const scriptsDir = path17.join(providerDir, "scripts");
|
|
43490
44897
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
43491
44898
|
if (latestScriptsDir) {
|
|
43492
44899
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -43494,11 +44901,11 @@ var init_dev_server = __esm({
|
|
|
43494
44901
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
43495
44902
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
43496
44903
|
lines.push("");
|
|
43497
|
-
for (const file2 of
|
|
44904
|
+
for (const file2 of fs14.readdirSync(latestScriptsDir)) {
|
|
43498
44905
|
if (!file2.endsWith(".js")) continue;
|
|
43499
44906
|
if (!targetFileNames.has(file2)) continue;
|
|
43500
44907
|
try {
|
|
43501
|
-
const content =
|
|
44908
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
43502
44909
|
lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
|
|
43503
44910
|
lines.push("```javascript");
|
|
43504
44911
|
lines.push(content);
|
|
@@ -43507,14 +44914,14 @@ var init_dev_server = __esm({
|
|
|
43507
44914
|
} catch {
|
|
43508
44915
|
}
|
|
43509
44916
|
}
|
|
43510
|
-
const refFiles =
|
|
44917
|
+
const refFiles = fs14.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
43511
44918
|
if (refFiles.length > 0) {
|
|
43512
44919
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
43513
44920
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
43514
44921
|
lines.push("");
|
|
43515
44922
|
for (const file2 of refFiles) {
|
|
43516
44923
|
try {
|
|
43517
|
-
const content =
|
|
44924
|
+
const content = fs14.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
|
|
43518
44925
|
lines.push(`### \`${file2}\` \u{1F512}`);
|
|
43519
44926
|
lines.push("```javascript");
|
|
43520
44927
|
lines.push(content);
|
|
@@ -43547,11 +44954,11 @@ var init_dev_server = __esm({
|
|
|
43547
44954
|
lines.push("");
|
|
43548
44955
|
}
|
|
43549
44956
|
}
|
|
43550
|
-
const docsDir =
|
|
44957
|
+
const docsDir = path17.join(providerDir, "../../docs");
|
|
43551
44958
|
const loadGuide = (name) => {
|
|
43552
44959
|
try {
|
|
43553
|
-
const p =
|
|
43554
|
-
if (
|
|
44960
|
+
const p = path17.join(docsDir, name);
|
|
44961
|
+
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
43555
44962
|
} catch {
|
|
43556
44963
|
}
|
|
43557
44964
|
return null;
|
|
@@ -43616,6 +45023,7 @@ var init_dev_server = __esm({
|
|
|
43616
45023
|
lines.push("### 2. Inspect parsed + raw adapter state");
|
|
43617
45024
|
lines.push("```bash");
|
|
43618
45025
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
|
|
45026
|
+
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/trace/${type}`);
|
|
43619
45027
|
lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
|
|
43620
45028
|
lines.push("```");
|
|
43621
45029
|
lines.push("");
|
|
@@ -43750,6 +45158,16 @@ data: ${JSON.stringify(msg.data)}
|
|
|
43750
45158
|
async handleCliSend(req, res) {
|
|
43751
45159
|
return handleCliSend(this, req, res);
|
|
43752
45160
|
}
|
|
45161
|
+
/** POST /api/cli/exercise — launch/send/approve/wait helper for provider-fix loops */
|
|
45162
|
+
async handleCliExercise(req, res) {
|
|
45163
|
+
return handleCliExercise(this, req, res);
|
|
45164
|
+
}
|
|
45165
|
+
async handleCliFixtureCapture(req, res) {
|
|
45166
|
+
return handleCliFixtureCapture(this, req, res);
|
|
45167
|
+
}
|
|
45168
|
+
async handleCliFixtureReplay(req, res) {
|
|
45169
|
+
return handleCliFixtureReplay(this, req, res);
|
|
45170
|
+
}
|
|
43753
45171
|
/** POST /api/cli/stop — stop a running CLI { type } */
|
|
43754
45172
|
async handleCliStop(req, res) {
|
|
43755
45173
|
return handleCliStop(this, req, res);
|
|
@@ -43773,6 +45191,13 @@ data: ${JSON.stringify(msg.data)}
|
|
|
43773
45191
|
async handleCliDebug(type, _req, res) {
|
|
43774
45192
|
return handleCliDebug(this, type, _req, res);
|
|
43775
45193
|
}
|
|
45194
|
+
/** GET /api/cli/trace/:type — recent CLI trace timeline plus current debug snapshot */
|
|
45195
|
+
async handleCliTrace(type, _req, res) {
|
|
45196
|
+
return handleCliTrace(this, type, _req, res);
|
|
45197
|
+
}
|
|
45198
|
+
async handleCliFixtureList(type, _req, res) {
|
|
45199
|
+
return handleCliFixtureList(this, type, _req, res);
|
|
45200
|
+
}
|
|
43776
45201
|
/** POST /api/cli/resolve — resolve an approval modal { type, buttonIndex } */
|
|
43777
45202
|
async handleCliResolve(req, res) {
|
|
43778
45203
|
return handleCliResolve(this, req, res);
|
|
@@ -44080,7 +45505,18 @@ var init_session_host_transport = __esm({
|
|
|
44080
45505
|
});
|
|
44081
45506
|
}
|
|
44082
45507
|
async boot() {
|
|
44083
|
-
|
|
45508
|
+
if (typeof this.options.ensureReady === "function") {
|
|
45509
|
+
await this.options.ensureReady();
|
|
45510
|
+
}
|
|
45511
|
+
try {
|
|
45512
|
+
await this.client.connect();
|
|
45513
|
+
} catch (error48) {
|
|
45514
|
+
if (typeof this.options.ensureReady !== "function") {
|
|
45515
|
+
throw error48;
|
|
45516
|
+
}
|
|
45517
|
+
await this.options.ensureReady();
|
|
45518
|
+
await this.client.connect();
|
|
45519
|
+
}
|
|
44084
45520
|
this.unsubscribe = this.client.onEvent((event) => this.handleEvent(event));
|
|
44085
45521
|
let record2 = null;
|
|
44086
45522
|
if (this.options.attachExisting) {
|
|
@@ -44967,17 +46403,17 @@ function canPeerUsePrivilegedShareCommand(commandType, permission) {
|
|
|
44967
46403
|
return false;
|
|
44968
46404
|
}
|
|
44969
46405
|
}
|
|
44970
|
-
var
|
|
46406
|
+
var fs15, path18, os19, import_node_module2, esmRequire, logFile, log, logDebug, DaemonP2PSender;
|
|
44971
46407
|
var init_daemon_p2p = __esm({
|
|
44972
46408
|
"src/daemon-p2p.ts"() {
|
|
44973
46409
|
"use strict";
|
|
44974
|
-
|
|
46410
|
+
fs15 = __toESM(require("fs"));
|
|
44975
46411
|
init_src();
|
|
44976
|
-
|
|
46412
|
+
path18 = __toESM(require("path"));
|
|
44977
46413
|
os19 = __toESM(require("os"));
|
|
44978
46414
|
import_node_module2 = require("module");
|
|
44979
46415
|
esmRequire = (0, import_node_module2.createRequire)(__filename);
|
|
44980
|
-
logFile =
|
|
46416
|
+
logFile = path18.join(os19.tmpdir(), "adhdev_daemon_p2p.log");
|
|
44981
46417
|
log = (msg) => {
|
|
44982
46418
|
LOG.info("P2P", `[${(/* @__PURE__ */ new Date()).toISOString()}] [P2P] ${msg}`);
|
|
44983
46419
|
};
|
|
@@ -45045,17 +46481,17 @@ ${e?.stack || ""}`);
|
|
|
45045
46481
|
const prebuildKey = `${platform11}-${arch3}`;
|
|
45046
46482
|
try {
|
|
45047
46483
|
const candidates = [
|
|
45048
|
-
|
|
45049
|
-
|
|
45050
|
-
|
|
46484
|
+
path18.join(__dirname, "node_modules", "node-datachannel"),
|
|
46485
|
+
path18.join(__dirname, "..", "node_modules", "node-datachannel"),
|
|
46486
|
+
path18.join(__dirname, "..", "..", "node_modules", "node-datachannel")
|
|
45051
46487
|
];
|
|
45052
46488
|
for (const candidate of candidates) {
|
|
45053
|
-
const prebuildPath =
|
|
45054
|
-
if (
|
|
45055
|
-
const targetDir =
|
|
45056
|
-
const targetPath =
|
|
45057
|
-
|
|
45058
|
-
|
|
46489
|
+
const prebuildPath = path18.join(candidate, "prebuilds", prebuildKey, "node_datachannel.node");
|
|
46490
|
+
if (fs15.existsSync(prebuildPath)) {
|
|
46491
|
+
const targetDir = path18.join(candidate, "build", "Release");
|
|
46492
|
+
const targetPath = path18.join(targetDir, "node_datachannel.node");
|
|
46493
|
+
fs15.mkdirSync(targetDir, { recursive: true });
|
|
46494
|
+
fs15.copyFileSync(prebuildPath, targetPath);
|
|
45059
46495
|
try {
|
|
45060
46496
|
delete esmRequire.cache[esmRequire.resolve("node-datachannel")];
|
|
45061
46497
|
} catch {
|
|
@@ -45949,48 +47385,122 @@ var init_screenshot_controller = __esm({
|
|
|
45949
47385
|
});
|
|
45950
47386
|
|
|
45951
47387
|
// src/session-host.ts
|
|
47388
|
+
function buildSessionHostEnv(baseEnv) {
|
|
47389
|
+
const env = {};
|
|
47390
|
+
for (const [key, value] of Object.entries(baseEnv)) {
|
|
47391
|
+
if (typeof value !== "string") continue;
|
|
47392
|
+
env[key] = value;
|
|
47393
|
+
}
|
|
47394
|
+
for (const key of Object.keys(env)) {
|
|
47395
|
+
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_")) {
|
|
47396
|
+
delete env[key];
|
|
47397
|
+
}
|
|
47398
|
+
}
|
|
47399
|
+
env.ADHDEV_SESSION_HOST_NAME = SESSION_HOST_APP_NAME;
|
|
47400
|
+
return env;
|
|
47401
|
+
}
|
|
45952
47402
|
function resolveSessionHostEntry() {
|
|
45953
47403
|
const packagedCandidates = [
|
|
45954
|
-
|
|
45955
|
-
|
|
47404
|
+
path19.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
|
|
47405
|
+
path19.resolve(__dirname, "../../vendor/session-host-daemon/index.js")
|
|
45956
47406
|
];
|
|
45957
47407
|
for (const candidate of packagedCandidates) {
|
|
45958
|
-
if (
|
|
47408
|
+
if (fs16.existsSync(candidate)) {
|
|
45959
47409
|
return candidate;
|
|
45960
47410
|
}
|
|
45961
47411
|
}
|
|
45962
47412
|
return require.resolve("@adhdev/session-host-daemon");
|
|
45963
47413
|
}
|
|
45964
|
-
|
|
45965
|
-
return
|
|
45966
|
-
|
|
45967
|
-
|
|
45968
|
-
|
|
45969
|
-
|
|
45970
|
-
|
|
45971
|
-
|
|
45972
|
-
|
|
45973
|
-
|
|
45974
|
-
|
|
45975
|
-
|
|
47414
|
+
function getSessionHostPidFile() {
|
|
47415
|
+
return path19.join(os20.homedir(), ".adhdev", `${SESSION_HOST_APP_NAME}-session-host.pid`);
|
|
47416
|
+
}
|
|
47417
|
+
function killPid(pid) {
|
|
47418
|
+
try {
|
|
47419
|
+
if (process.platform === "win32") {
|
|
47420
|
+
(0, import_child_process9.execFileSync)("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore" });
|
|
47421
|
+
} else {
|
|
47422
|
+
process.kill(pid, "SIGTERM");
|
|
47423
|
+
}
|
|
47424
|
+
return true;
|
|
47425
|
+
} catch {
|
|
47426
|
+
return false;
|
|
47427
|
+
}
|
|
47428
|
+
}
|
|
47429
|
+
function stopSessionHost() {
|
|
47430
|
+
let stopped = false;
|
|
47431
|
+
const pidFile = getSessionHostPidFile();
|
|
47432
|
+
try {
|
|
47433
|
+
if (fs16.existsSync(pidFile)) {
|
|
47434
|
+
const pid = Number.parseInt(fs16.readFileSync(pidFile, "utf8").trim(), 10);
|
|
47435
|
+
if (Number.isFinite(pid)) {
|
|
47436
|
+
stopped = killPid(pid) || stopped;
|
|
47437
|
+
}
|
|
47438
|
+
}
|
|
47439
|
+
} catch {
|
|
47440
|
+
} finally {
|
|
47441
|
+
try {
|
|
47442
|
+
fs16.unlinkSync(pidFile);
|
|
47443
|
+
} catch {
|
|
47444
|
+
}
|
|
47445
|
+
}
|
|
47446
|
+
if (process.platform !== "win32") {
|
|
47447
|
+
try {
|
|
47448
|
+
const raw = (0, import_child_process9.execFileSync)("pgrep", ["-f", "session-host-daemon"], { encoding: "utf8" }).trim();
|
|
47449
|
+
for (const line of raw.split("\n")) {
|
|
47450
|
+
const pid = Number.parseInt(line.trim(), 10);
|
|
47451
|
+
if (Number.isFinite(pid)) {
|
|
47452
|
+
stopped = killPid(pid) || stopped;
|
|
45976
47453
|
}
|
|
45977
|
-
}
|
|
45978
|
-
|
|
47454
|
+
}
|
|
47455
|
+
} catch {
|
|
45979
47456
|
}
|
|
45980
|
-
}
|
|
47457
|
+
}
|
|
47458
|
+
return stopped;
|
|
47459
|
+
}
|
|
47460
|
+
async function ensureSessionHostReady2() {
|
|
47461
|
+
const spawnHost = () => {
|
|
47462
|
+
const entry = resolveSessionHostEntry();
|
|
47463
|
+
const child = (0, import_child_process9.spawn)(process.execPath, [entry], {
|
|
47464
|
+
detached: true,
|
|
47465
|
+
stdio: "ignore",
|
|
47466
|
+
windowsHide: true,
|
|
47467
|
+
env: buildSessionHostEnv(process.env)
|
|
47468
|
+
});
|
|
47469
|
+
child.unref();
|
|
47470
|
+
};
|
|
47471
|
+
try {
|
|
47472
|
+
return await ensureSessionHostReady({
|
|
47473
|
+
appName: SESSION_HOST_APP_NAME,
|
|
47474
|
+
spawnHost,
|
|
47475
|
+
timeoutMs: SESSION_HOST_START_TIMEOUT_MS
|
|
47476
|
+
});
|
|
47477
|
+
} catch (error48) {
|
|
47478
|
+
stopSessionHost();
|
|
47479
|
+
return ensureSessionHostReady({
|
|
47480
|
+
appName: SESSION_HOST_APP_NAME,
|
|
47481
|
+
spawnHost,
|
|
47482
|
+
timeoutMs: SESSION_HOST_START_TIMEOUT_MS
|
|
47483
|
+
}).catch((retryError) => {
|
|
47484
|
+
const initialMessage = error48 instanceof Error ? error48.message : String(error48);
|
|
47485
|
+
const retryMessage = retryError instanceof Error ? retryError.message : String(retryError);
|
|
47486
|
+
throw new Error(`Session host failed to start after retry (${initialMessage}; retry: ${retryMessage})`);
|
|
47487
|
+
});
|
|
47488
|
+
}
|
|
45981
47489
|
}
|
|
45982
47490
|
async function listHostedCliRuntimes2(endpoint) {
|
|
45983
47491
|
return listHostedCliRuntimes(endpoint);
|
|
45984
47492
|
}
|
|
45985
|
-
var import_child_process9,
|
|
47493
|
+
var import_child_process9, fs16, os20, path19, SESSION_HOST_APP_NAME, SESSION_HOST_START_TIMEOUT_MS;
|
|
45986
47494
|
var init_session_host = __esm({
|
|
45987
47495
|
"src/session-host.ts"() {
|
|
45988
47496
|
"use strict";
|
|
45989
47497
|
import_child_process9 = require("child_process");
|
|
45990
|
-
|
|
45991
|
-
|
|
47498
|
+
fs16 = __toESM(require("fs"));
|
|
47499
|
+
os20 = __toESM(require("os"));
|
|
47500
|
+
path19 = __toESM(require("path"));
|
|
45992
47501
|
init_src();
|
|
45993
47502
|
SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
|
|
47503
|
+
SESSION_HOST_START_TIMEOUT_MS = 15e3;
|
|
45994
47504
|
}
|
|
45995
47505
|
});
|
|
45996
47506
|
|
|
@@ -46002,24 +47512,24 @@ __export(adhdev_daemon_exports, {
|
|
|
46002
47512
|
stopDaemon: () => stopDaemon
|
|
46003
47513
|
});
|
|
46004
47514
|
function getDaemonPidFile() {
|
|
46005
|
-
const dir =
|
|
46006
|
-
if (!
|
|
46007
|
-
return
|
|
47515
|
+
const dir = path20.join(os21.homedir(), ".adhdev");
|
|
47516
|
+
if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
|
|
47517
|
+
return path20.join(dir, "daemon.pid");
|
|
46008
47518
|
}
|
|
46009
47519
|
function writeDaemonPid(pid) {
|
|
46010
|
-
|
|
47520
|
+
fs17.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
|
|
46011
47521
|
}
|
|
46012
47522
|
function removeDaemonPid() {
|
|
46013
47523
|
try {
|
|
46014
|
-
|
|
47524
|
+
fs17.unlinkSync(getDaemonPidFile());
|
|
46015
47525
|
} catch (e) {
|
|
46016
47526
|
}
|
|
46017
47527
|
}
|
|
46018
47528
|
function isDaemonRunning() {
|
|
46019
47529
|
const pidFile = getDaemonPidFile();
|
|
46020
47530
|
try {
|
|
46021
|
-
if (!
|
|
46022
|
-
const pid = parseInt(
|
|
47531
|
+
if (!fs17.existsSync(pidFile)) return false;
|
|
47532
|
+
const pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim());
|
|
46023
47533
|
process.kill(pid, 0);
|
|
46024
47534
|
return true;
|
|
46025
47535
|
} catch {
|
|
@@ -46030,8 +47540,8 @@ function isDaemonRunning() {
|
|
|
46030
47540
|
function stopDaemon() {
|
|
46031
47541
|
const pidFile = getDaemonPidFile();
|
|
46032
47542
|
try {
|
|
46033
|
-
if (!
|
|
46034
|
-
const pid = parseInt(
|
|
47543
|
+
if (!fs17.existsSync(pidFile)) return false;
|
|
47544
|
+
const pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim());
|
|
46035
47545
|
process.kill(pid, "SIGTERM");
|
|
46036
47546
|
removeDaemonPid();
|
|
46037
47547
|
return true;
|
|
@@ -46040,7 +47550,7 @@ function stopDaemon() {
|
|
|
46040
47550
|
return false;
|
|
46041
47551
|
}
|
|
46042
47552
|
}
|
|
46043
|
-
var
|
|
47553
|
+
var os21, fs17, path20, import_chalk2, pkgVersion, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
46044
47554
|
var init_adhdev_daemon = __esm({
|
|
46045
47555
|
"src/adhdev-daemon.ts"() {
|
|
46046
47556
|
"use strict";
|
|
@@ -46050,20 +47560,20 @@ var init_adhdev_daemon = __esm({
|
|
|
46050
47560
|
init_screenshot_controller();
|
|
46051
47561
|
init_session_host();
|
|
46052
47562
|
init_dist();
|
|
46053
|
-
|
|
46054
|
-
|
|
46055
|
-
|
|
47563
|
+
os21 = __toESM(require("os"));
|
|
47564
|
+
fs17 = __toESM(require("fs"));
|
|
47565
|
+
path20 = __toESM(require("path"));
|
|
46056
47566
|
import_chalk2 = __toESM(require("chalk"));
|
|
46057
|
-
pkgVersion = "0.
|
|
47567
|
+
pkgVersion = "0.8.0";
|
|
46058
47568
|
if (pkgVersion === "unknown") {
|
|
46059
47569
|
try {
|
|
46060
47570
|
const possiblePaths = [
|
|
46061
|
-
|
|
46062
|
-
|
|
47571
|
+
path20.join(__dirname, "..", "package.json"),
|
|
47572
|
+
path20.join(__dirname, "package.json")
|
|
46063
47573
|
];
|
|
46064
47574
|
for (const p of possiblePaths) {
|
|
46065
47575
|
try {
|
|
46066
|
-
const data = JSON.parse(
|
|
47576
|
+
const data = JSON.parse(fs17.readFileSync(p, "utf-8"));
|
|
46067
47577
|
if (data.version) {
|
|
46068
47578
|
pkgVersion = data.version;
|
|
46069
47579
|
break;
|
|
@@ -46161,6 +47671,10 @@ ${err?.stack || ""}`);
|
|
|
46161
47671
|
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
46162
47672
|
createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, providerSessionId, attachExisting }) => new SessionHostPtyTransportFactory({
|
|
46163
47673
|
endpoint: sessionHostEndpoint,
|
|
47674
|
+
ensureReady: async () => {
|
|
47675
|
+
const activeEndpoint = await ensureSessionHostReady2();
|
|
47676
|
+
this.sessionHostEndpoint = activeEndpoint;
|
|
47677
|
+
},
|
|
46164
47678
|
clientId: `daemon_${config2.machineId}`,
|
|
46165
47679
|
runtimeId,
|
|
46166
47680
|
providerType,
|
|
@@ -46206,8 +47720,8 @@ ${err?.stack || ""}`);
|
|
|
46206
47720
|
cliInfo: {
|
|
46207
47721
|
type: "adhdev-daemon",
|
|
46208
47722
|
version: pkgVersion,
|
|
46209
|
-
platform:
|
|
46210
|
-
hostname:
|
|
47723
|
+
platform: os21.platform(),
|
|
47724
|
+
hostname: os21.hostname(),
|
|
46211
47725
|
machineId: config2.machineId,
|
|
46212
47726
|
instanceId
|
|
46213
47727
|
}
|
|
@@ -46672,16 +48186,16 @@ async function loginFlow() {
|
|
|
46672
48186
|
let verificationUrl;
|
|
46673
48187
|
try {
|
|
46674
48188
|
const config2 = loadConfig();
|
|
46675
|
-
const
|
|
48189
|
+
const os22 = await import("os");
|
|
46676
48190
|
const res = await fetch(`${SERVER_URL}/auth/cli/init`, {
|
|
46677
48191
|
method: "POST",
|
|
46678
48192
|
headers: { "Content-Type": "application/json" },
|
|
46679
48193
|
body: JSON.stringify({
|
|
46680
48194
|
clientMachineId: config2.machineId,
|
|
46681
48195
|
registeredMachineId: config2.registeredMachineId,
|
|
46682
|
-
hostname:
|
|
46683
|
-
platform:
|
|
46684
|
-
arch:
|
|
48196
|
+
hostname: os22.hostname(),
|
|
48197
|
+
platform: os22.platform(),
|
|
48198
|
+
arch: os22.arch()
|
|
46685
48199
|
})
|
|
46686
48200
|
});
|
|
46687
48201
|
if (!res.ok) {
|
|
@@ -46780,10 +48294,10 @@ async function startDaemonFlow() {
|
|
|
46780
48294
|
const { AdhdevDaemon: AdhdevDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
|
|
46781
48295
|
const daemon = new AdhdevDaemon2();
|
|
46782
48296
|
const { execSync: execSync6 } = await import("child_process");
|
|
46783
|
-
const
|
|
46784
|
-
const
|
|
46785
|
-
const logPath =
|
|
46786
|
-
const platform11 =
|
|
48297
|
+
const os22 = await import("os");
|
|
48298
|
+
const path21 = await import("path");
|
|
48299
|
+
const logPath = path21.join(os22.homedir(), ".adhdev", "daemon.log");
|
|
48300
|
+
const platform11 = os22.platform();
|
|
46787
48301
|
try {
|
|
46788
48302
|
if (platform11 === "win32") {
|
|
46789
48303
|
execSync6(`start /B adhdev daemon > "${logPath}" 2>&1`, {
|