adhdev 0.9.33 → 0.9.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +394 -155
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +394 -155
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11413,13 +11413,14 @@ function sliceFromOffset(text, start) {
|
|
|
11413
11413
|
function hydrateCliParsedMessages(parsedMessages, options) {
|
|
11414
11414
|
const { committedMessages, scope, lastOutputAt } = options;
|
|
11415
11415
|
const referenceMessages = [...committedMessages];
|
|
11416
|
+
const referenceComparables = referenceMessages.map((message) => normalizeComparableMessageContent(message?.content || ""));
|
|
11416
11417
|
const usedReferenceIndexes = /* @__PURE__ */ new Set();
|
|
11417
11418
|
const now = options.now ?? Date.now();
|
|
11418
11419
|
const findReferenceTimestamp = (role, content, parsedIndex) => {
|
|
11419
11420
|
const normalizedContent = normalizeComparableMessageContent(content);
|
|
11420
11421
|
if (!normalizedContent) return void 0;
|
|
11421
11422
|
const sameIndex = referenceMessages[parsedIndex];
|
|
11422
|
-
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role &&
|
|
11423
|
+
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && referenceComparables[parsedIndex] === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
|
|
11423
11424
|
usedReferenceIndexes.add(parsedIndex);
|
|
11424
11425
|
return sameIndex.timestamp;
|
|
11425
11426
|
}
|
|
@@ -11427,7 +11428,7 @@ function hydrateCliParsedMessages(parsedMessages, options) {
|
|
|
11427
11428
|
if (usedReferenceIndexes.has(i)) continue;
|
|
11428
11429
|
const candidate = referenceMessages[i];
|
|
11429
11430
|
if (!candidate || candidate.role !== role) continue;
|
|
11430
|
-
const candidateContent =
|
|
11431
|
+
const candidateContent = referenceComparables[i];
|
|
11431
11432
|
if (!candidateContent) continue;
|
|
11432
11433
|
const exactMatch = candidateContent === normalizedContent;
|
|
11433
11434
|
const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
|
|
@@ -12519,7 +12520,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
12519
12520
|
return;
|
|
12520
12521
|
}
|
|
12521
12522
|
if (this.currentTurnScope && !lastParsedAssistant) {
|
|
12522
|
-
LOG.
|
|
12523
|
+
LOG.debug(
|
|
12523
12524
|
"CLI",
|
|
12524
12525
|
`[${this.cliType}] Settled without assistant: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
|
|
12525
12526
|
);
|
|
@@ -13335,9 +13336,43 @@ var init_provider_cli_adapter = __esm({
|
|
|
13335
13336
|
}
|
|
13336
13337
|
armResponseTimeout() {
|
|
13337
13338
|
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
13339
|
+
const timeoutMs = this.timeouts.maxResponse;
|
|
13340
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
13341
|
+
this.responseTimeout = null;
|
|
13342
|
+
return;
|
|
13343
|
+
}
|
|
13338
13344
|
this.responseTimeout = setTimeout(() => {
|
|
13339
|
-
|
|
13340
|
-
|
|
13345
|
+
this.responseTimeout = null;
|
|
13346
|
+
if (!this.isWaitingForResponse) return;
|
|
13347
|
+
const detectedStatusBeforeEval = this.runDetectStatus(this.recentOutputBuffer);
|
|
13348
|
+
this.recordTrace("response_timeout_check", {
|
|
13349
|
+
timeoutMs,
|
|
13350
|
+
detectedStatus: detectedStatusBeforeEval,
|
|
13351
|
+
currentStatus: this.currentStatus,
|
|
13352
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
13353
|
+
hasActionableApproval: this.hasActionableApproval(),
|
|
13354
|
+
...buildCliTraceParseSnapshot({
|
|
13355
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
13356
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
13357
|
+
responseBuffer: this.responseBuffer,
|
|
13358
|
+
partialResponse: this.responseBuffer,
|
|
13359
|
+
scope: this.currentTurnScope
|
|
13360
|
+
})
|
|
13361
|
+
});
|
|
13362
|
+
this.settledBuffer = this.recentOutputBuffer;
|
|
13363
|
+
this.evaluateSettled();
|
|
13364
|
+
if (this.isWaitingForResponse && !this.hasActionableApproval()) {
|
|
13365
|
+
const detectedStatusAfterEval = this.runDetectStatus(this.recentOutputBuffer);
|
|
13366
|
+
this.recordTrace("response_timeout_kept_open", {
|
|
13367
|
+
timeoutMs,
|
|
13368
|
+
detectedStatusBeforeEval,
|
|
13369
|
+
detectedStatusAfterEval,
|
|
13370
|
+
currentStatus: this.currentStatus,
|
|
13371
|
+
isWaitingForResponse: this.isWaitingForResponse
|
|
13372
|
+
});
|
|
13373
|
+
this.armResponseTimeout();
|
|
13374
|
+
}
|
|
13375
|
+
}, timeoutMs);
|
|
13341
13376
|
}
|
|
13342
13377
|
writeSubmitKeyForRetry(mode) {
|
|
13343
13378
|
void this.writeToPty(this.sendKey).catch((error48) => {
|
|
@@ -14228,6 +14263,20 @@ var init_cli_provider_instance = __esm({
|
|
|
14228
14263
|
getPresentationMode() {
|
|
14229
14264
|
return this.presentationMode;
|
|
14230
14265
|
}
|
|
14266
|
+
getHotChatSessionState() {
|
|
14267
|
+
const adapterStatus = this.adapter.getStatus();
|
|
14268
|
+
const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
14269
|
+
const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
|
|
14270
|
+
const runtime = this.adapter.getRuntimeMetadata();
|
|
14271
|
+
return {
|
|
14272
|
+
id: this.instanceId,
|
|
14273
|
+
status: visibleStatus,
|
|
14274
|
+
runtimeLifecycle: runtime?.lifecycle ?? null,
|
|
14275
|
+
runtimeSurfaceKind: runtime?.surfaceKind,
|
|
14276
|
+
runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
|
|
14277
|
+
runtimeRecoveryState: runtime?.recoveryState ?? null
|
|
14278
|
+
};
|
|
14279
|
+
}
|
|
14231
14280
|
updateSettings(newSettings) {
|
|
14232
14281
|
this.settings = { ...newSettings };
|
|
14233
14282
|
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
@@ -14383,6 +14432,15 @@ var init_cli_provider_instance = __esm({
|
|
|
14383
14432
|
this.completedDebouncePending = { chatTitle, duration: duration3, timestamp: now };
|
|
14384
14433
|
this.completedDebounceTimer = setTimeout(() => {
|
|
14385
14434
|
if (this.completedDebouncePending) {
|
|
14435
|
+
const latestStatus = this.adapter.getStatus();
|
|
14436
|
+
const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
14437
|
+
const latestVisibleStatus = latestAutoApproveActive ? "generating" : latestStatus.status;
|
|
14438
|
+
if (latestVisibleStatus !== "idle") {
|
|
14439
|
+
LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
|
|
14440
|
+
this.completedDebouncePending = null;
|
|
14441
|
+
this.completedDebounceTimer = null;
|
|
14442
|
+
return;
|
|
14443
|
+
}
|
|
14386
14444
|
LOG.info("CLI", `[${this.type}] completed in ${this.completedDebouncePending.duration}s`);
|
|
14387
14445
|
this.pushEvent({ event: "agent:generating_completed", ...this.completedDebouncePending });
|
|
14388
14446
|
this.completedDebouncePending = null;
|
|
@@ -37502,6 +37560,51 @@ function killPid(pid) {
|
|
|
37502
37560
|
return false;
|
|
37503
37561
|
}
|
|
37504
37562
|
}
|
|
37563
|
+
function getWindowsProcessCommandLine(pid) {
|
|
37564
|
+
const pidFilter = `ProcessId=${pid}`;
|
|
37565
|
+
try {
|
|
37566
|
+
const psOut = (0, import_child_process8.execFileSync)("powershell.exe", [
|
|
37567
|
+
"-NoProfile",
|
|
37568
|
+
"-NonInteractive",
|
|
37569
|
+
"-ExecutionPolicy",
|
|
37570
|
+
"Bypass",
|
|
37571
|
+
"-Command",
|
|
37572
|
+
`(Get-CimInstance Win32_Process -Filter "${pidFilter}").CommandLine`
|
|
37573
|
+
], { encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
37574
|
+
if (psOut) return psOut;
|
|
37575
|
+
} catch {
|
|
37576
|
+
}
|
|
37577
|
+
try {
|
|
37578
|
+
const wmicOut = (0, import_child_process8.execFileSync)("wmic", [
|
|
37579
|
+
"process",
|
|
37580
|
+
"where",
|
|
37581
|
+
pidFilter,
|
|
37582
|
+
"get",
|
|
37583
|
+
"CommandLine"
|
|
37584
|
+
], { encoding: "utf8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
37585
|
+
if (wmicOut) return wmicOut;
|
|
37586
|
+
} catch {
|
|
37587
|
+
}
|
|
37588
|
+
return null;
|
|
37589
|
+
}
|
|
37590
|
+
function getProcessCommandLine(pid) {
|
|
37591
|
+
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
37592
|
+
if (process.platform === "win32") return getWindowsProcessCommandLine(pid);
|
|
37593
|
+
try {
|
|
37594
|
+
const text = (0, import_child_process8.execFileSync)("ps", ["-o", "command=", "-p", String(pid)], {
|
|
37595
|
+
encoding: "utf8",
|
|
37596
|
+
timeout: 3e3,
|
|
37597
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
37598
|
+
}).trim();
|
|
37599
|
+
return text || null;
|
|
37600
|
+
} catch {
|
|
37601
|
+
return null;
|
|
37602
|
+
}
|
|
37603
|
+
}
|
|
37604
|
+
function isManagedSessionHostPid(pid) {
|
|
37605
|
+
const commandLine = getProcessCommandLine(pid);
|
|
37606
|
+
return !!commandLine && /session-host-daemon/i.test(commandLine);
|
|
37607
|
+
}
|
|
37505
37608
|
async function waitForPidExit(pid, timeoutMs) {
|
|
37506
37609
|
const start = Date.now();
|
|
37507
37610
|
while (Date.now() - start < timeoutMs) {
|
|
@@ -37518,7 +37621,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
37518
37621
|
try {
|
|
37519
37622
|
if (fs8.existsSync(pidFile)) {
|
|
37520
37623
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
37521
|
-
if (Number.isFinite(pid)) {
|
|
37624
|
+
if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
|
|
37522
37625
|
killPid(pid);
|
|
37523
37626
|
}
|
|
37524
37627
|
}
|
|
@@ -37529,18 +37632,6 @@ function stopSessionHostProcesses(appName) {
|
|
|
37529
37632
|
} catch {
|
|
37530
37633
|
}
|
|
37531
37634
|
}
|
|
37532
|
-
if (process.platform !== "win32") {
|
|
37533
|
-
try {
|
|
37534
|
-
const raw = (0, import_child_process8.execFileSync)("pgrep", ["-f", "session-host-daemon"], { encoding: "utf8" }).trim();
|
|
37535
|
-
for (const line of raw.split("\n")) {
|
|
37536
|
-
const pid = Number.parseInt(line.trim(), 10);
|
|
37537
|
-
if (Number.isFinite(pid)) {
|
|
37538
|
-
killPid(pid);
|
|
37539
|
-
}
|
|
37540
|
-
}
|
|
37541
|
-
} catch {
|
|
37542
|
-
}
|
|
37543
|
-
}
|
|
37544
37635
|
}
|
|
37545
37636
|
function removeDaemonPidFile() {
|
|
37546
37637
|
const pidFile = path16.join(os19.homedir(), ".adhdev", "daemon.pid");
|
|
@@ -39882,6 +39973,20 @@ var init_forward = __esm({
|
|
|
39882
39973
|
});
|
|
39883
39974
|
|
|
39884
39975
|
// ../../oss/packages/daemon-core/src/providers/provider-instance-manager.ts
|
|
39976
|
+
function projectHotChatSessionStatesFromProviderState(state) {
|
|
39977
|
+
const project = (item) => ({
|
|
39978
|
+
id: item.instanceId,
|
|
39979
|
+
status: item.activeChat?.status || item.status,
|
|
39980
|
+
runtimeLifecycle: item.runtime?.lifecycle ?? null,
|
|
39981
|
+
runtimeSurfaceKind: item.runtime?.surfaceKind,
|
|
39982
|
+
runtimeRestoredFromStorage: item.runtime?.restoredFromStorage === true,
|
|
39983
|
+
runtimeRecoveryState: item.runtime?.recoveryState ?? null
|
|
39984
|
+
});
|
|
39985
|
+
if (state.category === "ide") {
|
|
39986
|
+
return [project(state), ...state.extensions.map(project)];
|
|
39987
|
+
}
|
|
39988
|
+
return [project(state)];
|
|
39989
|
+
}
|
|
39885
39990
|
var ProviderInstanceManager;
|
|
39886
39991
|
var init_provider_instance_manager = __esm({
|
|
39887
39992
|
"../../oss/packages/daemon-core/src/providers/provider-instance-manager.ts"() {
|
|
@@ -39982,6 +40087,27 @@ var init_provider_instance_manager = __esm({
|
|
|
39982
40087
|
}
|
|
39983
40088
|
return states;
|
|
39984
40089
|
}
|
|
40090
|
+
collectHotChatSessionStates() {
|
|
40091
|
+
const sessions = [];
|
|
40092
|
+
for (const [id, instance] of this.instances) {
|
|
40093
|
+
try {
|
|
40094
|
+
const projected = instance.getHotChatSessionState?.();
|
|
40095
|
+
if (Array.isArray(projected)) {
|
|
40096
|
+
sessions.push(...projected.filter((session) => !!session?.id));
|
|
40097
|
+
continue;
|
|
40098
|
+
}
|
|
40099
|
+
if (projected?.id) {
|
|
40100
|
+
sessions.push(projected);
|
|
40101
|
+
continue;
|
|
40102
|
+
}
|
|
40103
|
+
const state = instance.getState();
|
|
40104
|
+
sessions.push(...projectHotChatSessionStatesFromProviderState(state));
|
|
40105
|
+
} catch (e) {
|
|
40106
|
+
LOG.warn("InstanceMgr", `[InstanceManager] Failed to collect hot chat metadata from ${id}: ${e.message}`);
|
|
40107
|
+
}
|
|
40108
|
+
}
|
|
40109
|
+
return sessions;
|
|
40110
|
+
}
|
|
39985
40111
|
/**
|
|
39986
40112
|
* Per-category status collect
|
|
39987
40113
|
*/
|
|
@@ -47464,19 +47590,20 @@ var init_screenshot_sender = __esm({
|
|
|
47464
47590
|
}
|
|
47465
47591
|
return sentAny;
|
|
47466
47592
|
}
|
|
47467
|
-
sendScreenshot(peers, base64Data) {
|
|
47593
|
+
sendScreenshot(peers, base64Data, targetSessionId) {
|
|
47468
47594
|
const buffer = Buffer.from(base64Data, "base64");
|
|
47469
|
-
return this.sendScreenshotBuffer(peers, buffer);
|
|
47595
|
+
return this.sendScreenshotBuffer(peers, buffer, targetSessionId);
|
|
47470
47596
|
}
|
|
47471
47597
|
/** Send screenshot as raw Buffer (no base64 conversion overhead) */
|
|
47472
|
-
sendScreenshotBuffer(peers, buffer) {
|
|
47598
|
+
sendScreenshotBuffer(peers, buffer, targetSessionId) {
|
|
47473
47599
|
let sentAny = false;
|
|
47474
47600
|
let debugOnce = !this._ssDebugDone;
|
|
47475
47601
|
for (const [pid, peer] of peers.entries()) {
|
|
47476
47602
|
if (debugOnce) {
|
|
47477
|
-
logDebug(`sendScreenshot peer=${pid}: state=${peer.state}, hasCh=${!!peer.dataChannel}, ssActive=${peer.screenshotActive}, chOpen=${peer.dataChannel?.isOpen?.() ?? "N/A"}, bufSize=${buffer.length}`);
|
|
47603
|
+
logDebug(`sendScreenshot peer=${pid}: state=${peer.state}, hasCh=${!!peer.dataChannel}, ssActive=${peer.screenshotActive}, target=${peer.screenshotTargetSessionId || "none"}, chOpen=${peer.dataChannel?.isOpen?.() ?? "N/A"}, bufSize=${buffer.length}`);
|
|
47478
47604
|
}
|
|
47479
47605
|
if (peer.state !== "connected" || !peer.dataChannel || !peer.screenshotActive) continue;
|
|
47606
|
+
if (targetSessionId && peer.screenshotTargetSessionId !== targetSessionId) continue;
|
|
47480
47607
|
try {
|
|
47481
47608
|
if (!peer.dataChannel.isOpen()) continue;
|
|
47482
47609
|
const header = Buffer.alloc(4);
|
|
@@ -47508,18 +47635,32 @@ async function initiateConnection(deps, peerId, sharePermission) {
|
|
|
47508
47635
|
log("Cannot initiate \u2014 node-datachannel not available");
|
|
47509
47636
|
return;
|
|
47510
47637
|
}
|
|
47638
|
+
const pid = peerId || `legacy_${Date.now()}`;
|
|
47639
|
+
const existing = deps.peers.get(pid);
|
|
47640
|
+
if (existing?.state === "connected") {
|
|
47641
|
+
log(`initiateconnection() ignored for peer ${pid} \u2014 already connected`);
|
|
47642
|
+
return;
|
|
47643
|
+
}
|
|
47644
|
+
if (existing?.state === "connecting") {
|
|
47645
|
+
log(`initiateconnection() ignored for peer ${pid} \u2014 connection already in progress`);
|
|
47646
|
+
return;
|
|
47647
|
+
}
|
|
47511
47648
|
const limits = deps.serverConn.getPlanLimits();
|
|
47512
47649
|
if (limits && limits.maxP2PConnections !== -1) {
|
|
47513
47650
|
let connectedCount = 0;
|
|
47651
|
+
let reservedCount = 0;
|
|
47514
47652
|
for (const peer of deps.peers.values()) {
|
|
47515
47653
|
if (peer.state === "connected") connectedCount++;
|
|
47654
|
+
if (peer.state === "connected" || peer.state === "connecting") reservedCount++;
|
|
47516
47655
|
}
|
|
47517
|
-
if (
|
|
47656
|
+
if (reservedCount >= limits.maxP2PConnections) {
|
|
47518
47657
|
let oldestPeer = null;
|
|
47519
|
-
|
|
47520
|
-
|
|
47521
|
-
if (
|
|
47522
|
-
oldestPeer
|
|
47658
|
+
if (connectedCount >= limits.maxP2PConnections) {
|
|
47659
|
+
for (const [peerKey, peer] of deps.peers) {
|
|
47660
|
+
if (peer.state === "connected") {
|
|
47661
|
+
if (!oldestPeer || peer.connectedAt < oldestPeer.at) {
|
|
47662
|
+
oldestPeer = { id: peerKey, at: peer.connectedAt };
|
|
47663
|
+
}
|
|
47523
47664
|
}
|
|
47524
47665
|
}
|
|
47525
47666
|
}
|
|
@@ -47537,19 +47678,12 @@ async function initiateConnection(deps, peerId, sharePermission) {
|
|
|
47537
47678
|
}
|
|
47538
47679
|
}
|
|
47539
47680
|
disconnectPeer(deps.peers, oldestPeer.id, deps.notifyStateChange);
|
|
47681
|
+
} else {
|
|
47682
|
+
log(`P2P limit reached (${reservedCount}/${limits.maxP2PConnections}) with reserved connecting slot(s). Rejecting peer ${pid.slice(0, 12)}\u2026`);
|
|
47683
|
+
return;
|
|
47540
47684
|
}
|
|
47541
47685
|
}
|
|
47542
47686
|
}
|
|
47543
|
-
const pid = peerId || `legacy_${Date.now()}`;
|
|
47544
|
-
const existing = deps.peers.get(pid);
|
|
47545
|
-
if (existing?.state === "connected") {
|
|
47546
|
-
log(`initiateconnection() ignored for peer ${pid} \u2014 already connected`);
|
|
47547
|
-
return;
|
|
47548
|
-
}
|
|
47549
|
-
if (existing?.state === "connecting") {
|
|
47550
|
-
log(`initiateconnection() ignored for peer ${pid} \u2014 connection already in progress`);
|
|
47551
|
-
return;
|
|
47552
|
-
}
|
|
47553
47687
|
log(`initiateconnection() for peer ${pid}...`);
|
|
47554
47688
|
const mod = deps.nodeDatachannel;
|
|
47555
47689
|
const PeerConnectionCtor = mod.PeerConnection || mod.default?.PeerConnection || mod.default || mod;
|
|
@@ -47908,14 +48042,19 @@ var init_daemon_p2p = __esm({
|
|
|
47908
48042
|
}
|
|
47909
48043
|
return false;
|
|
47910
48044
|
}
|
|
47911
|
-
/** Get
|
|
47912
|
-
get
|
|
48045
|
+
/** Get all target sessions for active screenshot requests */
|
|
48046
|
+
get screenshotTargetSessionIds() {
|
|
48047
|
+
const targets = /* @__PURE__ */ new Set();
|
|
47913
48048
|
for (const peer of this.peers.values()) {
|
|
47914
48049
|
if (peer.screenshotActive && peer.state === "connected" && peer.screenshotTargetSessionId) {
|
|
47915
|
-
|
|
48050
|
+
targets.add(peer.screenshotTargetSessionId);
|
|
47916
48051
|
}
|
|
47917
48052
|
}
|
|
47918
|
-
return
|
|
48053
|
+
return Array.from(targets);
|
|
48054
|
+
}
|
|
48055
|
+
/** Get the target session for the currently active screenshot request */
|
|
48056
|
+
get screenshotTargetSessionId() {
|
|
48057
|
+
return this.screenshotTargetSessionIds[0];
|
|
47919
48058
|
}
|
|
47920
48059
|
constructor(serverConn) {
|
|
47921
48060
|
this.serverConn = serverConn;
|
|
@@ -48024,6 +48163,14 @@ ${e?.stack || ""}`);
|
|
|
48024
48163
|
}
|
|
48025
48164
|
return false;
|
|
48026
48165
|
}
|
|
48166
|
+
hasAnyNeedingFirstFrameForTarget(targetSessionId) {
|
|
48167
|
+
for (const peer of this.peers.values()) {
|
|
48168
|
+
if (peer.needsFirstFrame && peer.screenshotActive && peer.state === "connected" && peer.screenshotTargetSessionId === targetSessionId) {
|
|
48169
|
+
return true;
|
|
48170
|
+
}
|
|
48171
|
+
}
|
|
48172
|
+
return false;
|
|
48173
|
+
}
|
|
48027
48174
|
onStateChange(listener) {
|
|
48028
48175
|
this.stateListeners.push(listener);
|
|
48029
48176
|
}
|
|
@@ -48087,11 +48234,14 @@ ${e?.stack || ""}`);
|
|
|
48087
48234
|
if (targetPeers.size === 0) return false;
|
|
48088
48235
|
return this.screenshotSender.broadcastSessionOutput(targetPeers, sessionId, data);
|
|
48089
48236
|
}
|
|
48090
|
-
sendScreenshot(base64Data) {
|
|
48091
|
-
return this.screenshotSender.sendScreenshot(this.peers, base64Data);
|
|
48237
|
+
sendScreenshot(base64Data, targetSessionId) {
|
|
48238
|
+
return this.screenshotSender.sendScreenshot(this.peers, base64Data, targetSessionId);
|
|
48092
48239
|
}
|
|
48093
|
-
sendScreenshotBuffer(buffer) {
|
|
48094
|
-
return this.screenshotSender.sendScreenshotBuffer(this.peers, buffer);
|
|
48240
|
+
sendScreenshotBuffer(buffer, targetSessionId) {
|
|
48241
|
+
return this.screenshotSender.sendScreenshotBuffer(this.peers, buffer, targetSessionId);
|
|
48242
|
+
}
|
|
48243
|
+
sendScreenshotBufferForTarget(targetSessionId, buffer) {
|
|
48244
|
+
return this.sendScreenshotBuffer(buffer, targetSessionId);
|
|
48095
48245
|
}
|
|
48096
48246
|
// ─── Handler registration (unchanged API) ───────
|
|
48097
48247
|
onFileRequest(handler) {
|
|
@@ -54815,6 +54965,7 @@ var init_screenshot_controller = __esm({
|
|
|
54815
54965
|
lastSize = 0;
|
|
54816
54966
|
lastHash = 0;
|
|
54817
54967
|
staticFrameCount = 0;
|
|
54968
|
+
targetFrameState = /* @__PURE__ */ new Map();
|
|
54818
54969
|
currentInterval;
|
|
54819
54970
|
// Quality profiles
|
|
54820
54971
|
profileDirect;
|
|
@@ -54878,14 +55029,13 @@ var init_screenshot_controller = __esm({
|
|
|
54878
55029
|
async tick() {
|
|
54879
55030
|
if (!this.deps.isRunning()) return;
|
|
54880
55031
|
const active = this.deps.isScreenshotActive();
|
|
54881
|
-
const
|
|
54882
|
-
|
|
55032
|
+
const targetSessionIds = this.getActiveTargetSessionIds();
|
|
55033
|
+
const isRelay = this.deps.isUsingRelay();
|
|
55034
|
+
const profile = isRelay ? this.profileRelay : this.profileDirect;
|
|
55035
|
+
if (active && targetSessionIds.length === 0) {
|
|
54883
55036
|
this.timer = setTimeout(() => this.tick(), 500);
|
|
54884
55037
|
return;
|
|
54885
55038
|
}
|
|
54886
|
-
const cdp = targetSessionId ? this.deps.getCdp(targetSessionId) : null;
|
|
54887
|
-
const isRelay = this.deps.isUsingRelay();
|
|
54888
|
-
const profile = isRelay ? this.profileRelay : this.profileDirect;
|
|
54889
55039
|
this.checkBudgetReset();
|
|
54890
55040
|
if (this.dailyBudgetMs > 0) {
|
|
54891
55041
|
const now = Date.now();
|
|
@@ -54900,49 +55050,84 @@ var init_screenshot_controller = __esm({
|
|
|
54900
55050
|
}
|
|
54901
55051
|
}
|
|
54902
55052
|
const budgetBlocked = this.budgetExhausted && isRelay;
|
|
54903
|
-
if (!active ||
|
|
55053
|
+
if (!active || budgetBlocked) {
|
|
54904
55054
|
this.staticFrameCount = 0;
|
|
55055
|
+
this.targetFrameState.clear();
|
|
54905
55056
|
this.currentInterval = profile.maxInterval;
|
|
54906
55057
|
if (!active) this.lastActiveTimestamp = 0;
|
|
54907
55058
|
this.timer = setTimeout(() => this.tick(), budgetBlocked ? 3e4 : this.currentInterval);
|
|
54908
55059
|
return;
|
|
54909
55060
|
}
|
|
54910
55061
|
this.debugCount++;
|
|
54911
|
-
|
|
54912
|
-
|
|
54913
|
-
|
|
55062
|
+
let capturedAny = false;
|
|
55063
|
+
let sentAnyFrame = false;
|
|
55064
|
+
let anyFirstFrameAcrossTargets = false;
|
|
55065
|
+
for (const targetSessionId of targetSessionIds) {
|
|
55066
|
+
const cdp = this.deps.getCdp(targetSessionId);
|
|
55067
|
+
if (!cdp) continue;
|
|
55068
|
+
try {
|
|
55069
|
+
const buf = await cdp.captureScreenshot({ quality: profile.quality });
|
|
55070
|
+
if (!buf) {
|
|
55071
|
+
if (this.debugCount <= 5) LOG.debug("Screenshot", `captureScreenshot returned null for target=${targetSessionId}`);
|
|
55072
|
+
continue;
|
|
55073
|
+
}
|
|
55074
|
+
capturedAny = true;
|
|
55075
|
+
const state = this.getTargetFrameState(targetSessionId);
|
|
54914
55076
|
const hash2 = _ScreenshotController.fnvHash(buf);
|
|
54915
|
-
const sizeMatch = buf.length ===
|
|
54916
|
-
const hashMatch = hash2 ===
|
|
54917
|
-
const anyNeedsFirstFrame = this.deps.hasAnyNeedingFirstFrame();
|
|
55077
|
+
const sizeMatch = buf.length === state.lastSize;
|
|
55078
|
+
const hashMatch = hash2 === state.lastHash;
|
|
55079
|
+
const anyNeedsFirstFrame = this.deps.hasAnyNeedingFirstFrameForTarget?.(targetSessionId) ?? this.deps.hasAnyNeedingFirstFrame();
|
|
54918
55080
|
const resizeTarget = anyNeedsFirstFrame ? profile.firstFrameLongEdge : profile.maxLongEdge;
|
|
55081
|
+
anyFirstFrameAcrossTargets = anyFirstFrameAcrossTargets || anyNeedsFirstFrame;
|
|
54919
55082
|
if (sizeMatch && hashMatch && !anyNeedsFirstFrame) {
|
|
54920
|
-
|
|
54921
|
-
if (
|
|
55083
|
+
state.staticFrameCount++;
|
|
55084
|
+
if (state.staticFrameCount >= this.STATIC_THRESHOLD) {
|
|
54922
55085
|
this.currentInterval = Math.min(this.currentInterval + 200, profile.maxInterval);
|
|
54923
55086
|
}
|
|
54924
55087
|
if (this.debugCount <= 5 || this.debugCount % 50 === 0) {
|
|
54925
|
-
LOG.debug("Screenshot", `skip (unchanged, static=${
|
|
54926
|
-
}
|
|
54927
|
-
} else {
|
|
54928
|
-
const normalizedBuf = await this.normalizeBuffer(buf, resizeTarget, profile.quality);
|
|
54929
|
-
this.lastSize = buf.length;
|
|
54930
|
-
this.lastHash = hash2;
|
|
54931
|
-
this.staticFrameCount = 0;
|
|
54932
|
-
this.currentInterval = profile.minInterval;
|
|
54933
|
-
const sent = this.deps.sendScreenshotBuffer(normalizedBuf);
|
|
54934
|
-
if (this.debugCount <= 3 || anyNeedsFirstFrame) {
|
|
54935
|
-
LOG.debug("Screenshot", `sent: ${normalizedBuf.length} bytes, delivered=${sent}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"}${anyNeedsFirstFrame ? " (first-frame)" : ""}`);
|
|
55088
|
+
LOG.debug("Screenshot", `skip target=${targetSessionId} (unchanged, static=${state.staticFrameCount}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"})`);
|
|
54936
55089
|
}
|
|
55090
|
+
continue;
|
|
54937
55091
|
}
|
|
54938
|
-
|
|
54939
|
-
|
|
55092
|
+
const normalizedBuf = await this.normalizeBuffer(buf, resizeTarget, profile.quality);
|
|
55093
|
+
state.lastSize = buf.length;
|
|
55094
|
+
state.lastHash = hash2;
|
|
55095
|
+
state.staticFrameCount = 0;
|
|
55096
|
+
this.lastSize = buf.length;
|
|
55097
|
+
this.lastHash = hash2;
|
|
55098
|
+
this.staticFrameCount = 0;
|
|
55099
|
+
this.currentInterval = profile.minInterval;
|
|
55100
|
+
const sent = this.deps.sendScreenshotBufferForTarget ? this.deps.sendScreenshotBufferForTarget(targetSessionId, normalizedBuf) : this.deps.sendScreenshotBuffer(normalizedBuf);
|
|
55101
|
+
sentAnyFrame = sentAnyFrame || sent;
|
|
55102
|
+
if (this.debugCount <= 3 || anyNeedsFirstFrame) {
|
|
55103
|
+
LOG.debug("Screenshot", `sent target=${targetSessionId}: ${normalizedBuf.length} bytes, delivered=${sent}, interval=${this.currentInterval}ms, ${isRelay ? "RELAY" : "DIRECT"}${anyNeedsFirstFrame ? " (first-frame)" : ""}`);
|
|
55104
|
+
}
|
|
55105
|
+
} catch (e) {
|
|
55106
|
+
if (this.debugCount <= 5) LOG.warn("Screenshot", `error target=${targetSessionId}: ${e?.message}`);
|
|
54940
55107
|
}
|
|
54941
|
-
}
|
|
54942
|
-
|
|
55108
|
+
}
|
|
55109
|
+
if (!capturedAny) {
|
|
55110
|
+
this.currentInterval = profile.maxInterval;
|
|
55111
|
+
} else if (!sentAnyFrame && !anyFirstFrameAcrossTargets) {
|
|
55112
|
+
this.currentInterval = Math.min(this.currentInterval + 200, profile.maxInterval);
|
|
54943
55113
|
}
|
|
54944
55114
|
this.timer = setTimeout(() => this.tick(), this.currentInterval);
|
|
54945
55115
|
}
|
|
55116
|
+
getActiveTargetSessionIds() {
|
|
55117
|
+
const explicitTargets = this.deps.getScreenshotTargetSessionIds?.() || [];
|
|
55118
|
+
const normalized = explicitTargets.map((target) => typeof target === "string" ? target.trim() : "").filter((target) => target.length > 0);
|
|
55119
|
+
if (normalized.length > 0) return Array.from(new Set(normalized));
|
|
55120
|
+
const legacyTarget = this.deps.getScreenshotTargetSessionId();
|
|
55121
|
+
return legacyTarget ? [legacyTarget] : [];
|
|
55122
|
+
}
|
|
55123
|
+
getTargetFrameState(targetSessionId) {
|
|
55124
|
+
let state = this.targetFrameState.get(targetSessionId);
|
|
55125
|
+
if (!state) {
|
|
55126
|
+
state = { lastSize: 0, lastHash: 0, staticFrameCount: 0 };
|
|
55127
|
+
this.targetFrameState.set(targetSessionId, state);
|
|
55128
|
+
}
|
|
55129
|
+
return state;
|
|
55130
|
+
}
|
|
54946
55131
|
// ─── Budget ───────────────────────────────────
|
|
54947
55132
|
checkBudgetReset() {
|
|
54948
55133
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -55133,7 +55318,7 @@ function killPid2(pid) {
|
|
|
55133
55318
|
return false;
|
|
55134
55319
|
}
|
|
55135
55320
|
}
|
|
55136
|
-
function
|
|
55321
|
+
function getWindowsProcessCommandLine2(pid) {
|
|
55137
55322
|
const pidFilter = `ProcessId=${pid}`;
|
|
55138
55323
|
try {
|
|
55139
55324
|
const psOut = (0, import_child_process12.execFileSync)("powershell.exe", [
|
|
@@ -55162,13 +55347,32 @@ function getWindowsProcessCommandLine(pid) {
|
|
|
55162
55347
|
}
|
|
55163
55348
|
return null;
|
|
55164
55349
|
}
|
|
55350
|
+
function getProcessCommandLine2(pid) {
|
|
55351
|
+
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
55352
|
+
if (process.platform === "win32") return getWindowsProcessCommandLine2(pid);
|
|
55353
|
+
try {
|
|
55354
|
+
const text = (0, import_child_process12.execFileSync)("ps", ["-o", "command=", "-p", String(pid)], {
|
|
55355
|
+
encoding: "utf8",
|
|
55356
|
+
timeout: 3e3,
|
|
55357
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
55358
|
+
}).trim();
|
|
55359
|
+
return text || null;
|
|
55360
|
+
} catch {
|
|
55361
|
+
return null;
|
|
55362
|
+
}
|
|
55363
|
+
}
|
|
55364
|
+
function isManagedSessionHostPid2(pid) {
|
|
55365
|
+
const commandLine = getProcessCommandLine2(pid);
|
|
55366
|
+
if (!commandLine) return false;
|
|
55367
|
+
return /session-host-daemon/i.test(commandLine);
|
|
55368
|
+
}
|
|
55165
55369
|
function stopManagedSessionHostProcess() {
|
|
55166
55370
|
let stopped = false;
|
|
55167
55371
|
const pidFile = getSessionHostPidFile();
|
|
55168
55372
|
try {
|
|
55169
55373
|
if (fs17.existsSync(pidFile)) {
|
|
55170
55374
|
const pid = Number.parseInt(fs17.readFileSync(pidFile, "utf8").trim(), 10);
|
|
55171
|
-
if (Number.isFinite(pid) && pid !== process.pid) {
|
|
55375
|
+
if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid2(pid)) {
|
|
55172
55376
|
stopped = killPid2(pid) || stopped;
|
|
55173
55377
|
}
|
|
55174
55378
|
}
|
|
@@ -55182,40 +55386,7 @@ function stopManagedSessionHostProcess() {
|
|
|
55182
55386
|
return stopped;
|
|
55183
55387
|
}
|
|
55184
55388
|
function stopSessionHost() {
|
|
55185
|
-
|
|
55186
|
-
if (process.platform === "win32") {
|
|
55187
|
-
try {
|
|
55188
|
-
const raw = (0, import_child_process12.execFileSync)("tasklist", ["/FO", "CSV", "/NH", "/FI", "IMAGENAME eq node.exe"], {
|
|
55189
|
-
encoding: "utf8",
|
|
55190
|
-
timeout: 5e3,
|
|
55191
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
55192
|
-
windowsHide: true
|
|
55193
|
-
}).trim();
|
|
55194
|
-
for (const line of raw.split(/\r?\n/)) {
|
|
55195
|
-
const match = line.match(/^"node\.exe","(\d+)"/i);
|
|
55196
|
-
if (!match) continue;
|
|
55197
|
-
const candidatePid = Number.parseInt(match[1], 10);
|
|
55198
|
-
if (!Number.isFinite(candidatePid) || candidatePid === process.pid) continue;
|
|
55199
|
-
const commandLine = getWindowsProcessCommandLine(candidatePid);
|
|
55200
|
-
if (commandLine?.includes("session-host-daemon")) {
|
|
55201
|
-
stopped = killPid2(candidatePid) || stopped;
|
|
55202
|
-
}
|
|
55203
|
-
}
|
|
55204
|
-
} catch {
|
|
55205
|
-
}
|
|
55206
|
-
} else {
|
|
55207
|
-
try {
|
|
55208
|
-
const raw = (0, import_child_process12.execFileSync)("pgrep", ["-f", "session-host-daemon"], { encoding: "utf8" }).trim();
|
|
55209
|
-
for (const line of raw.split("\n")) {
|
|
55210
|
-
const pid = Number.parseInt(line.trim(), 10);
|
|
55211
|
-
if (Number.isFinite(pid) && pid !== process.pid && pid !== process.ppid) {
|
|
55212
|
-
stopped = killPid2(pid) || stopped;
|
|
55213
|
-
}
|
|
55214
|
-
}
|
|
55215
|
-
} catch {
|
|
55216
|
-
}
|
|
55217
|
-
}
|
|
55218
|
-
return stopped;
|
|
55389
|
+
return stopManagedSessionHostProcess();
|
|
55219
55390
|
}
|
|
55220
55391
|
async function ensureSessionHostReady2() {
|
|
55221
55392
|
const quarantine = quarantineLegacyStandaloneSessions({
|
|
@@ -55992,10 +56163,65 @@ var init_version = __esm({
|
|
|
55992
56163
|
var adhdev_daemon_exports = {};
|
|
55993
56164
|
__export(adhdev_daemon_exports, {
|
|
55994
56165
|
AdhdevDaemon: () => AdhdevDaemon,
|
|
56166
|
+
buildMandatoryUpdateInfoFromServerPayload: () => buildMandatoryUpdateInfoFromServerPayload,
|
|
56167
|
+
buildMandatoryUpdateRequiredPayload: () => buildMandatoryUpdateRequiredPayload,
|
|
55995
56168
|
getDaemonPid: () => getDaemonPid,
|
|
55996
56169
|
isDaemonRunning: () => isDaemonRunning,
|
|
55997
|
-
stopDaemon: () => stopDaemon
|
|
55998
|
-
|
|
56170
|
+
stopDaemon: () => stopDaemon,
|
|
56171
|
+
validateMandatoryUpdateTarget: () => validateMandatoryUpdateTarget,
|
|
56172
|
+
verifyPublishedMandatoryUpdateTarget: () => verifyPublishedMandatoryUpdateTarget
|
|
56173
|
+
});
|
|
56174
|
+
function validateMandatoryUpdateTarget(targetVersion) {
|
|
56175
|
+
if (typeof targetVersion !== "string") return { valid: false, error: "target version is required" };
|
|
56176
|
+
if (targetVersion !== targetVersion.trim()) return { valid: false, error: "target version must not contain whitespace" };
|
|
56177
|
+
const version2 = targetVersion;
|
|
56178
|
+
if (!version2) return { valid: false, error: "target version is required" };
|
|
56179
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*)?(?:\+[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*)?$/.test(version2)) {
|
|
56180
|
+
return { valid: false, error: `invalid semver target: ${version2}` };
|
|
56181
|
+
}
|
|
56182
|
+
return { valid: true };
|
|
56183
|
+
}
|
|
56184
|
+
function verifyPublishedMandatoryUpdateTarget(packageName, targetVersion, deps = {}) {
|
|
56185
|
+
if (!/^(?:adhdev|@adhdev\/daemon-standalone)$/.test(packageName)) {
|
|
56186
|
+
throw new Error(`invalid mandatory update package: ${packageName}`);
|
|
56187
|
+
}
|
|
56188
|
+
const validation = validateMandatoryUpdateTarget(targetVersion);
|
|
56189
|
+
if (!validation.valid) throw new Error(validation.error || "invalid mandatory update target");
|
|
56190
|
+
const run = deps.execFileSync || import_child_process13.execFileSync;
|
|
56191
|
+
const npmExecutable = deps.npmExecutable || resolveCurrentGlobalInstallSurface({ packageName }).npmExecutable;
|
|
56192
|
+
const published = String(run(npmExecutable, ["view", `${packageName}@${targetVersion}`, "version"], {
|
|
56193
|
+
encoding: "utf-8",
|
|
56194
|
+
timeout: 1e4,
|
|
56195
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
56196
|
+
...process.platform === "win32" ? { shell: true, windowsHide: true } : {}
|
|
56197
|
+
})).trim();
|
|
56198
|
+
if (published !== targetVersion) {
|
|
56199
|
+
throw new Error(`Published version mismatch: expected ${targetVersion}, got ${published || "unknown"}`);
|
|
56200
|
+
}
|
|
56201
|
+
return published;
|
|
56202
|
+
}
|
|
56203
|
+
function buildMandatoryUpdateInfoFromServerPayload(payload, fallbackVersion) {
|
|
56204
|
+
const targetVersion = typeof payload?.latest === "string" && payload.latest ? payload.latest : fallbackVersion;
|
|
56205
|
+
const validation = validateMandatoryUpdateTarget(targetVersion);
|
|
56206
|
+
if (!validation.valid) return { info: null, error: validation.error || targetVersion };
|
|
56207
|
+
return {
|
|
56208
|
+
info: {
|
|
56209
|
+
targetVersion,
|
|
56210
|
+
reason: typeof payload?.reason === "string" && payload.reason.trim() ? payload.reason.trim() : "major_minor_mismatch",
|
|
56211
|
+
minVersion: typeof payload?.minVersion === "string" && payload.minVersion.trim() ? payload.minVersion.trim() : void 0
|
|
56212
|
+
}
|
|
56213
|
+
};
|
|
56214
|
+
}
|
|
56215
|
+
function buildMandatoryUpdateRequiredPayload(pending, interactionId) {
|
|
56216
|
+
return {
|
|
56217
|
+
error: "A mandatory daemon update is pending. Finish current work and let the daemon update before starting a new session.",
|
|
56218
|
+
code: "DAEMON_UPDATE_REQUIRED",
|
|
56219
|
+
required: true,
|
|
56220
|
+
latest: pending.targetVersion,
|
|
56221
|
+
reason: pending.reason,
|
|
56222
|
+
interactionId
|
|
56223
|
+
};
|
|
56224
|
+
}
|
|
55999
56225
|
function resolveDaemonPort(ref = {}) {
|
|
56000
56226
|
return Number.isFinite(ref.port) && Number(ref.port) > 0 ? Number(ref.port) : DEFAULT_DAEMON_PORT;
|
|
56001
56227
|
}
|
|
@@ -56022,7 +56248,7 @@ function removeDaemonPid(ref = {}) {
|
|
|
56022
56248
|
function isDaemonRunning(ref = {}) {
|
|
56023
56249
|
const port = resolveDaemonPort(ref);
|
|
56024
56250
|
try {
|
|
56025
|
-
const { execFileSync:
|
|
56251
|
+
const { execFileSync: execFileSync6 } = require("child_process");
|
|
56026
56252
|
const probe = `
|
|
56027
56253
|
const http = require('http');
|
|
56028
56254
|
const req = http.get('http://127.0.0.1:${port}/health', { timeout: 1500 }, (res) => {
|
|
@@ -56032,7 +56258,7 @@ function isDaemonRunning(ref = {}) {
|
|
|
56032
56258
|
req.on('error', () => process.stdout.write('0'));
|
|
56033
56259
|
req.on('timeout', () => { req.destroy(); process.stdout.write('0'); });
|
|
56034
56260
|
`;
|
|
56035
|
-
const result =
|
|
56261
|
+
const result = execFileSync6(process.execPath, ["-e", probe], {
|
|
56036
56262
|
encoding: "utf-8",
|
|
56037
56263
|
timeout: 3e3,
|
|
56038
56264
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -56058,9 +56284,9 @@ function isDaemonRunning(ref = {}) {
|
|
|
56058
56284
|
function isAdhdevProcess(pid) {
|
|
56059
56285
|
try {
|
|
56060
56286
|
if (process.platform === "win32") {
|
|
56061
|
-
const { execFileSync:
|
|
56287
|
+
const { execFileSync: execFileSync6 } = require("child_process");
|
|
56062
56288
|
try {
|
|
56063
|
-
const psOut =
|
|
56289
|
+
const psOut = execFileSync6("powershell.exe", [
|
|
56064
56290
|
"-NoProfile",
|
|
56065
56291
|
"-NonInteractive",
|
|
56066
56292
|
"-ExecutionPolicy",
|
|
@@ -56073,8 +56299,8 @@ function isAdhdevProcess(pid) {
|
|
|
56073
56299
|
return true;
|
|
56074
56300
|
}
|
|
56075
56301
|
} else {
|
|
56076
|
-
const { execFileSync:
|
|
56077
|
-
const cmdline =
|
|
56302
|
+
const { execFileSync: execFileSync6 } = require("child_process");
|
|
56303
|
+
const cmdline = execFileSync6("ps", ["-o", "command=", "-p", String(pid)], {
|
|
56078
56304
|
encoding: "utf-8",
|
|
56079
56305
|
timeout: 2e3,
|
|
56080
56306
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -56088,7 +56314,7 @@ function isAdhdevProcess(pid) {
|
|
|
56088
56314
|
function getDaemonHealthPid(ref = {}) {
|
|
56089
56315
|
const port = resolveDaemonPort(ref);
|
|
56090
56316
|
try {
|
|
56091
|
-
const { execFileSync:
|
|
56317
|
+
const { execFileSync: execFileSync6 } = require("child_process");
|
|
56092
56318
|
const probe = `
|
|
56093
56319
|
const http = require('http');
|
|
56094
56320
|
const req = http.get('http://127.0.0.1:${port}/health', { timeout: 1500 }, (res) => {
|
|
@@ -56106,7 +56332,7 @@ function getDaemonHealthPid(ref = {}) {
|
|
|
56106
56332
|
req.on('error', () => {});
|
|
56107
56333
|
req.on('timeout', () => { req.destroy(); });
|
|
56108
56334
|
`;
|
|
56109
|
-
const result =
|
|
56335
|
+
const result = execFileSync6(process.execPath, ["-e", probe], {
|
|
56110
56336
|
encoding: "utf-8",
|
|
56111
56337
|
timeout: 3e3,
|
|
56112
56338
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -56152,7 +56378,7 @@ function stopDaemon(ref = {}) {
|
|
|
56152
56378
|
return false;
|
|
56153
56379
|
}
|
|
56154
56380
|
}
|
|
56155
|
-
var os26, fs18, path26, import_http, import_ws3, pkgVersion, AdhdevDaemon;
|
|
56381
|
+
var os26, fs18, path26, import_http, import_child_process13, import_ws3, pkgVersion, AdhdevDaemon;
|
|
56156
56382
|
var init_adhdev_daemon = __esm({
|
|
56157
56383
|
"src/adhdev-daemon.ts"() {
|
|
56158
56384
|
"use strict";
|
|
@@ -56168,12 +56394,13 @@ var init_adhdev_daemon = __esm({
|
|
|
56168
56394
|
fs18 = __toESM(require("fs"));
|
|
56169
56395
|
path26 = __toESM(require("path"));
|
|
56170
56396
|
import_http = require("http");
|
|
56397
|
+
import_child_process13 = require("child_process");
|
|
56171
56398
|
import_ws3 = require("ws");
|
|
56172
56399
|
init_source2();
|
|
56173
56400
|
init_version();
|
|
56174
56401
|
init_src();
|
|
56175
56402
|
init_runtime_defaults();
|
|
56176
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.
|
|
56403
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.34" });
|
|
56177
56404
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
56178
56405
|
localHttpServer = null;
|
|
56179
56406
|
localWss = null;
|
|
@@ -56266,6 +56493,10 @@ var init_adhdev_daemon = __esm({
|
|
|
56266
56493
|
getUpgradePackageName() {
|
|
56267
56494
|
return process.argv[1]?.includes("daemon-standalone") ? "@adhdev/daemon-standalone" : "adhdev";
|
|
56268
56495
|
}
|
|
56496
|
+
getMandatoryUpdateBlockPayload(cmd, interactionId) {
|
|
56497
|
+
if (!this.pendingMandatoryUpdate || !_AdhdevDaemon.MANDATORY_UPDATE_BLOCKED_COMMANDS.has(cmd)) return null;
|
|
56498
|
+
return buildMandatoryUpdateRequiredPayload(this.pendingMandatoryUpdate, interactionId);
|
|
56499
|
+
}
|
|
56269
56500
|
hasBlockingSessionsForMandatoryUpdate() {
|
|
56270
56501
|
if (!this.components) return false;
|
|
56271
56502
|
const blocking = /* @__PURE__ */ new Set(["generating", "waiting_approval", "starting"]);
|
|
@@ -56291,15 +56522,7 @@ var init_adhdev_daemon = __esm({
|
|
|
56291
56522
|
const pkgName = this.getUpgradePackageName();
|
|
56292
56523
|
this.mandatoryUpgradeInFlight = true;
|
|
56293
56524
|
try {
|
|
56294
|
-
|
|
56295
|
-
const published = execSync7(`npm view ${pkgName}@${pending.targetVersion} version`, {
|
|
56296
|
-
encoding: "utf-8",
|
|
56297
|
-
timeout: 1e4,
|
|
56298
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
56299
|
-
}).trim();
|
|
56300
|
-
if (published !== pending.targetVersion) {
|
|
56301
|
-
throw new Error(`Published version mismatch: expected ${pending.targetVersion}, got ${published || "unknown"}`);
|
|
56302
|
-
}
|
|
56525
|
+
verifyPublishedMandatoryUpdateTarget(pkgName, pending.targetVersion);
|
|
56303
56526
|
LOG.warn("Upgrade", `Applying mandatory daemon update (${pending.reason}) \u2192 v${pending.targetVersion}`);
|
|
56304
56527
|
spawnDetachedDaemonUpgradeHelper({
|
|
56305
56528
|
packageName: pkgName,
|
|
@@ -56401,7 +56624,7 @@ var init_adhdev_daemon = __esm({
|
|
|
56401
56624
|
const now = Date.now();
|
|
56402
56625
|
const cached2 = this.hotChatSnapshotCache;
|
|
56403
56626
|
const sessions = cached2 && now - cached2.builtAt < _AdhdevDaemon.HOT_CHAT_SNAPSHOT_CACHE_TTL_MS ? cached2.sessions : (() => {
|
|
56404
|
-
const built = this.
|
|
56627
|
+
const built = this.components.instanceManager.collectHotChatSessionStates();
|
|
56405
56628
|
this.hotChatSnapshotCache = { sessions: built, builtAt: now };
|
|
56406
56629
|
return built;
|
|
56407
56630
|
})();
|
|
@@ -56786,14 +57009,17 @@ ${err?.stack || ""}`);
|
|
|
56786
57009
|
isRunning: () => this.running,
|
|
56787
57010
|
isScreenshotActive: () => this.p2p?.screenshotActive ?? false,
|
|
56788
57011
|
getScreenshotTargetSessionId: () => this.p2p?.screenshotTargetSessionId,
|
|
57012
|
+
getScreenshotTargetSessionIds: () => this.p2p?.screenshotTargetSessionIds ?? [],
|
|
56789
57013
|
isUsingRelay: () => this.p2p?.isUsingRelay ?? false,
|
|
56790
57014
|
hasAnyNeedingFirstFrame: () => this.p2p?.hasAnyNeedingFirstFrame() ?? false,
|
|
57015
|
+
hasAnyNeedingFirstFrameForTarget: (targetSessionId) => this.p2p?.hasAnyNeedingFirstFrameForTarget(targetSessionId) ?? false,
|
|
56791
57016
|
getCdp: (targetSessionId) => {
|
|
56792
57017
|
if (targetSessionId) return this.getCdpFor(targetSessionId);
|
|
56793
57018
|
LOG.warn("P2P", "Screenshot requested without targetSessionId \u2014 cannot determine target session. Skipping frame.");
|
|
56794
57019
|
return null;
|
|
56795
57020
|
},
|
|
56796
|
-
sendScreenshotBuffer: (buf) => this.p2p.sendScreenshotBuffer(buf)
|
|
57021
|
+
sendScreenshotBuffer: (buf) => this.p2p.sendScreenshotBuffer(buf),
|
|
57022
|
+
sendScreenshotBufferForTarget: (targetSessionId, buf) => this.p2p.sendScreenshotBufferForTarget(targetSessionId, buf)
|
|
56797
57023
|
}, planLimits ?? void 0);
|
|
56798
57024
|
this.screenshotController.start();
|
|
56799
57025
|
this.p2p.onScreenshotStart(() => this.screenshotController?.triggerImmediate());
|
|
@@ -56822,11 +57048,12 @@ ${err?.stack || ""}`);
|
|
|
56822
57048
|
});
|
|
56823
57049
|
this.serverConn.on("force_update_required", (msg) => {
|
|
56824
57050
|
const payload = msg.payload;
|
|
56825
|
-
|
|
56826
|
-
|
|
56827
|
-
|
|
56828
|
-
|
|
56829
|
-
}
|
|
57051
|
+
const parsedUpdate = buildMandatoryUpdateInfoFromServerPayload(payload, pkgVersion);
|
|
57052
|
+
if (!parsedUpdate.info) {
|
|
57053
|
+
LOG.error("Upgrade", `Ignoring invalid mandatory daemon update target from server: ${parsedUpdate.error || "unknown"}`);
|
|
57054
|
+
return;
|
|
57055
|
+
}
|
|
57056
|
+
this.pendingMandatoryUpdate = parsedUpdate.info;
|
|
56830
57057
|
LOG.warn("Upgrade", `Mandatory daemon update required (${this.pendingMandatoryUpdate.reason})`);
|
|
56831
57058
|
void this.maybeApplyMandatoryUpdate("server-force-update");
|
|
56832
57059
|
});
|
|
@@ -56937,15 +57164,9 @@ ${err?.stack || ""}`);
|
|
|
56937
57164
|
const cmdStart = Date.now();
|
|
56938
57165
|
const source = msg.ipcWs ? "ext" : typeof msg.source === "string" && msg.source.trim() ? msg.source : "ws";
|
|
56939
57166
|
try {
|
|
56940
|
-
|
|
56941
|
-
|
|
56942
|
-
|
|
56943
|
-
code: "DAEMON_UPDATE_REQUIRED",
|
|
56944
|
-
required: true,
|
|
56945
|
-
latest: this.pendingMandatoryUpdate.targetVersion,
|
|
56946
|
-
reason: this.pendingMandatoryUpdate.reason,
|
|
56947
|
-
interactionId
|
|
56948
|
-
});
|
|
57167
|
+
const mandatoryUpdateBlock = this.getMandatoryUpdateBlockPayload(cmd, interactionId);
|
|
57168
|
+
if (mandatoryUpdateBlock) {
|
|
57169
|
+
this.sendResult(msg, false, mandatoryUpdateBlock);
|
|
56949
57170
|
return;
|
|
56950
57171
|
}
|
|
56951
57172
|
if (source === "api" && !loadConfig().allowServerApiProxy) {
|
|
@@ -56990,6 +57211,10 @@ ${err?.stack || ""}`);
|
|
|
56990
57211
|
const interactionId = String(normalizedData._interactionId);
|
|
56991
57212
|
const cmdStart = Date.now();
|
|
56992
57213
|
try {
|
|
57214
|
+
const mandatoryUpdateBlock = this.getMandatoryUpdateBlockPayload(cmdType, interactionId);
|
|
57215
|
+
if (mandatoryUpdateBlock) {
|
|
57216
|
+
return { success: false, ...mandatoryUpdateBlock };
|
|
57217
|
+
}
|
|
56993
57218
|
switch (cmdType) {
|
|
56994
57219
|
case "get_runtime_snapshot": {
|
|
56995
57220
|
const sessionId = typeof normalizedData.sessionId === "string" ? normalizedData.sessionId : "";
|
|
@@ -57168,8 +57393,22 @@ ${err?.stack || ""}`);
|
|
|
57168
57393
|
}));
|
|
57169
57394
|
return;
|
|
57170
57395
|
}
|
|
57396
|
+
const normalizedArgs = this.ensureInteractionContext(args);
|
|
57397
|
+
const interactionId = String(normalizedArgs._interactionId);
|
|
57398
|
+
const mandatoryUpdateBlock = this.getMandatoryUpdateBlockPayload(command, interactionId);
|
|
57399
|
+
if (mandatoryUpdateBlock) {
|
|
57400
|
+
ws.send(JSON.stringify({
|
|
57401
|
+
type: "ext:command_result",
|
|
57402
|
+
payload: {
|
|
57403
|
+
requestId,
|
|
57404
|
+
success: false,
|
|
57405
|
+
...mandatoryUpdateBlock
|
|
57406
|
+
}
|
|
57407
|
+
}));
|
|
57408
|
+
return;
|
|
57409
|
+
}
|
|
57171
57410
|
try {
|
|
57172
|
-
const result = await this.components.router.execute(command,
|
|
57411
|
+
const result = await this.components.router.execute(command, normalizedArgs, "ipc");
|
|
57173
57412
|
ws.send(JSON.stringify({
|
|
57174
57413
|
type: "ext:command_result",
|
|
57175
57414
|
payload: {
|
|
@@ -85994,12 +86233,12 @@ function splitStringBySpace(str) {
|
|
|
85994
86233
|
}
|
|
85995
86234
|
return pieces;
|
|
85996
86235
|
}
|
|
85997
|
-
var import_chardet,
|
|
86236
|
+
var import_chardet, import_child_process14, import_fs7, import_node_path2, import_node_os4, import_node_crypto, import_iconv_lite, ExternalEditor;
|
|
85998
86237
|
var init_esm2 = __esm({
|
|
85999
86238
|
"../../node_modules/@inquirer/external-editor/dist/esm/index.js"() {
|
|
86000
86239
|
"use strict";
|
|
86001
86240
|
import_chardet = __toESM(require_lib2(), 1);
|
|
86002
|
-
|
|
86241
|
+
import_child_process14 = require("child_process");
|
|
86003
86242
|
import_fs7 = require("fs");
|
|
86004
86243
|
import_node_path2 = __toESM(require("path"), 1);
|
|
86005
86244
|
import_node_os4 = __toESM(require("os"), 1);
|
|
@@ -86106,7 +86345,7 @@ var init_esm2 = __esm({
|
|
|
86106
86345
|
}
|
|
86107
86346
|
launchEditor() {
|
|
86108
86347
|
try {
|
|
86109
|
-
const editorProcess = (0,
|
|
86348
|
+
const editorProcess = (0, import_child_process14.spawnSync)(this.editor.bin, this.editor.args.concat([this.tempFile]), { stdio: "inherit" });
|
|
86110
86349
|
this.lastExitStatus = editorProcess.status ?? 0;
|
|
86111
86350
|
} catch (launchError) {
|
|
86112
86351
|
throw new LaunchEditorError(launchError);
|
|
@@ -86114,7 +86353,7 @@ var init_esm2 = __esm({
|
|
|
86114
86353
|
}
|
|
86115
86354
|
launchEditorAsync(callback) {
|
|
86116
86355
|
try {
|
|
86117
|
-
const editorProcess = (0,
|
|
86356
|
+
const editorProcess = (0, import_child_process14.spawn)(this.editor.bin, this.editor.args.concat([this.tempFile]), { stdio: "inherit" });
|
|
86118
86357
|
editorProcess.on("exit", (code) => {
|
|
86119
86358
|
this.lastExitStatus = code;
|
|
86120
86359
|
setImmediate(callback);
|
|
@@ -88392,9 +88631,9 @@ async function runWizard(options = {}) {
|
|
|
88392
88631
|
}
|
|
88393
88632
|
async function checkForUpdate() {
|
|
88394
88633
|
try {
|
|
88395
|
-
const { execFileSync:
|
|
88634
|
+
const { execFileSync: execFileSync6 } = await import("child_process");
|
|
88396
88635
|
const currentVersion = resolvePackageVersion();
|
|
88397
|
-
const latestVersion = readLatestPublishedCliVersion(
|
|
88636
|
+
const latestVersion = readLatestPublishedCliVersion(execFileSync6);
|
|
88398
88637
|
if (!latestVersion) return;
|
|
88399
88638
|
if (!currentVersion || !latestVersion || currentVersion === latestVersion) return;
|
|
88400
88639
|
console.log(source_default2.yellow(` Update available: ${currentVersion} \u2192 ${latestVersion}`));
|
|
@@ -88411,7 +88650,7 @@ async function checkForUpdate() {
|
|
|
88411
88650
|
const spinner = (await Promise.resolve().then(() => (init_ora(), ora_exports))).default("Updating adhdev CLI...").start();
|
|
88412
88651
|
try {
|
|
88413
88652
|
const installCommand = buildPinnedGlobalInstallCommand({ packageName: "adhdev", targetVersion: "latest" });
|
|
88414
|
-
|
|
88653
|
+
execFileSync6(installCommand.command, installCommand.args, {
|
|
88415
88654
|
encoding: "utf-8",
|
|
88416
88655
|
timeout: 6e4,
|
|
88417
88656
|
stdio: ["pipe", "pipe", "pipe"]
|