@adhdev/daemon-standalone 0.8.21 → 0.8.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1160 -313
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/index-BkwEAeWn.js +55 -0
- package/public/assets/index-DGZ1wx9R.css +1 -0
- package/public/assets/terminal-Cpt8BO0p.js +94 -0
- package/public/assets/terminal-DYP7pi_n.css +32 -0
- package/public/assets/{vendor-CPghmr9Y.js → vendor-BRZ4K-AC.js} +1 -1
- package/public/index.html +3 -5
- package/public/assets/index-BE507Aby.css +0 -1
- package/public/assets/index-C8mhaDTP.js +0 -61
- package/public/assets/terminal-6GBZ9nXN.css +0 -32
- package/public/assets/terminal-CKqklWLC.js +0 -13
package/dist/index.js
CHANGED
|
@@ -27855,7 +27855,8 @@ var require_dist2 = __commonJS({
|
|
|
27855
27855
|
providerSettings: isPlainObject2(parsed.providerSettings) ? parsed.providerSettings : {},
|
|
27856
27856
|
ideSettings: isPlainObject2(parsed.ideSettings) ? parsed.ideSettings : {},
|
|
27857
27857
|
disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
|
|
27858
|
-
providerDir: asOptionalString(parsed.providerDir)
|
|
27858
|
+
providerDir: asOptionalString(parsed.providerDir),
|
|
27859
|
+
terminalSizingMode: parsed.terminalSizingMode === "fit" ? "fit" : "measured"
|
|
27859
27860
|
};
|
|
27860
27861
|
}
|
|
27861
27862
|
function generateMachineId() {
|
|
@@ -28008,7 +28009,8 @@ var require_dist2 = __commonJS({
|
|
|
28008
28009
|
registeredMachineId: void 0,
|
|
28009
28010
|
providerSettings: {},
|
|
28010
28011
|
ideSettings: {},
|
|
28011
|
-
disableUpstream: false
|
|
28012
|
+
disableUpstream: false,
|
|
28013
|
+
terminalSizingMode: "measured"
|
|
28012
28014
|
};
|
|
28013
28015
|
MACHINE_ID_PREFIX = "mach_";
|
|
28014
28016
|
}
|
|
@@ -28604,6 +28606,53 @@ var require_dist2 = __commonJS({
|
|
|
28604
28606
|
function sanitizeTerminalText(str) {
|
|
28605
28607
|
return stripTerminalNoise(stripAnsi(str));
|
|
28606
28608
|
}
|
|
28609
|
+
function splitCliScreenLines(text) {
|
|
28610
|
+
return String(text || "").replace(/\u0007/g, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n").map((line) => line.replace(/\s+$/, ""));
|
|
28611
|
+
}
|
|
28612
|
+
function isPromptLikeCliLine(line) {
|
|
28613
|
+
const trimmed = String(line || "").trim();
|
|
28614
|
+
if (!trimmed) return false;
|
|
28615
|
+
return /^[❯›>]\s*(?:$|\S.*)$/.test(trimmed);
|
|
28616
|
+
}
|
|
28617
|
+
function buildCliScreenSnapshot(text) {
|
|
28618
|
+
const normalizedText = String(text || "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
28619
|
+
const rawLines = splitCliScreenLines(normalizedText);
|
|
28620
|
+
const lines = rawLines.map((line, index, arr) => {
|
|
28621
|
+
const trimmed = String(line || "").trim();
|
|
28622
|
+
return {
|
|
28623
|
+
index,
|
|
28624
|
+
fromTop: index,
|
|
28625
|
+
fromBottom: arr.length - index - 1,
|
|
28626
|
+
text: line,
|
|
28627
|
+
trimmed,
|
|
28628
|
+
isEmpty: trimmed.length === 0
|
|
28629
|
+
};
|
|
28630
|
+
});
|
|
28631
|
+
const nonEmptyLines = lines.filter((line) => !line.isEmpty);
|
|
28632
|
+
const firstNonEmptyLine = nonEmptyLines[0] ?? null;
|
|
28633
|
+
const lastNonEmptyLine = nonEmptyLines[nonEmptyLines.length - 1] ?? null;
|
|
28634
|
+
let promptLineIndex = -1;
|
|
28635
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
28636
|
+
if (isPromptLikeCliLine(lines[i].text)) {
|
|
28637
|
+
promptLineIndex = i;
|
|
28638
|
+
break;
|
|
28639
|
+
}
|
|
28640
|
+
}
|
|
28641
|
+
return {
|
|
28642
|
+
text: normalizedText,
|
|
28643
|
+
lineCount: lines.length,
|
|
28644
|
+
lines,
|
|
28645
|
+
nonEmptyLines,
|
|
28646
|
+
firstNonEmptyLineIndex: firstNonEmptyLine?.index ?? -1,
|
|
28647
|
+
lastNonEmptyLineIndex: lastNonEmptyLine?.index ?? -1,
|
|
28648
|
+
firstNonEmptyLine,
|
|
28649
|
+
lastNonEmptyLine,
|
|
28650
|
+
promptLineIndex,
|
|
28651
|
+
promptLine: promptLineIndex >= 0 ? lines[promptLineIndex] : null,
|
|
28652
|
+
linesAbovePrompt: promptLineIndex >= 0 ? lines.slice(0, promptLineIndex) : [...lines],
|
|
28653
|
+
linesBelowPrompt: promptLineIndex >= 0 ? lines.slice(promptLineIndex + 1) : []
|
|
28654
|
+
};
|
|
28655
|
+
}
|
|
28607
28656
|
function computeTerminalQueryTail(buffer) {
|
|
28608
28657
|
const prefixes = ["\x1B[6n", "\x1B[?6n"];
|
|
28609
28658
|
const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
|
|
@@ -28849,7 +28898,9 @@ var require_dist2 = __commonJS({
|
|
|
28849
28898
|
ready = false;
|
|
28850
28899
|
startupBuffer = "";
|
|
28851
28900
|
startupParseGate = false;
|
|
28901
|
+
startupSettleTimer = null;
|
|
28852
28902
|
spawnAt = 0;
|
|
28903
|
+
startupFirstOutputAt = 0;
|
|
28853
28904
|
// PTY I/O
|
|
28854
28905
|
onPtyDataCallback = null;
|
|
28855
28906
|
pendingOutputParseBuffer = "";
|
|
@@ -28890,6 +28941,7 @@ var require_dist2 = __commonJS({
|
|
|
28890
28941
|
statusHistory = [];
|
|
28891
28942
|
// ─── CLI Scripts (script-based parsing) ───
|
|
28892
28943
|
cliScripts;
|
|
28944
|
+
runtimeSettings = {};
|
|
28893
28945
|
/** Full accumulated ANSI-stripped PTY output */
|
|
28894
28946
|
accumulatedBuffer = "";
|
|
28895
28947
|
/** Full accumulated raw PTY output (with ANSI) */
|
|
@@ -28904,14 +28956,15 @@ var require_dist2 = __commonJS({
|
|
|
28904
28956
|
traceSessionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
28905
28957
|
static MAX_TRACE_ENTRIES = 250;
|
|
28906
28958
|
providerResolutionMeta;
|
|
28907
|
-
static IDLE_FINISH_CONFIRM_MS =
|
|
28959
|
+
static IDLE_FINISH_CONFIRM_MS = 2e3;
|
|
28960
|
+
static STATUS_ACTIVITY_HOLD_MS = 2e3;
|
|
28908
28961
|
static FINISH_RETRY_DELAY_MS = 300;
|
|
28909
28962
|
static MAX_FINISH_RETRIES = 2;
|
|
28910
28963
|
syncMessageViews() {
|
|
28911
28964
|
this.messages = [...this.committedMessages];
|
|
28912
28965
|
this.structuredMessages = [...this.committedMessages];
|
|
28913
28966
|
}
|
|
28914
|
-
|
|
28967
|
+
hydrateParsedMessages(parsedMessages, scope) {
|
|
28915
28968
|
const referenceMessages = [...this.committedMessages];
|
|
28916
28969
|
const usedReferenceIndexes = /* @__PURE__ */ new Set();
|
|
28917
28970
|
const now = Date.now();
|
|
@@ -28944,13 +28997,30 @@ var require_dist2 = __commonJS({
|
|
|
28944
28997
|
const content = typeof message.content === "string" ? message.content : String(message.content || "");
|
|
28945
28998
|
const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
|
|
28946
28999
|
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(role, content, index);
|
|
29000
|
+
const fallbackTimestamp = role === "user" ? scope?.startedAt || now : this.lastOutputAt || scope?.startedAt || now;
|
|
29001
|
+
const timestamp = referenceTimestamp ?? fallbackTimestamp;
|
|
28947
29002
|
return {
|
|
29003
|
+
...message,
|
|
28948
29004
|
role,
|
|
28949
29005
|
content,
|
|
28950
|
-
timestamp
|
|
29006
|
+
timestamp,
|
|
29007
|
+
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
|
|
28951
29008
|
};
|
|
28952
29009
|
});
|
|
28953
29010
|
}
|
|
29011
|
+
normalizeParsedMessages(parsedMessages, scope) {
|
|
29012
|
+
return this.hydrateParsedMessages(parsedMessages, scope).map((message) => ({
|
|
29013
|
+
role: message.role,
|
|
29014
|
+
content: message.content,
|
|
29015
|
+
timestamp: message.timestamp,
|
|
29016
|
+
receivedAt: message.receivedAt,
|
|
29017
|
+
kind: message.kind,
|
|
29018
|
+
id: message.id,
|
|
29019
|
+
index: message.index,
|
|
29020
|
+
meta: message.meta,
|
|
29021
|
+
senderName: message.senderName
|
|
29022
|
+
}));
|
|
29023
|
+
}
|
|
28954
29024
|
sliceFromOffset(text, start) {
|
|
28955
29025
|
if (!text) return "";
|
|
28956
29026
|
if (!Number.isFinite(start) || start <= 0) return text;
|
|
@@ -28960,14 +29030,20 @@ var require_dist2 = __commonJS({
|
|
|
28960
29030
|
buildParseInput(baseMessages, partialResponse, scope) {
|
|
28961
29031
|
const buffer = scope ? this.sliceFromOffset(this.accumulatedBuffer, scope.bufferStart) || this.accumulatedBuffer : this.accumulatedBuffer;
|
|
28962
29032
|
const rawBuffer = scope ? this.sliceFromOffset(this.accumulatedRawBuffer, scope.rawBufferStart) || this.accumulatedRawBuffer : this.accumulatedRawBuffer;
|
|
29033
|
+
const screenText = this.terminalScreen.getText();
|
|
29034
|
+
const recentBuffer = buffer.slice(-1e3) || this.recentOutputBuffer;
|
|
28963
29035
|
return {
|
|
28964
29036
|
buffer,
|
|
28965
29037
|
rawBuffer,
|
|
28966
|
-
recentBuffer
|
|
28967
|
-
screenText
|
|
29038
|
+
recentBuffer,
|
|
29039
|
+
screenText,
|
|
29040
|
+
screen: buildCliScreenSnapshot(screenText),
|
|
29041
|
+
bufferScreen: buildCliScreenSnapshot(buffer),
|
|
29042
|
+
recentScreen: buildCliScreenSnapshot(recentBuffer),
|
|
28968
29043
|
messages: [...baseMessages],
|
|
28969
29044
|
partialResponse,
|
|
28970
|
-
promptText: scope?.prompt || ""
|
|
29045
|
+
promptText: scope?.prompt || "",
|
|
29046
|
+
settings: { ...this.runtimeSettings }
|
|
28971
29047
|
};
|
|
28972
29048
|
}
|
|
28973
29049
|
setStatus(status, trigger) {
|
|
@@ -29073,6 +29149,9 @@ var require_dist2 = __commonJS({
|
|
|
29073
29149
|
const scriptNames = Object.keys(scripts).filter((k) => typeof scripts[k] === "function");
|
|
29074
29150
|
LOG2.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
29075
29151
|
}
|
|
29152
|
+
updateRuntimeSettings(settings) {
|
|
29153
|
+
this.runtimeSettings = { ...settings };
|
|
29154
|
+
}
|
|
29076
29155
|
// ─── Lifecycle ─────────────────────────────────
|
|
29077
29156
|
setServerConn(serverConn) {
|
|
29078
29157
|
this.serverConn = serverConn;
|
|
@@ -29109,7 +29188,7 @@ var require_dist2 = __commonJS({
|
|
|
29109
29188
|
let shellArgs;
|
|
29110
29189
|
const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
29111
29190
|
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
29112
|
-
const useShellWin = isCmdShim || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
29191
|
+
const useShellWin = !!spawnConfig.shell || isCmdShim || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
29113
29192
|
const useShell = isWin ? useShellWin : useShellUnix;
|
|
29114
29193
|
if (useShell) {
|
|
29115
29194
|
if (!spawnConfig.shell && !isWin) {
|
|
@@ -29207,6 +29286,11 @@ var require_dist2 = __commonJS({
|
|
|
29207
29286
|
this.spawnAt = Date.now();
|
|
29208
29287
|
this.startupParseGate = true;
|
|
29209
29288
|
this.startupBuffer = "";
|
|
29289
|
+
this.startupFirstOutputAt = 0;
|
|
29290
|
+
if (this.startupSettleTimer) {
|
|
29291
|
+
clearTimeout(this.startupSettleTimer);
|
|
29292
|
+
this.startupSettleTimer = null;
|
|
29293
|
+
}
|
|
29210
29294
|
this.terminalScreen.reset(24, 80);
|
|
29211
29295
|
this.pendingTerminalQueryTail = "";
|
|
29212
29296
|
this.currentTurnScope = null;
|
|
@@ -29220,7 +29304,8 @@ var require_dist2 = __commonJS({
|
|
|
29220
29304
|
this.recordTrace("ready", {
|
|
29221
29305
|
runtimeMeta: this.getRuntimeMetadata()
|
|
29222
29306
|
});
|
|
29223
|
-
this.setStatus("
|
|
29307
|
+
this.setStatus("starting", "pty_ready");
|
|
29308
|
+
this.scheduleStartupSettleCheck();
|
|
29224
29309
|
this.onStatusChange?.();
|
|
29225
29310
|
}
|
|
29226
29311
|
// ─── Output Handling ────────────────────────────
|
|
@@ -29235,6 +29320,9 @@ var require_dist2 = __commonJS({
|
|
|
29235
29320
|
this.lastScreenSnapshot = normalizedScreenSnapshot;
|
|
29236
29321
|
this.lastScreenChangeAt = now;
|
|
29237
29322
|
}
|
|
29323
|
+
if (this.startupParseGate && !this.startupFirstOutputAt && (cleanData.trim() || normalizedScreenSnapshot.trim())) {
|
|
29324
|
+
this.startupFirstOutputAt = now;
|
|
29325
|
+
}
|
|
29238
29326
|
if (this.idleFinishCandidate && (rawData.length > 0 || cleanData.length > 0)) {
|
|
29239
29327
|
this.clearIdleFinishCandidate("new_output");
|
|
29240
29328
|
}
|
|
@@ -29245,6 +29333,9 @@ var require_dist2 = __commonJS({
|
|
|
29245
29333
|
cleanPreview: this.summarizeTraceText(cleanData, 300),
|
|
29246
29334
|
screenText: this.summarizeTraceText(this.terminalScreen.getText(), 1200)
|
|
29247
29335
|
});
|
|
29336
|
+
if (this.startupParseGate) {
|
|
29337
|
+
this.scheduleStartupSettleCheck();
|
|
29338
|
+
}
|
|
29248
29339
|
if (this.isWaitingForResponse && cleanData) {
|
|
29249
29340
|
this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
|
|
29250
29341
|
}
|
|
@@ -29258,27 +29349,51 @@ var require_dist2 = __commonJS({
|
|
|
29258
29349
|
this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
|
|
29259
29350
|
this.accumulatedBuffer = (this.accumulatedBuffer + cleanData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
29260
29351
|
this.accumulatedRawBuffer = (this.accumulatedRawBuffer + rawData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
29261
|
-
|
|
29262
|
-
this.startupBuffer += cleanData;
|
|
29263
|
-
const elapsed = Date.now() - this.spawnAt;
|
|
29264
|
-
const screenText = this.terminalScreen.getText() || "";
|
|
29265
|
-
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
29266
|
-
const scriptStatus = startupModal ? "waiting_approval" : this.runDetectStatus(this.startupBuffer);
|
|
29267
|
-
const hasInteractivePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
29268
|
-
const startupStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
29269
|
-
const isReady = (scriptStatus === "idle" || scriptStatus === "waiting_approval") && hasInteractivePrompt && startupStableMs >= 700 || !!startupModal && startupStableMs >= 700 || elapsed > 8e3 || this.startupBuffer.length > 12e3;
|
|
29270
|
-
if (isReady) {
|
|
29271
|
-
this.startupParseGate = false;
|
|
29272
|
-
this.ready = true;
|
|
29273
|
-
LOG2.info(
|
|
29274
|
-
"CLI",
|
|
29275
|
-
`[${this.cliType}] Startup ready (${elapsed}ms, scriptStatus=${scriptStatus}, prompt=${hasInteractivePrompt}, stableMs=${startupStableMs}) providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
29276
|
-
);
|
|
29277
|
-
this.onStatusChange?.();
|
|
29278
|
-
}
|
|
29279
|
-
}
|
|
29352
|
+
this.resolveStartupState("output");
|
|
29280
29353
|
this.scheduleSettle();
|
|
29281
29354
|
}
|
|
29355
|
+
resolveStartupState(trigger) {
|
|
29356
|
+
if (!this.startupParseGate) return;
|
|
29357
|
+
const now = Date.now();
|
|
29358
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
29359
|
+
const normalizedScreen = normalizeScreenSnapshot(screenText);
|
|
29360
|
+
const hasStartupOutput = !!this.startupFirstOutputAt || !!normalizedScreen.trim();
|
|
29361
|
+
if (!hasStartupOutput) return;
|
|
29362
|
+
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
29363
|
+
if (stableMs < 2e3) return;
|
|
29364
|
+
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
29365
|
+
this.startupParseGate = false;
|
|
29366
|
+
if (this.startupSettleTimer) {
|
|
29367
|
+
clearTimeout(this.startupSettleTimer);
|
|
29368
|
+
this.startupSettleTimer = null;
|
|
29369
|
+
}
|
|
29370
|
+
this.ready = true;
|
|
29371
|
+
if (startupModal) {
|
|
29372
|
+
this.activeModal = startupModal;
|
|
29373
|
+
this.setStatus("waiting_approval", `startup_ready:${trigger}`);
|
|
29374
|
+
} else {
|
|
29375
|
+
this.setStatus("idle", `startup_ready:${trigger}`);
|
|
29376
|
+
}
|
|
29377
|
+
LOG2.info(
|
|
29378
|
+
"CLI",
|
|
29379
|
+
`[${this.cliType}] Startup settled (${trigger}, stableMs=${stableMs}, modal=${!!startupModal}) providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
29380
|
+
);
|
|
29381
|
+
this.onStatusChange?.();
|
|
29382
|
+
}
|
|
29383
|
+
scheduleStartupSettleCheck() {
|
|
29384
|
+
if (!this.startupParseGate) return;
|
|
29385
|
+
if (this.startupSettleTimer) clearTimeout(this.startupSettleTimer);
|
|
29386
|
+
const now = Date.now();
|
|
29387
|
+
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
29388
|
+
const delayMs = Math.max(250, 2050 - stableMs);
|
|
29389
|
+
this.startupSettleTimer = setTimeout(() => {
|
|
29390
|
+
this.startupSettleTimer = null;
|
|
29391
|
+
this.resolveStartupState("startup_timer");
|
|
29392
|
+
if (this.startupParseGate && Date.now() - this.spawnAt < 1e4) {
|
|
29393
|
+
this.scheduleStartupSettleCheck();
|
|
29394
|
+
}
|
|
29395
|
+
}, delayMs);
|
|
29396
|
+
}
|
|
29282
29397
|
scheduleSettle() {
|
|
29283
29398
|
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
29284
29399
|
const settleEpoch = this.responseEpoch;
|
|
@@ -29320,6 +29435,43 @@ var require_dist2 = __commonJS({
|
|
|
29320
29435
|
if (!text.trim()) return false;
|
|
29321
29436
|
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);
|
|
29322
29437
|
}
|
|
29438
|
+
findLastMatchingLineIndex(lines, predicate) {
|
|
29439
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
29440
|
+
if (predicate(lines[index])) return index;
|
|
29441
|
+
}
|
|
29442
|
+
return -1;
|
|
29443
|
+
}
|
|
29444
|
+
looksLikeClaudeGeneratingLine(line) {
|
|
29445
|
+
const trimmed = String(line || "").trim();
|
|
29446
|
+
if (!trimmed) return false;
|
|
29447
|
+
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) return true;
|
|
29448
|
+
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+\S+.*\b(?:thinking|thought for \d+s?)\b/i.test(trimmed)) return true;
|
|
29449
|
+
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+[A-Z][A-Za-z-]{3,}ing\b.*(?:…|\.{3})/u.test(trimmed)) return true;
|
|
29450
|
+
if (/^[⏺•]\s+(?:Reading|Writing|Editing|Searching|Inspecting|Planning|Analyzing|Synthesizing|Drafting|Running|Listing|Scanning|Matching)\b.*(?:…|\.{3})/i.test(trimmed)) {
|
|
29451
|
+
return /ctrl\+o to expand/i.test(trimmed) || /\b\d+\s+(?:file|files|pattern|patterns|director(?:y|ies)|match|matches|result|results)\b/i.test(trimmed);
|
|
29452
|
+
}
|
|
29453
|
+
return false;
|
|
29454
|
+
}
|
|
29455
|
+
detectClaudeGeneratingOverride(screenText, tail) {
|
|
29456
|
+
if (this.cliType !== "claude-cli") return false;
|
|
29457
|
+
const source = sanitizeTerminalText(screenText || tail || "");
|
|
29458
|
+
if (!source.trim()) return false;
|
|
29459
|
+
const allLines = source.split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
|
|
29460
|
+
if (allLines.length === 0) return false;
|
|
29461
|
+
const recentLines = allLines.slice(-12);
|
|
29462
|
+
const promptIndex = this.findLastMatchingLineIndex(recentLines, (line) => /^[❯›>]\s*$/.test(line));
|
|
29463
|
+
const activeRegion = promptIndex >= 0 ? recentLines.slice(Math.max(0, promptIndex - 2), promptIndex) : recentLines;
|
|
29464
|
+
if (activeRegion.length === 0) return false;
|
|
29465
|
+
return activeRegion.some((line) => this.looksLikeClaudeGeneratingLine(line));
|
|
29466
|
+
}
|
|
29467
|
+
refineDetectedStatus(status, tail, screenText) {
|
|
29468
|
+
if (this.startupParseGate) {
|
|
29469
|
+
return this.getStartupConfirmationModal(screenText || "") ? "waiting_approval" : "starting";
|
|
29470
|
+
}
|
|
29471
|
+
if (status === "waiting_approval") return status;
|
|
29472
|
+
if (this.detectClaudeGeneratingOverride(screenText || "", tail)) return "generating";
|
|
29473
|
+
return status;
|
|
29474
|
+
}
|
|
29323
29475
|
looksLikeVisibleAssistantCandidate(screenText) {
|
|
29324
29476
|
const lines = sanitizeTerminalText(String(screenText || "")).split(/\r\n|\n|\r/g);
|
|
29325
29477
|
for (const line of lines) {
|
|
@@ -29354,6 +29506,11 @@ var require_dist2 = __commonJS({
|
|
|
29354
29506
|
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
29355
29507
|
return quietForMs < 1200 || screenStableMs < 1200 || !commitResult.hasAssistant;
|
|
29356
29508
|
}
|
|
29509
|
+
hasRecentInteractiveActivity(now) {
|
|
29510
|
+
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
29511
|
+
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : Number.MAX_SAFE_INTEGER;
|
|
29512
|
+
return quietForMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS || screenStableMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
|
|
29513
|
+
}
|
|
29357
29514
|
getStartupConfirmationModal(screenText) {
|
|
29358
29515
|
const text = sanitizeTerminalText(String(screenText || ""));
|
|
29359
29516
|
if (!text.trim()) return null;
|
|
@@ -29381,13 +29538,14 @@ var require_dist2 = __commonJS({
|
|
|
29381
29538
|
const startedAt = Date.now();
|
|
29382
29539
|
let loggedWait = false;
|
|
29383
29540
|
while (Date.now() - startedAt < maxWaitMs) {
|
|
29541
|
+
this.resolveStartupState("interactive_wait");
|
|
29384
29542
|
const screenText = this.terminalScreen.getText() || "";
|
|
29385
29543
|
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
29386
29544
|
const stableMs = this.lastScreenChangeAt ? Date.now() - this.lastScreenChangeAt : 0;
|
|
29387
29545
|
const recentlyOutput = this.lastNonEmptyOutputAt ? Date.now() - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
29388
29546
|
const status = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
|
|
29389
29547
|
const startupLikelyActive = /Welcome back|Tips for getting|Recent activity|Claude Code v\d/i.test(screenText);
|
|
29390
|
-
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "
|
|
29548
|
+
const interactiveReady = hasPrompt && stableMs >= 700 && recentlyOutput >= 350 && status !== "generating";
|
|
29391
29549
|
if (interactiveReady) {
|
|
29392
29550
|
if (loggedWait) {
|
|
29393
29551
|
LOG2.info(
|
|
@@ -29426,6 +29584,10 @@ var require_dist2 = __commonJS({
|
|
|
29426
29584
|
}
|
|
29427
29585
|
const tail = this.settledBuffer;
|
|
29428
29586
|
const screenText = this.terminalScreen.getText() || "";
|
|
29587
|
+
this.resolveStartupState("settled");
|
|
29588
|
+
if (this.startupParseGate) {
|
|
29589
|
+
return;
|
|
29590
|
+
}
|
|
29429
29591
|
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
29430
29592
|
const modal = this.runParseApproval(tail) || startupModal;
|
|
29431
29593
|
const rawScriptStatus = this.runDetectStatus(tail);
|
|
@@ -29488,6 +29650,28 @@ var require_dist2 = __commonJS({
|
|
|
29488
29650
|
} else {
|
|
29489
29651
|
clearPendingScriptStatus();
|
|
29490
29652
|
}
|
|
29653
|
+
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
29654
|
+
const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity;
|
|
29655
|
+
if (shouldHoldGenerating) {
|
|
29656
|
+
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
29657
|
+
this.setStatus("generating", "recent_activity_hold");
|
|
29658
|
+
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
29659
|
+
this.idleTimeout = setTimeout(() => {
|
|
29660
|
+
if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
|
|
29661
|
+
this.finishResponse();
|
|
29662
|
+
}
|
|
29663
|
+
}, this.timeouts.generatingIdle);
|
|
29664
|
+
this.recordTrace("hold_generating_recent_activity", {
|
|
29665
|
+
scriptStatus,
|
|
29666
|
+
recentInteractiveActivity,
|
|
29667
|
+
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
29668
|
+
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
29669
|
+
holdMs: _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS,
|
|
29670
|
+
...this.buildTraceParseSnapshot(this.currentTurnScope, this.responseBuffer)
|
|
29671
|
+
});
|
|
29672
|
+
this.onStatusChange?.();
|
|
29673
|
+
return;
|
|
29674
|
+
}
|
|
29491
29675
|
if (scriptStatus === "waiting_approval") {
|
|
29492
29676
|
this.clearIdleFinishCandidate("waiting_approval");
|
|
29493
29677
|
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
@@ -29565,8 +29749,8 @@ var require_dist2 = __commonJS({
|
|
|
29565
29749
|
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
29566
29750
|
const hasAssistantTurn = !!lastParsedAssistant;
|
|
29567
29751
|
const assistantLength = lastParsedAssistant?.content?.length || 0;
|
|
29568
|
-
const idleQuietThresholdMs = Math.max(
|
|
29569
|
-
const idleStableThresholdMs =
|
|
29752
|
+
const idleQuietThresholdMs = Math.max(2e3, this.timeouts.outputSettle);
|
|
29753
|
+
const idleStableThresholdMs = 2e3;
|
|
29570
29754
|
const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
|
|
29571
29755
|
const candidate = this.idleFinishCandidate;
|
|
29572
29756
|
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;
|
|
@@ -29680,7 +29864,7 @@ var require_dist2 = __commonJS({
|
|
|
29680
29864
|
this.currentTurnScope
|
|
29681
29865
|
);
|
|
29682
29866
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
29683
|
-
this.committedMessages = this.normalizeParsedMessages(parsed.messages);
|
|
29867
|
+
this.committedMessages = this.normalizeParsedMessages(parsed.messages, this.currentTurnScope);
|
|
29684
29868
|
const promptForTrim = this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages);
|
|
29685
29869
|
if (promptForTrim) {
|
|
29686
29870
|
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
@@ -29717,11 +29901,15 @@ var require_dist2 = __commonJS({
|
|
|
29717
29901
|
runDetectStatus(text) {
|
|
29718
29902
|
if (!this.cliScripts?.detectStatus) return null;
|
|
29719
29903
|
try {
|
|
29720
|
-
|
|
29904
|
+
const screenText = this.terminalScreen.getText();
|
|
29905
|
+
const status = this.cliScripts.detectStatus({
|
|
29721
29906
|
tail: text.slice(-500),
|
|
29722
|
-
screenText
|
|
29723
|
-
rawBuffer: this.accumulatedRawBuffer
|
|
29907
|
+
screenText,
|
|
29908
|
+
rawBuffer: this.accumulatedRawBuffer,
|
|
29909
|
+
screen: buildCliScreenSnapshot(screenText),
|
|
29910
|
+
tailScreen: buildCliScreenSnapshot(text.slice(-500))
|
|
29724
29911
|
});
|
|
29912
|
+
return this.refineDetectedStatus(status, text, screenText || "");
|
|
29725
29913
|
} catch (e) {
|
|
29726
29914
|
LOG2.warn("CLI", `[${this.cliType}] detectStatus error: ${e.message}`);
|
|
29727
29915
|
return null;
|
|
@@ -29730,11 +29918,16 @@ var require_dist2 = __commonJS({
|
|
|
29730
29918
|
runParseApproval(tail) {
|
|
29731
29919
|
if (!this.cliScripts?.parseApproval) return null;
|
|
29732
29920
|
try {
|
|
29921
|
+
const screenText = this.terminalScreen.getText();
|
|
29922
|
+
const buffer = screenText || this.accumulatedBuffer;
|
|
29733
29923
|
return this.cliScripts.parseApproval({
|
|
29734
|
-
buffer
|
|
29735
|
-
screenText
|
|
29924
|
+
buffer,
|
|
29925
|
+
screenText,
|
|
29736
29926
|
rawBuffer: this.accumulatedRawBuffer,
|
|
29737
|
-
tail
|
|
29927
|
+
tail,
|
|
29928
|
+
screen: buildCliScreenSnapshot(screenText),
|
|
29929
|
+
bufferScreen: buildCliScreenSnapshot(buffer),
|
|
29930
|
+
tailScreen: buildCliScreenSnapshot(tail)
|
|
29738
29931
|
});
|
|
29739
29932
|
} catch (e) {
|
|
29740
29933
|
LOG2.warn("CLI", `[${this.cliType}] parseApproval error: ${e.message}`);
|
|
@@ -29750,6 +29943,21 @@ var require_dist2 = __commonJS({
|
|
|
29750
29943
|
activeModal: this.activeModal
|
|
29751
29944
|
};
|
|
29752
29945
|
}
|
|
29946
|
+
seedCommittedMessages(messages) {
|
|
29947
|
+
const normalized = (Array.isArray(messages) ? messages : []).filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
|
|
29948
|
+
role: message.role,
|
|
29949
|
+
content: typeof message.content === "string" ? message.content : String(message.content || ""),
|
|
29950
|
+
timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0,
|
|
29951
|
+
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : void 0,
|
|
29952
|
+
kind: typeof message.kind === "string" ? message.kind : void 0,
|
|
29953
|
+
id: typeof message.id === "string" ? message.id : void 0,
|
|
29954
|
+
index: typeof message.index === "number" ? message.index : void 0,
|
|
29955
|
+
meta: message.meta && typeof message.meta === "object" ? { ...message.meta } : void 0,
|
|
29956
|
+
senderName: typeof message.senderName === "string" ? message.senderName : void 0
|
|
29957
|
+
}));
|
|
29958
|
+
this.committedMessages = normalized;
|
|
29959
|
+
this.syncMessageViews();
|
|
29960
|
+
}
|
|
29753
29961
|
/**
|
|
29754
29962
|
* Script-based full parse — returns ReadChatResult.
|
|
29755
29963
|
* Called by command handler / dashboard for rich content rendering.
|
|
@@ -29760,12 +29968,20 @@ var require_dist2 = __commonJS({
|
|
|
29760
29968
|
this.responseBuffer,
|
|
29761
29969
|
this.currentTurnScope
|
|
29762
29970
|
);
|
|
29971
|
+
const shouldPreferCommittedMessages = !this.currentTurnScope && this.currentStatus === "idle" && !this.activeModal;
|
|
29763
29972
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
29973
|
+
const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => ({
|
|
29974
|
+
...message,
|
|
29975
|
+
id: message.id || `msg_${index}`,
|
|
29976
|
+
index: typeof message.index === "number" ? message.index : index,
|
|
29977
|
+
kind: message.kind || "standard",
|
|
29978
|
+
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
29979
|
+
})) : this.hydrateParsedMessages(parsed.messages, this.currentTurnScope);
|
|
29764
29980
|
return {
|
|
29765
29981
|
id: parsed.id || "cli_session",
|
|
29766
29982
|
status: parsed.status || this.currentStatus,
|
|
29767
29983
|
title: parsed.title || this.cliName,
|
|
29768
|
-
messages:
|
|
29984
|
+
messages: hydratedMessages,
|
|
29769
29985
|
activeModal: parsed.activeModal ?? this.activeModal,
|
|
29770
29986
|
providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0
|
|
29771
29987
|
};
|
|
@@ -29786,11 +30002,30 @@ var require_dist2 = __commonJS({
|
|
|
29786
30002
|
activeModal: this.activeModal
|
|
29787
30003
|
};
|
|
29788
30004
|
}
|
|
30005
|
+
async invokeScript(scriptName, args) {
|
|
30006
|
+
const fn2 = this.cliScripts?.[scriptName];
|
|
30007
|
+
if (typeof fn2 !== "function") {
|
|
30008
|
+
throw new Error(`CLI script '${scriptName}' not available`);
|
|
30009
|
+
}
|
|
30010
|
+
const input = this.buildParseInput(
|
|
30011
|
+
this.committedMessages,
|
|
30012
|
+
this.responseBuffer,
|
|
30013
|
+
this.currentTurnScope
|
|
30014
|
+
);
|
|
30015
|
+
return await Promise.resolve(fn2({
|
|
30016
|
+
...input,
|
|
30017
|
+
args: args && typeof args === "object" ? { ...args } : {}
|
|
30018
|
+
}));
|
|
30019
|
+
}
|
|
29789
30020
|
parseCurrentTranscript(baseMessages, partialResponse, scope) {
|
|
29790
30021
|
if (!this.cliScripts?.parseOutput) return null;
|
|
29791
30022
|
try {
|
|
29792
30023
|
const input = this.buildParseInput(baseMessages, partialResponse, scope);
|
|
29793
30024
|
const parsed = this.cliScripts.parseOutput(input);
|
|
30025
|
+
const refinedStatus = this.refineDetectedStatus(typeof parsed?.status === "string" ? parsed.status : null, input.recentBuffer, input.screenText);
|
|
30026
|
+
if (parsed && refinedStatus && parsed.status !== refinedStatus) {
|
|
30027
|
+
parsed.status = refinedStatus;
|
|
30028
|
+
}
|
|
29794
30029
|
const promptForTrim = scope?.prompt || getLastUserPromptText(baseMessages);
|
|
29795
30030
|
if (parsed && Array.isArray(parsed.messages) && promptForTrim) {
|
|
29796
30031
|
const lastAssistant = [...parsed.messages].reverse().find((message) => message?.role === "assistant" && typeof message.content === "string");
|
|
@@ -29837,12 +30072,23 @@ ${data.message || ""}`.trim();
|
|
|
29837
30072
|
if (this.startupParseGate) {
|
|
29838
30073
|
const deadline = Date.now() + 1e4;
|
|
29839
30074
|
while (this.startupParseGate && Date.now() < deadline) {
|
|
30075
|
+
this.resolveStartupState("send_wait");
|
|
29840
30076
|
await new Promise((resolve9) => setTimeout(resolve9, 50));
|
|
29841
30077
|
}
|
|
29842
30078
|
}
|
|
30079
|
+
await this.waitForInteractivePrompt();
|
|
30080
|
+
if (!this.ready) {
|
|
30081
|
+
this.resolveStartupState("send_precheck");
|
|
30082
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
30083
|
+
const hasPrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
30084
|
+
if (hasPrompt && this.currentStatus === "idle") {
|
|
30085
|
+
this.ready = true;
|
|
30086
|
+
this.startupParseGate = false;
|
|
30087
|
+
LOG2.info("CLI", `[${this.cliType}] sendMessage recovered idle prompt readiness`);
|
|
30088
|
+
}
|
|
30089
|
+
}
|
|
29843
30090
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
29844
30091
|
if (this.isWaitingForResponse) return;
|
|
29845
|
-
await this.waitForInteractivePrompt();
|
|
29846
30092
|
const blockingModal = this.activeModal || this.getStartupConfirmationModal(this.terminalScreen.getText() || "");
|
|
29847
30093
|
if (blockingModal || this.currentStatus === "waiting_approval") {
|
|
29848
30094
|
throw new Error(`${this.cliName} is awaiting confirmation before it can accept a prompt`);
|
|
@@ -29886,8 +30132,6 @@ ${data.message || ""}`.trim();
|
|
|
29886
30132
|
}
|
|
29887
30133
|
this.responseEpoch += 1;
|
|
29888
30134
|
this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
|
|
29889
|
-
this.setStatus("generating", "sendMessage");
|
|
29890
|
-
this.onStatusChange?.();
|
|
29891
30135
|
const startResponseTimeout = () => {
|
|
29892
30136
|
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
29893
30137
|
this.responseTimeout = setTimeout(() => {
|
|
@@ -29906,7 +30150,7 @@ ${data.message || ""}`.trim();
|
|
|
29906
30150
|
const retrySubmitIfStuck = (attempt) => {
|
|
29907
30151
|
this.submitRetryTimer = null;
|
|
29908
30152
|
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
29909
|
-
if (this.currentStatus
|
|
30153
|
+
if (this.currentStatus === "waiting_approval") return;
|
|
29910
30154
|
if ((this.responseBuffer || "").trim()) return;
|
|
29911
30155
|
const screenText = this.terminalScreen.getText();
|
|
29912
30156
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
@@ -29941,7 +30185,7 @@ ${data.message || ""}`.trim();
|
|
|
29941
30185
|
this.submitRetryTimer = setTimeout(() => {
|
|
29942
30186
|
this.submitRetryTimer = null;
|
|
29943
30187
|
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
29944
|
-
if (this.currentStatus
|
|
30188
|
+
if (this.currentStatus === "waiting_approval") return;
|
|
29945
30189
|
if ((this.responseBuffer || "").trim()) return;
|
|
29946
30190
|
const screenText = this.terminalScreen.getText();
|
|
29947
30191
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
@@ -32355,198 +32599,93 @@ ${data.message || ""}`.trim();
|
|
|
32355
32599
|
}
|
|
32356
32600
|
}
|
|
32357
32601
|
};
|
|
32358
|
-
|
|
32359
|
-
|
|
32360
|
-
|
|
32361
|
-
|
|
32362
|
-
|
|
32363
|
-
|
|
32364
|
-
|
|
32365
|
-
|
|
32366
|
-
|
|
32367
|
-
|
|
32368
|
-
|
|
32369
|
-
|
|
32370
|
-
|
|
32371
|
-
|
|
32372
|
-
|
|
32373
|
-
|
|
32374
|
-
|
|
32375
|
-
|
|
32376
|
-
|
|
32377
|
-
|
|
32378
|
-
|
|
32379
|
-
|
|
32380
|
-
|
|
32381
|
-
|
|
32382
|
-
|
|
32383
|
-
|
|
32384
|
-
|
|
32385
|
-
|
|
32386
|
-
|
|
32387
|
-
|
|
32388
|
-
|
|
32389
|
-
|
|
32390
|
-
|
|
32391
|
-
|
|
32392
|
-
|
|
32393
|
-
|
|
32394
|
-
|
|
32395
|
-
|
|
32396
|
-
|
|
32397
|
-
|
|
32398
|
-
|
|
32399
|
-
|
|
32400
|
-
|
|
32401
|
-
}
|
|
32402
|
-
getState() {
|
|
32403
|
-
return {
|
|
32404
|
-
type: this.type,
|
|
32405
|
-
name: this.provider.name,
|
|
32406
|
-
category: "extension",
|
|
32407
|
-
status: this.currentStatus,
|
|
32408
|
-
activeChat: this.messages.length > 0 ? {
|
|
32409
|
-
id: this.chatId || this.instanceId,
|
|
32410
|
-
title: this.chatTitle || this.agentName || this.provider.name,
|
|
32411
|
-
status: this.currentStatus,
|
|
32412
|
-
messages: this.messages,
|
|
32413
|
-
activeModal: this.activeModal,
|
|
32414
|
-
inputContent: ""
|
|
32415
|
-
} : null,
|
|
32416
|
-
currentModel: this.currentModel || void 0,
|
|
32417
|
-
currentPlan: this.currentMode || void 0,
|
|
32418
|
-
controlValues: this.controlValues,
|
|
32419
|
-
providerControls: this.provider.controls,
|
|
32420
|
-
agentStreams: this.agentStreams,
|
|
32421
|
-
instanceId: this.instanceId,
|
|
32422
|
-
lastUpdated: Date.now(),
|
|
32423
|
-
settings: this.settings,
|
|
32424
|
-
pendingEvents: this.flushEvents()
|
|
32425
|
-
};
|
|
32426
|
-
}
|
|
32427
|
-
onEvent(event, data) {
|
|
32428
|
-
if (event === "stream_update") {
|
|
32429
|
-
if (data?.streams) this.agentStreams = data.streams;
|
|
32430
|
-
if (data?.messages) this.messages = data.messages;
|
|
32431
|
-
if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
|
|
32432
|
-
if (data?.model) this.currentModel = data.model;
|
|
32433
|
-
if (data?.mode) this.currentMode = data.mode;
|
|
32434
|
-
if (data?.controlValues) this.controlValues = data.controlValues;
|
|
32435
|
-
if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
|
|
32436
|
-
if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
|
|
32437
|
-
if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
|
|
32438
|
-
if (typeof data?.extensionId === "string" && data.extensionId.trim()) this.extensionId = data.extensionId;
|
|
32439
|
-
if (data?.status) {
|
|
32440
|
-
const newStatus = data.status;
|
|
32441
|
-
this.detectTransition(newStatus, data);
|
|
32442
|
-
this.currentStatus = newStatus;
|
|
32443
|
-
}
|
|
32444
|
-
} else if (event === "stream_reset") {
|
|
32445
|
-
this.resetStreamState();
|
|
32446
|
-
} else if (event === "extension_connected") {
|
|
32447
|
-
this.ideType = data?.ideType || "";
|
|
32602
|
+
function extractProviderControlValues(controls, data) {
|
|
32603
|
+
if (!data || typeof data !== "object") return void 0;
|
|
32604
|
+
const values = {};
|
|
32605
|
+
const explicit = data.controlValues;
|
|
32606
|
+
if (explicit && typeof explicit === "object") {
|
|
32607
|
+
for (const [key, value] of Object.entries(explicit)) {
|
|
32608
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
32609
|
+
values[key] = value;
|
|
32610
|
+
}
|
|
32611
|
+
}
|
|
32612
|
+
}
|
|
32613
|
+
for (const ctrl of controls || []) {
|
|
32614
|
+
if (!ctrl.readFrom) continue;
|
|
32615
|
+
const rawValue = data[ctrl.readFrom];
|
|
32616
|
+
if (rawValue === void 0 || rawValue === null) continue;
|
|
32617
|
+
values[ctrl.id] = normalizeControlValue(rawValue);
|
|
32618
|
+
}
|
|
32619
|
+
if (data.model !== void 0 && values.model === void 0) values.model = normalizeControlValue(data.model);
|
|
32620
|
+
if (data.mode !== void 0 && values.mode === void 0) values.mode = normalizeControlValue(data.mode);
|
|
32621
|
+
return Object.keys(values).length > 0 ? values : void 0;
|
|
32622
|
+
}
|
|
32623
|
+
function normalizeProviderEffects(data) {
|
|
32624
|
+
const rawEffects = Array.isArray(data?.effects) ? data.effects : [];
|
|
32625
|
+
const effects = [];
|
|
32626
|
+
for (const raw of rawEffects) {
|
|
32627
|
+
if (!raw || typeof raw !== "object") continue;
|
|
32628
|
+
const type = raw.type;
|
|
32629
|
+
if (type === "message" && raw.message && typeof raw.message === "object") {
|
|
32630
|
+
const content = raw.message.content;
|
|
32631
|
+
if (typeof content !== "string" && !Array.isArray(content)) continue;
|
|
32632
|
+
effects.push({
|
|
32633
|
+
type: "message",
|
|
32634
|
+
id: typeof raw.id === "string" ? raw.id : void 0,
|
|
32635
|
+
when: raw.when === "turn_completed" ? "turn_completed" : "immediate",
|
|
32636
|
+
persist: raw.persist !== false,
|
|
32637
|
+
message: {
|
|
32638
|
+
role: raw.message.role === "assistant" || raw.message.role === "user" ? raw.message.role : "system",
|
|
32639
|
+
content,
|
|
32640
|
+
kind: typeof raw.message.kind === "string" ? raw.message.kind : void 0,
|
|
32641
|
+
senderName: typeof raw.message.senderName === "string" ? raw.message.senderName : void 0
|
|
32642
|
+
}
|
|
32643
|
+
});
|
|
32644
|
+
continue;
|
|
32448
32645
|
}
|
|
32449
|
-
|
|
32450
|
-
|
|
32451
|
-
|
|
32452
|
-
|
|
32453
|
-
|
|
32454
|
-
|
|
32455
|
-
|
|
32456
|
-
|
|
32457
|
-
|
|
32458
|
-
|
|
32459
|
-
|
|
32460
|
-
|
|
32461
|
-
const now = Date.now();
|
|
32462
|
-
const agentStatus = newStatus === "streaming" || newStatus === "generating" ? "generating" : newStatus === "waiting_approval" ? "waiting_approval" : "idle";
|
|
32463
|
-
const lastMsg = Array.isArray(data?.messages) && data.messages.length > 0 ? data.messages[data.messages.length - 1] : null;
|
|
32464
|
-
const progressFingerprint = agentStatus === "generating" ? `${lastMsg?.role || ""}:${typeof lastMsg?.content === "string" ? lastMsg.content : JSON.stringify(lastMsg?.content || "")}`.slice(-2e3) : void 0;
|
|
32465
|
-
if (agentStatus !== this.lastAgentStatus) {
|
|
32466
|
-
if (this.lastAgentStatus === "idle" && agentStatus === "generating") {
|
|
32467
|
-
this.generatingStartedAt = now;
|
|
32468
|
-
this.pushEvent({
|
|
32469
|
-
event: "agent:generating_started",
|
|
32470
|
-
chatTitle: this.resolveChatTitle(data),
|
|
32471
|
-
timestamp: now,
|
|
32472
|
-
ideType: this.ideType || this.type,
|
|
32473
|
-
agentType: this.type,
|
|
32474
|
-
agentName: this.agentName || this.provider.name,
|
|
32475
|
-
extensionId: this.extensionId || this.type
|
|
32476
|
-
});
|
|
32477
|
-
} else if (agentStatus === "waiting_approval") {
|
|
32478
|
-
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
32479
|
-
this.pushEvent({
|
|
32480
|
-
event: "agent:waiting_approval",
|
|
32481
|
-
chatTitle: this.resolveChatTitle(data),
|
|
32482
|
-
timestamp: now,
|
|
32483
|
-
ideType: this.ideType || this.type,
|
|
32484
|
-
agentType: this.type,
|
|
32485
|
-
agentName: this.agentName || this.provider.name,
|
|
32486
|
-
extensionId: this.extensionId || this.type,
|
|
32487
|
-
modalMessage: data?.activeModal?.message,
|
|
32488
|
-
modalButtons: data?.activeModal?.buttons
|
|
32489
|
-
});
|
|
32490
|
-
} else if (agentStatus === "idle" && (this.lastAgentStatus === "generating" || this.lastAgentStatus === "waiting_approval")) {
|
|
32491
|
-
const duration3 = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
32492
|
-
this.pushEvent({
|
|
32493
|
-
event: "agent:generating_completed",
|
|
32494
|
-
chatTitle: this.resolveChatTitle(data),
|
|
32495
|
-
duration: duration3,
|
|
32496
|
-
timestamp: now,
|
|
32497
|
-
ideType: this.ideType || this.type,
|
|
32498
|
-
agentType: this.type,
|
|
32499
|
-
agentName: this.agentName || this.provider.name,
|
|
32500
|
-
extensionId: this.extensionId || this.type
|
|
32501
|
-
});
|
|
32502
|
-
this.generatingStartedAt = 0;
|
|
32503
|
-
}
|
|
32504
|
-
this.lastAgentStatus = agentStatus;
|
|
32646
|
+
if (type === "toast" && raw.toast && typeof raw.toast.message === "string") {
|
|
32647
|
+
effects.push({
|
|
32648
|
+
type: "toast",
|
|
32649
|
+
id: typeof raw.id === "string" ? raw.id : void 0,
|
|
32650
|
+
when: raw.when === "turn_completed" ? "turn_completed" : "immediate",
|
|
32651
|
+
persist: raw.persist !== false,
|
|
32652
|
+
toast: {
|
|
32653
|
+
level: raw.toast.level === "success" || raw.toast.level === "warning" ? raw.toast.level : "info",
|
|
32654
|
+
message: raw.toast.message
|
|
32655
|
+
}
|
|
32656
|
+
});
|
|
32657
|
+
continue;
|
|
32505
32658
|
}
|
|
32506
|
-
|
|
32507
|
-
|
|
32508
|
-
|
|
32509
|
-
|
|
32659
|
+
if (type === "notification" && raw.notification && typeof raw.notification.body === "string") {
|
|
32660
|
+
effects.push({
|
|
32661
|
+
type: "notification",
|
|
32662
|
+
id: typeof raw.id === "string" ? raw.id : void 0,
|
|
32663
|
+
when: raw.when === "turn_completed" ? "turn_completed" : "immediate",
|
|
32664
|
+
persist: raw.persist !== false,
|
|
32665
|
+
notification: {
|
|
32666
|
+
title: typeof raw.notification.title === "string" ? raw.notification.title : void 0,
|
|
32667
|
+
body: raw.notification.body,
|
|
32668
|
+
level: raw.notification.level === "success" || raw.notification.level === "warning" ? raw.notification.level : "info",
|
|
32669
|
+
channels: Array.isArray(raw.notification.channels) ? raw.notification.channels.filter((channel) => channel === "bubble" || channel === "toast" || channel === "browser") : void 0,
|
|
32670
|
+
preferenceKey: raw.notification.preferenceKey === "disconnect" || raw.notification.preferenceKey === "completion" || raw.notification.preferenceKey === "approval" || raw.notification.preferenceKey === "browser" ? raw.notification.preferenceKey : void 0,
|
|
32671
|
+
bubbleContent: typeof raw.notification.bubbleContent === "string" || Array.isArray(raw.notification.bubbleContent) ? raw.notification.bubbleContent : void 0
|
|
32672
|
+
}
|
|
32673
|
+
});
|
|
32510
32674
|
}
|
|
32511
32675
|
}
|
|
32512
|
-
|
|
32513
|
-
|
|
32514
|
-
|
|
32515
|
-
|
|
32516
|
-
|
|
32517
|
-
const events = [...this.events];
|
|
32518
|
-
this.events = [];
|
|
32519
|
-
return events;
|
|
32520
|
-
}
|
|
32521
|
-
resolveChatTitle(data) {
|
|
32522
|
-
const title = typeof data?.title === "string" && data.title.trim() ? data.title.trim() : this.chatTitle;
|
|
32523
|
-
return title || this.agentName || this.provider.name;
|
|
32676
|
+
return effects;
|
|
32677
|
+
}
|
|
32678
|
+
function normalizeControlValue(value) {
|
|
32679
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
32680
|
+
return value;
|
|
32524
32681
|
}
|
|
32525
|
-
|
|
32526
|
-
if (
|
|
32527
|
-
|
|
32528
|
-
|
|
32529
|
-
agentName: this.agentName,
|
|
32530
|
-
extensionId: this.extensionId,
|
|
32531
|
-
messages: this.messages
|
|
32532
|
-
});
|
|
32533
|
-
}
|
|
32534
|
-
this.agentStreams = [];
|
|
32535
|
-
this.messages = [];
|
|
32536
|
-
this.activeModal = null;
|
|
32537
|
-
this.currentModel = "";
|
|
32538
|
-
this.currentMode = "";
|
|
32539
|
-
this.controlValues = {};
|
|
32540
|
-
this.currentStatus = "idle";
|
|
32541
|
-
this.chatId = null;
|
|
32542
|
-
this.chatTitle = null;
|
|
32543
|
-
this.agentName = "";
|
|
32544
|
-
this.extensionId = "";
|
|
32545
|
-
this.lastAgentStatus = "idle";
|
|
32546
|
-
this.generatingStartedAt = 0;
|
|
32547
|
-
this.monitor.reset();
|
|
32682
|
+
if (value && typeof value === "object") {
|
|
32683
|
+
if (typeof value.label === "string") return value.label;
|
|
32684
|
+
if (typeof value.name === "string") return value.name;
|
|
32685
|
+
if (typeof value.id === "string") return value.id;
|
|
32548
32686
|
}
|
|
32549
|
-
|
|
32687
|
+
return String(value);
|
|
32688
|
+
}
|
|
32550
32689
|
var fs32 = __toESM2(require("fs"));
|
|
32551
32690
|
var path52 = __toESM2(require("path"));
|
|
32552
32691
|
var os52 = __toESM2(require("os"));
|
|
@@ -32797,28 +32936,355 @@ ${data.message || ""}`.trim();
|
|
|
32797
32936
|
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
32798
32937
|
}
|
|
32799
32938
|
}
|
|
32800
|
-
if (messageCount === 0 || !lastMessageAt) continue;
|
|
32801
|
-
summaries.push({
|
|
32802
|
-
historySessionId,
|
|
32803
|
-
sessionTitle: sessionTitle || void 0,
|
|
32804
|
-
messageCount,
|
|
32805
|
-
firstMessageAt,
|
|
32806
|
-
lastMessageAt,
|
|
32807
|
-
preview: preview || void 0
|
|
32939
|
+
if (messageCount === 0 || !lastMessageAt) continue;
|
|
32940
|
+
summaries.push({
|
|
32941
|
+
historySessionId,
|
|
32942
|
+
sessionTitle: sessionTitle || void 0,
|
|
32943
|
+
messageCount,
|
|
32944
|
+
firstMessageAt,
|
|
32945
|
+
lastMessageAt,
|
|
32946
|
+
preview: preview || void 0
|
|
32947
|
+
});
|
|
32948
|
+
}
|
|
32949
|
+
summaries.sort((a, b2) => b2.lastMessageAt - a.lastMessageAt);
|
|
32950
|
+
const offset = Math.max(0, options.offset || 0);
|
|
32951
|
+
const limit = Math.max(1, options.limit || 30);
|
|
32952
|
+
const sliced = summaries.slice(offset, offset + limit);
|
|
32953
|
+
return {
|
|
32954
|
+
sessions: sliced,
|
|
32955
|
+
hasMore: summaries.length > offset + limit
|
|
32956
|
+
};
|
|
32957
|
+
} catch {
|
|
32958
|
+
return { sessions: [], hasMore: false };
|
|
32959
|
+
}
|
|
32960
|
+
}
|
|
32961
|
+
var ExtensionProviderInstance = class {
|
|
32962
|
+
type;
|
|
32963
|
+
category = "extension";
|
|
32964
|
+
provider;
|
|
32965
|
+
context = null;
|
|
32966
|
+
settings = {};
|
|
32967
|
+
events = [];
|
|
32968
|
+
// status
|
|
32969
|
+
currentStatus = "idle";
|
|
32970
|
+
agentStreams = [];
|
|
32971
|
+
messages = [];
|
|
32972
|
+
activeModal = null;
|
|
32973
|
+
currentModel = "";
|
|
32974
|
+
currentMode = "";
|
|
32975
|
+
controlValues = {};
|
|
32976
|
+
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
32977
|
+
runtimeMessages = [];
|
|
32978
|
+
lastAgentStatus = "idle";
|
|
32979
|
+
generatingStartedAt = 0;
|
|
32980
|
+
monitor;
|
|
32981
|
+
historyWriter;
|
|
32982
|
+
// meta
|
|
32983
|
+
instanceId;
|
|
32984
|
+
ideType = "";
|
|
32985
|
+
chatId = null;
|
|
32986
|
+
chatTitle = null;
|
|
32987
|
+
agentName = "";
|
|
32988
|
+
extensionId = "";
|
|
32989
|
+
constructor(provider) {
|
|
32990
|
+
this.type = provider.type;
|
|
32991
|
+
this.provider = provider;
|
|
32992
|
+
this.instanceId = crypto.randomUUID();
|
|
32993
|
+
this.monitor = new StatusMonitor();
|
|
32994
|
+
this.historyWriter = new ChatHistoryWriter();
|
|
32995
|
+
}
|
|
32996
|
+
// ─── Lifecycle ──────────────────────────────────
|
|
32997
|
+
async init(context) {
|
|
32998
|
+
this.context = context;
|
|
32999
|
+
this.settings = context.settings || {};
|
|
33000
|
+
this.monitor.updateConfig({
|
|
33001
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
33002
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
33003
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
33004
|
+
});
|
|
33005
|
+
}
|
|
33006
|
+
async onTick() {
|
|
33007
|
+
if (!this.context?.cdp?.isConnected) return;
|
|
33008
|
+
}
|
|
33009
|
+
getState() {
|
|
33010
|
+
return {
|
|
33011
|
+
type: this.type,
|
|
33012
|
+
name: this.provider.name,
|
|
33013
|
+
category: "extension",
|
|
33014
|
+
status: this.currentStatus,
|
|
33015
|
+
activeChat: this.messages.length > 0 || this.runtimeMessages.length > 0 ? {
|
|
33016
|
+
id: this.chatId || this.instanceId,
|
|
33017
|
+
title: this.chatTitle || this.agentName || this.provider.name,
|
|
33018
|
+
status: this.currentStatus,
|
|
33019
|
+
messages: this.mergeConversationMessages(this.messages),
|
|
33020
|
+
activeModal: this.activeModal,
|
|
33021
|
+
inputContent: ""
|
|
33022
|
+
} : null,
|
|
33023
|
+
currentModel: this.currentModel || void 0,
|
|
33024
|
+
currentPlan: this.currentMode || void 0,
|
|
33025
|
+
controlValues: this.controlValues,
|
|
33026
|
+
providerControls: this.provider.controls,
|
|
33027
|
+
agentStreams: this.agentStreams,
|
|
33028
|
+
instanceId: this.instanceId,
|
|
33029
|
+
lastUpdated: Date.now(),
|
|
33030
|
+
settings: this.settings,
|
|
33031
|
+
pendingEvents: this.flushEvents()
|
|
33032
|
+
};
|
|
33033
|
+
}
|
|
33034
|
+
onEvent(event, data) {
|
|
33035
|
+
if (event === "stream_update") {
|
|
33036
|
+
if (data?.streams) this.agentStreams = data.streams;
|
|
33037
|
+
if (data?.messages) this.messages = data.messages;
|
|
33038
|
+
if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
|
|
33039
|
+
if (data?.model) this.currentModel = data.model;
|
|
33040
|
+
if (data?.mode) this.currentMode = data.mode;
|
|
33041
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data) || data?.controlValues;
|
|
33042
|
+
if (controlValues) this.controlValues = controlValues;
|
|
33043
|
+
if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
|
|
33044
|
+
if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
|
|
33045
|
+
if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
|
|
33046
|
+
if (typeof data?.extensionId === "string" && data.extensionId.trim()) this.extensionId = data.extensionId;
|
|
33047
|
+
if (data?.status) {
|
|
33048
|
+
const newStatus = data.status;
|
|
33049
|
+
this.detectTransition(newStatus, data);
|
|
33050
|
+
this.currentStatus = newStatus;
|
|
33051
|
+
}
|
|
33052
|
+
} else if (event === "stream_reset") {
|
|
33053
|
+
this.resetStreamState();
|
|
33054
|
+
} else if (event === "extension_connected") {
|
|
33055
|
+
this.ideType = data?.ideType || "";
|
|
33056
|
+
} else if (event === "provider_state_patch" && data && typeof data === "object") {
|
|
33057
|
+
this.applyProviderResponse(data, { phase: "immediate" });
|
|
33058
|
+
}
|
|
33059
|
+
}
|
|
33060
|
+
dispose() {
|
|
33061
|
+
this.agentStreams = [];
|
|
33062
|
+
this.messages = [];
|
|
33063
|
+
this.monitor.reset();
|
|
33064
|
+
this.appliedEffectKeys.clear();
|
|
33065
|
+
this.runtimeMessages = [];
|
|
33066
|
+
}
|
|
33067
|
+
updateSettings(newSettings) {
|
|
33068
|
+
this.settings = { ...newSettings };
|
|
33069
|
+
this.monitor.updateConfig({
|
|
33070
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
33071
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
33072
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
33073
|
+
});
|
|
33074
|
+
}
|
|
33075
|
+
/** Query UUID instanceId */
|
|
33076
|
+
getInstanceId() {
|
|
33077
|
+
return this.instanceId;
|
|
33078
|
+
}
|
|
33079
|
+
// ─── status transition detect ──────────────────────────────
|
|
33080
|
+
detectTransition(newStatus, data) {
|
|
33081
|
+
const now = Date.now();
|
|
33082
|
+
const agentStatus = newStatus === "streaming" || newStatus === "generating" ? "generating" : newStatus === "waiting_approval" ? "waiting_approval" : "idle";
|
|
33083
|
+
const lastMsg = Array.isArray(data?.messages) && data.messages.length > 0 ? data.messages[data.messages.length - 1] : null;
|
|
33084
|
+
const progressFingerprint = agentStatus === "generating" ? `${lastMsg?.role || ""}:${typeof lastMsg?.content === "string" ? lastMsg.content : JSON.stringify(lastMsg?.content || "")}`.slice(-2e3) : void 0;
|
|
33085
|
+
const previousStatus = this.lastAgentStatus;
|
|
33086
|
+
if (agentStatus !== this.lastAgentStatus) {
|
|
33087
|
+
if (this.lastAgentStatus === "idle" && agentStatus === "generating") {
|
|
33088
|
+
this.generatingStartedAt = now;
|
|
33089
|
+
this.pushEvent({
|
|
33090
|
+
event: "agent:generating_started",
|
|
33091
|
+
chatTitle: this.resolveChatTitle(data),
|
|
33092
|
+
timestamp: now,
|
|
33093
|
+
ideType: this.ideType || this.type,
|
|
33094
|
+
agentType: this.type,
|
|
33095
|
+
agentName: this.agentName || this.provider.name,
|
|
33096
|
+
extensionId: this.extensionId || this.type
|
|
33097
|
+
});
|
|
33098
|
+
} else if (agentStatus === "waiting_approval") {
|
|
33099
|
+
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
33100
|
+
this.pushEvent({
|
|
33101
|
+
event: "agent:waiting_approval",
|
|
33102
|
+
chatTitle: this.resolveChatTitle(data),
|
|
33103
|
+
timestamp: now,
|
|
33104
|
+
ideType: this.ideType || this.type,
|
|
33105
|
+
agentType: this.type,
|
|
33106
|
+
agentName: this.agentName || this.provider.name,
|
|
33107
|
+
extensionId: this.extensionId || this.type,
|
|
33108
|
+
modalMessage: data?.activeModal?.message,
|
|
33109
|
+
modalButtons: data?.activeModal?.buttons
|
|
33110
|
+
});
|
|
33111
|
+
} else if (agentStatus === "idle" && (this.lastAgentStatus === "generating" || this.lastAgentStatus === "waiting_approval")) {
|
|
33112
|
+
const duration3 = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
33113
|
+
this.pushEvent({
|
|
33114
|
+
event: "agent:generating_completed",
|
|
33115
|
+
chatTitle: this.resolveChatTitle(data),
|
|
33116
|
+
duration: duration3,
|
|
33117
|
+
timestamp: now,
|
|
33118
|
+
ideType: this.ideType || this.type,
|
|
33119
|
+
agentType: this.type,
|
|
33120
|
+
agentName: this.agentName || this.provider.name,
|
|
33121
|
+
extensionId: this.extensionId || this.type
|
|
33122
|
+
});
|
|
33123
|
+
this.generatingStartedAt = 0;
|
|
33124
|
+
}
|
|
33125
|
+
this.lastAgentStatus = agentStatus;
|
|
33126
|
+
}
|
|
33127
|
+
this.applyProviderResponse(data, {
|
|
33128
|
+
phase: agentStatus === "idle" && (previousStatus === "generating" || previousStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
33129
|
+
});
|
|
33130
|
+
const agentKey = `${this.type}:ext`;
|
|
33131
|
+
const monitorEvents = this.monitor.check(agentKey, agentStatus, now, progressFingerprint);
|
|
33132
|
+
for (const me of monitorEvents) {
|
|
33133
|
+
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
33134
|
+
}
|
|
33135
|
+
}
|
|
33136
|
+
pushEvent(event) {
|
|
33137
|
+
this.events.push(event);
|
|
33138
|
+
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
33139
|
+
}
|
|
33140
|
+
applyProviderResponse(data, options) {
|
|
33141
|
+
if (!data || typeof data !== "object") return;
|
|
33142
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
33143
|
+
if (controlValues) this.controlValues = { ...this.controlValues, ...controlValues };
|
|
33144
|
+
const effects = normalizeProviderEffects(data);
|
|
33145
|
+
for (const effect of effects) {
|
|
33146
|
+
const effectWhen = effect.when || "immediate";
|
|
33147
|
+
if (effectWhen === "turn_completed" && options.phase !== "turn_completed") continue;
|
|
33148
|
+
if (effectWhen === "immediate" && options.phase === "turn_completed") continue;
|
|
33149
|
+
const effectKey = this.getEffectDedupKey(effect);
|
|
33150
|
+
if (this.appliedEffectKeys.has(effectKey)) continue;
|
|
33151
|
+
this.appliedEffectKeys.add(effectKey);
|
|
33152
|
+
if (effect.persist !== false) {
|
|
33153
|
+
const persisted = this.getPersistedEffectContent(effect);
|
|
33154
|
+
if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
|
|
33155
|
+
}
|
|
33156
|
+
if (effect.type === "message" && effect.message) {
|
|
33157
|
+
this.pushEvent({
|
|
33158
|
+
event: "provider:message",
|
|
33159
|
+
timestamp: Date.now(),
|
|
33160
|
+
content: typeof effect.message.content === "string" ? effect.message.content : JSON.stringify(effect.message.content),
|
|
33161
|
+
role: effect.message.role || "system",
|
|
33162
|
+
kind: effect.message.kind,
|
|
33163
|
+
senderName: effect.message.senderName
|
|
33164
|
+
});
|
|
33165
|
+
} else if (effect.type === "toast" && effect.toast) {
|
|
33166
|
+
this.pushEvent({
|
|
33167
|
+
event: "provider:toast",
|
|
33168
|
+
effectId: effect.id || effectKey,
|
|
33169
|
+
timestamp: Date.now(),
|
|
33170
|
+
message: effect.toast.message,
|
|
33171
|
+
level: effect.toast.level || "info"
|
|
33172
|
+
});
|
|
33173
|
+
} else if (effect.type === "notification" && effect.notification) {
|
|
33174
|
+
this.pushEvent({
|
|
33175
|
+
event: "provider:notification",
|
|
33176
|
+
effectId: effect.id || effectKey,
|
|
33177
|
+
timestamp: Date.now(),
|
|
33178
|
+
title: effect.notification.title,
|
|
33179
|
+
message: effect.notification.body,
|
|
33180
|
+
content: typeof effect.notification.bubbleContent === "string" ? effect.notification.bubbleContent : effect.notification.body,
|
|
33181
|
+
level: effect.notification.level || "info",
|
|
33182
|
+
channels: effect.notification.channels || ["toast"],
|
|
33183
|
+
preferenceKey: effect.notification.preferenceKey
|
|
33184
|
+
});
|
|
33185
|
+
}
|
|
33186
|
+
}
|
|
33187
|
+
}
|
|
33188
|
+
appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
|
|
33189
|
+
const normalizedContent = String(content || "").trim();
|
|
33190
|
+
if (!normalizedContent) return;
|
|
33191
|
+
if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
|
|
33192
|
+
this.runtimeMessages.push({
|
|
33193
|
+
key: dedupKey,
|
|
33194
|
+
message: {
|
|
33195
|
+
role: "system",
|
|
33196
|
+
senderName: "System",
|
|
33197
|
+
content: normalizedContent,
|
|
33198
|
+
receivedAt,
|
|
33199
|
+
timestamp: receivedAt
|
|
33200
|
+
}
|
|
33201
|
+
});
|
|
33202
|
+
if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
|
|
33203
|
+
this.historyWriter.appendNewMessages(
|
|
33204
|
+
this.type,
|
|
33205
|
+
[{
|
|
33206
|
+
role: "system",
|
|
33207
|
+
senderName: "System",
|
|
33208
|
+
content: normalizedContent,
|
|
33209
|
+
kind: "system",
|
|
33210
|
+
receivedAt,
|
|
33211
|
+
historyDedupKey: dedupKey
|
|
33212
|
+
}],
|
|
33213
|
+
this.chatTitle || this.agentName || this.provider.name,
|
|
33214
|
+
this.instanceId,
|
|
33215
|
+
this.chatId || this.instanceId
|
|
33216
|
+
);
|
|
33217
|
+
}
|
|
33218
|
+
mergeConversationMessages(messages) {
|
|
33219
|
+
if (this.runtimeMessages.length === 0) return messages;
|
|
33220
|
+
return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
|
|
33221
|
+
const aTime = a.message.receivedAt || a.message.timestamp || 0;
|
|
33222
|
+
const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
|
|
33223
|
+
if (aTime !== bTime) return aTime - bTime;
|
|
33224
|
+
return a.index - b2.index;
|
|
33225
|
+
}).map((entry) => entry.message);
|
|
33226
|
+
}
|
|
33227
|
+
getPersistedEffectContent(effect) {
|
|
33228
|
+
if (effect.type === "message") {
|
|
33229
|
+
return typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
33230
|
+
}
|
|
33231
|
+
if (effect.type === "toast") {
|
|
33232
|
+
return effect.toast?.message || null;
|
|
33233
|
+
}
|
|
33234
|
+
if (effect.type === "notification") {
|
|
33235
|
+
if (typeof effect.notification?.bubbleContent === "string") return effect.notification.bubbleContent;
|
|
33236
|
+
if (typeof effect.notification?.title === "string" && effect.notification.title.trim()) {
|
|
33237
|
+
return `${effect.notification.title}
|
|
33238
|
+
${effect.notification.body || ""}`.trim();
|
|
33239
|
+
}
|
|
33240
|
+
return effect.notification?.body || null;
|
|
33241
|
+
}
|
|
33242
|
+
return null;
|
|
33243
|
+
}
|
|
33244
|
+
getEffectDedupKey(effect) {
|
|
33245
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
33246
|
+
if (effect.type === "message") {
|
|
33247
|
+
return `provider_effect:message:${typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "")}`;
|
|
33248
|
+
}
|
|
33249
|
+
if (effect.type === "notification") {
|
|
33250
|
+
return `provider_effect:notification:${effect.notification?.title || ""}:${effect.notification?.body || ""}`;
|
|
33251
|
+
}
|
|
33252
|
+
return `provider_effect:toast:${effect.toast?.message || ""}`;
|
|
33253
|
+
}
|
|
33254
|
+
flushEvents() {
|
|
33255
|
+
const events = [...this.events];
|
|
33256
|
+
this.events = [];
|
|
33257
|
+
return events;
|
|
33258
|
+
}
|
|
33259
|
+
resolveChatTitle(data) {
|
|
33260
|
+
const title = typeof data?.title === "string" && data.title.trim() ? data.title.trim() : this.chatTitle;
|
|
33261
|
+
return title || this.agentName || this.provider.name;
|
|
33262
|
+
}
|
|
33263
|
+
resetStreamState() {
|
|
33264
|
+
if (this.currentStatus !== "idle") {
|
|
33265
|
+
this.detectTransition("idle", {
|
|
33266
|
+
title: this.chatTitle,
|
|
33267
|
+
agentName: this.agentName,
|
|
33268
|
+
extensionId: this.extensionId,
|
|
33269
|
+
messages: this.messages
|
|
32808
33270
|
});
|
|
32809
33271
|
}
|
|
32810
|
-
|
|
32811
|
-
|
|
32812
|
-
|
|
32813
|
-
|
|
32814
|
-
|
|
32815
|
-
|
|
32816
|
-
|
|
32817
|
-
|
|
32818
|
-
|
|
32819
|
-
|
|
33272
|
+
this.agentStreams = [];
|
|
33273
|
+
this.messages = [];
|
|
33274
|
+
this.activeModal = null;
|
|
33275
|
+
this.currentModel = "";
|
|
33276
|
+
this.currentMode = "";
|
|
33277
|
+
this.controlValues = {};
|
|
33278
|
+
this.currentStatus = "idle";
|
|
33279
|
+
this.chatId = null;
|
|
33280
|
+
this.chatTitle = null;
|
|
33281
|
+
this.agentName = "";
|
|
33282
|
+
this.extensionId = "";
|
|
33283
|
+
this.lastAgentStatus = "idle";
|
|
33284
|
+
this.generatingStartedAt = 0;
|
|
33285
|
+
this.monitor.reset();
|
|
32820
33286
|
}
|
|
32821
|
-
}
|
|
33287
|
+
};
|
|
32822
33288
|
init_logger();
|
|
32823
33289
|
var IdeProviderInstance = class {
|
|
32824
33290
|
type;
|
|
@@ -32837,6 +33303,8 @@ ${data.message || ""}`.trim();
|
|
|
32837
33303
|
monitor;
|
|
32838
33304
|
historyWriter;
|
|
32839
33305
|
autoApproveBusy = false;
|
|
33306
|
+
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
33307
|
+
runtimeMessages = [];
|
|
32840
33308
|
// IDE meta
|
|
32841
33309
|
ideVersion = "";
|
|
32842
33310
|
instanceId;
|
|
@@ -32897,7 +33365,7 @@ ${data.message || ""}`.trim();
|
|
|
32897
33365
|
id: this.cachedChat.id || "active_session",
|
|
32898
33366
|
title: this.cachedChat.title || this.type,
|
|
32899
33367
|
status: this.cachedChat.status || this.currentStatus,
|
|
32900
|
-
messages: this.cachedChat.messages || [],
|
|
33368
|
+
messages: this.mergeConversationMessages(this.cachedChat.messages || []),
|
|
32901
33369
|
activeModal: this.cachedChat.activeModal || null,
|
|
32902
33370
|
inputContent: this.cachedChat.inputContent || ""
|
|
32903
33371
|
} : null,
|
|
@@ -32937,6 +33405,13 @@ ${data.message || ""}`.trim();
|
|
|
32937
33405
|
for (const ext of this.extensions.values()) {
|
|
32938
33406
|
ext.onEvent("stream_reset");
|
|
32939
33407
|
}
|
|
33408
|
+
} else if (event === "provider_state_patch" && data && typeof data === "object") {
|
|
33409
|
+
const extType = typeof data.extensionType === "string" ? data.extensionType : "";
|
|
33410
|
+
if (extType && this.extensions.has(extType)) {
|
|
33411
|
+
this.extensions.get(extType).onEvent("provider_state_patch", data);
|
|
33412
|
+
} else {
|
|
33413
|
+
this.applyProviderResponse(data, { phase: "immediate" });
|
|
33414
|
+
}
|
|
32940
33415
|
}
|
|
32941
33416
|
}
|
|
32942
33417
|
dispose() {
|
|
@@ -32944,11 +33419,21 @@ ${data.message || ""}`.trim();
|
|
|
32944
33419
|
this.lastAgentStatuses.clear();
|
|
32945
33420
|
this.generatingStartedAt.clear();
|
|
32946
33421
|
this.monitor.reset();
|
|
33422
|
+
this.appliedEffectKeys.clear();
|
|
33423
|
+
this.runtimeMessages = [];
|
|
32947
33424
|
for (const ext of this.extensions.values()) {
|
|
32948
33425
|
ext.dispose();
|
|
32949
33426
|
}
|
|
32950
33427
|
this.extensions.clear();
|
|
32951
33428
|
}
|
|
33429
|
+
updateSettings(newSettings) {
|
|
33430
|
+
this.settings = { ...newSettings };
|
|
33431
|
+
this.monitor.updateConfig({
|
|
33432
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
33433
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
33434
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
33435
|
+
});
|
|
33436
|
+
}
|
|
32952
33437
|
// ─── Extension manage ─────────────────────────────
|
|
32953
33438
|
/** Extension Instance add */
|
|
32954
33439
|
async addExtension(provider, settings) {
|
|
@@ -33061,6 +33546,8 @@ ${data.message || ""}`.trim();
|
|
|
33061
33546
|
raw.messages = raw.messages.filter((m) => !hiddenKinds.has(m.kind));
|
|
33062
33547
|
}
|
|
33063
33548
|
}
|
|
33549
|
+
const controlValues = extractProviderControlValues(this.provider.controls, raw);
|
|
33550
|
+
if (controlValues) raw.controlValues = controlValues;
|
|
33064
33551
|
this.cachedChat = { ...raw, activeModal };
|
|
33065
33552
|
this.detectAgentTransitions(raw, now);
|
|
33066
33553
|
if (raw.messages?.length > 0) {
|
|
@@ -33127,6 +33614,9 @@ ${data.message || ""}`.trim();
|
|
|
33127
33614
|
}
|
|
33128
33615
|
this.lastAgentStatuses.set(agentKey, agentStatus);
|
|
33129
33616
|
}
|
|
33617
|
+
this.applyProviderResponse(chatData, {
|
|
33618
|
+
phase: agentStatus === "idle" && (lastStatus === "generating" || lastStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
33619
|
+
});
|
|
33130
33620
|
if (agentStatus === "waiting_approval" && this.settings.autoApprove && !this.autoApproveBusy) {
|
|
33131
33621
|
this.autoApproveViaScript(chatData);
|
|
33132
33622
|
}
|
|
@@ -33139,6 +33629,136 @@ ${data.message || ""}`.trim();
|
|
|
33139
33629
|
this.events.push(event);
|
|
33140
33630
|
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
33141
33631
|
}
|
|
33632
|
+
applyProviderResponse(data, options) {
|
|
33633
|
+
if (!data || typeof data !== "object") return;
|
|
33634
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
33635
|
+
if (controlValues) {
|
|
33636
|
+
this.cachedChat = {
|
|
33637
|
+
...this.cachedChat || {},
|
|
33638
|
+
...data,
|
|
33639
|
+
controlValues: { ...this.cachedChat?.controlValues || {}, ...controlValues }
|
|
33640
|
+
};
|
|
33641
|
+
}
|
|
33642
|
+
const effects = normalizeProviderEffects(data);
|
|
33643
|
+
for (const effect of effects) {
|
|
33644
|
+
const effectWhen = effect.when || "immediate";
|
|
33645
|
+
if (effectWhen === "turn_completed" && options.phase !== "turn_completed") continue;
|
|
33646
|
+
if (effectWhen === "immediate" && options.phase === "turn_completed") continue;
|
|
33647
|
+
const effectKey = this.getEffectDedupKey(effect);
|
|
33648
|
+
if (this.appliedEffectKeys.has(effectKey)) continue;
|
|
33649
|
+
this.appliedEffectKeys.add(effectKey);
|
|
33650
|
+
if (effect.persist !== false) {
|
|
33651
|
+
const persisted = this.getPersistedEffectContent(effect);
|
|
33652
|
+
if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
|
|
33653
|
+
}
|
|
33654
|
+
if (effect.type === "message" && effect.message) {
|
|
33655
|
+
this.pushEvent({
|
|
33656
|
+
event: "provider:message",
|
|
33657
|
+
timestamp: Date.now(),
|
|
33658
|
+
content: typeof effect.message.content === "string" ? effect.message.content : JSON.stringify(effect.message.content),
|
|
33659
|
+
role: effect.message.role || "system",
|
|
33660
|
+
kind: effect.message.kind,
|
|
33661
|
+
senderName: effect.message.senderName
|
|
33662
|
+
});
|
|
33663
|
+
} else if (effect.type === "toast" && effect.toast) {
|
|
33664
|
+
this.pushEvent({
|
|
33665
|
+
event: "provider:toast",
|
|
33666
|
+
effectId: effect.id || effectKey,
|
|
33667
|
+
timestamp: Date.now(),
|
|
33668
|
+
message: effect.toast.message,
|
|
33669
|
+
level: effect.toast.level || "info"
|
|
33670
|
+
});
|
|
33671
|
+
} else if (effect.type === "notification" && effect.notification) {
|
|
33672
|
+
this.pushEvent({
|
|
33673
|
+
event: "provider:notification",
|
|
33674
|
+
effectId: effect.id || effectKey,
|
|
33675
|
+
timestamp: Date.now(),
|
|
33676
|
+
title: effect.notification.title,
|
|
33677
|
+
message: effect.notification.body,
|
|
33678
|
+
content: typeof effect.notification.bubbleContent === "string" ? effect.notification.bubbleContent : effect.notification.body,
|
|
33679
|
+
level: effect.notification.level || "info",
|
|
33680
|
+
channels: effect.notification.channels || ["toast"],
|
|
33681
|
+
preferenceKey: effect.notification.preferenceKey
|
|
33682
|
+
});
|
|
33683
|
+
}
|
|
33684
|
+
}
|
|
33685
|
+
}
|
|
33686
|
+
appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
|
|
33687
|
+
const normalizedContent = String(content || "").trim();
|
|
33688
|
+
if (!normalizedContent) return;
|
|
33689
|
+
if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
|
|
33690
|
+
if (!this.cachedChat) {
|
|
33691
|
+
this.cachedChat = {
|
|
33692
|
+
id: "active_session",
|
|
33693
|
+
title: this.provider.name,
|
|
33694
|
+
status: this.currentStatus,
|
|
33695
|
+
messages: [],
|
|
33696
|
+
activeModal: null,
|
|
33697
|
+
inputContent: ""
|
|
33698
|
+
};
|
|
33699
|
+
}
|
|
33700
|
+
this.runtimeMessages.push({
|
|
33701
|
+
key: dedupKey,
|
|
33702
|
+
message: {
|
|
33703
|
+
role: "system",
|
|
33704
|
+
senderName: "System",
|
|
33705
|
+
content: normalizedContent,
|
|
33706
|
+
receivedAt,
|
|
33707
|
+
timestamp: receivedAt
|
|
33708
|
+
}
|
|
33709
|
+
});
|
|
33710
|
+
if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
|
|
33711
|
+
this.historyWriter.appendNewMessages(
|
|
33712
|
+
this.type,
|
|
33713
|
+
[{
|
|
33714
|
+
role: "system",
|
|
33715
|
+
senderName: "System",
|
|
33716
|
+
content: normalizedContent,
|
|
33717
|
+
kind: "system",
|
|
33718
|
+
receivedAt,
|
|
33719
|
+
historyDedupKey: dedupKey
|
|
33720
|
+
}],
|
|
33721
|
+
this.cachedChat?.title || this.provider.name,
|
|
33722
|
+
this.instanceId,
|
|
33723
|
+
this.cachedChat?.id || this.instanceId
|
|
33724
|
+
);
|
|
33725
|
+
}
|
|
33726
|
+
mergeConversationMessages(messages) {
|
|
33727
|
+
if (this.runtimeMessages.length === 0) return messages;
|
|
33728
|
+
return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b2) => {
|
|
33729
|
+
const aTime = a.message.receivedAt || a.message.timestamp || 0;
|
|
33730
|
+
const bTime = b2.message.receivedAt || b2.message.timestamp || 0;
|
|
33731
|
+
if (aTime !== bTime) return aTime - bTime;
|
|
33732
|
+
return a.index - b2.index;
|
|
33733
|
+
}).map((entry) => entry.message);
|
|
33734
|
+
}
|
|
33735
|
+
getPersistedEffectContent(effect) {
|
|
33736
|
+
if (effect.type === "message") {
|
|
33737
|
+
return typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
33738
|
+
}
|
|
33739
|
+
if (effect.type === "toast") {
|
|
33740
|
+
return effect.toast?.message || null;
|
|
33741
|
+
}
|
|
33742
|
+
if (effect.type === "notification") {
|
|
33743
|
+
if (typeof effect.notification?.bubbleContent === "string") return effect.notification.bubbleContent;
|
|
33744
|
+
if (typeof effect.notification?.title === "string" && effect.notification.title.trim()) {
|
|
33745
|
+
return `${effect.notification.title}
|
|
33746
|
+
${effect.notification.body || ""}`.trim();
|
|
33747
|
+
}
|
|
33748
|
+
return effect.notification?.body || null;
|
|
33749
|
+
}
|
|
33750
|
+
return null;
|
|
33751
|
+
}
|
|
33752
|
+
getEffectDedupKey(effect) {
|
|
33753
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
33754
|
+
if (effect.type === "message") {
|
|
33755
|
+
return `provider_effect:message:${typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "")}`;
|
|
33756
|
+
}
|
|
33757
|
+
if (effect.type === "notification") {
|
|
33758
|
+
return `provider_effect:notification:${effect.notification?.title || ""}:${effect.notification?.body || ""}`;
|
|
33759
|
+
}
|
|
33760
|
+
return `provider_effect:toast:${effect.toast?.message || ""}`;
|
|
33761
|
+
}
|
|
33142
33762
|
flushEvents() {
|
|
33143
33763
|
const events = [...this.events];
|
|
33144
33764
|
this.events = [];
|
|
@@ -34009,6 +34629,24 @@ ${data.message || ""}`.trim();
|
|
|
34009
34629
|
recentSendByTarget.set(key, now);
|
|
34010
34630
|
return false;
|
|
34011
34631
|
}
|
|
34632
|
+
function parseMaybeJson(value) {
|
|
34633
|
+
if (typeof value !== "string") return value;
|
|
34634
|
+
try {
|
|
34635
|
+
return JSON.parse(value);
|
|
34636
|
+
} catch {
|
|
34637
|
+
return value;
|
|
34638
|
+
}
|
|
34639
|
+
}
|
|
34640
|
+
function didProviderConfirmSend(result) {
|
|
34641
|
+
const parsed = parseMaybeJson(result);
|
|
34642
|
+
if (parsed === true) return true;
|
|
34643
|
+
if (typeof parsed === "string") {
|
|
34644
|
+
const normalized = parsed.trim().toLowerCase();
|
|
34645
|
+
return normalized === "ok" || normalized === "sent" || normalized === "success" || normalized === "true";
|
|
34646
|
+
}
|
|
34647
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
34648
|
+
return parsed.sent === true || parsed.success === true || parsed.ok === true || parsed.submitted === true || parsed.dispatched === true;
|
|
34649
|
+
}
|
|
34012
34650
|
async function handleChatHistory(h, args) {
|
|
34013
34651
|
const { agentType, offset, limit } = args;
|
|
34014
34652
|
const historySessionId = getHistorySessionId(h, args);
|
|
@@ -34191,14 +34829,8 @@ ${data.message || ""}`.trim();
|
|
|
34191
34829
|
try {
|
|
34192
34830
|
const evalResult = await h.evaluateProviderScript("sendMessage", { MESSAGE: text }, 3e4);
|
|
34193
34831
|
if (evalResult?.result) {
|
|
34194
|
-
|
|
34195
|
-
if (
|
|
34196
|
-
try {
|
|
34197
|
-
parsed = JSON.parse(parsed);
|
|
34198
|
-
} catch {
|
|
34199
|
-
}
|
|
34200
|
-
}
|
|
34201
|
-
if (parsed?.sent) {
|
|
34832
|
+
const parsed = parseMaybeJson(evalResult.result);
|
|
34833
|
+
if (didProviderConfirmSend(parsed)) {
|
|
34202
34834
|
_log(`Extension script sent OK`);
|
|
34203
34835
|
return _logSendSuccess("extension-script");
|
|
34204
34836
|
}
|
|
@@ -34230,14 +34862,8 @@ ${data.message || ""}`.trim();
|
|
|
34230
34862
|
if (sendScript) {
|
|
34231
34863
|
try {
|
|
34232
34864
|
const result = await targetCdp.evaluate(sendScript, 3e4);
|
|
34233
|
-
|
|
34234
|
-
if (
|
|
34235
|
-
try {
|
|
34236
|
-
parsed = JSON.parse(result);
|
|
34237
|
-
} catch {
|
|
34238
|
-
}
|
|
34239
|
-
}
|
|
34240
|
-
if (parsed?.sent) {
|
|
34865
|
+
const parsed = parseMaybeJson(result);
|
|
34866
|
+
if (didProviderConfirmSend(parsed)) {
|
|
34241
34867
|
_log(`sendMessage script OK`);
|
|
34242
34868
|
return _logSendSuccess("script");
|
|
34243
34869
|
}
|
|
@@ -34282,14 +34908,8 @@ ${data.message || ""}`.trim();
|
|
|
34282
34908
|
const matchText = provider.webviewMatchText;
|
|
34283
34909
|
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
34284
34910
|
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
34285
|
-
|
|
34286
|
-
if (
|
|
34287
|
-
try {
|
|
34288
|
-
wvParsed = JSON.parse(wvResult);
|
|
34289
|
-
} catch {
|
|
34290
|
-
}
|
|
34291
|
-
}
|
|
34292
|
-
if (wvParsed?.sent) {
|
|
34911
|
+
const wvParsed = parseMaybeJson(wvResult);
|
|
34912
|
+
if (didProviderConfirmSend(wvParsed)) {
|
|
34293
34913
|
_log(`webviewSendMessage OK`);
|
|
34294
34914
|
return _logSendSuccess("webview-script");
|
|
34295
34915
|
}
|
|
@@ -34311,14 +34931,8 @@ ${data.message || ""}`.trim();
|
|
|
34311
34931
|
const matchText = provider.webviewMatchText;
|
|
34312
34932
|
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
34313
34933
|
const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
34314
|
-
|
|
34315
|
-
if (
|
|
34316
|
-
try {
|
|
34317
|
-
wvParsed = JSON.parse(wvResult);
|
|
34318
|
-
} catch {
|
|
34319
|
-
}
|
|
34320
|
-
}
|
|
34321
|
-
if (wvParsed?.sent) {
|
|
34934
|
+
const wvParsed = parseMaybeJson(wvResult);
|
|
34935
|
+
if (didProviderConfirmSend(wvParsed)) {
|
|
34322
34936
|
_log(`webviewSendMessage OK`);
|
|
34323
34937
|
return _logSendSuccess("webview-script");
|
|
34324
34938
|
}
|
|
@@ -35200,7 +35814,56 @@ ${data.message || ""}`.trim();
|
|
|
35200
35814
|
}
|
|
35201
35815
|
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
35202
35816
|
}
|
|
35203
|
-
|
|
35817
|
+
function normalizeProviderScriptArgs(args) {
|
|
35818
|
+
const normalizedArgs = { ...args || {} };
|
|
35819
|
+
for (const key of ["mode", "model", "message", "action", "button", "text", "sessionId", "value"]) {
|
|
35820
|
+
if (key in normalizedArgs && !(key.toUpperCase() in normalizedArgs)) {
|
|
35821
|
+
normalizedArgs[key.toUpperCase()] = normalizedArgs[key];
|
|
35822
|
+
}
|
|
35823
|
+
}
|
|
35824
|
+
return normalizedArgs;
|
|
35825
|
+
}
|
|
35826
|
+
function parseScriptResult(result) {
|
|
35827
|
+
if (typeof result === "string") {
|
|
35828
|
+
try {
|
|
35829
|
+
const parsed = JSON.parse(result);
|
|
35830
|
+
if (parsed && typeof parsed === "object" && parsed.success === false) {
|
|
35831
|
+
return { success: false, payload: parsed };
|
|
35832
|
+
}
|
|
35833
|
+
return { success: true, payload: parsed };
|
|
35834
|
+
} catch {
|
|
35835
|
+
return { success: true, payload: { result } };
|
|
35836
|
+
}
|
|
35837
|
+
}
|
|
35838
|
+
if (result && typeof result === "object" && result.success === false) {
|
|
35839
|
+
return { success: false, payload: result };
|
|
35840
|
+
}
|
|
35841
|
+
return { success: true, payload: result };
|
|
35842
|
+
}
|
|
35843
|
+
function getCliScriptCommand(payload) {
|
|
35844
|
+
if (!payload || typeof payload !== "object") return null;
|
|
35845
|
+
if (typeof payload.sendMessage === "string" && payload.sendMessage.trim()) {
|
|
35846
|
+
return { type: "send_message", text: payload.sendMessage.trim() };
|
|
35847
|
+
}
|
|
35848
|
+
const command = payload.command;
|
|
35849
|
+
if (!command || typeof command !== "object") return null;
|
|
35850
|
+
if (command.type !== "send_message") return null;
|
|
35851
|
+
const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
|
|
35852
|
+
if (!text) return null;
|
|
35853
|
+
return { type: "send_message", text };
|
|
35854
|
+
}
|
|
35855
|
+
function applyProviderPatch(h, args, payload) {
|
|
35856
|
+
if (!payload || typeof payload !== "object") return;
|
|
35857
|
+
const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
35858
|
+
const targetSession = targetSessionId ? h.ctx.sessionRegistry?.get(targetSessionId) : void 0;
|
|
35859
|
+
const instanceKey = targetSession?.instanceKey || targetSessionId;
|
|
35860
|
+
if (!instanceKey) return;
|
|
35861
|
+
h.ctx.instanceManager?.sendEvent(instanceKey, "provider_state_patch", {
|
|
35862
|
+
...payload,
|
|
35863
|
+
extensionType: targetSession?.transport === "cdp-webview" ? targetSession.providerType : void 0
|
|
35864
|
+
});
|
|
35865
|
+
}
|
|
35866
|
+
async function executeProviderScript(h, args, scriptName) {
|
|
35204
35867
|
const { agentType, ideType } = args || {};
|
|
35205
35868
|
if (!agentType) return { success: false, error: "agentType is required" };
|
|
35206
35869
|
const loader = h.ctx.providerLoader;
|
|
@@ -35213,13 +35876,29 @@ ${data.message || ""}`.trim();
|
|
|
35213
35876
|
if (!provider.scripts?.[actualScriptName]) {
|
|
35214
35877
|
return { success: false, error: `Script '${actualScriptName}' not available for ${agentType}` };
|
|
35215
35878
|
}
|
|
35216
|
-
const
|
|
35217
|
-
|
|
35218
|
-
|
|
35219
|
-
if (
|
|
35220
|
-
|
|
35879
|
+
const normalizedArgs = normalizeProviderScriptArgs(args);
|
|
35880
|
+
if (provider.category === "cli") {
|
|
35881
|
+
const adapter = h.getCliAdapter(args?.targetSessionId || agentType);
|
|
35882
|
+
if (!adapter?.invokeScript) {
|
|
35883
|
+
return { success: false, error: `CLI adapter does not support script '${actualScriptName}'` };
|
|
35884
|
+
}
|
|
35885
|
+
try {
|
|
35886
|
+
const raw = await adapter.invokeScript(actualScriptName, normalizedArgs);
|
|
35887
|
+
const parsed = parseScriptResult(raw);
|
|
35888
|
+
if (!parsed.success) {
|
|
35889
|
+
return { success: false, ...parsed.payload || {} };
|
|
35890
|
+
}
|
|
35891
|
+
const cliCommand = getCliScriptCommand(parsed.payload);
|
|
35892
|
+
if (cliCommand?.type === "send_message" && cliCommand.text) {
|
|
35893
|
+
await adapter.sendMessage(cliCommand.text);
|
|
35894
|
+
}
|
|
35895
|
+
applyProviderPatch(h, args, parsed.payload);
|
|
35896
|
+
return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
|
|
35897
|
+
} catch (e) {
|
|
35898
|
+
return { success: false, error: `Script execution failed: ${e.message}` };
|
|
35221
35899
|
}
|
|
35222
35900
|
}
|
|
35901
|
+
const scriptFn = provider.scripts[actualScriptName];
|
|
35223
35902
|
const scriptCode = scriptFn(normalizedArgs);
|
|
35224
35903
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
35225
35904
|
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || agentType : h.currentSession?.cdpManagerKey || h.currentManagerKey || ideType;
|
|
@@ -35273,16 +35952,29 @@ ${data.message || ""}`.trim();
|
|
|
35273
35952
|
if (typeof result === "string") {
|
|
35274
35953
|
try {
|
|
35275
35954
|
const parsed = JSON.parse(result);
|
|
35955
|
+
applyProviderPatch(h, args, parsed);
|
|
35956
|
+
if (parsed && typeof parsed === "object" && parsed.success === false) {
|
|
35957
|
+
return { success: false, ...parsed };
|
|
35958
|
+
}
|
|
35276
35959
|
return { success: true, ...parsed };
|
|
35277
35960
|
} catch {
|
|
35278
35961
|
return { success: true, result };
|
|
35279
35962
|
}
|
|
35280
35963
|
}
|
|
35964
|
+
applyProviderPatch(h, args, result);
|
|
35281
35965
|
return { success: true, result };
|
|
35282
35966
|
} catch (e) {
|
|
35283
35967
|
return { success: false, error: `Script execution failed: ${e.message}` };
|
|
35284
35968
|
}
|
|
35285
35969
|
}
|
|
35970
|
+
async function handleExtensionScript(h, args, scriptName) {
|
|
35971
|
+
return executeProviderScript(h, args, scriptName);
|
|
35972
|
+
}
|
|
35973
|
+
async function handleProviderScript(h, args) {
|
|
35974
|
+
const scriptName = typeof args?.scriptName === "string" ? args.scriptName.trim() : "";
|
|
35975
|
+
if (!scriptName) return { success: false, error: "scriptName is required" };
|
|
35976
|
+
return executeProviderScript(h, args, scriptName);
|
|
35977
|
+
}
|
|
35286
35978
|
function handleGetIdeExtensions(h, args) {
|
|
35287
35979
|
const { ideType } = args || {};
|
|
35288
35980
|
const loader = h.ctx.providerLoader;
|
|
@@ -35778,6 +36470,8 @@ ${data.message || ""}`.trim();
|
|
|
35778
36470
|
case "set_ide_extension":
|
|
35779
36471
|
return handleSetIdeExtension(this, args);
|
|
35780
36472
|
// ─── Extension Model / Mode Control (stream-commands.ts) ──────────
|
|
36473
|
+
case "invoke_provider_script":
|
|
36474
|
+
return handleProviderScript(this, args);
|
|
35781
36475
|
case "list_extension_models":
|
|
35782
36476
|
return handleExtensionScript(this, args, "listModels");
|
|
35783
36477
|
case "set_extension_model":
|
|
@@ -35950,6 +36644,8 @@ ${data.message || ""}`.trim();
|
|
|
35950
36644
|
generatingDebounceTimer = null;
|
|
35951
36645
|
generatingDebouncePending = null;
|
|
35952
36646
|
lastApprovalEventAt = 0;
|
|
36647
|
+
controlValues = {};
|
|
36648
|
+
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
35953
36649
|
historyWriter;
|
|
35954
36650
|
runtimeMessages = [];
|
|
35955
36651
|
instanceId;
|
|
@@ -35962,6 +36658,7 @@ ${data.message || ""}`.trim();
|
|
|
35962
36658
|
async init(context) {
|
|
35963
36659
|
this.context = context;
|
|
35964
36660
|
this.settings = context.settings || {};
|
|
36661
|
+
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
35965
36662
|
this.monitor.updateConfig({
|
|
35966
36663
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
35967
36664
|
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
@@ -35977,6 +36674,21 @@ ${data.message || ""}`.trim();
|
|
|
35977
36674
|
this.detectStatusTransition();
|
|
35978
36675
|
});
|
|
35979
36676
|
await this.adapter.spawn();
|
|
36677
|
+
if (this.providerSessionId) {
|
|
36678
|
+
const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
|
|
36679
|
+
if (restoredHistory.messages.length > 0) {
|
|
36680
|
+
this.adapter.seedCommittedMessages(
|
|
36681
|
+
restoredHistory.messages.map((message) => ({
|
|
36682
|
+
role: message.role,
|
|
36683
|
+
content: message.content,
|
|
36684
|
+
timestamp: message.receivedAt,
|
|
36685
|
+
receivedAt: message.receivedAt,
|
|
36686
|
+
kind: message.kind,
|
|
36687
|
+
senderName: message.senderName
|
|
36688
|
+
}))
|
|
36689
|
+
);
|
|
36690
|
+
}
|
|
36691
|
+
}
|
|
35980
36692
|
if (this.providerSessionId && this.launchMode === "resume") {
|
|
35981
36693
|
const resumedAt = Date.now();
|
|
35982
36694
|
this.historyWriter.appendSystemMarker(
|
|
@@ -36057,6 +36769,12 @@ ${data.message || ""}`.trim();
|
|
|
36057
36769
|
}
|
|
36058
36770
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
36059
36771
|
const parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
|
|
36772
|
+
const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
|
|
36773
|
+
if (controlValues) {
|
|
36774
|
+
this.controlValues = controlValues;
|
|
36775
|
+
} else if (Object.keys(this.controlValues).length > 0) {
|
|
36776
|
+
this.controlValues = {};
|
|
36777
|
+
}
|
|
36060
36778
|
const mergedMessages = this.mergeConversationMessages(parsedMessages);
|
|
36061
36779
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
36062
36780
|
if (parsedMessages.length > 0) {
|
|
@@ -36077,6 +36795,7 @@ ${data.message || ""}`.trim();
|
|
|
36077
36795
|
);
|
|
36078
36796
|
}
|
|
36079
36797
|
}
|
|
36798
|
+
this.applyProviderResponse(parsedStatus, { phase: "immediate" });
|
|
36080
36799
|
return {
|
|
36081
36800
|
type: this.type,
|
|
36082
36801
|
name: this.provider.name,
|
|
@@ -36106,8 +36825,7 @@ ${data.message || ""}`.trim();
|
|
|
36106
36825
|
attachedClients: runtime.attachedClients || []
|
|
36107
36826
|
} : void 0,
|
|
36108
36827
|
resume: this.provider.resume,
|
|
36109
|
-
controlValues:
|
|
36110
|
-
// CLI controls not yet wired from stream
|
|
36828
|
+
controlValues: this.controlValues,
|
|
36111
36829
|
providerControls: this.provider.controls
|
|
36112
36830
|
};
|
|
36113
36831
|
}
|
|
@@ -36118,6 +36836,15 @@ ${data.message || ""}`.trim();
|
|
|
36118
36836
|
getPresentationMode() {
|
|
36119
36837
|
return this.presentationMode;
|
|
36120
36838
|
}
|
|
36839
|
+
updateSettings(newSettings) {
|
|
36840
|
+
this.settings = { ...newSettings };
|
|
36841
|
+
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
36842
|
+
this.monitor.updateConfig({
|
|
36843
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
36844
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
36845
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
36846
|
+
});
|
|
36847
|
+
}
|
|
36121
36848
|
onEvent(event, data) {
|
|
36122
36849
|
if (event === "send_message" && data?.text) {
|
|
36123
36850
|
void this.adapter.sendMessage(data.text).catch((e) => {
|
|
@@ -36129,22 +36856,27 @@ ${data.message || ""}`.trim();
|
|
|
36129
36856
|
void this.adapter.resolveAction(data).catch((e) => {
|
|
36130
36857
|
LOG2.warn("CLI", `[${this.type}] resolve_action failed: ${e?.message || e}`);
|
|
36131
36858
|
});
|
|
36859
|
+
} else if (event === "provider_state_patch" && data && typeof data === "object") {
|
|
36860
|
+
this.applyProviderResponse(data, { phase: "immediate" });
|
|
36132
36861
|
}
|
|
36133
36862
|
}
|
|
36134
36863
|
dispose() {
|
|
36135
36864
|
this.adapter.shutdown();
|
|
36136
36865
|
this.monitor.reset();
|
|
36866
|
+
this.appliedEffectKeys.clear();
|
|
36137
36867
|
}
|
|
36138
36868
|
completedDebounceTimer = null;
|
|
36139
36869
|
completedDebouncePending = null;
|
|
36140
36870
|
detectStatusTransition() {
|
|
36141
36871
|
const now = Date.now();
|
|
36142
36872
|
const adapterStatus = this.adapter.getStatus();
|
|
36873
|
+
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
36143
36874
|
const newStatus = adapterStatus.status;
|
|
36144
36875
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
36145
36876
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
36146
36877
|
const partial2 = this.adapter.getPartialResponse();
|
|
36147
36878
|
const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}::${adapterStatus.messages.at(-1)?.content || ""}`.slice(-2e3) : void 0;
|
|
36879
|
+
const previousStatus = this.lastStatus;
|
|
36148
36880
|
if (newStatus !== this.lastStatus) {
|
|
36149
36881
|
LOG2.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
|
|
36150
36882
|
if (this.lastStatus === "idle" && newStatus === "generating") {
|
|
@@ -36237,6 +36969,9 @@ ${data.message || ""}`.trim();
|
|
|
36237
36969
|
}
|
|
36238
36970
|
this.lastStatus = newStatus;
|
|
36239
36971
|
}
|
|
36972
|
+
this.applyProviderResponse(parsedStatus, {
|
|
36973
|
+
phase: newStatus === "idle" && (previousStatus === "generating" || previousStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
36974
|
+
});
|
|
36240
36975
|
const agentKey = `${this.type}:cli`;
|
|
36241
36976
|
const monitorEvents = this.monitor.check(agentKey, newStatus, now, progressFingerprint);
|
|
36242
36977
|
for (const me of monitorEvents) {
|
|
@@ -36252,6 +36987,88 @@ ${data.message || ""}`.trim();
|
|
|
36252
36987
|
this.events = [];
|
|
36253
36988
|
return events;
|
|
36254
36989
|
}
|
|
36990
|
+
applyProviderResponse(data, options) {
|
|
36991
|
+
if (!data || typeof data !== "object") return;
|
|
36992
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
36993
|
+
if (controlValues) {
|
|
36994
|
+
this.controlValues = { ...this.controlValues, ...controlValues };
|
|
36995
|
+
}
|
|
36996
|
+
const effects = normalizeProviderEffects(data);
|
|
36997
|
+
for (const effect of effects) {
|
|
36998
|
+
const effectWhen = effect.when || "immediate";
|
|
36999
|
+
if (effectWhen === "turn_completed" && options.phase !== "turn_completed") continue;
|
|
37000
|
+
if (effectWhen === "immediate" && options.phase === "turn_completed") continue;
|
|
37001
|
+
const effectKey = this.getEffectDedupKey(effect);
|
|
37002
|
+
if (this.appliedEffectKeys.has(effectKey)) continue;
|
|
37003
|
+
this.appliedEffectKeys.add(effectKey);
|
|
37004
|
+
if (effect.persist !== false) {
|
|
37005
|
+
const persisted = this.getPersistedEffectContent(effect);
|
|
37006
|
+
if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
|
|
37007
|
+
}
|
|
37008
|
+
if (effect.type === "message" && effect.message) {
|
|
37009
|
+
const content = typeof effect.message.content === "string" ? effect.message.content : JSON.stringify(effect.message.content);
|
|
37010
|
+
this.pushEvent({
|
|
37011
|
+
event: "provider:message",
|
|
37012
|
+
timestamp: Date.now(),
|
|
37013
|
+
content,
|
|
37014
|
+
role: effect.message.role || "system",
|
|
37015
|
+
kind: effect.message.kind,
|
|
37016
|
+
senderName: effect.message.senderName
|
|
37017
|
+
});
|
|
37018
|
+
} else if (effect.type === "toast" && effect.toast) {
|
|
37019
|
+
this.pushEvent({
|
|
37020
|
+
event: "provider:toast",
|
|
37021
|
+
effectId: effect.id || effectKey,
|
|
37022
|
+
timestamp: Date.now(),
|
|
37023
|
+
message: effect.toast.message,
|
|
37024
|
+
level: effect.toast.level || "info"
|
|
37025
|
+
});
|
|
37026
|
+
} else if (effect.type === "notification" && effect.notification) {
|
|
37027
|
+
this.pushEvent({
|
|
37028
|
+
event: "provider:notification",
|
|
37029
|
+
effectId: effect.id || effectKey,
|
|
37030
|
+
timestamp: Date.now(),
|
|
37031
|
+
title: effect.notification.title,
|
|
37032
|
+
message: effect.notification.body,
|
|
37033
|
+
content: typeof effect.notification.bubbleContent === "string" ? effect.notification.bubbleContent : effect.notification.body,
|
|
37034
|
+
level: effect.notification.level || "info",
|
|
37035
|
+
channels: effect.notification.channels || ["toast"],
|
|
37036
|
+
preferenceKey: effect.notification.preferenceKey
|
|
37037
|
+
});
|
|
37038
|
+
}
|
|
37039
|
+
}
|
|
37040
|
+
if (this.appliedEffectKeys.size > 200) {
|
|
37041
|
+
this.appliedEffectKeys = new Set(Array.from(this.appliedEffectKeys).slice(-100));
|
|
37042
|
+
}
|
|
37043
|
+
}
|
|
37044
|
+
getEffectDedupKey(effect) {
|
|
37045
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
37046
|
+
if (effect.type === "message") {
|
|
37047
|
+
const content = typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
37048
|
+
return `provider_effect:message:${content}`;
|
|
37049
|
+
}
|
|
37050
|
+
if (effect.type === "notification") {
|
|
37051
|
+
return `provider_effect:notification:${effect.notification?.title || ""}:${effect.notification?.body || ""}`;
|
|
37052
|
+
}
|
|
37053
|
+
return `provider_effect:toast:${effect.toast?.message || ""}`;
|
|
37054
|
+
}
|
|
37055
|
+
getPersistedEffectContent(effect) {
|
|
37056
|
+
if (effect.type === "message") {
|
|
37057
|
+
return typeof effect.message?.content === "string" ? effect.message.content : JSON.stringify(effect.message?.content || "");
|
|
37058
|
+
}
|
|
37059
|
+
if (effect.type === "toast") {
|
|
37060
|
+
return effect.toast?.message || null;
|
|
37061
|
+
}
|
|
37062
|
+
if (effect.type === "notification") {
|
|
37063
|
+
if (typeof effect.notification?.bubbleContent === "string") return effect.notification.bubbleContent;
|
|
37064
|
+
if (typeof effect.notification?.title === "string" && effect.notification.title.trim()) {
|
|
37065
|
+
return `${effect.notification.title}
|
|
37066
|
+
${effect.notification.body || ""}`.trim();
|
|
37067
|
+
}
|
|
37068
|
+
return effect.notification?.body || null;
|
|
37069
|
+
}
|
|
37070
|
+
return null;
|
|
37071
|
+
}
|
|
36255
37072
|
// ─── Adapter access (backward compat) ──────────────────
|
|
36256
37073
|
getAdapter() {
|
|
36257
37074
|
return this.adapter;
|
|
@@ -39010,6 +39827,22 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39010
39827
|
function getWinProcessNames() {
|
|
39011
39828
|
return getProviderLoader().getWinProcessNames();
|
|
39012
39829
|
}
|
|
39830
|
+
function getProviderMeta(ideId) {
|
|
39831
|
+
return getProviderLoader().getMeta(ideId);
|
|
39832
|
+
}
|
|
39833
|
+
function getPreferredLaunchMethod(ideId, platform9) {
|
|
39834
|
+
const prefer = getProviderMeta(ideId)?.launch?.prefer;
|
|
39835
|
+
const value = prefer?.[platform9];
|
|
39836
|
+
return value === "cli" || value === "app" || value === "auto" ? value : "auto";
|
|
39837
|
+
}
|
|
39838
|
+
function getCdpStartupTimeoutMs(ideId) {
|
|
39839
|
+
const value = getProviderMeta(ideId)?.launch?.cdpStartupTimeoutMs;
|
|
39840
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return 15e3;
|
|
39841
|
+
return Math.max(1e3, Math.floor(value));
|
|
39842
|
+
}
|
|
39843
|
+
function escapeForAppleScript(value) {
|
|
39844
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
39845
|
+
}
|
|
39013
39846
|
async function findFreePort(ports) {
|
|
39014
39847
|
for (const port2 of ports) {
|
|
39015
39848
|
const free = await checkPortFree(port2);
|
|
@@ -39062,12 +39895,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39062
39895
|
try {
|
|
39063
39896
|
if (plat === "darwin" && appName) {
|
|
39064
39897
|
try {
|
|
39065
|
-
(0, import_child_process6.execSync)(`osascript -e 'tell application "${appName}" to quit' 2>/dev/null`, {
|
|
39898
|
+
(0, import_child_process6.execSync)(`osascript -e 'tell application "${escapeForAppleScript(appName)}" to quit' 2>/dev/null`, {
|
|
39066
39899
|
timeout: 5e3
|
|
39067
39900
|
});
|
|
39068
39901
|
} catch {
|
|
39069
39902
|
try {
|
|
39070
|
-
(0, import_child_process6.execSync)(`pkill -
|
|
39903
|
+
(0, import_child_process6.execSync)(`pkill -x "${appName}" 2>/dev/null`, { timeout: 5e3 });
|
|
39071
39904
|
} catch {
|
|
39072
39905
|
}
|
|
39073
39906
|
}
|
|
@@ -39097,7 +39930,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39097
39930
|
}
|
|
39098
39931
|
if (plat === "darwin" && appName) {
|
|
39099
39932
|
try {
|
|
39100
|
-
(0, import_child_process6.execSync)(`pkill -9 -
|
|
39933
|
+
(0, import_child_process6.execSync)(`pkill -9 -x "${appName}" 2>/dev/null`, { timeout: 5e3 });
|
|
39101
39934
|
} catch {
|
|
39102
39935
|
}
|
|
39103
39936
|
} else if (plat === "win32" && winProcesses) {
|
|
@@ -39120,8 +39953,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39120
39953
|
if (plat === "darwin") {
|
|
39121
39954
|
const appName = getMacAppIdentifiers()[ideId];
|
|
39122
39955
|
if (!appName) return false;
|
|
39123
|
-
|
|
39124
|
-
|
|
39956
|
+
try {
|
|
39957
|
+
const result = (0, import_child_process6.execSync)(`pgrep -x "${appName}" 2>/dev/null`, {
|
|
39958
|
+
encoding: "utf-8",
|
|
39959
|
+
timeout: 3e3
|
|
39960
|
+
});
|
|
39961
|
+
return result.trim().length > 0;
|
|
39962
|
+
} catch {
|
|
39963
|
+
const result = (0, import_child_process6.execSync)(
|
|
39964
|
+
`osascript -e 'tell application "System Events" to count (every process whose name is "${escapeForAppleScript(appName)}")'`,
|
|
39965
|
+
{
|
|
39966
|
+
encoding: "utf-8",
|
|
39967
|
+
timeout: 3e3,
|
|
39968
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
39969
|
+
}
|
|
39970
|
+
);
|
|
39971
|
+
return Number.parseInt(result.trim() || "0", 10) > 0;
|
|
39972
|
+
}
|
|
39125
39973
|
} else if (plat === "win32") {
|
|
39126
39974
|
const winProcesses = getWinProcessNames()[ideId];
|
|
39127
39975
|
if (!winProcesses) return false;
|
|
@@ -39270,7 +40118,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39270
40118
|
await launchLinux(targetIde, port, workspace, options.newWindow);
|
|
39271
40119
|
}
|
|
39272
40120
|
let cdpReady = false;
|
|
39273
|
-
|
|
40121
|
+
const waitDeadline = Date.now() + getCdpStartupTimeoutMs(targetIde.id);
|
|
40122
|
+
while (Date.now() < waitDeadline) {
|
|
39274
40123
|
await new Promise((r) => setTimeout(r, 500));
|
|
39275
40124
|
if (await isCdpActive(port)) {
|
|
39276
40125
|
cdpReady = true;
|
|
@@ -39299,14 +40148,18 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39299
40148
|
}
|
|
39300
40149
|
async function launchMacOS(ide, port, workspace, newWindow) {
|
|
39301
40150
|
const appName = getMacAppIdentifiers()[ide.id];
|
|
40151
|
+
const preferredMethod = getPreferredLaunchMethod(ide.id, "darwin");
|
|
39302
40152
|
const args = ["--remote-debugging-port=" + port];
|
|
39303
40153
|
if (newWindow) args.push("--new-window");
|
|
39304
40154
|
if (workspace) args.push(workspace);
|
|
39305
|
-
|
|
40155
|
+
const canUseCli = !!ide.cliCommand;
|
|
40156
|
+
const canUseAppLauncher = !!appName;
|
|
40157
|
+
const useAppLauncher = preferredMethod === "app" ? canUseAppLauncher : preferredMethod === "cli" ? false : !canUseCli && canUseAppLauncher;
|
|
40158
|
+
if (!useAppLauncher && ide.cliCommand) {
|
|
40159
|
+
(0, import_child_process6.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
|
|
40160
|
+
} else if (appName) {
|
|
39306
40161
|
const openArgs = ["-a", appName, "--args", ...args];
|
|
39307
40162
|
(0, import_child_process6.spawn)("open", openArgs, { detached: true, stdio: "ignore" }).unref();
|
|
39308
|
-
} else if (ide.cliCommand) {
|
|
39309
|
-
(0, import_child_process6.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
|
|
39310
40163
|
} else {
|
|
39311
40164
|
throw new Error(`No app identifier or CLI for ${ide.displayName}`);
|
|
39312
40165
|
}
|
|
@@ -39609,6 +40462,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39609
40462
|
workspaces: wsState.workspaces,
|
|
39610
40463
|
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
39611
40464
|
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
40465
|
+
terminalSizingMode: cfg.terminalSizingMode || "measured",
|
|
39612
40466
|
recentLaunches: buildRecentLaunches(recentActivity),
|
|
39613
40467
|
terminalBackend,
|
|
39614
40468
|
availableProviders: buildAvailableProviders(options.providerLoader)
|
|
@@ -40444,19 +41298,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40444
41298
|
mode: data.mode,
|
|
40445
41299
|
activeModal: data.activeModal
|
|
40446
41300
|
};
|
|
40447
|
-
|
|
40448
|
-
|
|
40449
|
-
|
|
40450
|
-
|
|
40451
|
-
const val = data[ctrl.readFrom];
|
|
40452
|
-
if (val !== void 0 && val !== null) {
|
|
40453
|
-
cv[ctrl.id] = typeof val === "object" ? val.name || val.id || String(val) : val;
|
|
40454
|
-
}
|
|
40455
|
-
}
|
|
40456
|
-
if (data.model && !cv["model"]) cv["model"] = data.model;
|
|
40457
|
-
if (data.mode && !cv["mode"]) cv["mode"] = data.mode;
|
|
40458
|
-
if (Object.keys(cv).length > 0) state.controlValues = cv;
|
|
40459
|
-
}
|
|
41301
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
41302
|
+
if (controlValues) state.controlValues = controlValues;
|
|
41303
|
+
const effects = normalizeProviderEffects(data);
|
|
41304
|
+
if (effects.length > 0) state.effects = effects;
|
|
40460
41305
|
if (state.messages.length > 0) {
|
|
40461
41306
|
this.lastSuccessState = state;
|
|
40462
41307
|
}
|
|
@@ -40976,6 +41821,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
40976
41821
|
activeModal: stream.activeModal || null,
|
|
40977
41822
|
model: stream.model || void 0,
|
|
40978
41823
|
mode: stream.mode || void 0,
|
|
41824
|
+
controlValues: stream.controlValues || void 0,
|
|
41825
|
+
effects: stream.effects || void 0,
|
|
40979
41826
|
sessionId: stream.sessionId || stream.instanceId || void 0,
|
|
40980
41827
|
title: stream.title || stream.agentName || void 0,
|
|
40981
41828
|
agentType: stream.agentType || void 0,
|