@adhdev/daemon-core 1.0.18-rc.2 → 1.0.18-rc.3
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-adapters/cli-state-engine.d.ts +77 -0
- package/dist/cli-adapters/pty-transport.d.ts +2 -1
- package/dist/commands/process-lifecycle.d.ts +43 -0
- package/dist/commands/windows-atomic-upgrade.d.ts +12 -1
- package/dist/index.js +470 -147
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +479 -156
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/cli-adapters/cli-state-engine.ts +204 -3
- package/src/cli-adapters/provider-cli-adapter.ts +39 -5
- package/src/cli-adapters/pty-transport.d.ts +2 -1
- package/src/cli-adapters/pty-transport.ts +1 -1
- package/src/cli-adapters/session-host-transport.ts +8 -3
- package/src/commands/process-lifecycle.ts +248 -0
- package/src/commands/upgrade-helper.ts +29 -68
- package/src/commands/windows-atomic-upgrade.ts +96 -4
- package/src/session-host/managed-host.ts +34 -0
package/dist/index.mjs
CHANGED
|
@@ -437,10 +437,10 @@ function readInjected(value) {
|
|
|
437
437
|
}
|
|
438
438
|
function getDaemonBuildInfo() {
|
|
439
439
|
if (cached) return cached;
|
|
440
|
-
const commit = readInjected(true ? "
|
|
441
|
-
const commitShort = readInjected(true ? "
|
|
442
|
-
const version = readInjected(true ? "1.0.18-rc.
|
|
443
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
440
|
+
const commit = readInjected(true ? "96f3f1365be0d875f5089fc7ce7e4e254ca8e08d" : void 0) ?? "unknown";
|
|
441
|
+
const commitShort = readInjected(true ? "96f3f136" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
442
|
+
const version = readInjected(true ? "1.0.18-rc.3" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
443
|
+
const builtAt = readInjected(true ? "2026-07-21T13:00:17.395Z" : void 0);
|
|
444
444
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
445
445
|
return cached;
|
|
446
446
|
}
|
|
@@ -25780,6 +25780,22 @@ var init_cli_state_engine = __esm({
|
|
|
25780
25780
|
// ── Approval ─────────────────────────────────────
|
|
25781
25781
|
lastApprovalResolvedAt = 0;
|
|
25782
25782
|
lastResolvedModalMessage = "";
|
|
25783
|
+
/**
|
|
25784
|
+
* Normalized approval-context signature captured at resolve time (see
|
|
25785
|
+
* `computeApprovalContentSignature`) — the screen text with blank-line
|
|
25786
|
+
* padding and any manifest-declared chrome (transcriptPty.chromePatterns,
|
|
25787
|
+
* spinner.patterns) stripped out. Used by applyWaitingApproval's
|
|
25788
|
+
* isStaleResolvedRepaint check to tell "the same already-answered modal,
|
|
25789
|
+
* re-parsed from a screen that has not meaningfully changed" apart from
|
|
25790
|
+
* "a genuinely new approval" — content-based, not time-based, because
|
|
25791
|
+
* ordinary TUI chrome (status bar, context meter, blank-line repaint)
|
|
25792
|
+
* keeps producing fresh PTY bytes on an otherwise-unchanged screen and
|
|
25793
|
+
* defeats any output-timestamp discriminator within a few hundred ms.
|
|
25794
|
+
* Cleared whenever a turn starts or the session tears down (see
|
|
25795
|
+
* onTurnStarted / resetActiveTurnState / onPtyExit) so a next-turn
|
|
25796
|
+
* approval is never compared against stale prior-turn state.
|
|
25797
|
+
*/
|
|
25798
|
+
lastApprovalResolvedContentSignature = "";
|
|
25783
25799
|
/**
|
|
25784
25800
|
* Monotonic counter bumped every time the FSM *enters* waiting_approval
|
|
25785
25801
|
* with a freshly captured modal (see `applyWaitingApproval`). It is the
|
|
@@ -25899,11 +25915,17 @@ var init_cli_state_engine = __esm({
|
|
|
25899
25915
|
this.currentTurnTaskId = typeof turnScope.taskId === "string" && turnScope.taskId.trim() ? turnScope.taskId : null;
|
|
25900
25916
|
this.currentTurnStartedAt = Date.now();
|
|
25901
25917
|
this.responseEpoch += 1;
|
|
25918
|
+
this.clearApprovalResolutionMemory();
|
|
25919
|
+
if (this.provider.transcriptAuthority === "provider" && this.currentStatus !== "waiting_approval") {
|
|
25920
|
+
this.setStatus("generating", "turn_started");
|
|
25921
|
+
this.callbacks.onStatusChange();
|
|
25922
|
+
}
|
|
25902
25923
|
}
|
|
25903
25924
|
/** Called when PTY exits */
|
|
25904
25925
|
onPtyExit() {
|
|
25905
25926
|
this.clearAllTimers();
|
|
25906
25927
|
this.setStatus("stopped", "pty_exit");
|
|
25928
|
+
this.clearApprovalResolutionMemory();
|
|
25907
25929
|
}
|
|
25908
25930
|
/** Called when adapter starts up successfully */
|
|
25909
25931
|
onSpawnReady() {
|
|
@@ -25945,6 +25967,7 @@ var init_cli_state_engine = __esm({
|
|
|
25945
25967
|
this.activeModal = null;
|
|
25946
25968
|
this.lastApprovalResolvedAt = Date.now();
|
|
25947
25969
|
this.lastResolvedModalMessage = currentModalMessage;
|
|
25970
|
+
this.lastApprovalResolvedContentSignature = this.computeApprovalContentSignature(snap);
|
|
25948
25971
|
this.lastResolvedEntrySeq = this.approvalEntrySeq;
|
|
25949
25972
|
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
25950
25973
|
if (this.approvalExitTimeout) {
|
|
@@ -26067,6 +26090,7 @@ var init_cli_state_engine = __esm({
|
|
|
26067
26090
|
this.pendingScriptStatusSince = 0;
|
|
26068
26091
|
this.approvalResumeDeferSince = 0;
|
|
26069
26092
|
this.approvalResumeDeferEpoch = -1;
|
|
26093
|
+
this.clearApprovalResolutionMemory();
|
|
26070
26094
|
}
|
|
26071
26095
|
clearIdleFinishCandidate(reason) {
|
|
26072
26096
|
if (!this.idleFinishCandidate) return;
|
|
@@ -26225,7 +26249,15 @@ var init_cli_state_engine = __esm({
|
|
|
26225
26249
|
}
|
|
26226
26250
|
if (!status) return;
|
|
26227
26251
|
const prevStatus = this.currentStatus;
|
|
26228
|
-
const ctx = {
|
|
26252
|
+
const ctx = {
|
|
26253
|
+
now,
|
|
26254
|
+
modal,
|
|
26255
|
+
status,
|
|
26256
|
+
parsedMessages,
|
|
26257
|
+
lastParsedAssistant,
|
|
26258
|
+
parsedStatus: parsedStatus || null,
|
|
26259
|
+
prevStatus
|
|
26260
|
+
};
|
|
26229
26261
|
if (!this.applyPendingScriptStatusDebounce(ctx)) return;
|
|
26230
26262
|
const recentInteractiveActivity = this.hasRecentInteractiveActivity(snap, now);
|
|
26231
26263
|
LOG.debug(
|
|
@@ -26261,7 +26293,7 @@ var init_cli_state_engine = __esm({
|
|
|
26261
26293
|
return;
|
|
26262
26294
|
}
|
|
26263
26295
|
if (status === "waiting_approval") {
|
|
26264
|
-
this.applyWaitingApproval(ctx);
|
|
26296
|
+
this.applyWaitingApproval(ctx, snap);
|
|
26265
26297
|
return;
|
|
26266
26298
|
}
|
|
26267
26299
|
if (status === "generating") {
|
|
@@ -26321,7 +26353,7 @@ var init_cli_state_engine = __esm({
|
|
|
26321
26353
|
}, this.timeouts.generatingIdle);
|
|
26322
26354
|
this.callbacks.onStatusChange();
|
|
26323
26355
|
}
|
|
26324
|
-
applyWaitingApproval(ctx) {
|
|
26356
|
+
applyWaitingApproval(ctx, snap) {
|
|
26325
26357
|
const { modal } = ctx;
|
|
26326
26358
|
this.clearIdleFinishCandidate("waiting_approval");
|
|
26327
26359
|
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
@@ -26368,6 +26400,11 @@ var init_cli_state_engine = __esm({
|
|
|
26368
26400
|
}
|
|
26369
26401
|
return;
|
|
26370
26402
|
}
|
|
26403
|
+
const isStaleResolvedRepaint = !this.activeModal && this.isStaleResolvedApproval(modal, snap);
|
|
26404
|
+
if (isStaleResolvedRepaint) {
|
|
26405
|
+
LOG.debug("CLI", `[${this.provider.type}] ignoring stale re-parsed approval matching the just-resolved modal (approval-context signature unchanged)`);
|
|
26406
|
+
return;
|
|
26407
|
+
}
|
|
26371
26408
|
this.modalLostAt = 0;
|
|
26372
26409
|
this.isWaitingForResponse = true;
|
|
26373
26410
|
this.setStatus("waiting_approval", "script_detect");
|
|
@@ -26653,6 +26690,86 @@ var init_cli_state_engine = __esm({
|
|
|
26653
26690
|
this.recordTrace("idle_finish_cancelled", { trigger: reason });
|
|
26654
26691
|
}
|
|
26655
26692
|
// ─── Helpers ────────────────────────────────────────────────────────────
|
|
26693
|
+
/**
|
|
26694
|
+
* Derive a stable approval-context signature from the current screen,
|
|
26695
|
+
* with blank-line padding and any manifest-declared chrome stripped out.
|
|
26696
|
+
*
|
|
26697
|
+
* Generic by design — no kimi- or provider-specific hardcoding: it reads
|
|
26698
|
+
* whatever `tui.transcriptPty.chromePatterns` and `tui.spinner.patterns`
|
|
26699
|
+
* the ACTIVE provider's own manifest already declares (present on any
|
|
26700
|
+
* declarative-TUI provider; simply absent/empty for scripted providers,
|
|
26701
|
+
* in which case this degrades to blank-line stripping only — never worse
|
|
26702
|
+
* than comparing the raw screen). Those pattern lists exist precisely to
|
|
26703
|
+
* name "known volatile repaint noise" (status bar, context meter, spinner
|
|
26704
|
+
* ticks, banners) — reusing them here means the SAME declared knowledge
|
|
26705
|
+
* that governs transcript-chrome stripping also governs staleness
|
|
26706
|
+
* detection, instead of re-encoding provider knowledge into daemon-core.
|
|
26707
|
+
*
|
|
26708
|
+
* Deliberately NOT a hash of the whole screen/buffer: an ordinary TUI
|
|
26709
|
+
* repaints its footer/status/context-meter chrome continuously even while
|
|
26710
|
+
* genuinely idle, so a raw whole-screen or whole-buffer fingerprint (or a
|
|
26711
|
+
* mere "did any bytes arrive" timestamp) changes on every repaint tick
|
|
26712
|
+
* regardless of whether anything approval-relevant actually happened.
|
|
26713
|
+
* Stripping the declared chrome first yields a signature that only
|
|
26714
|
+
* changes when the surrounding conversation/tool-output content itself
|
|
26715
|
+
* changes — exactly the discriminator applyWaitingApproval's
|
|
26716
|
+
* isStaleResolvedRepaint check needs.
|
|
26717
|
+
*/
|
|
26718
|
+
computeApprovalContentSignature(snap) {
|
|
26719
|
+
const screenText = snap.screenText || snap.accumulatedBuffer || "";
|
|
26720
|
+
if (!screenText) return "";
|
|
26721
|
+
const tui = this.provider.tui;
|
|
26722
|
+
const patternSpecs = [
|
|
26723
|
+
...Array.isArray(tui?.transcriptPty?.chromePatterns) ? tui.transcriptPty.chromePatterns : [],
|
|
26724
|
+
...Array.isArray(tui?.spinner?.patterns) ? tui.spinner.patterns : []
|
|
26725
|
+
];
|
|
26726
|
+
const chromeRegexes = [];
|
|
26727
|
+
for (const spec of patternSpecs) {
|
|
26728
|
+
if (spec && typeof spec.regex === "string") {
|
|
26729
|
+
try {
|
|
26730
|
+
chromeRegexes.push(new RegExp(spec.regex, typeof spec.flags === "string" ? spec.flags : ""));
|
|
26731
|
+
} catch {
|
|
26732
|
+
}
|
|
26733
|
+
}
|
|
26734
|
+
}
|
|
26735
|
+
const kept = [];
|
|
26736
|
+
for (const rawLine of screenText.split("\n")) {
|
|
26737
|
+
const line = rawLine.trim();
|
|
26738
|
+
if (!line) continue;
|
|
26739
|
+
if (chromeRegexes.some((re) => re.test(line))) continue;
|
|
26740
|
+
kept.push(line);
|
|
26741
|
+
}
|
|
26742
|
+
return kept.join("\n");
|
|
26743
|
+
}
|
|
26744
|
+
/**
|
|
26745
|
+
* True when `modal` is a stale re-parse of an already-resolved approval:
|
|
26746
|
+
* same message text, and the chrome-stripped approval-context signature
|
|
26747
|
+
* of `snap` is unchanged from the signature captured at resolve time.
|
|
26748
|
+
*
|
|
26749
|
+
* Public and reused verbatim by BOTH the settled-eval capture path
|
|
26750
|
+
* (applyWaitingApproval, below) and any OUTSIDE re-parse the adapter
|
|
26751
|
+
* performs independently of the settle loop — e.g. provider-cli-adapter's
|
|
26752
|
+
* getStatus()/getDebugState() startup-gate modal detection, which reads
|
|
26753
|
+
* `recentOutputBuffer` directly while `startupParseGate` is open and can
|
|
26754
|
+
* re-surface the same already-resolved modal before the gate closes.
|
|
26755
|
+
* Centralizing the discriminator here means there is exactly ONE
|
|
26756
|
+
* definition of "stale" for the whole session — no divergent duplicate
|
|
26757
|
+
* heuristic re-implemented per call site.
|
|
26758
|
+
*/
|
|
26759
|
+
isStaleResolvedApproval(modal, snap) {
|
|
26760
|
+
if (!modal) return false;
|
|
26761
|
+
const normalizedMessage = typeof modal.message === "string" ? modal.message.trim() : "";
|
|
26762
|
+
if (!normalizedMessage) return false;
|
|
26763
|
+
return this.lastApprovalResolvedAt > 0 && normalizedMessage === this.lastResolvedModalMessage && this.computeApprovalContentSignature(snap) === this.lastApprovalResolvedContentSignature;
|
|
26764
|
+
}
|
|
26765
|
+
/** Clear all resolve-time approval bookkeeping (message, timestamp, content
|
|
26766
|
+
* signature) — called at turn/session boundaries so a next-turn or
|
|
26767
|
+
* next-session approval is never compared against stale prior state. */
|
|
26768
|
+
clearApprovalResolutionMemory() {
|
|
26769
|
+
this.lastApprovalResolvedAt = 0;
|
|
26770
|
+
this.lastResolvedModalMessage = "";
|
|
26771
|
+
this.lastApprovalResolvedContentSignature = "";
|
|
26772
|
+
}
|
|
26656
26773
|
/**
|
|
26657
26774
|
* Schedule one more settled evaluation while pinned to `waiting_approval`
|
|
26658
26775
|
* with no actionable modal. The settled FSM normally only re-runs on new
|
|
@@ -27477,8 +27594,8 @@ ${lastSnapshot}`;
|
|
|
27477
27594
|
}
|
|
27478
27595
|
}
|
|
27479
27596
|
});
|
|
27480
|
-
this.ptyProcess.onExit(({ exitCode }) => {
|
|
27481
|
-
LOG.info("CLI", `[${this.cliType}] Exit code ${exitCode}`);
|
|
27597
|
+
this.ptyProcess.onExit(({ exitCode, signal }) => {
|
|
27598
|
+
LOG.info("CLI", `[${this.cliType}] Exit code ${exitCode === null || exitCode === void 0 ? "unknown" : exitCode}${signal ? ` (signal ${signal})` : ""}`);
|
|
27482
27599
|
this.flushPendingOutputParse();
|
|
27483
27600
|
this.ptyProcess = null;
|
|
27484
27601
|
this.engine.onPtyExit();
|
|
@@ -27784,7 +27901,10 @@ ${lastSnapshot}`;
|
|
|
27784
27901
|
// ─── Public API (CliAdapter) ───────────────────
|
|
27785
27902
|
getStatus(options = {}) {
|
|
27786
27903
|
const allowParse = options.allowParse !== false;
|
|
27787
|
-
|
|
27904
|
+
let startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
27905
|
+
if (startupModal && this.engine.isStaleResolvedApproval(startupModal, { screenText: this.terminalScreen.getText(), accumulatedBuffer: this.accumulatedBuffer })) {
|
|
27906
|
+
startupModal = null;
|
|
27907
|
+
}
|
|
27788
27908
|
const startupDetectedStatus = allowParse && this.startupParseGate && !startupModal ? this.runDetectStatus(this.recentOutputBuffer || this.terminalScreen.getText()) : null;
|
|
27789
27909
|
if (allowParse && this.engine.currentStatus === "generating" && !this.engine.currentTurnScope && !this.engine.activeModal) {
|
|
27790
27910
|
const now = Date.now();
|
|
@@ -27818,7 +27938,7 @@ ${lastSnapshot}`;
|
|
|
27818
27938
|
if (liveDetect === "waiting_approval") {
|
|
27819
27939
|
const liveModal = this.runParseApproval(this.terminalScreen.getText()) || this.runParseApproval(this.recentOutputBuffer);
|
|
27820
27940
|
const buttonsOk = liveModal && Array.isArray(liveModal.buttons) && liveModal.buttons.some((b) => typeof b === "string" && b.trim());
|
|
27821
|
-
if (liveModal && buttonsOk) {
|
|
27941
|
+
if (liveModal && buttonsOk && !this.engine.isStaleResolvedApproval(liveModal, { screenText: this.terminalScreen.getText(), accumulatedBuffer: this.accumulatedBuffer })) {
|
|
27822
27942
|
effectiveModal = liveModal;
|
|
27823
27943
|
if (!this.engine.activeModal) this.engine.activeModal = liveModal;
|
|
27824
27944
|
}
|
|
@@ -28944,7 +29064,10 @@ ${lastSnapshot}`;
|
|
|
28944
29064
|
}
|
|
28945
29065
|
getDebugState() {
|
|
28946
29066
|
const screenText = sanitizeTerminalText(this.terminalScreen.getText());
|
|
28947
|
-
|
|
29067
|
+
let startupModal = this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
29068
|
+
if (startupModal && this.engine.isStaleResolvedApproval(startupModal, { screenText: this.terminalScreen.getText(), accumulatedBuffer: this.accumulatedBuffer })) {
|
|
29069
|
+
startupModal = null;
|
|
29070
|
+
}
|
|
28948
29071
|
const startupDetectedStatus = this.startupParseGate && !startupModal ? this.runDetectStatus(this.recentOutputBuffer || screenText) : null;
|
|
28949
29072
|
const effectiveReady = this.ready || !!startupModal || startupDetectedStatus === "waiting_approval";
|
|
28950
29073
|
const parsedDebugState = this.getParsedDebugState();
|
|
@@ -42279,20 +42402,202 @@ var notificationHandlers = {
|
|
|
42279
42402
|
init_config();
|
|
42280
42403
|
|
|
42281
42404
|
// src/commands/upgrade-helper.ts
|
|
42282
|
-
import { execFileSync as
|
|
42405
|
+
import { execFileSync as execFileSync5 } from "child_process";
|
|
42283
42406
|
import { spawn as spawn2 } from "child_process";
|
|
42284
42407
|
import * as fs15 from "fs";
|
|
42285
42408
|
import * as os13 from "os";
|
|
42286
42409
|
import * as path21 from "path";
|
|
42287
42410
|
|
|
42288
42411
|
// src/commands/windows-atomic-upgrade.ts
|
|
42289
|
-
import { execFileSync as
|
|
42412
|
+
import { execFileSync as execFileSync4, spawn, spawnSync } from "child_process";
|
|
42290
42413
|
import * as fs14 from "fs";
|
|
42291
42414
|
import * as http2 from "http";
|
|
42292
42415
|
import * as path20 from "path";
|
|
42416
|
+
|
|
42417
|
+
// src/commands/process-lifecycle.ts
|
|
42418
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
42419
|
+
function defaultExecFileSync() {
|
|
42420
|
+
return execFileSync3;
|
|
42421
|
+
}
|
|
42422
|
+
function getWindowsProcessCommandLine(pid, exec7) {
|
|
42423
|
+
const pidFilter = `ProcessId=${pid}`;
|
|
42424
|
+
try {
|
|
42425
|
+
const psOut = exec7("powershell.exe", [
|
|
42426
|
+
"-NoProfile",
|
|
42427
|
+
"-NonInteractive",
|
|
42428
|
+
"-ExecutionPolicy",
|
|
42429
|
+
"Bypass",
|
|
42430
|
+
"-Command",
|
|
42431
|
+
`(Get-CimInstance Win32_Process -Filter "${pidFilter}").CommandLine`
|
|
42432
|
+
], { encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "ignore"], windowsHide: true });
|
|
42433
|
+
const text = String(psOut).trim();
|
|
42434
|
+
if (text) return text;
|
|
42435
|
+
} catch {
|
|
42436
|
+
}
|
|
42437
|
+
try {
|
|
42438
|
+
const wmicOut = exec7("wmic", [
|
|
42439
|
+
"process",
|
|
42440
|
+
"where",
|
|
42441
|
+
pidFilter,
|
|
42442
|
+
"get",
|
|
42443
|
+
"CommandLine"
|
|
42444
|
+
], { encoding: "utf8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"], windowsHide: true });
|
|
42445
|
+
const text = String(wmicOut).trim();
|
|
42446
|
+
if (text) return text;
|
|
42447
|
+
} catch {
|
|
42448
|
+
}
|
|
42449
|
+
return null;
|
|
42450
|
+
}
|
|
42451
|
+
function getProcessCommandLine(pid, options = {}) {
|
|
42452
|
+
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
42453
|
+
const exec7 = options.execFileSync ?? defaultExecFileSync();
|
|
42454
|
+
const platform10 = options.platform ?? process.platform;
|
|
42455
|
+
if (platform10 === "win32") {
|
|
42456
|
+
return getWindowsProcessCommandLine(pid, exec7);
|
|
42457
|
+
}
|
|
42458
|
+
try {
|
|
42459
|
+
const text = String(exec7("ps", ["-o", "command=", "-p", String(pid)], {
|
|
42460
|
+
encoding: "utf8",
|
|
42461
|
+
timeout: 3e3,
|
|
42462
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
42463
|
+
})).trim();
|
|
42464
|
+
return text || null;
|
|
42465
|
+
} catch {
|
|
42466
|
+
return null;
|
|
42467
|
+
}
|
|
42468
|
+
}
|
|
42469
|
+
function parseNodeScriptPath(commandLine) {
|
|
42470
|
+
if (!commandLine) return null;
|
|
42471
|
+
let rest = commandLine.trim();
|
|
42472
|
+
if (rest.startsWith('"')) {
|
|
42473
|
+
const end = rest.indexOf('"', 1);
|
|
42474
|
+
if (end === -1) return null;
|
|
42475
|
+
rest = rest.slice(end + 1).trim();
|
|
42476
|
+
} else {
|
|
42477
|
+
const idx2 = rest.search(/\s/);
|
|
42478
|
+
if (idx2 === -1) return null;
|
|
42479
|
+
rest = rest.slice(idx2 + 1).trim();
|
|
42480
|
+
}
|
|
42481
|
+
if (!rest) return null;
|
|
42482
|
+
if (rest.startsWith('"')) {
|
|
42483
|
+
const end = rest.indexOf('"', 1);
|
|
42484
|
+
return end === -1 ? rest.slice(1) : rest.slice(1, end);
|
|
42485
|
+
}
|
|
42486
|
+
const idx = rest.search(/\s/);
|
|
42487
|
+
return idx === -1 ? rest : rest.slice(0, idx);
|
|
42488
|
+
}
|
|
42489
|
+
function normalizeWindowsPath(value) {
|
|
42490
|
+
return value.toLowerCase().replace(/\//g, "\\").replace(/\\+$/, "");
|
|
42491
|
+
}
|
|
42492
|
+
function killProcess(pid, options = {}) {
|
|
42493
|
+
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
42494
|
+
const exec7 = options.execFileSync ?? defaultExecFileSync();
|
|
42495
|
+
const platform10 = options.platform ?? process.platform;
|
|
42496
|
+
try {
|
|
42497
|
+
if (platform10 === "win32") {
|
|
42498
|
+
exec7("taskkill", ["/PID", String(pid), "/T", "/F"], {
|
|
42499
|
+
stdio: "ignore",
|
|
42500
|
+
windowsHide: true
|
|
42501
|
+
});
|
|
42502
|
+
} else {
|
|
42503
|
+
process.kill(pid, "SIGTERM");
|
|
42504
|
+
}
|
|
42505
|
+
return true;
|
|
42506
|
+
} catch {
|
|
42507
|
+
return false;
|
|
42508
|
+
}
|
|
42509
|
+
}
|
|
42510
|
+
async function waitForPidExit(pid, timeoutMs) {
|
|
42511
|
+
const start = Date.now();
|
|
42512
|
+
while (Date.now() - start < timeoutMs) {
|
|
42513
|
+
try {
|
|
42514
|
+
process.kill(pid, 0);
|
|
42515
|
+
await new Promise((resolve27) => setTimeout(resolve27, 250));
|
|
42516
|
+
} catch {
|
|
42517
|
+
return true;
|
|
42518
|
+
}
|
|
42519
|
+
}
|
|
42520
|
+
return false;
|
|
42521
|
+
}
|
|
42522
|
+
function listOwnedNodeProcesses(options) {
|
|
42523
|
+
const platform10 = options.platform ?? process.platform;
|
|
42524
|
+
if (platform10 !== "win32") return [];
|
|
42525
|
+
const exec7 = options.execFileSync ?? defaultExecFileSync();
|
|
42526
|
+
const prefixes = options.prefixes.map((p) => normalizeWindowsPath(p));
|
|
42527
|
+
const exclude = new Set((options.excludePids ?? []).filter((n) => Number.isFinite(n) && n > 0));
|
|
42528
|
+
const markers = (options.markers ?? []).map((m) => m.toLowerCase().replace(/\//g, "\\"));
|
|
42529
|
+
let pids = [];
|
|
42530
|
+
try {
|
|
42531
|
+
const out = String(exec7("powershell.exe", [
|
|
42532
|
+
"-NoProfile",
|
|
42533
|
+
"-NonInteractive",
|
|
42534
|
+
"-ExecutionPolicy",
|
|
42535
|
+
"Bypass",
|
|
42536
|
+
"-Command",
|
|
42537
|
+
"Get-Process node -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Id | ConvertTo-Json -Compress"
|
|
42538
|
+
], { encoding: "utf8", timeout: 8e3, stdio: ["ignore", "pipe", "ignore"], windowsHide: true })).trim();
|
|
42539
|
+
if (out) {
|
|
42540
|
+
const parsed = JSON.parse(out);
|
|
42541
|
+
pids = Array.isArray(parsed) ? parsed : [parsed];
|
|
42542
|
+
}
|
|
42543
|
+
} catch {
|
|
42544
|
+
return [];
|
|
42545
|
+
}
|
|
42546
|
+
const results = [];
|
|
42547
|
+
for (const pid of pids) {
|
|
42548
|
+
if (!Number.isFinite(pid) || pid <= 0 || exclude.has(pid)) continue;
|
|
42549
|
+
const commandLine = getProcessCommandLine(pid, { platform: platform10, execFileSync: exec7 });
|
|
42550
|
+
if (!commandLine) continue;
|
|
42551
|
+
const lower = commandLine.toLowerCase();
|
|
42552
|
+
const underPrefix = prefixes.some((prefix) => lower.includes(prefix));
|
|
42553
|
+
if (!underPrefix) continue;
|
|
42554
|
+
if (markers.length > 0 && !markers.some((marker) => lower.includes(marker))) continue;
|
|
42555
|
+
results.push({ pid, commandLine });
|
|
42556
|
+
}
|
|
42557
|
+
return results;
|
|
42558
|
+
}
|
|
42559
|
+
async function stopOwnedProcesses(options) {
|
|
42560
|
+
const waitMs = options.waitMs ?? 15e3;
|
|
42561
|
+
const killed = /* @__PURE__ */ new Set();
|
|
42562
|
+
for (const p of options.processes) {
|
|
42563
|
+
if (killProcess(p.pid, options)) killed.add(p.pid);
|
|
42564
|
+
}
|
|
42565
|
+
const survivors = [];
|
|
42566
|
+
for (const p of options.processes) {
|
|
42567
|
+
if (!killed.has(p.pid)) {
|
|
42568
|
+
survivors.push(p);
|
|
42569
|
+
continue;
|
|
42570
|
+
}
|
|
42571
|
+
const exited = await waitForPidExit(p.pid, waitMs);
|
|
42572
|
+
if (!exited) survivors.push(p);
|
|
42573
|
+
}
|
|
42574
|
+
return { stopped: options.processes.length - survivors.length, survivors };
|
|
42575
|
+
}
|
|
42576
|
+
async function stopOwnedProcessesForPrefixes(options) {
|
|
42577
|
+
const processes = listOwnedNodeProcesses(options);
|
|
42578
|
+
if (processes.length === 0) return { stopped: 0, survivors: [] };
|
|
42579
|
+
options.log?.(`Stopping ${processes.length} owned process(es) under prefixes: ${options.prefixes.join(", ")}`);
|
|
42580
|
+
const result = await stopOwnedProcesses({
|
|
42581
|
+
processes,
|
|
42582
|
+
waitMs: options.waitMs,
|
|
42583
|
+
platform: options.platform,
|
|
42584
|
+
execFileSync: options.execFileSync
|
|
42585
|
+
});
|
|
42586
|
+
if (result.survivors.length > 0) {
|
|
42587
|
+
options.log?.(`Could not stop ${result.survivors.length} owned process(es): ${result.survivors.map((s2) => s2.pid).join(", ")}`);
|
|
42588
|
+
}
|
|
42589
|
+
return result;
|
|
42590
|
+
}
|
|
42591
|
+
|
|
42592
|
+
// src/commands/windows-atomic-upgrade.ts
|
|
42293
42593
|
var POINTER_NAME = ".adhdev-current";
|
|
42294
42594
|
var STABLE_FILES = [POINTER_NAME, "adhdev.cmd", "adhdev.ps1", "adhdev"];
|
|
42295
42595
|
var DEFAULT_HEALTH_PORT = 19222;
|
|
42596
|
+
var ADHDEV_OWNED_MARKERS = [
|
|
42597
|
+
"session-host-daemon",
|
|
42598
|
+
"node_modules/adhdev",
|
|
42599
|
+
"node_modules/@adhdev/daemon-standalone"
|
|
42600
|
+
];
|
|
42296
42601
|
function normalizeForCompare(value) {
|
|
42297
42602
|
return path20.resolve(value).replace(/[\\/]+$/, "").toLowerCase();
|
|
42298
42603
|
}
|
|
@@ -42315,7 +42620,7 @@ function resolveWindowsInstallerLayout(options) {
|
|
|
42315
42620
|
}
|
|
42316
42621
|
function nodeMajor(nodeExecutable) {
|
|
42317
42622
|
try {
|
|
42318
|
-
const version = String(
|
|
42623
|
+
const version = String(execFileSync4(nodeExecutable, ["-p", "process.versions.node"], {
|
|
42319
42624
|
encoding: "utf8",
|
|
42320
42625
|
timeout: 5e3,
|
|
42321
42626
|
windowsHide: true,
|
|
@@ -42377,7 +42682,7 @@ exit $LASTEXITCODE\r
|
|
|
42377
42682
|
}
|
|
42378
42683
|
}
|
|
42379
42684
|
function validateStagedCli(portableNode, cliEntry, targetVersion) {
|
|
42380
|
-
const output = String(
|
|
42685
|
+
const output = String(execFileSync4(portableNode, [cliEntry, "--version"], {
|
|
42381
42686
|
encoding: "utf8",
|
|
42382
42687
|
timeout: 15e3,
|
|
42383
42688
|
windowsHide: true,
|
|
@@ -42491,6 +42796,19 @@ async function performWindowsAtomicUpgrade(options) {
|
|
|
42491
42796
|
pinStagedShims(stagedPrefix, portableNode, stagedCliEntry);
|
|
42492
42797
|
validateStagedCli(portableNode, stagedCliEntry, targetVersion);
|
|
42493
42798
|
hooks.log(`Validated staged CLI and portable Node 22 shims in ${stagedPrefix}`);
|
|
42799
|
+
const excludedPids = new Set([process.pid, ...options.excludePids ?? []].filter((n) => Number.isFinite(n) && n > 0));
|
|
42800
|
+
const preStop = await stopOwnedProcessesForPrefixes({
|
|
42801
|
+
prefixes: [layout.activePrefix, layout.stablePrefix],
|
|
42802
|
+
excludePids: Array.from(excludedPids),
|
|
42803
|
+
markers: Array.from(ADHDEV_OWNED_MARKERS),
|
|
42804
|
+
waitMs: 15e3,
|
|
42805
|
+
log: hooks.log
|
|
42806
|
+
});
|
|
42807
|
+
if (preStop.survivors.length > 0) {
|
|
42808
|
+
throw new Error(
|
|
42809
|
+
`Cannot activate ${versionName}: ${preStop.survivors.length} owned process(es) still running under the current prefix`
|
|
42810
|
+
);
|
|
42811
|
+
}
|
|
42494
42812
|
activated = true;
|
|
42495
42813
|
publishStableShimsAndPointer(layout, versionName);
|
|
42496
42814
|
hooks.log(`Atomically activated ${versionName}`);
|
|
@@ -42500,7 +42818,7 @@ async function performWindowsAtomicUpgrade(options) {
|
|
|
42500
42818
|
throw new Error("replacement daemon did not pass the health/version gate");
|
|
42501
42819
|
}
|
|
42502
42820
|
hooks.log(`Replacement daemon pid ${daemonPid} passed health for ${targetVersion}`);
|
|
42503
|
-
hooks.cleanup(layout, stagedPrefix);
|
|
42821
|
+
await hooks.cleanup(layout, stagedPrefix);
|
|
42504
42822
|
return { stagedPrefix, stagedCliEntry, daemonPid };
|
|
42505
42823
|
} catch (error) {
|
|
42506
42824
|
if (restarted?.pid) hooks.stopProcess(restarted.pid);
|
|
@@ -42518,7 +42836,7 @@ async function performWindowsAtomicUpgrade(options) {
|
|
|
42518
42836
|
hooks.log("Failed to restart the previous daemon during rollback");
|
|
42519
42837
|
}
|
|
42520
42838
|
try {
|
|
42521
|
-
hooks.cleanup(layout, layout.activePrefix);
|
|
42839
|
+
await hooks.cleanup(layout, layout.activePrefix);
|
|
42522
42840
|
} catch {
|
|
42523
42841
|
}
|
|
42524
42842
|
throw error;
|
|
@@ -42530,7 +42848,7 @@ function createDefaultWindowsAtomicHooks(options) {
|
|
|
42530
42848
|
const env = { ...options.env, ADHDEV_BOOTSTRAP: "1" };
|
|
42531
42849
|
const pathKey = Object.keys(env).find((key2) => key2.toLowerCase() === "path") || "Path";
|
|
42532
42850
|
env[pathKey] = `${path20.dirname(portableNode)};${env[pathKey] || ""}`;
|
|
42533
|
-
|
|
42851
|
+
execFileSync4(portableNode, [
|
|
42534
42852
|
options.npmCliPath,
|
|
42535
42853
|
"install",
|
|
42536
42854
|
"-g",
|
|
@@ -42600,15 +42918,23 @@ function createDefaultWindowsAtomicHooks(options) {
|
|
|
42600
42918
|
},
|
|
42601
42919
|
stopProcess: (pid) => {
|
|
42602
42920
|
try {
|
|
42603
|
-
|
|
42921
|
+
execFileSync4("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
|
|
42604
42922
|
} catch {
|
|
42605
42923
|
}
|
|
42606
42924
|
},
|
|
42607
|
-
cleanup: (layout, activePrefix) =>
|
|
42925
|
+
cleanup: async (layout, activePrefix) => cleanupInactivePrefixesWithGuard({
|
|
42926
|
+
layout,
|
|
42927
|
+
activePrefix,
|
|
42928
|
+
excludePids: [process.pid],
|
|
42929
|
+
markers: Array.from(ADHDEV_OWNED_MARKERS),
|
|
42930
|
+
waitMs: 15e3,
|
|
42931
|
+
log: options.log
|
|
42932
|
+
}),
|
|
42608
42933
|
log: options.log
|
|
42609
42934
|
};
|
|
42610
42935
|
}
|
|
42611
|
-
function
|
|
42936
|
+
async function cleanupInactivePrefixesWithGuard(options) {
|
|
42937
|
+
const { layout, activePrefix, log } = options;
|
|
42612
42938
|
let candidates = [];
|
|
42613
42939
|
try {
|
|
42614
42940
|
candidates = fs14.readdirSync(layout.installRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("version-")).map((entry) => path20.join(layout.installRoot, entry.name)).filter((entry) => normalizeForCompare(entry) !== normalizeForCompare(activePrefix)).sort().slice(0, 8);
|
|
@@ -42616,19 +42942,41 @@ function boundedCleanupInactivePrefixes(layout, activePrefix, log) {
|
|
|
42616
42942
|
return;
|
|
42617
42943
|
}
|
|
42618
42944
|
if (candidates.length === 0) return;
|
|
42619
|
-
const
|
|
42620
|
-
|
|
42621
|
-
|
|
42622
|
-
|
|
42623
|
-
|
|
42624
|
-
|
|
42625
|
-
|
|
42626
|
-
|
|
42627
|
-
|
|
42628
|
-
|
|
42629
|
-
|
|
42630
|
-
|
|
42631
|
-
|
|
42945
|
+
for (const candidate of candidates) {
|
|
42946
|
+
const stopResult = await stopOwnedProcessesForPrefixes({
|
|
42947
|
+
prefixes: [candidate],
|
|
42948
|
+
excludePids: options.excludePids,
|
|
42949
|
+
markers: options.markers,
|
|
42950
|
+
waitMs: options.waitMs ?? 15e3,
|
|
42951
|
+
log
|
|
42952
|
+
});
|
|
42953
|
+
if (stopResult.survivors.length > 0) {
|
|
42954
|
+
log?.(`Skipping cleanup of ${candidate}: ${stopResult.survivors.length} owned process(es) could not be stopped`);
|
|
42955
|
+
continue;
|
|
42956
|
+
}
|
|
42957
|
+
removeInactivePrefix(candidate, log);
|
|
42958
|
+
}
|
|
42959
|
+
}
|
|
42960
|
+
function removeInactivePrefix(target, log) {
|
|
42961
|
+
try {
|
|
42962
|
+
const escaped = quotePowerShellLiteral(target);
|
|
42963
|
+
const script = `if (Test-Path -LiteralPath ${escaped}) { Remove-Item -LiteralPath ${escaped} -Recurse -Force }`;
|
|
42964
|
+
const encoded = Buffer.from(script, "utf16le").toString("base64");
|
|
42965
|
+
const result = spawnSync("powershell.exe", [
|
|
42966
|
+
"-NoLogo",
|
|
42967
|
+
"-NoProfile",
|
|
42968
|
+
"-NonInteractive",
|
|
42969
|
+
"-ExecutionPolicy",
|
|
42970
|
+
"Bypass",
|
|
42971
|
+
"-EncodedCommand",
|
|
42972
|
+
encoded
|
|
42973
|
+
], { timeout: 5e3, windowsHide: true, stdio: "ignore" });
|
|
42974
|
+
if (result.error || result.status !== 0) {
|
|
42975
|
+
log?.(`Failed to remove inactive prefix ${target}: ${result.error?.message || `exit ${result.status}`}`);
|
|
42976
|
+
}
|
|
42977
|
+
} catch (error) {
|
|
42978
|
+
log?.(`Failed to remove inactive prefix ${target}: ${error?.message || String(error)}`);
|
|
42979
|
+
}
|
|
42632
42980
|
}
|
|
42633
42981
|
|
|
42634
42982
|
// src/commands/upgrade-helper.ts
|
|
@@ -42757,7 +43105,7 @@ function getNpmExecOptions(platform10 = process.platform) {
|
|
|
42757
43105
|
}
|
|
42758
43106
|
function execNpmCommandSync(args, options = {}, surface) {
|
|
42759
43107
|
const execOptions = surface?.execOptions || getNpmExecOptions();
|
|
42760
|
-
return
|
|
43108
|
+
return execFileSync5(
|
|
42761
43109
|
surface?.npmExecutable || "npm",
|
|
42762
43110
|
[...surface?.npmArgsPrefix || [], ...args],
|
|
42763
43111
|
{
|
|
@@ -42767,74 +43115,10 @@ function execNpmCommandSync(args, options = {}, surface) {
|
|
|
42767
43115
|
}
|
|
42768
43116
|
);
|
|
42769
43117
|
}
|
|
42770
|
-
function killPid(pid) {
|
|
42771
|
-
try {
|
|
42772
|
-
if (process.platform === "win32") {
|
|
42773
|
-
execFileSync4("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
|
|
42774
|
-
} else {
|
|
42775
|
-
process.kill(pid, "SIGTERM");
|
|
42776
|
-
}
|
|
42777
|
-
return true;
|
|
42778
|
-
} catch {
|
|
42779
|
-
return false;
|
|
42780
|
-
}
|
|
42781
|
-
}
|
|
42782
|
-
function getWindowsProcessCommandLine(pid) {
|
|
42783
|
-
const pidFilter = `ProcessId=${pid}`;
|
|
42784
|
-
try {
|
|
42785
|
-
const psOut = execFileSync4("powershell.exe", [
|
|
42786
|
-
"-NoProfile",
|
|
42787
|
-
"-NonInteractive",
|
|
42788
|
-
"-ExecutionPolicy",
|
|
42789
|
-
"Bypass",
|
|
42790
|
-
"-Command",
|
|
42791
|
-
`(Get-CimInstance Win32_Process -Filter "${pidFilter}").CommandLine`
|
|
42792
|
-
], { encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "ignore"], windowsHide: true }).trim();
|
|
42793
|
-
if (psOut) return psOut;
|
|
42794
|
-
} catch {
|
|
42795
|
-
}
|
|
42796
|
-
try {
|
|
42797
|
-
const wmicOut = execFileSync4("wmic", [
|
|
42798
|
-
"process",
|
|
42799
|
-
"where",
|
|
42800
|
-
pidFilter,
|
|
42801
|
-
"get",
|
|
42802
|
-
"CommandLine"
|
|
42803
|
-
], { encoding: "utf8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"], windowsHide: true }).trim();
|
|
42804
|
-
if (wmicOut) return wmicOut;
|
|
42805
|
-
} catch {
|
|
42806
|
-
}
|
|
42807
|
-
return null;
|
|
42808
|
-
}
|
|
42809
|
-
function getProcessCommandLine(pid) {
|
|
42810
|
-
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
42811
|
-
if (process.platform === "win32") return getWindowsProcessCommandLine(pid);
|
|
42812
|
-
try {
|
|
42813
|
-
const text = execFileSync4("ps", ["-o", "command=", "-p", String(pid)], {
|
|
42814
|
-
encoding: "utf8",
|
|
42815
|
-
timeout: 3e3,
|
|
42816
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
42817
|
-
}).trim();
|
|
42818
|
-
return text || null;
|
|
42819
|
-
} catch {
|
|
42820
|
-
return null;
|
|
42821
|
-
}
|
|
42822
|
-
}
|
|
42823
43118
|
function isManagedSessionHostPid(pid) {
|
|
42824
43119
|
const commandLine = getProcessCommandLine(pid);
|
|
42825
43120
|
return !!commandLine && /session-host-daemon/i.test(commandLine);
|
|
42826
43121
|
}
|
|
42827
|
-
async function waitForPidExit(pid, timeoutMs) {
|
|
42828
|
-
const start = Date.now();
|
|
42829
|
-
while (Date.now() - start < timeoutMs) {
|
|
42830
|
-
try {
|
|
42831
|
-
process.kill(pid, 0);
|
|
42832
|
-
await new Promise((resolve27) => setTimeout(resolve27, 250));
|
|
42833
|
-
} catch {
|
|
42834
|
-
return;
|
|
42835
|
-
}
|
|
42836
|
-
}
|
|
42837
|
-
}
|
|
42838
43122
|
async function stopSessionHostProcesses(appName) {
|
|
42839
43123
|
const pidFile = path21.join(os13.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
42840
43124
|
let killedPid = null;
|
|
@@ -42842,7 +43126,7 @@ async function stopSessionHostProcesses(appName) {
|
|
|
42842
43126
|
if (fs15.existsSync(pidFile)) {
|
|
42843
43127
|
const pid = Number.parseInt(fs15.readFileSync(pidFile, "utf8").trim(), 10);
|
|
42844
43128
|
if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
|
|
42845
|
-
if (
|
|
43129
|
+
if (killProcess(pid)) killedPid = pid;
|
|
42846
43130
|
}
|
|
42847
43131
|
}
|
|
42848
43132
|
} catch {
|
|
@@ -42878,7 +43162,7 @@ function listForeignNativeAddonHolders(packageRoot) {
|
|
|
42878
43162
|
].join("\n");
|
|
42879
43163
|
let out = "";
|
|
42880
43164
|
try {
|
|
42881
|
-
out = String(
|
|
43165
|
+
out = String(execFileSync5("powershell.exe", [
|
|
42882
43166
|
"-NoProfile",
|
|
42883
43167
|
"-NonInteractive",
|
|
42884
43168
|
"-ExecutionPolicy",
|
|
@@ -42910,7 +43194,7 @@ async function stopForeignNativeAddonHolders(packageRoot, options = {}) {
|
|
|
42910
43194
|
appendUpgradeLog(
|
|
42911
43195
|
`Foreign native-addon holder found: pid ${holder.pid}${holder.commandLine ? ` \u2014 ${holder.commandLine}` : ""}`
|
|
42912
43196
|
);
|
|
42913
|
-
const killed =
|
|
43197
|
+
const killed = killProcess(holder.pid);
|
|
42914
43198
|
if (killed) {
|
|
42915
43199
|
await waitForPidExit(holder.pid, 15e3);
|
|
42916
43200
|
appendUpgradeLog(`Terminated foreign native-addon holder pid ${holder.pid}`);
|
|
@@ -43043,11 +43327,25 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
43043
43327
|
throw new Error(`portable Node.js 22 npm CLI is missing: ${npmCliPath}`);
|
|
43044
43328
|
}
|
|
43045
43329
|
appendUpgradeLog(`Installer-managed pointer layout detected; active prefix will remain untouched: ${windowsInstallerLayout.activePrefix}`);
|
|
43330
|
+
const upgradePids = [process.pid, payload.parentPid].filter((n) => Number.isFinite(n) && n > 0);
|
|
43331
|
+
const preStop = await stopOwnedProcessesForPrefixes({
|
|
43332
|
+
prefixes: [windowsInstallerLayout.activePrefix, windowsInstallerLayout.stablePrefix],
|
|
43333
|
+
excludePids: upgradePids,
|
|
43334
|
+
markers: Array.from(ADHDEV_OWNED_MARKERS),
|
|
43335
|
+
waitMs: 15e3,
|
|
43336
|
+
log: appendUpgradeLog
|
|
43337
|
+
});
|
|
43338
|
+
if (preStop.survivors.length > 0) {
|
|
43339
|
+
throw new Error(
|
|
43340
|
+
`Cannot upgrade: owned processes still running under current prefix: ${preStop.survivors.map((s2) => s2.pid).join(", ")}`
|
|
43341
|
+
);
|
|
43342
|
+
}
|
|
43046
43343
|
await performWindowsAtomicUpgrade({
|
|
43047
43344
|
layout: windowsInstallerLayout,
|
|
43048
43345
|
packageName: payload.packageName,
|
|
43049
43346
|
targetVersion: payload.targetVersion,
|
|
43050
43347
|
portableNode,
|
|
43348
|
+
excludePids: upgradePids,
|
|
43051
43349
|
hooks: createDefaultWindowsAtomicHooks({
|
|
43052
43350
|
packageName: payload.packageName,
|
|
43053
43351
|
targetVersion: payload.targetVersion,
|
|
@@ -43073,7 +43371,7 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
43073
43371
|
let installOutput = "";
|
|
43074
43372
|
for (let attempt = 1; attempt <= maxInstallAttempts; attempt++) {
|
|
43075
43373
|
try {
|
|
43076
|
-
installOutput = String(
|
|
43374
|
+
installOutput = String(execFileSync5(
|
|
43077
43375
|
installCommand.command,
|
|
43078
43376
|
installCommand.args,
|
|
43079
43377
|
{
|
|
@@ -43716,7 +44014,7 @@ import * as os22 from "os";
|
|
|
43716
44014
|
import * as path30 from "path";
|
|
43717
44015
|
import * as crypto6 from "crypto";
|
|
43718
44016
|
import { existsSync as existsSync33, mkdirSync as mkdirSync14, writeFileSync as writeFileSync17 } from "fs";
|
|
43719
|
-
import { execFileSync as
|
|
44017
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
43720
44018
|
import chalk from "chalk";
|
|
43721
44019
|
init_summary_metadata();
|
|
43722
44020
|
|
|
@@ -52087,7 +52385,7 @@ function commandExists(command) {
|
|
|
52087
52385
|
return existsSync33(expandExecutable(trimmed));
|
|
52088
52386
|
}
|
|
52089
52387
|
try {
|
|
52090
|
-
|
|
52388
|
+
execFileSync6(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
52091
52389
|
stdio: "ignore",
|
|
52092
52390
|
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
52093
52391
|
});
|
|
@@ -57998,15 +58296,15 @@ var ideHandlers = {
|
|
|
57998
58296
|
stop_ide: async (ctx, args) => {
|
|
57999
58297
|
const ideType = args?.ideType;
|
|
58000
58298
|
if (!ideType) throw new Error("ideType required");
|
|
58001
|
-
const
|
|
58002
|
-
await ctx.stopIde(ideType,
|
|
58299
|
+
const killProcess2 = args?.killProcess !== false;
|
|
58300
|
+
await ctx.stopIde(ideType, killProcess2);
|
|
58003
58301
|
try {
|
|
58004
58302
|
const results = await detectIDEs(ctx.deps.providerLoader);
|
|
58005
58303
|
ctx.deps.detectedIdes.value = results;
|
|
58006
58304
|
ctx.deps.providerLoader.setIdeDetectionResults(results, true);
|
|
58007
58305
|
} catch {
|
|
58008
58306
|
}
|
|
58009
|
-
return { success: true, ideType, stopped: true, processKilled:
|
|
58307
|
+
return { success: true, ideType, stopped: true, processKilled: killProcess2 };
|
|
58010
58308
|
},
|
|
58011
58309
|
// ─── IDE restart ───
|
|
58012
58310
|
restart_ide: async (ctx, args) => {
|
|
@@ -60279,7 +60577,7 @@ import * as fs32 from "fs";
|
|
|
60279
60577
|
import { hostname as osHostname } from "os";
|
|
60280
60578
|
|
|
60281
60579
|
// src/mesh/preview-freshness.ts
|
|
60282
|
-
import { execFileSync as
|
|
60580
|
+
import { execFileSync as execFileSync8 } from "child_process";
|
|
60283
60581
|
import { existsSync as existsSync42, readFileSync as readFileSync32 } from "fs";
|
|
60284
60582
|
import { resolve as resolve21 } from "path";
|
|
60285
60583
|
var PREVIEW_DEPLOY_RECORD = ".adhdev/preview-deploy.json";
|
|
@@ -60305,7 +60603,7 @@ function isPreviewPipelineConfigured(repoRoot) {
|
|
|
60305
60603
|
}
|
|
60306
60604
|
function runGit2(repoRoot, args) {
|
|
60307
60605
|
try {
|
|
60308
|
-
return
|
|
60606
|
+
return execFileSync8("git", args, {
|
|
60309
60607
|
cwd: repoRoot,
|
|
60310
60608
|
encoding: "utf8",
|
|
60311
60609
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -61129,7 +61427,7 @@ init_dist();
|
|
|
61129
61427
|
init_mesh_events();
|
|
61130
61428
|
init_mesh_reconcile_identity();
|
|
61131
61429
|
init_mesh_fast_forward();
|
|
61132
|
-
import { execFileSync as
|
|
61430
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
61133
61431
|
|
|
61134
61432
|
// src/mesh/mesh-refine-batch.ts
|
|
61135
61433
|
init_resolve_executable();
|
|
@@ -61232,7 +61530,7 @@ init_worktree_bootstrap_config();
|
|
|
61232
61530
|
init_resolve_executable();
|
|
61233
61531
|
import { basename as pathBasename, join as pathJoin2, resolve as pathResolve2 } from "path";
|
|
61234
61532
|
import * as fs34 from "fs";
|
|
61235
|
-
import { execFileSync as
|
|
61533
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
61236
61534
|
var GIT2 = process.platform === "win32" ? resolveWin32Executable("git") : "git";
|
|
61237
61535
|
var REFINE_VALIDATION_TIMEOUT_MS = 12e4;
|
|
61238
61536
|
var REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
@@ -61287,18 +61585,18 @@ function resolveRefineryAutoPublishSubmoduleMainCommits(mesh, workspace) {
|
|
|
61287
61585
|
return { enabled: false };
|
|
61288
61586
|
}
|
|
61289
61587
|
async function computeGitPatchId(cwd, fromRef, toRef, excludePaths = []) {
|
|
61290
|
-
const { execFileSync:
|
|
61588
|
+
const { execFileSync: execFileSync12 } = await import("child_process");
|
|
61291
61589
|
const diffArgs = ["diff", "--patch", "--full-index", fromRef, toRef];
|
|
61292
61590
|
if (excludePaths.length > 0) {
|
|
61293
61591
|
diffArgs.push("--", ".", ...excludePaths.map((path46) => `:(exclude)${path46}`));
|
|
61294
61592
|
}
|
|
61295
|
-
const diff =
|
|
61593
|
+
const diff = execFileSync12(GIT2, diffArgs, {
|
|
61296
61594
|
cwd,
|
|
61297
61595
|
encoding: "utf8",
|
|
61298
61596
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
61299
61597
|
});
|
|
61300
61598
|
if (!diff.trim()) return "";
|
|
61301
|
-
const patchId =
|
|
61599
|
+
const patchId = execFileSync12(GIT2, ["patch-id", "--stable"], {
|
|
61302
61600
|
cwd,
|
|
61303
61601
|
input: diff,
|
|
61304
61602
|
encoding: "utf8",
|
|
@@ -61309,8 +61607,8 @@ async function computeGitPatchId(cwd, fromRef, toRef, excludePaths = []) {
|
|
|
61309
61607
|
async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead) {
|
|
61310
61608
|
const startedAt = Date.now();
|
|
61311
61609
|
try {
|
|
61312
|
-
const { execFileSync:
|
|
61313
|
-
const git = (args) =>
|
|
61610
|
+
const { execFileSync: execFileSync12 } = await import("child_process");
|
|
61611
|
+
const git = (args) => execFileSync12(GIT2, args, {
|
|
61314
61612
|
cwd: repoRoot,
|
|
61315
61613
|
encoding: "utf8",
|
|
61316
61614
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
@@ -61411,7 +61709,7 @@ async function classifyPatchEquivalenceFailure(repoRoot, baseHead, branchHead, s
|
|
|
61411
61709
|
...autoPublish !== void 0 ? { autoPublishSubmoduleMainCommits: autoPublish } : {}
|
|
61412
61710
|
};
|
|
61413
61711
|
try {
|
|
61414
|
-
const git = (args) =>
|
|
61712
|
+
const git = (args) => execFileSync9(GIT2, args, {
|
|
61415
61713
|
cwd: repoRoot,
|
|
61416
61714
|
encoding: "utf8",
|
|
61417
61715
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES,
|
|
@@ -61536,7 +61834,7 @@ async function classifyPatchEquivalenceFailure(repoRoot, baseHead, branchHead, s
|
|
|
61536
61834
|
}
|
|
61537
61835
|
function execGitOk(cwd, args) {
|
|
61538
61836
|
try {
|
|
61539
|
-
|
|
61837
|
+
execFileSync9(GIT2, args, { cwd, encoding: "utf8", maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES, windowsHide: true });
|
|
61540
61838
|
return true;
|
|
61541
61839
|
} catch {
|
|
61542
61840
|
return false;
|
|
@@ -61545,8 +61843,8 @@ function execGitOk(cwd, args) {
|
|
|
61545
61843
|
async function checkWorktreeChangesPatchEquivalentInRef(repoRoot, ref, worktreeHead) {
|
|
61546
61844
|
const startedAt = Date.now();
|
|
61547
61845
|
try {
|
|
61548
|
-
const { execFileSync:
|
|
61549
|
-
const git = (gitArgs) =>
|
|
61846
|
+
const { execFileSync: execFileSync12 } = await import("child_process");
|
|
61847
|
+
const git = (gitArgs) => execFileSync12(GIT2, gitArgs, {
|
|
61550
61848
|
cwd: repoRoot,
|
|
61551
61849
|
encoding: "utf8",
|
|
61552
61850
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
@@ -61609,8 +61907,8 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
61609
61907
|
async function runMeshRefineEffectiveDiffGate(repoRoot, baseHead, branchHead) {
|
|
61610
61908
|
const startedAt = Date.now();
|
|
61611
61909
|
try {
|
|
61612
|
-
const { execFileSync:
|
|
61613
|
-
const git = (args, opts) =>
|
|
61910
|
+
const { execFileSync: execFileSync12 } = await import("child_process");
|
|
61911
|
+
const git = (args, opts) => execFileSync12(GIT2, args, {
|
|
61614
61912
|
cwd: opts?.cwd || repoRoot,
|
|
61615
61913
|
encoding: "utf8",
|
|
61616
61914
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
@@ -61686,7 +61984,7 @@ function buildPatchEquivalenceSubmoduleConflictHint(repoRoot, baseHead, branchHe
|
|
|
61686
61984
|
}
|
|
61687
61985
|
function readChangedGitlinkPaths(repoRoot, fromRef, toRef) {
|
|
61688
61986
|
try {
|
|
61689
|
-
const output =
|
|
61987
|
+
const output = execFileSync9(GIT2, ["diff", "--raw", "--no-abbrev", fromRef, toRef], {
|
|
61690
61988
|
cwd: repoRoot,
|
|
61691
61989
|
encoding: "utf8",
|
|
61692
61990
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
@@ -61710,7 +62008,7 @@ function readChangedGitlinkPaths(repoRoot, fromRef, toRef) {
|
|
|
61710
62008
|
}
|
|
61711
62009
|
function readTreeObject(repoRoot, ref, path46) {
|
|
61712
62010
|
try {
|
|
61713
|
-
const output =
|
|
62011
|
+
const output = execFileSync9(GIT2, ["ls-tree", ref, "--", path46], {
|
|
61714
62012
|
cwd: repoRoot,
|
|
61715
62013
|
encoding: "utf8",
|
|
61716
62014
|
maxBuffer: 1024 * 1024
|
|
@@ -61722,7 +62020,7 @@ function readTreeObject(repoRoot, ref, path46) {
|
|
|
61722
62020
|
}
|
|
61723
62021
|
}
|
|
61724
62022
|
function resolveGitDir(repoRoot) {
|
|
61725
|
-
const out =
|
|
62023
|
+
const out = execFileSync9(GIT2, ["rev-parse", "--absolute-git-dir"], {
|
|
61726
62024
|
cwd: repoRoot,
|
|
61727
62025
|
encoding: "utf8",
|
|
61728
62026
|
maxBuffer: 1024 * 1024
|
|
@@ -61734,9 +62032,9 @@ function isSubmoduleFastForward(submoduleRepoPath, baseCommit, branchCommit) {
|
|
|
61734
62032
|
if (baseCommit === branchCommit) return true;
|
|
61735
62033
|
try {
|
|
61736
62034
|
if (!fs34.existsSync(submoduleRepoPath)) return false;
|
|
61737
|
-
|
|
61738
|
-
|
|
61739
|
-
|
|
62035
|
+
execFileSync9(GIT2, ["cat-file", "-e", `${baseCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
62036
|
+
execFileSync9(GIT2, ["cat-file", "-e", `${branchCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
62037
|
+
execFileSync9(GIT2, ["merge-base", "--is-ancestor", baseCommit, branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
61740
62038
|
return true;
|
|
61741
62039
|
} catch {
|
|
61742
62040
|
return false;
|
|
@@ -61744,7 +62042,7 @@ function isSubmoduleFastForward(submoduleRepoPath, baseCommit, branchCommit) {
|
|
|
61744
62042
|
}
|
|
61745
62043
|
function readChangedPathKinds(repoRoot, fromRef, toRef) {
|
|
61746
62044
|
try {
|
|
61747
|
-
const output =
|
|
62045
|
+
const output = execFileSync9(GIT2, ["diff", "--raw", "--no-abbrev", fromRef, toRef], {
|
|
61748
62046
|
cwd: repoRoot,
|
|
61749
62047
|
encoding: "utf8",
|
|
61750
62048
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
@@ -61796,7 +62094,7 @@ function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
|
|
|
61796
62094
|
}
|
|
61797
62095
|
let mergeBase = "";
|
|
61798
62096
|
try {
|
|
61799
|
-
mergeBase =
|
|
62097
|
+
mergeBase = execFileSync9(GIT2, ["merge-base", baseHead, branchHead], {
|
|
61800
62098
|
cwd: repoRoot,
|
|
61801
62099
|
encoding: "utf8",
|
|
61802
62100
|
maxBuffer: 1024 * 1024
|
|
@@ -61826,7 +62124,7 @@ function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
|
|
|
61826
62124
|
}
|
|
61827
62125
|
function buildTreeWithGitlinksEqualized(repoRoot, commitish, paths, placeholderCommit) {
|
|
61828
62126
|
try {
|
|
61829
|
-
const tree =
|
|
62127
|
+
const tree = execFileSync9(GIT2, ["rev-parse", `${commitish}^{tree}`], {
|
|
61830
62128
|
cwd: repoRoot,
|
|
61831
62129
|
encoding: "utf8",
|
|
61832
62130
|
maxBuffer: 1024 * 1024
|
|
@@ -61837,8 +62135,8 @@ function buildTreeWithGitlinksEqualized(repoRoot, commitish, paths, placeholderC
|
|
|
61837
62135
|
const tmpIndex = pathJoin2(resolveGitDir(repoRoot), `adhdev-refine-eq-${commitish.slice(0, 12)}.index`);
|
|
61838
62136
|
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
61839
62137
|
try {
|
|
61840
|
-
|
|
61841
|
-
|
|
62138
|
+
execFileSync9(GIT2, ["read-tree", tree], { cwd: repoRoot, env, stdio: "ignore" });
|
|
62139
|
+
execFileSync9(GIT2, ["update-index", "--index-info"], {
|
|
61842
62140
|
cwd: repoRoot,
|
|
61843
62141
|
env,
|
|
61844
62142
|
input: `${updates}
|
|
@@ -61846,7 +62144,7 @@ function buildTreeWithGitlinksEqualized(repoRoot, commitish, paths, placeholderC
|
|
|
61846
62144
|
encoding: "utf8",
|
|
61847
62145
|
stdio: ["pipe", "ignore", "ignore"]
|
|
61848
62146
|
});
|
|
61849
|
-
const newTree =
|
|
62147
|
+
const newTree = execFileSync9(GIT2, ["write-tree"], { cwd: repoRoot, env, encoding: "utf8" }).trim();
|
|
61850
62148
|
return newTree || void 0;
|
|
61851
62149
|
} finally {
|
|
61852
62150
|
try {
|
|
@@ -61862,7 +62160,7 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
61862
62160
|
try {
|
|
61863
62161
|
const branchGitlinks = gitlinks.filter((entry) => entry.branchCommit);
|
|
61864
62162
|
const gitlinkPaths = branchGitlinks.map((entry) => entry.path);
|
|
61865
|
-
const mergeBase =
|
|
62163
|
+
const mergeBase = execFileSync9(GIT2, ["merge-base", baseHead, branchHead], {
|
|
61866
62164
|
cwd: repoRoot,
|
|
61867
62165
|
encoding: "utf8",
|
|
61868
62166
|
maxBuffer: 1024 * 1024
|
|
@@ -61875,22 +62173,22 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
61875
62173
|
const theirsEqTree = buildTreeWithGitlinksEqualized(repoRoot, branchHead, gitlinkPaths, placeholder);
|
|
61876
62174
|
if (baseEqTree && oursEqTree && theirsEqTree) {
|
|
61877
62175
|
try {
|
|
61878
|
-
const baseEqCommit =
|
|
62176
|
+
const baseEqCommit = execFileSync9(GIT2, ["commit-tree", baseEqTree, "-m", "refine-ff-base"], {
|
|
61879
62177
|
cwd: repoRoot,
|
|
61880
62178
|
encoding: "utf8",
|
|
61881
62179
|
maxBuffer: 1024 * 1024
|
|
61882
62180
|
}).trim();
|
|
61883
|
-
const oursEqCommit =
|
|
62181
|
+
const oursEqCommit = execFileSync9(GIT2, ["commit-tree", oursEqTree, "-p", baseEqCommit, "-m", "refine-ff-ours"], {
|
|
61884
62182
|
cwd: repoRoot,
|
|
61885
62183
|
encoding: "utf8",
|
|
61886
62184
|
maxBuffer: 1024 * 1024
|
|
61887
62185
|
}).trim();
|
|
61888
|
-
const theirsEqCommit =
|
|
62186
|
+
const theirsEqCommit = execFileSync9(GIT2, ["commit-tree", theirsEqTree, "-p", baseEqCommit, "-m", "refine-ff-theirs"], {
|
|
61889
62187
|
cwd: repoRoot,
|
|
61890
62188
|
encoding: "utf8",
|
|
61891
62189
|
maxBuffer: 1024 * 1024
|
|
61892
62190
|
}).trim();
|
|
61893
|
-
const mergeOut =
|
|
62191
|
+
const mergeOut = execFileSync9(GIT2, ["merge-tree", "--write-tree", oursEqCommit, theirsEqCommit], {
|
|
61894
62192
|
cwd: repoRoot,
|
|
61895
62193
|
encoding: "utf8",
|
|
61896
62194
|
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
@@ -61901,7 +62199,7 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
61901
62199
|
}
|
|
61902
62200
|
}
|
|
61903
62201
|
}
|
|
61904
|
-
const contentTree = mergedContentTree ||
|
|
62202
|
+
const contentTree = mergedContentTree || execFileSync9(GIT2, ["rev-parse", `${baseHead}^{tree}`], {
|
|
61905
62203
|
cwd: repoRoot,
|
|
61906
62204
|
encoding: "utf8",
|
|
61907
62205
|
maxBuffer: 1024 * 1024
|
|
@@ -61912,8 +62210,8 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
61912
62210
|
const tmpIndex = pathJoin2(resolveGitDir(repoRoot), `adhdev-refine-ff-${baseHead.slice(0, 12)}-${branchHead.slice(0, 12)}.index`);
|
|
61913
62211
|
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
61914
62212
|
try {
|
|
61915
|
-
|
|
61916
|
-
|
|
62213
|
+
execFileSync9(GIT2, ["read-tree", contentTree], { cwd: repoRoot, env, stdio: "ignore" });
|
|
62214
|
+
execFileSync9(GIT2, ["update-index", "--index-info"], {
|
|
61917
62215
|
cwd: repoRoot,
|
|
61918
62216
|
env,
|
|
61919
62217
|
input: `${updates}
|
|
@@ -61921,7 +62219,7 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
61921
62219
|
encoding: "utf8",
|
|
61922
62220
|
stdio: ["pipe", "ignore", "ignore"]
|
|
61923
62221
|
});
|
|
61924
|
-
const newTree =
|
|
62222
|
+
const newTree = execFileSync9(GIT2, ["write-tree"], { cwd: repoRoot, env, encoding: "utf8" }).trim();
|
|
61925
62223
|
return newTree || void 0;
|
|
61926
62224
|
} finally {
|
|
61927
62225
|
try {
|
|
@@ -62834,10 +63132,10 @@ async function refineSyncBaseStage(self, ctx) {
|
|
|
62834
63132
|
}
|
|
62835
63133
|
const rebaseStarted = Date.now();
|
|
62836
63134
|
try {
|
|
62837
|
-
|
|
63135
|
+
execFileSync10("git", ["rebase", baseHead], { cwd: node.workspace, stdio: ["ignore", "pipe", "pipe"] });
|
|
62838
63136
|
} catch (rebaseErr) {
|
|
62839
63137
|
try {
|
|
62840
|
-
|
|
63138
|
+
execFileSync10("git", ["rebase", "--abort"], { cwd: node.workspace, stdio: "ignore" });
|
|
62841
63139
|
} catch {
|
|
62842
63140
|
}
|
|
62843
63141
|
let submoduleHintPatchEquivalence;
|
|
@@ -65719,7 +66017,7 @@ var DaemonCommandRouter = class {
|
|
|
65719
66017
|
/**
|
|
65720
66018
|
* IDE stop: CDP disconnect + InstanceManager cleanup + optionally kill OS process
|
|
65721
66019
|
*/
|
|
65722
|
-
async stopIde(ideType,
|
|
66020
|
+
async stopIde(ideType, killProcess2 = false) {
|
|
65723
66021
|
const cdpKeysToRemove = [];
|
|
65724
66022
|
for (const key2 of this.deps.cdpManagers.keys()) {
|
|
65725
66023
|
if (key2 === ideType || key2.startsWith(`${ideType}_`)) {
|
|
@@ -65757,7 +66055,7 @@ var DaemonCommandRouter = class {
|
|
|
65757
66055
|
LOG.info("StopIDE", `Instance removed: ${instanceKey}`);
|
|
65758
66056
|
}
|
|
65759
66057
|
}
|
|
65760
|
-
if (
|
|
66058
|
+
if (killProcess2) {
|
|
65761
66059
|
const running = await isIdeRunning(ideType);
|
|
65762
66060
|
if (running) {
|
|
65763
66061
|
LOG.info("StopIDE", `Killing IDE process: ${ideType}`);
|
|
@@ -65772,7 +66070,7 @@ var DaemonCommandRouter = class {
|
|
|
65772
66070
|
}
|
|
65773
66071
|
}
|
|
65774
66072
|
this.deps.onStatusChange?.();
|
|
65775
|
-
LOG.info("StopIDE", `IDE stopped: ${ideType} (processKill=${
|
|
66073
|
+
LOG.info("StopIDE", `IDE stopped: ${ideType} (processKill=${killProcess2})`);
|
|
65776
66074
|
}
|
|
65777
66075
|
};
|
|
65778
66076
|
|
|
@@ -72709,8 +73007,10 @@ var SessionHostRuntimeTransport = class {
|
|
|
72709
73007
|
return;
|
|
72710
73008
|
}
|
|
72711
73009
|
if (event.type === "session_exit") {
|
|
73010
|
+
const exitCode = typeof event.exitCode === "number" ? event.exitCode : null;
|
|
73011
|
+
const signal = typeof event.signal === "number" ? event.signal : null;
|
|
72712
73012
|
for (const callback of this.exitCallbacks) {
|
|
72713
|
-
callback({ exitCode
|
|
73013
|
+
callback({ exitCode, signal });
|
|
72714
73014
|
}
|
|
72715
73015
|
void this.closeClient(false);
|
|
72716
73016
|
}
|
|
@@ -73102,7 +73402,7 @@ async function listHostedCliRuntimes(endpoint) {
|
|
|
73102
73402
|
}
|
|
73103
73403
|
|
|
73104
73404
|
// src/session-host/managed-host.ts
|
|
73105
|
-
import { execFileSync as
|
|
73405
|
+
import { execFileSync as execFileSync11, spawn as spawn5 } from "child_process";
|
|
73106
73406
|
import * as fs43 from "fs";
|
|
73107
73407
|
import * as os31 from "os";
|
|
73108
73408
|
import * as path45 from "path";
|
|
@@ -73110,6 +73410,7 @@ import {
|
|
|
73110
73410
|
getDefaultSessionHostEndpoint as getDefaultSessionHostEndpoint2,
|
|
73111
73411
|
sanitizeSpawnEnv as sanitizeSpawnEnv2
|
|
73112
73412
|
} from "@adhdev/session-host-core";
|
|
73413
|
+
init_logger();
|
|
73113
73414
|
init_runtime_defaults();
|
|
73114
73415
|
function createManagedSessionHost(options) {
|
|
73115
73416
|
const appName = options.appName;
|
|
@@ -73133,6 +73434,14 @@ function createManagedSessionHost(options) {
|
|
|
73133
73434
|
}
|
|
73134
73435
|
return __require.resolve("@adhdev/session-host-daemon");
|
|
73135
73436
|
}
|
|
73437
|
+
function pathsEquivalent(left, right) {
|
|
73438
|
+
return path45.resolve(left).toLowerCase() === path45.resolve(right).toLowerCase();
|
|
73439
|
+
}
|
|
73440
|
+
function getRunningSessionHostScriptPath(pid) {
|
|
73441
|
+
const commandLine = getProcessCommandLine(pid);
|
|
73442
|
+
if (!commandLine || !/session-host-daemon/i.test(commandLine)) return null;
|
|
73443
|
+
return parseNodeScriptPath(commandLine);
|
|
73444
|
+
}
|
|
73136
73445
|
function getPidFile() {
|
|
73137
73446
|
return path45.join(os31.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
73138
73447
|
}
|
|
@@ -73146,12 +73455,12 @@ function createManagedSessionHost(options) {
|
|
|
73146
73455
|
return null;
|
|
73147
73456
|
}
|
|
73148
73457
|
}
|
|
73149
|
-
function
|
|
73458
|
+
function killPid(pid) {
|
|
73150
73459
|
try {
|
|
73151
73460
|
if (process.platform === "win32") {
|
|
73152
73461
|
const spawnOpts = { stdio: "ignore" };
|
|
73153
73462
|
if (options.killWindowsHide) spawnOpts.windowsHide = true;
|
|
73154
|
-
|
|
73463
|
+
execFileSync11("taskkill", ["/PID", String(pid), "/T", "/F"], spawnOpts);
|
|
73155
73464
|
} else {
|
|
73156
73465
|
process.kill(pid, "SIGTERM");
|
|
73157
73466
|
}
|
|
@@ -73191,7 +73500,7 @@ function createManagedSessionHost(options) {
|
|
|
73191
73500
|
if (fs43.existsSync(pidFile)) {
|
|
73192
73501
|
const pid = Number.parseInt(fs43.readFileSync(pidFile, "utf8").trim(), 10);
|
|
73193
73502
|
if (Number.isFinite(pid) && pid !== process.pid && isManagedPid(pid)) {
|
|
73194
|
-
stopped =
|
|
73503
|
+
stopped = killPid(pid) || stopped;
|
|
73195
73504
|
}
|
|
73196
73505
|
}
|
|
73197
73506
|
} catch {
|
|
@@ -73208,6 +73517,20 @@ function createManagedSessionHost(options) {
|
|
|
73208
73517
|
}
|
|
73209
73518
|
async function ensureReady() {
|
|
73210
73519
|
options.beforeEnsureReady?.();
|
|
73520
|
+
if (process.platform === "win32") {
|
|
73521
|
+
const existingPid = getPid();
|
|
73522
|
+
if (existingPid !== null) {
|
|
73523
|
+
const runningPath = getRunningSessionHostScriptPath(existingPid);
|
|
73524
|
+
const currentEntry = resolveEntry();
|
|
73525
|
+
if (runningPath && !pathsEquivalent(runningPath, currentEntry)) {
|
|
73526
|
+
LOG.warn(
|
|
73527
|
+
"SessionHost",
|
|
73528
|
+
`Detected stale host pid ${existingPid} running from ${runningPath}; restarting from ${currentEntry}`
|
|
73529
|
+
);
|
|
73530
|
+
stopManagedSessionHostProcess();
|
|
73531
|
+
}
|
|
73532
|
+
}
|
|
73533
|
+
}
|
|
73211
73534
|
try {
|
|
73212
73535
|
return await ensureSessionHostReady({
|
|
73213
73536
|
appName,
|
|
@@ -73236,7 +73559,7 @@ function createManagedSessionHost(options) {
|
|
|
73236
73559
|
getPid,
|
|
73237
73560
|
buildEnv,
|
|
73238
73561
|
resolveEntry,
|
|
73239
|
-
killPid
|
|
73562
|
+
killPid,
|
|
73240
73563
|
spawnHost,
|
|
73241
73564
|
stopManagedSessionHostProcess,
|
|
73242
73565
|
ensureReady,
|