adhdev 0.9.82-rc.2 → 0.9.82-rc.21
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 +958 -499
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +477 -109
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/vendor/mcp-server/index.js +175 -19
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -784,8 +784,14 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
784
784
|
const includeSubmodules = options.includeSubmodules !== false;
|
|
785
785
|
try {
|
|
786
786
|
const repo = await resolveGitRepository(workspace, options);
|
|
787
|
-
|
|
788
|
-
|
|
787
|
+
let parsed = await readPorcelainStatus(repo, options);
|
|
788
|
+
let upstreamProbe = getInitialUpstreamProbe(parsed);
|
|
789
|
+
if (options.refreshUpstream) {
|
|
790
|
+
upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
|
|
791
|
+
if (upstreamProbe.upstreamStatus === "fresh") {
|
|
792
|
+
parsed = await readPorcelainStatus(repo, options);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
789
795
|
const head = await readHead(repo, options);
|
|
790
796
|
const stashCount = await readStashCount(repo, options);
|
|
791
797
|
let submodules;
|
|
@@ -800,6 +806,9 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
800
806
|
headCommit: head.commit,
|
|
801
807
|
headMessage: head.message,
|
|
802
808
|
upstream: parsed.upstream,
|
|
809
|
+
upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
|
|
810
|
+
upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
|
|
811
|
+
upstreamFetchError: upstreamProbe.upstreamFetchError,
|
|
803
812
|
ahead: parsed.ahead,
|
|
804
813
|
behind: parsed.behind,
|
|
805
814
|
staged: parsed.staged,
|
|
@@ -824,6 +833,60 @@ async function getGitRepoStatus(workspace, options = {}) {
|
|
|
824
833
|
);
|
|
825
834
|
}
|
|
826
835
|
}
|
|
836
|
+
async function readPorcelainStatus(repo, options) {
|
|
837
|
+
const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
|
|
838
|
+
return parsePorcelainV2Status(statusOutput.stdout);
|
|
839
|
+
}
|
|
840
|
+
function getInitialUpstreamProbe(parsed) {
|
|
841
|
+
return {
|
|
842
|
+
upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
async function refreshTrackedUpstream(repo, parsed, options) {
|
|
846
|
+
if (!parsed.upstream || !parsed.branch) {
|
|
847
|
+
return { upstreamStatus: "no_upstream" };
|
|
848
|
+
}
|
|
849
|
+
const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
|
|
850
|
+
if (!remoteName) {
|
|
851
|
+
return {
|
|
852
|
+
upstreamStatus: "stale",
|
|
853
|
+
upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
try {
|
|
857
|
+
await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
|
|
858
|
+
return {
|
|
859
|
+
upstreamStatus: "fresh",
|
|
860
|
+
upstreamFetchedAt: Date.now()
|
|
861
|
+
};
|
|
862
|
+
} catch (error48) {
|
|
863
|
+
return {
|
|
864
|
+
upstreamStatus: "stale",
|
|
865
|
+
upstreamFetchError: formatGitError(error48)
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
async function readBranchRemote(repo, branch, options) {
|
|
870
|
+
try {
|
|
871
|
+
const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
|
|
872
|
+
return result.stdout.trim() || null;
|
|
873
|
+
} catch {
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
function inferRemoteName(upstream) {
|
|
878
|
+
const [remoteName] = upstream.split("/");
|
|
879
|
+
return remoteName?.trim() || null;
|
|
880
|
+
}
|
|
881
|
+
function formatGitError(error48) {
|
|
882
|
+
if (error48 instanceof GitCommandError) {
|
|
883
|
+
return error48.stderr || error48.message;
|
|
884
|
+
}
|
|
885
|
+
if (error48 instanceof Error) {
|
|
886
|
+
return error48.message;
|
|
887
|
+
}
|
|
888
|
+
return String(error48);
|
|
889
|
+
}
|
|
827
890
|
function parsePorcelainV2Status(output) {
|
|
828
891
|
const parsed = {
|
|
829
892
|
branch: null,
|
|
@@ -918,6 +981,7 @@ function emptyStatus(workspace, lastCheckedAt, error48) {
|
|
|
918
981
|
headCommit: null,
|
|
919
982
|
headMessage: null,
|
|
920
983
|
upstream: null,
|
|
984
|
+
upstreamStatus: "unavailable",
|
|
921
985
|
ahead: 0,
|
|
922
986
|
behind: 0,
|
|
923
987
|
staged: 0,
|
|
@@ -1210,6 +1274,9 @@ function createGitCompactSummary(status, diffSummary) {
|
|
|
1210
1274
|
isGitRepo: status.isGitRepo,
|
|
1211
1275
|
repoRoot: status.repoRoot,
|
|
1212
1276
|
branch: status.branch,
|
|
1277
|
+
upstreamStatus: status.upstreamStatus,
|
|
1278
|
+
upstreamFetchedAt: status.upstreamFetchedAt,
|
|
1279
|
+
upstreamFetchError: status.upstreamFetchError,
|
|
1213
1280
|
dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
|
|
1214
1281
|
changedFiles,
|
|
1215
1282
|
ahead: status.ahead,
|
|
@@ -1537,7 +1604,7 @@ function serviceNotImplemented(command) {
|
|
|
1537
1604
|
}
|
|
1538
1605
|
function createDefaultGitCommandServices() {
|
|
1539
1606
|
return {
|
|
1540
|
-
getStatus: ({ workspace }) => getGitRepoStatus(workspace),
|
|
1607
|
+
getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
|
|
1541
1608
|
getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
|
|
1542
1609
|
getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
|
|
1543
1610
|
createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
|
|
@@ -1622,7 +1689,7 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
|
|
|
1622
1689
|
switch (command) {
|
|
1623
1690
|
case "git_status": {
|
|
1624
1691
|
if (!services.getStatus) return serviceNotImplemented(command);
|
|
1625
|
-
const status = await runService(() => services.getStatus({ workspace }));
|
|
1692
|
+
const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
|
|
1626
1693
|
return "success" in status ? status : { success: true, status };
|
|
1627
1694
|
}
|
|
1628
1695
|
case "git_diff_summary": {
|
|
@@ -4279,10 +4346,18 @@ __export(mesh_events_exports, {
|
|
|
4279
4346
|
drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
|
|
4280
4347
|
getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
|
|
4281
4348
|
handleMeshForwardEvent: () => handleMeshForwardEvent,
|
|
4349
|
+
queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
|
|
4282
4350
|
setupMeshEventForwarding: () => setupMeshEventForwarding,
|
|
4283
4351
|
triggerMeshQueue: () => triggerMeshQueue,
|
|
4284
4352
|
tryAssignQueueTask: () => tryAssignQueueTask
|
|
4285
4353
|
});
|
|
4354
|
+
function queuePendingMeshCoordinatorEvent(event) {
|
|
4355
|
+
if (pendingMeshCoordinatorEvents.length >= MAX_PENDING_EVENTS) {
|
|
4356
|
+
return false;
|
|
4357
|
+
}
|
|
4358
|
+
pendingMeshCoordinatorEvents.push(event);
|
|
4359
|
+
return true;
|
|
4360
|
+
}
|
|
4286
4361
|
function drainPendingMeshCoordinatorEvents() {
|
|
4287
4362
|
return pendingMeshCoordinatorEvents.splice(0);
|
|
4288
4363
|
}
|
|
@@ -4854,17 +4929,18 @@ function injectMeshSystemMessage(components, args) {
|
|
|
4854
4929
|
return true;
|
|
4855
4930
|
});
|
|
4856
4931
|
if (coordinatorInstances.length === 0) {
|
|
4857
|
-
if (
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
}
|
|
4866
|
-
|
|
4867
|
-
|
|
4932
|
+
if (queuePendingMeshCoordinatorEvent({
|
|
4933
|
+
event: args.event,
|
|
4934
|
+
meshId: args.meshId,
|
|
4935
|
+
nodeLabel: args.nodeLabel,
|
|
4936
|
+
nodeId: args.nodeId || void 0,
|
|
4937
|
+
workspace: readNonEmptyString(args.metadataEvent.workspace),
|
|
4938
|
+
metadataEvent: {
|
|
4939
|
+
...args.metadataEvent,
|
|
4940
|
+
...recoveryContext ? { recoveryContext } : {}
|
|
4941
|
+
},
|
|
4942
|
+
queuedAt: Date.now()
|
|
4943
|
+
})) {
|
|
4868
4944
|
LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
4869
4945
|
}
|
|
4870
4946
|
return { success: true, forwarded: 0 };
|
|
@@ -7199,7 +7275,7 @@ var init_status_monitor = __esm({
|
|
|
7199
7275
|
});
|
|
7200
7276
|
|
|
7201
7277
|
// ../../oss/packages/daemon-core/src/providers/chat-message-normalization.ts
|
|
7202
|
-
function extractFinalSummaryFromMessages(messages, maxChars =
|
|
7278
|
+
function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
|
|
7203
7279
|
if (!Array.isArray(messages) || messages.length === 0) return "";
|
|
7204
7280
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
7205
7281
|
const msg = messages[i];
|
|
@@ -7501,11 +7577,12 @@ function filterInternalChatMessages(messages) {
|
|
|
7501
7577
|
function filterChatMessagesByVisibility(messages, surface) {
|
|
7502
7578
|
return (Array.isArray(messages) ? messages : []).filter((message) => classifyChatMessageVisibility(message).surface === surface);
|
|
7503
7579
|
}
|
|
7504
|
-
var BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET;
|
|
7580
|
+
var DEFAULT_FINAL_SUMMARY_MAX_CHARS, BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET;
|
|
7505
7581
|
var init_chat_message_normalization = __esm({
|
|
7506
7582
|
"../../oss/packages/daemon-core/src/providers/chat-message-normalization.ts"() {
|
|
7507
7583
|
"use strict";
|
|
7508
7584
|
init_contracts();
|
|
7585
|
+
DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
|
|
7509
7586
|
BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
|
|
7510
7587
|
CHAT_MESSAGE_VISIBILITIES = ["user", "debug", "internal", "hidden"];
|
|
7511
7588
|
CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES = ["visible", "chat", "user", "debug", "internal", "hidden"];
|
|
@@ -46402,6 +46479,26 @@ function readBooleanValue(...values) {
|
|
|
46402
46479
|
}
|
|
46403
46480
|
return void 0;
|
|
46404
46481
|
}
|
|
46482
|
+
function readGitSubmodules(value) {
|
|
46483
|
+
if (!Array.isArray(value)) return void 0;
|
|
46484
|
+
const submodules = value.map((entry) => {
|
|
46485
|
+
const submodule = readObjectRecord(entry);
|
|
46486
|
+
const path42 = readStringValue(submodule.path);
|
|
46487
|
+
const commit = readStringValue(submodule.commit);
|
|
46488
|
+
const repoPath = readStringValue(submodule.repoPath, submodule.repo_root);
|
|
46489
|
+
if (!path42 || !commit || !repoPath) return null;
|
|
46490
|
+
return {
|
|
46491
|
+
path: path42,
|
|
46492
|
+
commit,
|
|
46493
|
+
repoPath,
|
|
46494
|
+
dirty: readBooleanValue(submodule.dirty) ?? false,
|
|
46495
|
+
outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
|
|
46496
|
+
lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
|
|
46497
|
+
...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
|
|
46498
|
+
};
|
|
46499
|
+
}).filter((entry) => entry !== null);
|
|
46500
|
+
return submodules.length > 0 ? submodules : void 0;
|
|
46501
|
+
}
|
|
46405
46502
|
function buildCachedInlineMeshGitStatus(node) {
|
|
46406
46503
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46407
46504
|
const cachedGit = readObjectRecord(cachedStatus.git);
|
|
@@ -46411,6 +46508,7 @@ function buildCachedInlineMeshGitStatus(node) {
|
|
|
46411
46508
|
const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
|
|
46412
46509
|
const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
|
|
46413
46510
|
if (isGitRepo2 !== void 0) {
|
|
46511
|
+
const submodules2 = readGitSubmodules(cachedGit.submodules);
|
|
46414
46512
|
return {
|
|
46415
46513
|
workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
|
|
46416
46514
|
repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
|
|
@@ -46429,7 +46527,8 @@ function buildCachedInlineMeshGitStatus(node) {
|
|
|
46429
46527
|
hasConflicts: hasConflicts2,
|
|
46430
46528
|
conflictFiles: conflictFiles2,
|
|
46431
46529
|
stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
|
|
46432
|
-
lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now()
|
|
46530
|
+
lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now(),
|
|
46531
|
+
...submodules2 ? { submodules: submodules2 } : {}
|
|
46433
46532
|
};
|
|
46434
46533
|
}
|
|
46435
46534
|
}
|
|
@@ -46448,6 +46547,7 @@ function buildCachedInlineMeshGitStatus(node) {
|
|
|
46448
46547
|
const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
|
|
46449
46548
|
const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
|
|
46450
46549
|
const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
|
|
46550
|
+
const submodules = readGitSubmodules(status.submodules);
|
|
46451
46551
|
return {
|
|
46452
46552
|
workspace: readStringValue(status.workspace, node?.workspace) || "",
|
|
46453
46553
|
repoRoot: readStringValue(status.repoRoot, node?.repoRoot, node?.workspace) || null,
|
|
@@ -46466,29 +46566,161 @@ function buildCachedInlineMeshGitStatus(node) {
|
|
|
46466
46566
|
hasConflicts,
|
|
46467
46567
|
conflictFiles,
|
|
46468
46568
|
stashCount: readNumberValue(status.stashCount) ?? 0,
|
|
46469
|
-
lastCheckedAt: Date.now()
|
|
46569
|
+
lastCheckedAt: Date.now(),
|
|
46570
|
+
...submodules ? { submodules } : {}
|
|
46470
46571
|
};
|
|
46471
46572
|
}
|
|
46573
|
+
function hasGitWorktreeChanges(git) {
|
|
46574
|
+
if (!git) return false;
|
|
46575
|
+
return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
|
|
46576
|
+
}
|
|
46577
|
+
function getGitSubmoduleDriftState(git) {
|
|
46578
|
+
const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
|
|
46579
|
+
let dirty = false;
|
|
46580
|
+
let outOfSync = false;
|
|
46581
|
+
for (const entry of submodules) {
|
|
46582
|
+
const submodule = readObjectRecord(entry);
|
|
46583
|
+
if (readBooleanValue(submodule.dirty) === true) dirty = true;
|
|
46584
|
+
if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
|
|
46585
|
+
}
|
|
46586
|
+
return { dirty, outOfSync };
|
|
46587
|
+
}
|
|
46588
|
+
function deriveMeshNodeHealthFromGit(git) {
|
|
46589
|
+
if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
|
|
46590
|
+
const branch = readStringValue(git.branch);
|
|
46591
|
+
if (!branch) return "degraded";
|
|
46592
|
+
const submoduleDrift = getGitSubmoduleDriftState(git);
|
|
46593
|
+
if (submoduleDrift.outOfSync) return "degraded";
|
|
46594
|
+
if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
|
|
46595
|
+
return "online";
|
|
46596
|
+
}
|
|
46597
|
+
function readCachedInlineMeshActiveSessions(node) {
|
|
46598
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46599
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
46600
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
46601
|
+
const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
|
|
46602
|
+
return sessionId ? [sessionId] : [];
|
|
46603
|
+
}
|
|
46604
|
+
function readCachedInlineMeshActiveSessionDetails(node) {
|
|
46605
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46606
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
46607
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
46608
|
+
const sessionId = readStringValue(
|
|
46609
|
+
fallbackSession.id,
|
|
46610
|
+
fallbackSession.sessionId,
|
|
46611
|
+
fallbackSession.session_id,
|
|
46612
|
+
node?.activeSessionId,
|
|
46613
|
+
node?.active_session_id,
|
|
46614
|
+
node?.sessionId,
|
|
46615
|
+
node?.session_id
|
|
46616
|
+
);
|
|
46617
|
+
if (!sessionId) return [];
|
|
46618
|
+
return [{
|
|
46619
|
+
sessionId,
|
|
46620
|
+
providerType: readStringValue(
|
|
46621
|
+
fallbackSession.providerType,
|
|
46622
|
+
fallbackSession.provider_type,
|
|
46623
|
+
fallbackSession.cliType,
|
|
46624
|
+
fallbackSession.cli_type,
|
|
46625
|
+
fallbackSession.provider,
|
|
46626
|
+
node?.providerType,
|
|
46627
|
+
node?.provider_type
|
|
46628
|
+
),
|
|
46629
|
+
state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
|
|
46630
|
+
lifecycle: readStringValue(fallbackSession.lifecycle),
|
|
46631
|
+
title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
|
|
46632
|
+
workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
|
|
46633
|
+
lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
|
|
46634
|
+
recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
|
|
46635
|
+
isCached: true
|
|
46636
|
+
}];
|
|
46637
|
+
}
|
|
46638
|
+
function readLiveMeshSessionState(record2) {
|
|
46639
|
+
return readStringValue(
|
|
46640
|
+
record2?.meta?.sessionStatus,
|
|
46641
|
+
record2?.meta?.status,
|
|
46642
|
+
record2?.meta?.providerStatus,
|
|
46643
|
+
record2?.status,
|
|
46644
|
+
record2?.state,
|
|
46645
|
+
record2?.lifecycle
|
|
46646
|
+
);
|
|
46647
|
+
}
|
|
46648
|
+
function toIsoTimestamp(value) {
|
|
46649
|
+
if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
|
|
46650
|
+
const stringValue = readStringValue(value);
|
|
46651
|
+
return stringValue || null;
|
|
46652
|
+
}
|
|
46653
|
+
function summarizeMeshSessionRecord(record2) {
|
|
46654
|
+
return {
|
|
46655
|
+
sessionId: readStringValue(record2?.sessionId) || "unknown",
|
|
46656
|
+
providerType: readStringValue(record2?.providerType),
|
|
46657
|
+
state: readLiveMeshSessionState(record2),
|
|
46658
|
+
lifecycle: readStringValue(record2?.lifecycle),
|
|
46659
|
+
surfaceKind: getSessionHostSurfaceKind(record2),
|
|
46660
|
+
recoveryState: readStringValue(record2?.meta?.runtimeRecoveryState) ?? null,
|
|
46661
|
+
workspace: readStringValue(record2?.workspace) ?? null,
|
|
46662
|
+
title: readStringValue(record2?.displayName, record2?.workspaceLabel) ?? null,
|
|
46663
|
+
lastActivityAt: toIsoTimestamp(record2?.updatedAt ?? record2?.lastActivityAt ?? record2?.last_activity_at),
|
|
46664
|
+
isCached: false
|
|
46665
|
+
};
|
|
46666
|
+
}
|
|
46667
|
+
function readLiveMeshNodeWorkspace(args) {
|
|
46668
|
+
const directNodeWorkspace = args.liveSessionRecords.find((record2) => readStringValue(record2?.meta?.meshNodeId) === args.nodeId && readStringValue(record2?.workspace));
|
|
46669
|
+
if (directNodeWorkspace) {
|
|
46670
|
+
return readStringValue(directNodeWorkspace.workspace) || "";
|
|
46671
|
+
}
|
|
46672
|
+
if (args.allowCoordinatorSession) {
|
|
46673
|
+
const coordinatorWorkspace = args.liveSessionRecords.find((record2) => readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record2?.workspace));
|
|
46674
|
+
if (coordinatorWorkspace) {
|
|
46675
|
+
return readStringValue(coordinatorWorkspace.workspace) || "";
|
|
46676
|
+
}
|
|
46677
|
+
}
|
|
46678
|
+
return "";
|
|
46679
|
+
}
|
|
46680
|
+
function collectLiveMeshSessionRecords(args) {
|
|
46681
|
+
const matches = args.liveSessionRecords.filter((record2) => {
|
|
46682
|
+
if (readStringValue(record2?.meta?.meshNodeId) === args.nodeId) return true;
|
|
46683
|
+
const recordWorkspace = readStringValue(record2?.workspace);
|
|
46684
|
+
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
46685
|
+
return !!recordWorkspace && !!nodeWorkspace && recordWorkspace === nodeWorkspace;
|
|
46686
|
+
});
|
|
46687
|
+
if (args.allowCoordinatorSession) {
|
|
46688
|
+
for (const record2 of args.liveSessionRecords) {
|
|
46689
|
+
if (readStringValue(record2?.meta?.meshCoordinatorFor) !== args.meshId) continue;
|
|
46690
|
+
const sessionId = readStringValue(record2?.sessionId);
|
|
46691
|
+
if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
|
|
46692
|
+
matches.push(record2);
|
|
46693
|
+
}
|
|
46694
|
+
}
|
|
46695
|
+
return matches;
|
|
46696
|
+
}
|
|
46472
46697
|
function applyCachedInlineMeshNodeStatus(status, node) {
|
|
46473
46698
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46474
46699
|
const git = buildCachedInlineMeshGitStatus(node);
|
|
46475
46700
|
const error48 = readStringValue(cachedStatus.error, node?.error);
|
|
46476
46701
|
const health = readStringValue(cachedStatus.health, node?.health);
|
|
46477
46702
|
const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
|
|
46478
|
-
|
|
46479
|
-
|
|
46703
|
+
const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
|
|
46704
|
+
const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
|
|
46705
|
+
const activeSessions = readCachedInlineMeshActiveSessions(node);
|
|
46706
|
+
const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
|
|
46707
|
+
if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
|
|
46480
46708
|
if (git) status.git = git;
|
|
46481
46709
|
if (error48) status.error = error48;
|
|
46710
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
46711
|
+
if (lastSeenAt) status.lastSeenAt = lastSeenAt;
|
|
46712
|
+
if (updatedAt) status.updatedAt = updatedAt;
|
|
46713
|
+
if (activeSessions.length > 0) status.activeSessions = activeSessions;
|
|
46714
|
+
if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
|
|
46482
46715
|
if (health) {
|
|
46483
46716
|
status.health = health;
|
|
46484
46717
|
return true;
|
|
46485
46718
|
}
|
|
46486
46719
|
if (git) {
|
|
46487
|
-
|
|
46488
|
-
status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
|
|
46720
|
+
status.health = deriveMeshNodeHealthFromGit(git);
|
|
46489
46721
|
return true;
|
|
46490
46722
|
}
|
|
46491
|
-
return
|
|
46723
|
+
return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
|
|
46492
46724
|
}
|
|
46493
46725
|
async function resolveProviderTypeFromPriority(args) {
|
|
46494
46726
|
if (!args.providerPriority.length) {
|
|
@@ -46878,6 +47110,7 @@ var init_router = __esm({
|
|
|
46878
47110
|
init_chat_history();
|
|
46879
47111
|
init_ide_detector();
|
|
46880
47112
|
init_cli_detector();
|
|
47113
|
+
init_git_status();
|
|
46881
47114
|
init_logger();
|
|
46882
47115
|
init_command_log();
|
|
46883
47116
|
init_js_yaml();
|
|
@@ -46922,25 +47155,35 @@ var init_router = __esm({
|
|
|
46922
47155
|
}
|
|
46923
47156
|
getCachedInlineMesh(meshId, inlineMesh) {
|
|
46924
47157
|
if (inlineMesh && typeof inlineMesh === "object") {
|
|
46925
|
-
this.
|
|
46926
|
-
return inlineMesh;
|
|
47158
|
+
return this.warmInlineMeshCache(meshId, inlineMesh);
|
|
46927
47159
|
}
|
|
46928
47160
|
return this.inlineMeshCache.get(meshId);
|
|
46929
47161
|
}
|
|
47162
|
+
warmInlineMeshCache(meshId, inlineMesh) {
|
|
47163
|
+
if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
|
|
47164
|
+
const cached2 = this.inlineMeshCache.get(meshId);
|
|
47165
|
+
if (cached2) return cached2;
|
|
47166
|
+
this.inlineMeshCache.set(meshId, inlineMesh);
|
|
47167
|
+
return inlineMesh;
|
|
47168
|
+
}
|
|
46930
47169
|
async getMeshForCommand(meshId, inlineMesh, options) {
|
|
46931
47170
|
const preferInline = options?.preferInline === true;
|
|
46932
47171
|
if (preferInline) {
|
|
46933
|
-
const cached3 = this.getCachedInlineMesh(meshId
|
|
46934
|
-
if (cached3) return { mesh: cached3, inline: true };
|
|
47172
|
+
const cached3 = this.getCachedInlineMesh(meshId);
|
|
47173
|
+
if (cached3) return { mesh: cached3, inline: true, source: "inline_cache" };
|
|
47174
|
+
const warmedInline2 = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
47175
|
+
if (warmedInline2) return { mesh: warmedInline2, inline: true, source: "inline_bootstrap" };
|
|
46935
47176
|
}
|
|
46936
47177
|
try {
|
|
46937
47178
|
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
46938
47179
|
const mesh = getMesh3(meshId);
|
|
46939
|
-
if (mesh) return { mesh, inline: false };
|
|
47180
|
+
if (mesh) return { mesh, inline: false, source: "local_config" };
|
|
46940
47181
|
} catch {
|
|
46941
47182
|
}
|
|
46942
|
-
const cached2 = this.getCachedInlineMesh(meshId
|
|
46943
|
-
|
|
47183
|
+
const cached2 = this.getCachedInlineMesh(meshId);
|
|
47184
|
+
if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
|
|
47185
|
+
const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
47186
|
+
return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
|
|
46944
47187
|
}
|
|
46945
47188
|
updateInlineMeshNode(meshId, mesh, node) {
|
|
46946
47189
|
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
@@ -47169,6 +47412,7 @@ var init_router = __esm({
|
|
|
47169
47412
|
const deletedSessionIds = [];
|
|
47170
47413
|
const skippedSessionIds = [];
|
|
47171
47414
|
const skippedLiveSessionIds = [];
|
|
47415
|
+
const skippedCoordinatorSessionIds = [];
|
|
47172
47416
|
const deleteUnsupportedSessionIds = [];
|
|
47173
47417
|
const recordsRemainSessionIds = [];
|
|
47174
47418
|
const errors = [];
|
|
@@ -47201,6 +47445,12 @@ var init_router = __esm({
|
|
|
47201
47445
|
const completed = this.isCompletedHostedSession(record2);
|
|
47202
47446
|
const surfaceKind = getSessionHostSurfaceKind(record2);
|
|
47203
47447
|
const liveRuntime = surfaceKind === "live_runtime";
|
|
47448
|
+
const coordinatorSession = readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId;
|
|
47449
|
+
if (!hasExplicitSessionIds && coordinatorSession) {
|
|
47450
|
+
skippedSessionIds.push(sessionId);
|
|
47451
|
+
skippedCoordinatorSessionIds.push(sessionId);
|
|
47452
|
+
continue;
|
|
47453
|
+
}
|
|
47204
47454
|
if (!hasExplicitSessionIds && liveRuntime) {
|
|
47205
47455
|
skippedSessionIds.push(sessionId);
|
|
47206
47456
|
skippedLiveSessionIds.push(sessionId);
|
|
@@ -47266,6 +47516,7 @@ var init_router = __esm({
|
|
|
47266
47516
|
deletedSessionIds,
|
|
47267
47517
|
skippedSessionIds,
|
|
47268
47518
|
skippedLiveSessionIds,
|
|
47519
|
+
skippedCoordinatorSessionIds,
|
|
47269
47520
|
...deleteUnsupported ? {
|
|
47270
47521
|
deleteUnsupported: true,
|
|
47271
47522
|
effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
|
|
@@ -47927,14 +48178,8 @@ var init_router = __esm({
|
|
|
47927
48178
|
case "get_mesh": {
|
|
47928
48179
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47929
48180
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
47930
|
-
|
|
47931
|
-
|
|
47932
|
-
const mesh = getMesh3(meshId);
|
|
47933
|
-
if (mesh) return { success: true, mesh };
|
|
47934
|
-
} catch {
|
|
47935
|
-
}
|
|
47936
|
-
const cached2 = this.inlineMeshCache.get(meshId);
|
|
47937
|
-
if (cached2) return { success: true, mesh: cached2 };
|
|
48181
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48182
|
+
if (meshRecord?.mesh) return { success: true, mesh: meshRecord.mesh };
|
|
47938
48183
|
return { success: false, error: "Mesh not found" };
|
|
47939
48184
|
}
|
|
47940
48185
|
case "create_mesh": {
|
|
@@ -48456,7 +48701,14 @@ var init_router = __esm({
|
|
|
48456
48701
|
cliType
|
|
48457
48702
|
};
|
|
48458
48703
|
}
|
|
48459
|
-
const
|
|
48704
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
48705
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
48706
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
48707
|
+
meshId,
|
|
48708
|
+
nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
|
|
48709
|
+
liveSessionRecords: liveMeshSessions,
|
|
48710
|
+
allowCoordinatorSession: true
|
|
48711
|
+
}) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
|
|
48460
48712
|
if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
|
|
48461
48713
|
if (!cliType) {
|
|
48462
48714
|
const resolved = await resolveProviderTypeFromPriority({
|
|
@@ -48764,84 +49016,111 @@ ${block}`);
|
|
|
48764
49016
|
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48765
49017
|
const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
|
|
48766
49018
|
const ledgerSummary = getLedgerSummary2(meshId);
|
|
49019
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
49020
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
49021
|
+
const localMachineId = loadConfig().machineId || "";
|
|
49022
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
49023
|
+
mesh.coordinator?.preferredNodeId,
|
|
49024
|
+
mesh.nodes?.[0]?.id,
|
|
49025
|
+
mesh.nodes?.[0]?.nodeId
|
|
49026
|
+
);
|
|
49027
|
+
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
|
|
49028
|
+
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
48767
49029
|
const nodeStatuses = [];
|
|
48768
|
-
for (const node of mesh.nodes || []) {
|
|
49030
|
+
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
49031
|
+
const nodeId = String(node.id || node.nodeId || "");
|
|
49032
|
+
const daemonId = readStringValue(node.daemonId);
|
|
49033
|
+
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
49034
|
+
const isSelfNode = Boolean(
|
|
49035
|
+
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
|
|
49036
|
+
) || Boolean(
|
|
49037
|
+
daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
|
|
49038
|
+
) || Boolean(meshRecord?.inline && nodeIndex === 0);
|
|
48769
49039
|
const status = {
|
|
48770
|
-
nodeId
|
|
49040
|
+
nodeId,
|
|
48771
49041
|
machineLabel: node.machineLabel || node.id || node.nodeId,
|
|
48772
49042
|
workspace: node.workspace,
|
|
48773
49043
|
repoRoot: node.repoRoot,
|
|
48774
49044
|
isLocalWorktree: node.isLocalWorktree,
|
|
48775
49045
|
worktreeBranch: node.worktreeBranch,
|
|
48776
|
-
daemonId
|
|
49046
|
+
daemonId,
|
|
48777
49047
|
machineId: node.machineId,
|
|
49048
|
+
machineStatus: node.machineStatus,
|
|
48778
49049
|
health: "unknown",
|
|
48779
49050
|
providers: node.providers || [],
|
|
48780
|
-
|
|
49051
|
+
providerPriority,
|
|
49052
|
+
activeSessions: [],
|
|
49053
|
+
activeSessionDetails: [],
|
|
49054
|
+
launchReady: false
|
|
48781
49055
|
};
|
|
48782
|
-
if (
|
|
48783
|
-
|
|
49056
|
+
if (isSelfNode) {
|
|
49057
|
+
status.connection = {
|
|
49058
|
+
perspective: "selected_coordinator",
|
|
49059
|
+
source: "mesh_peer_status",
|
|
49060
|
+
state: "self",
|
|
49061
|
+
transport: "local",
|
|
49062
|
+
reported: true,
|
|
49063
|
+
reason: "Selected coordinator daemon",
|
|
49064
|
+
lastStateChangeAt: refreshedAt
|
|
49065
|
+
};
|
|
49066
|
+
} else if (daemonId) {
|
|
49067
|
+
const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
49068
|
+
status.connection = connection ?? {
|
|
49069
|
+
perspective: "selected_coordinator",
|
|
49070
|
+
source: "not_reported",
|
|
49071
|
+
state: "unknown",
|
|
49072
|
+
transport: "unknown",
|
|
49073
|
+
reported: false,
|
|
49074
|
+
reason: "No live mesh peer telemetry reported by the selected coordinator yet."
|
|
49075
|
+
};
|
|
49076
|
+
} else {
|
|
49077
|
+
status.connection = {
|
|
49078
|
+
perspective: "selected_coordinator",
|
|
49079
|
+
source: "not_reported",
|
|
49080
|
+
state: "unknown",
|
|
49081
|
+
transport: "unknown",
|
|
49082
|
+
reported: false,
|
|
49083
|
+
reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
|
|
49084
|
+
};
|
|
49085
|
+
}
|
|
49086
|
+
const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
|
|
49087
|
+
meshId,
|
|
49088
|
+
node,
|
|
49089
|
+
nodeId,
|
|
49090
|
+
liveSessionRecords: liveMeshSessions,
|
|
49091
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
49092
|
+
});
|
|
49093
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
49094
|
+
meshId,
|
|
49095
|
+
nodeId,
|
|
49096
|
+
liveSessionRecords: matchedLiveSessionRecords,
|
|
49097
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
49098
|
+
}) || (typeof node.workspace === "string" ? node.workspace : "");
|
|
49099
|
+
status.workspace = workspace || node.workspace;
|
|
49100
|
+
if (matchedLiveSessionRecords.length > 0) {
|
|
49101
|
+
const sessionIds = matchedLiveSessionRecords.map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
|
|
49102
|
+
const providerTypes = matchedLiveSessionRecords.map((record2) => readStringValue(record2?.providerType)).filter(Boolean);
|
|
49103
|
+
status.activeSessions = sessionIds;
|
|
49104
|
+
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
49105
|
+
if (providerTypes.length > 0) {
|
|
49106
|
+
status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
|
|
49107
|
+
}
|
|
49108
|
+
}
|
|
49109
|
+
if (workspace) {
|
|
49110
|
+
if (!fs10.existsSync(workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
|
|
49111
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
|
|
48784
49112
|
nodeStatuses.push(status);
|
|
48785
49113
|
continue;
|
|
48786
49114
|
}
|
|
48787
49115
|
try {
|
|
48788
|
-
const {
|
|
48789
|
-
|
|
48790
|
-
|
|
48791
|
-
|
|
48792
|
-
|
|
48793
|
-
|
|
48794
|
-
|
|
48795
|
-
});
|
|
48796
|
-
return result.stdout.trim();
|
|
48797
|
-
};
|
|
48798
|
-
const branch = await runGit2(["branch", "--show-current"]).catch(() => "");
|
|
48799
|
-
const porc = await runGit2(["status", "--porcelain"]).catch(() => "");
|
|
48800
|
-
const headCommit = await runGit2(["rev-parse", "--short", "HEAD"]).catch(() => null);
|
|
48801
|
-
const headMessage = await runGit2(["log", "-1", "--format=%s"]).catch(() => null);
|
|
48802
|
-
const upstream = await runGit2(["rev-parse", "--abbrev-ref", "@{upstream}"]).catch(() => null);
|
|
48803
|
-
const aheadBehind = await runGit2(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]).catch(() => "");
|
|
48804
|
-
const stashCount = await runGit2(["stash", "list"]).catch(() => "");
|
|
48805
|
-
let ahead = 0, behind = 0;
|
|
48806
|
-
if (aheadBehind) {
|
|
48807
|
-
const parts = aheadBehind.split(/\s+/);
|
|
48808
|
-
if (parts.length >= 2) {
|
|
48809
|
-
behind = parseInt(parts[0], 10) || 0;
|
|
48810
|
-
ahead = parseInt(parts[1], 10) || 0;
|
|
48811
|
-
}
|
|
48812
|
-
}
|
|
48813
|
-
const dirty = porc.length > 0;
|
|
48814
|
-
const lines = porc ? porc.split("\n").filter(Boolean) : [];
|
|
48815
|
-
let staged = 0, modified = 0, untracked = 0, deleted = 0, renamed2 = 0;
|
|
48816
|
-
for (const line of lines) {
|
|
48817
|
-
const xy = line.slice(0, 2);
|
|
48818
|
-
if (xy[0] !== " " && xy[0] !== "?") staged++;
|
|
48819
|
-
if (xy[1] === "M") modified++;
|
|
48820
|
-
if (xy[1] === "D") deleted++;
|
|
48821
|
-
if (xy[0] === "R" || xy[1] === "R") renamed2++;
|
|
48822
|
-
if (xy === "??") untracked++;
|
|
49116
|
+
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
49117
|
+
status.git = gitStatus;
|
|
49118
|
+
if (gitStatus.isGitRepo) {
|
|
49119
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
49120
|
+
} else {
|
|
49121
|
+
status.health = "degraded";
|
|
49122
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
48823
49123
|
}
|
|
48824
|
-
status.git = {
|
|
48825
|
-
workspace: node.workspace,
|
|
48826
|
-
repoRoot: node.workspace,
|
|
48827
|
-
isGitRepo: true,
|
|
48828
|
-
branch: branch || null,
|
|
48829
|
-
headCommit,
|
|
48830
|
-
headMessage,
|
|
48831
|
-
upstream,
|
|
48832
|
-
ahead,
|
|
48833
|
-
behind,
|
|
48834
|
-
staged,
|
|
48835
|
-
modified,
|
|
48836
|
-
untracked,
|
|
48837
|
-
deleted,
|
|
48838
|
-
renamed: renamed2,
|
|
48839
|
-
hasConflicts: false,
|
|
48840
|
-
conflictFiles: [],
|
|
48841
|
-
stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
|
|
48842
|
-
lastCheckedAt: Date.now()
|
|
48843
|
-
};
|
|
48844
|
-
status.health = branch ? dirty ? "dirty" : "online" : "degraded";
|
|
48845
49124
|
} catch {
|
|
48846
49125
|
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
48847
49126
|
status.health = "degraded";
|
|
@@ -48850,6 +49129,7 @@ ${block}`);
|
|
|
48850
49129
|
} else {
|
|
48851
49130
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
48852
49131
|
}
|
|
49132
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
|
|
48853
49133
|
nodeStatuses.push(status);
|
|
48854
49134
|
}
|
|
48855
49135
|
return {
|
|
@@ -48858,6 +49138,12 @@ ${block}`);
|
|
|
48858
49138
|
meshName: mesh.name,
|
|
48859
49139
|
repoIdentity: mesh.repoIdentity,
|
|
48860
49140
|
defaultBranch: mesh.defaultBranch,
|
|
49141
|
+
refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
49142
|
+
sourceOfTruth: {
|
|
49143
|
+
membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
49144
|
+
coordinatorOwnsLiveTruth: meshRecord?.source !== "inline_bootstrap",
|
|
49145
|
+
historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
|
|
49146
|
+
},
|
|
48861
49147
|
nodes: nodeStatuses,
|
|
48862
49148
|
queue: { tasks: queue, summary: queueSummary },
|
|
48863
49149
|
ledger: { entries: ledgerEntries, summary: ledgerSummary }
|
|
@@ -56936,6 +57222,7 @@ async function initDaemonComponents(config2) {
|
|
|
56936
57222
|
sessionHostControl: config2.sessionHostControl,
|
|
56937
57223
|
statusInstanceId: config2.statusInstanceId,
|
|
56938
57224
|
statusVersion: config2.statusVersion,
|
|
57225
|
+
getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
|
|
56939
57226
|
getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
|
|
56940
57227
|
});
|
|
56941
57228
|
poller = new AgentStreamPoller({
|
|
@@ -57237,6 +57524,7 @@ __export(src_exports, {
|
|
|
57237
57524
|
prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
|
|
57238
57525
|
prepareSessionModalUpdate: () => prepareSessionModalUpdate,
|
|
57239
57526
|
probeCdpPort: () => probeCdpPort,
|
|
57527
|
+
queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
|
|
57240
57528
|
readChatHistory: () => readChatHistory,
|
|
57241
57529
|
readLedgerEntries: () => readLedgerEntries,
|
|
57242
57530
|
readLedgerSlice: () => readLedgerSlice,
|
|
@@ -57693,7 +57981,7 @@ var require_yoctocolors_cjs = __commonJS({
|
|
|
57693
57981
|
}
|
|
57694
57982
|
});
|
|
57695
57983
|
|
|
57696
|
-
// ../../node_modules/@inquirer/figures/dist/esm/index.
|
|
57984
|
+
// ../../node_modules/@inquirer/figures/dist/esm/index.mjs
|
|
57697
57985
|
function isUnicodeSupported() {
|
|
57698
57986
|
if (import_node_process3.default.platform !== "win32") {
|
|
57699
57987
|
return import_node_process3.default.env["TERM"] !== "linux";
|
|
@@ -57705,7 +57993,7 @@ function isUnicodeSupported() {
|
|
|
57705
57993
|
}
|
|
57706
57994
|
var import_node_process3, common2, specialMainSymbols, specialFallbackSymbols, mainSymbols, fallbackSymbols, shouldUseMain, figures, esm_default, replacements;
|
|
57707
57995
|
var init_esm3 = __esm({
|
|
57708
|
-
"../../node_modules/@inquirer/figures/dist/esm/index.
|
|
57996
|
+
"../../node_modules/@inquirer/figures/dist/esm/index.mjs"() {
|
|
57709
57997
|
"use strict";
|
|
57710
57998
|
import_node_process3 = __toESM(require("process"), 1);
|
|
57711
57999
|
common2 = {
|
|
@@ -57976,10 +58264,7 @@ var init_esm3 = __esm({
|
|
|
57976
58264
|
oneNinth: "1/9",
|
|
57977
58265
|
oneTenth: "1/10"
|
|
57978
58266
|
};
|
|
57979
|
-
mainSymbols = {
|
|
57980
|
-
...common2,
|
|
57981
|
-
...specialMainSymbols
|
|
57982
|
-
};
|
|
58267
|
+
mainSymbols = { ...common2, ...specialMainSymbols };
|
|
57983
58268
|
fallbackSymbols = {
|
|
57984
58269
|
...common2,
|
|
57985
58270
|
...specialFallbackSymbols
|
|
@@ -97213,11 +97498,30 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97213
97498
|
nodeDatachannel = null;
|
|
97214
97499
|
peers = /* @__PURE__ */ new Map();
|
|
97215
97500
|
// Map<targetDaemonId, PeerEntry>
|
|
97501
|
+
peerSnapshots = /* @__PURE__ */ new Map();
|
|
97216
97502
|
pendingRequests = /* @__PURE__ */ new Map();
|
|
97217
97503
|
commandCallback;
|
|
97218
97504
|
p2pFailure(message, command, targetDaemonId) {
|
|
97219
97505
|
return new P2pRelayFailureError(message, { command, targetDaemonId });
|
|
97220
97506
|
}
|
|
97507
|
+
updatePeerSnapshot(targetDaemonId, state, patch = {}) {
|
|
97508
|
+
const previous = this.peerSnapshots.get(targetDaemonId);
|
|
97509
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
97510
|
+
this.peerSnapshots.set(targetDaemonId, {
|
|
97511
|
+
perspective: "selected_coordinator",
|
|
97512
|
+
source: "mesh_peer_status",
|
|
97513
|
+
reported: true,
|
|
97514
|
+
state,
|
|
97515
|
+
transport: patch.transport ?? previous?.transport ?? "unknown",
|
|
97516
|
+
reason: patch.reason ?? previous?.reason,
|
|
97517
|
+
lastStateChangeAt: now,
|
|
97518
|
+
lastConnectedAt: patch.lastConnectedAt ?? previous?.lastConnectedAt,
|
|
97519
|
+
lastCommandAt: patch.lastCommandAt ?? previous?.lastCommandAt
|
|
97520
|
+
});
|
|
97521
|
+
}
|
|
97522
|
+
getPeerConnectionStatus(targetDaemonId) {
|
|
97523
|
+
return this.peerSnapshots.get(targetDaemonId) ?? null;
|
|
97524
|
+
}
|
|
97221
97525
|
invalidatePeer(targetDaemonId, reason, options = {}) {
|
|
97222
97526
|
const peer = this.peers.get(targetDaemonId);
|
|
97223
97527
|
if (peer?.commandQueue) {
|
|
@@ -97232,6 +97536,11 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97232
97536
|
pending.reject(this.p2pFailure(reason, pending.command, targetDaemonId));
|
|
97233
97537
|
}
|
|
97234
97538
|
}
|
|
97539
|
+
const snapshotState = peer?.state === "closed" ? "closed" : peer?.state === "disconnected" ? "disconnected" : "failed";
|
|
97540
|
+
this.updatePeerSnapshot(targetDaemonId, snapshotState, {
|
|
97541
|
+
reason,
|
|
97542
|
+
transport: peer?.isRelay === true ? "relay" : peer?.isRelay === false ? "direct" : "unknown"
|
|
97543
|
+
});
|
|
97235
97544
|
if (options.closeResources !== false && peer) {
|
|
97236
97545
|
try {
|
|
97237
97546
|
peer.dataChannel?.close?.();
|
|
@@ -97264,6 +97573,7 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97264
97573
|
"send_chat",
|
|
97265
97574
|
"read_chat",
|
|
97266
97575
|
"get_chat_debug_bundle",
|
|
97576
|
+
"get_pending_mesh_events",
|
|
97267
97577
|
"git_status",
|
|
97268
97578
|
"git_diff_summary",
|
|
97269
97579
|
"launch_cli",
|
|
@@ -97351,6 +97661,20 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97351
97661
|
if (!peer) {
|
|
97352
97662
|
throw this.p2pFailure("Failed to initiate P2P connection entry", command, targetDaemonId);
|
|
97353
97663
|
}
|
|
97664
|
+
const lastCommandAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
97665
|
+
if (peer.state === "connected") {
|
|
97666
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
97667
|
+
transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
|
|
97668
|
+
lastConnectedAt: this.peerSnapshots.get(targetDaemonId)?.lastConnectedAt,
|
|
97669
|
+
lastCommandAt
|
|
97670
|
+
});
|
|
97671
|
+
} else {
|
|
97672
|
+
this.updatePeerSnapshot(targetDaemonId, "connecting", {
|
|
97673
|
+
transport: peer.isRelay === true ? "relay" : peer.isRelay === false ? "direct" : "unknown",
|
|
97674
|
+
reason: "Waiting for mesh DataChannel to open.",
|
|
97675
|
+
lastCommandAt
|
|
97676
|
+
});
|
|
97677
|
+
}
|
|
97354
97678
|
return new Promise((resolve23, reject) => {
|
|
97355
97679
|
const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
97356
97680
|
const timer = setTimeout(() => {
|
|
@@ -97494,6 +97818,9 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97494
97818
|
remoteDescriptionSet: false
|
|
97495
97819
|
};
|
|
97496
97820
|
this.peers.set(targetDaemonId, entry);
|
|
97821
|
+
this.updatePeerSnapshot(targetDaemonId, "connecting", {
|
|
97822
|
+
reason: isInitiator ? "P2P mesh connection initiated by the selected coordinator." : "Waiting for the remote daemon to finish the mesh DataChannel handshake."
|
|
97823
|
+
});
|
|
97497
97824
|
pc.onLocalDescription((sdp, type2) => {
|
|
97498
97825
|
this.serverConn.sendMeshCommand(targetDaemonId, type2 === "offer" ? "mesh_p2p_offer" : "mesh_p2p_answer", { sdp, type: type2 });
|
|
97499
97826
|
});
|
|
@@ -97504,7 +97831,26 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97504
97831
|
LOG.info("Mesh", `[Mesh] P2P state with ${targetDaemonId.slice(0, 12)}: ${state}`);
|
|
97505
97832
|
if (state === "connected") {
|
|
97506
97833
|
entry.state = "connected";
|
|
97834
|
+
let transport = "unknown";
|
|
97835
|
+
try {
|
|
97836
|
+
const pair = pc.getSelectedCandidatePair?.();
|
|
97837
|
+
if (pair) {
|
|
97838
|
+
const localType = pair.local?.type || "unknown";
|
|
97839
|
+
const remoteType = pair.remote?.type || "unknown";
|
|
97840
|
+
entry.isRelay = localType === "relay" || remoteType === "relay";
|
|
97841
|
+
transport = entry.isRelay ? "relay" : "direct";
|
|
97842
|
+
LOG.info("Mesh", `[Mesh] Candidate pair with ${targetDaemonId.slice(0, 12)}: local=${localType} remote=${remoteType} \u2192 ${transport}`);
|
|
97843
|
+
}
|
|
97844
|
+
} catch {
|
|
97845
|
+
transport = entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown";
|
|
97846
|
+
}
|
|
97847
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
97848
|
+
transport,
|
|
97849
|
+
reason: transport === "relay" ? "Connected over TURN relay." : transport === "direct" ? "Connected directly peer-to-peer." : "Connected, but selected candidate pair details are unavailable.",
|
|
97850
|
+
lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
97851
|
+
});
|
|
97507
97852
|
} else if (state === "failed" || state === "closed" || state === "disconnected") {
|
|
97853
|
+
entry.state = state;
|
|
97508
97854
|
this.invalidatePeer(targetDaemonId, `P2P state changed to ${state}`, { rejectPending: true, closeResources: false });
|
|
97509
97855
|
}
|
|
97510
97856
|
});
|
|
@@ -97522,6 +97868,11 @@ var init_daemon_mesh_manager = __esm({
|
|
|
97522
97868
|
dc.onOpen(() => {
|
|
97523
97869
|
LOG.info("Mesh", `[Mesh] DataChannel OPEN with ${targetDaemonId.slice(0, 12)}`);
|
|
97524
97870
|
entry.state = "connected";
|
|
97871
|
+
this.updatePeerSnapshot(targetDaemonId, "connected", {
|
|
97872
|
+
transport: entry.isRelay === true ? "relay" : entry.isRelay === false ? "direct" : "unknown",
|
|
97873
|
+
reason: entry.isRelay === true ? "Connected over TURN relay." : entry.isRelay === false ? "Connected directly peer-to-peer." : "DataChannel open; transport details not reported yet.",
|
|
97874
|
+
lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
97875
|
+
});
|
|
97525
97876
|
if (entry.commandQueue) {
|
|
97526
97877
|
const queue = entry.commandQueue;
|
|
97527
97878
|
entry.commandQueue = [];
|
|
@@ -97801,6 +98152,7 @@ var init_adhdev_daemon = __esm({
|
|
|
97801
98152
|
"use strict";
|
|
97802
98153
|
init_server_connection();
|
|
97803
98154
|
init_src();
|
|
98155
|
+
init_mesh_events();
|
|
97804
98156
|
init_daemon_p2p2();
|
|
97805
98157
|
init_screenshot_controller();
|
|
97806
98158
|
init_session_host();
|
|
@@ -97817,7 +98169,7 @@ var init_adhdev_daemon = __esm({
|
|
|
97817
98169
|
init_version();
|
|
97818
98170
|
init_src();
|
|
97819
98171
|
init_runtime_defaults();
|
|
97820
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.
|
|
98172
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.82-rc.21" });
|
|
97821
98173
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
97822
98174
|
localHttpServer = null;
|
|
97823
98175
|
localWss = null;
|
|
@@ -98341,6 +98693,7 @@ ${err?.stack || ""}`);
|
|
|
98341
98693
|
if (!this.meshManager) throw new Error("Mesh manager not initialized");
|
|
98342
98694
|
return this.meshManager.sendCommand(daemonId, command, args);
|
|
98343
98695
|
},
|
|
98696
|
+
getMeshPeerConnectionStatus: (daemonId) => this.meshManager?.getPeerConnectionStatus(daemonId) ?? null,
|
|
98344
98697
|
onStatusChange: () => {
|
|
98345
98698
|
this.invalidateHotChatSnapshotCache();
|
|
98346
98699
|
this.statusReporter?.onStatusChange();
|
|
@@ -98733,6 +99086,21 @@ ${err?.stack || ""}`);
|
|
|
98733
99086
|
await this.meshManager.sendCommand(coordinatorDaemonId, "mesh_forward_event", payload);
|
|
98734
99087
|
LOG.info("MeshEvents", `Relayed ${payload.event} for mesh ${meshId} to coordinator daemon ${coordinatorDaemonId.slice(0, 12)}\u2026`);
|
|
98735
99088
|
} catch (error48) {
|
|
99089
|
+
queuePendingMeshCoordinatorEvent({
|
|
99090
|
+
event: payload.event,
|
|
99091
|
+
meshId,
|
|
99092
|
+
nodeLabel: payload.nodeId ? `Node '${payload.nodeId}'` : payload.workspace ? `Agent at ${payload.workspace}` : "Remote agent",
|
|
99093
|
+
nodeId: payload.nodeId || void 0,
|
|
99094
|
+
workspace: payload.workspace || void 0,
|
|
99095
|
+
metadataEvent: {
|
|
99096
|
+
targetSessionId: payload.targetSessionId,
|
|
99097
|
+
providerType: payload.providerType,
|
|
99098
|
+
providerSessionId: payload.providerSessionId,
|
|
99099
|
+
finalSummary: payload.finalSummary,
|
|
99100
|
+
workspace: payload.workspace
|
|
99101
|
+
},
|
|
99102
|
+
queuedAt: Date.now()
|
|
99103
|
+
});
|
|
98736
99104
|
LOG.warn("MeshEvents", `Failed to relay ${payload.event} for mesh ${meshId}: ${error48?.message || error48}`);
|
|
98737
99105
|
}
|
|
98738
99106
|
}
|
|
@@ -99639,6 +100007,420 @@ var init_runtime_target_trace = __esm({
|
|
|
99639
100007
|
}
|
|
99640
100008
|
});
|
|
99641
100009
|
|
|
100010
|
+
// src/cli/service-commands.ts
|
|
100011
|
+
var service_commands_exports = {};
|
|
100012
|
+
__export(service_commands_exports, {
|
|
100013
|
+
buildPlist: () => buildPlist,
|
|
100014
|
+
installAutoStartServiceForCurrentProcess: () => installAutoStartServiceForCurrentProcess,
|
|
100015
|
+
isAutoStartServiceInstalled: () => isAutoStartServiceInstalled,
|
|
100016
|
+
registerServiceCommands: () => registerServiceCommands
|
|
100017
|
+
});
|
|
100018
|
+
function getDarwinPlistPath() {
|
|
100019
|
+
return import_node_path5.default.join(import_node_os4.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
100020
|
+
}
|
|
100021
|
+
function getWindowsStartupDir() {
|
|
100022
|
+
const appData = process.env.APPDATA || import_node_path5.default.join(import_node_os4.default.homedir(), "AppData", "Roaming");
|
|
100023
|
+
return import_node_path5.default.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
|
|
100024
|
+
}
|
|
100025
|
+
function getWindowsVbsPath() {
|
|
100026
|
+
return import_node_path5.default.join(getWindowsStartupDir(), "adhdev-daemon.vbs");
|
|
100027
|
+
}
|
|
100028
|
+
function resolveCliPath() {
|
|
100029
|
+
return import_node_fs4.default.realpathSync(process.argv[1]);
|
|
100030
|
+
}
|
|
100031
|
+
function ensureDir(dir) {
|
|
100032
|
+
if (!import_node_fs4.default.existsSync(dir)) import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
100033
|
+
}
|
|
100034
|
+
async function fetchHealth() {
|
|
100035
|
+
const controller = new AbortController();
|
|
100036
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS2);
|
|
100037
|
+
try {
|
|
100038
|
+
const res = await fetch(`http://127.0.0.1:${DEFAULT_DAEMON_PORT}/health`, { signal: controller.signal });
|
|
100039
|
+
if (!res.ok) return null;
|
|
100040
|
+
return await res.json();
|
|
100041
|
+
} catch {
|
|
100042
|
+
return null;
|
|
100043
|
+
} finally {
|
|
100044
|
+
clearTimeout(timer);
|
|
100045
|
+
}
|
|
100046
|
+
}
|
|
100047
|
+
function getProcessInfo(pid) {
|
|
100048
|
+
try {
|
|
100049
|
+
if (process.platform === "win32") {
|
|
100050
|
+
const out = (0, import_node_child_process4.execSync)(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { encoding: "utf-8" });
|
|
100051
|
+
const match = out.match(/"(\d[\d,]+)\sK"/);
|
|
100052
|
+
const memKB = match ? parseInt(match[1].replace(/,/g, ""), 10) : 0;
|
|
100053
|
+
return { uptime: "-", memMB: Math.round(memKB / 1024) };
|
|
100054
|
+
} else {
|
|
100055
|
+
const out = (0, import_node_child_process4.execSync)(`ps -o etime=,rss= -p ${pid}`, { encoding: "utf-8" }).trim();
|
|
100056
|
+
const parts = out.split(/\s+/);
|
|
100057
|
+
const etime = parts[0] || "-";
|
|
100058
|
+
const rssKB = parseInt(parts[1] || "0", 10);
|
|
100059
|
+
return { uptime: formatElapsed(etime), memMB: Math.round(rssKB / 1024) };
|
|
100060
|
+
}
|
|
100061
|
+
} catch {
|
|
100062
|
+
return null;
|
|
100063
|
+
}
|
|
100064
|
+
}
|
|
100065
|
+
function formatElapsed(etime) {
|
|
100066
|
+
const parts = etime.replace("-", ":").split(":").map(Number);
|
|
100067
|
+
if (parts.length === 4) return `${parts[0]}d ${parts[1]}h ${parts[2]}m`;
|
|
100068
|
+
if (parts.length === 3) return `${parts[0]}h ${parts[1]}m`;
|
|
100069
|
+
if (parts.length === 2) return `${parts[0]}m ${parts[1]}s`;
|
|
100070
|
+
return etime;
|
|
100071
|
+
}
|
|
100072
|
+
function rotateLogIfNeeded(logPath) {
|
|
100073
|
+
try {
|
|
100074
|
+
if (!import_node_fs4.default.existsSync(logPath)) return;
|
|
100075
|
+
const stat5 = import_node_fs4.default.statSync(logPath);
|
|
100076
|
+
if (stat5.size > MAX_LOG_SIZE2) {
|
|
100077
|
+
const rotated = logPath + ".old";
|
|
100078
|
+
if (import_node_fs4.default.existsSync(rotated)) import_node_fs4.default.unlinkSync(rotated);
|
|
100079
|
+
import_node_fs4.default.renameSync(logPath, rotated);
|
|
100080
|
+
import_node_fs4.default.writeFileSync(logPath, `[log rotated at ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
100081
|
+
`, "utf-8");
|
|
100082
|
+
}
|
|
100083
|
+
} catch {
|
|
100084
|
+
}
|
|
100085
|
+
}
|
|
100086
|
+
function rotateLogs() {
|
|
100087
|
+
rotateLogIfNeeded(LOG_OUT);
|
|
100088
|
+
rotateLogIfNeeded(LOG_ERR);
|
|
100089
|
+
}
|
|
100090
|
+
function normalizeLaunchdPathEntry(entry) {
|
|
100091
|
+
const trimmed = String(entry || "").trim();
|
|
100092
|
+
if (!trimmed) return null;
|
|
100093
|
+
if (trimmed.startsWith("~")) {
|
|
100094
|
+
return import_node_path5.default.join(import_node_os4.default.homedir(), trimmed.slice(1));
|
|
100095
|
+
}
|
|
100096
|
+
return import_node_path5.default.isAbsolute(trimmed) ? trimmed : null;
|
|
100097
|
+
}
|
|
100098
|
+
function buildLaunchdPath(nodeExe, currentPath = process.env.PATH || "") {
|
|
100099
|
+
const brewPrefix = import_node_fs4.default.existsSync("/opt/homebrew/bin") ? "/opt/homebrew/bin" : "/usr/local/bin";
|
|
100100
|
+
const entries = [];
|
|
100101
|
+
const seen = /* @__PURE__ */ new Set();
|
|
100102
|
+
const addEntry = (value) => {
|
|
100103
|
+
if (!value) return;
|
|
100104
|
+
const normalized = normalizeLaunchdPathEntry(value);
|
|
100105
|
+
if (!normalized || seen.has(normalized)) return;
|
|
100106
|
+
seen.add(normalized);
|
|
100107
|
+
entries.push(normalized);
|
|
100108
|
+
};
|
|
100109
|
+
addEntry(import_node_path5.default.dirname(nodeExe));
|
|
100110
|
+
for (const entry of String(currentPath || "").split(import_node_path5.default.delimiter)) {
|
|
100111
|
+
addEntry(entry);
|
|
100112
|
+
}
|
|
100113
|
+
for (const entry of [brewPrefix, "/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"]) {
|
|
100114
|
+
addEntry(entry);
|
|
100115
|
+
}
|
|
100116
|
+
return entries.join(":");
|
|
100117
|
+
}
|
|
100118
|
+
function buildPlist(nodeExe, cliExe, currentPath = process.env.PATH || "") {
|
|
100119
|
+
const pathValue = buildLaunchdPath(nodeExe, currentPath);
|
|
100120
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
100121
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
100122
|
+
<plist version="1.0">
|
|
100123
|
+
<dict>
|
|
100124
|
+
<key>Label</key>
|
|
100125
|
+
<string>${LAUNCHD_LABEL}</string>
|
|
100126
|
+
<key>ProgramArguments</key>
|
|
100127
|
+
<array>
|
|
100128
|
+
<string>${nodeExe}</string>
|
|
100129
|
+
<string>${cliExe}</string>
|
|
100130
|
+
<string>daemon</string>
|
|
100131
|
+
</array>
|
|
100132
|
+
<key>RunAtLoad</key>
|
|
100133
|
+
<true/>
|
|
100134
|
+
<key>KeepAlive</key>
|
|
100135
|
+
<dict>
|
|
100136
|
+
<key>SuccessfulExit</key>
|
|
100137
|
+
<false/>
|
|
100138
|
+
</dict>
|
|
100139
|
+
<key>ThrottleInterval</key>
|
|
100140
|
+
<integer>30</integer>
|
|
100141
|
+
<key>StandardOutPath</key>
|
|
100142
|
+
<string>${LOG_OUT}</string>
|
|
100143
|
+
<key>StandardErrorPath</key>
|
|
100144
|
+
<string>${LOG_ERR}</string>
|
|
100145
|
+
<key>EnvironmentVariables</key>
|
|
100146
|
+
<dict>
|
|
100147
|
+
<key>PATH</key>
|
|
100148
|
+
<string>${pathValue}</string>
|
|
100149
|
+
</dict>
|
|
100150
|
+
</dict>
|
|
100151
|
+
</plist>`;
|
|
100152
|
+
}
|
|
100153
|
+
function installDarwin(nodeExe, cliExe) {
|
|
100154
|
+
const plistPath = getDarwinPlistPath();
|
|
100155
|
+
ensureDir(ADHDEV_DIR);
|
|
100156
|
+
ensureDir(import_node_path5.default.dirname(plistPath));
|
|
100157
|
+
import_node_fs4.default.writeFileSync(plistPath, buildPlist(nodeExe, cliExe), "utf-8");
|
|
100158
|
+
console.log(source_default.gray(` Plist: ${plistPath}`));
|
|
100159
|
+
try {
|
|
100160
|
+
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
100161
|
+
} catch {
|
|
100162
|
+
}
|
|
100163
|
+
try {
|
|
100164
|
+
(0, import_node_child_process4.execSync)(`launchctl load -w "${plistPath}"`, { stdio: "ignore" });
|
|
100165
|
+
console.log(source_default.green("\n \u2713 Registered as LaunchAgent \u2014 daemon will start on login."));
|
|
100166
|
+
console.log(source_default.gray(` Logs: ~/.adhdev/daemon-launchd.{out,err}`));
|
|
100167
|
+
} catch (e) {
|
|
100168
|
+
console.log(source_default.red(`
|
|
100169
|
+
\u2717 launchctl load failed: ${e.message}`));
|
|
100170
|
+
}
|
|
100171
|
+
}
|
|
100172
|
+
function uninstallDarwin() {
|
|
100173
|
+
const plistPath = getDarwinPlistPath();
|
|
100174
|
+
if (!import_node_fs4.default.existsSync(plistPath)) {
|
|
100175
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
100176
|
+
return;
|
|
100177
|
+
}
|
|
100178
|
+
try {
|
|
100179
|
+
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
100180
|
+
} catch {
|
|
100181
|
+
}
|
|
100182
|
+
import_node_fs4.default.unlinkSync(plistPath);
|
|
100183
|
+
console.log(source_default.green("\n \u2713 Removed LaunchAgent. Daemon will no longer auto-start."));
|
|
100184
|
+
}
|
|
100185
|
+
function isInstalledDarwin() {
|
|
100186
|
+
return import_node_fs4.default.existsSync(getDarwinPlistPath());
|
|
100187
|
+
}
|
|
100188
|
+
function buildVbs(nodeExe, cliExe) {
|
|
100189
|
+
const logFile = import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log").replace(/\\/g, "\\\\");
|
|
100190
|
+
const escapedNodeExe = nodeExe.replace(/\\/g, "\\\\");
|
|
100191
|
+
const escapedCliExe = cliExe.replace(/\\/g, "\\\\");
|
|
100192
|
+
return `' ADHDev Daemon Auto-Start (generated by adhdev service install)
|
|
100193
|
+
Set WshShell = CreateObject("WScript.Shell")
|
|
100194
|
+
WshShell.Run "cmd.exe /c """"${escapedNodeExe}"""" """"${escapedCliExe}"""" daemon >> """"${logFile}"""" 2>&1", 0, False
|
|
100195
|
+
`;
|
|
100196
|
+
}
|
|
100197
|
+
function installWindows(nodeExe, cliExe) {
|
|
100198
|
+
const vbsPath = getWindowsVbsPath();
|
|
100199
|
+
ensureDir(ADHDEV_DIR);
|
|
100200
|
+
ensureDir(import_node_path5.default.dirname(vbsPath));
|
|
100201
|
+
import_node_fs4.default.writeFileSync(vbsPath, buildVbs(nodeExe, cliExe), "utf-8");
|
|
100202
|
+
console.log(source_default.gray(` Startup script: ${vbsPath}`));
|
|
100203
|
+
console.log(source_default.green("\n \u2713 Registered in Startup folder \u2014 daemon will start on login (hidden)."));
|
|
100204
|
+
console.log(source_default.gray(` Logs: ${import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log")}`));
|
|
100205
|
+
console.log(source_default.gray(" To start now without rebooting, run: adhdev daemon"));
|
|
100206
|
+
}
|
|
100207
|
+
function uninstallWindows() {
|
|
100208
|
+
const vbsPath = getWindowsVbsPath();
|
|
100209
|
+
if (!import_node_fs4.default.existsSync(vbsPath)) {
|
|
100210
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
100211
|
+
return;
|
|
100212
|
+
}
|
|
100213
|
+
import_node_fs4.default.unlinkSync(vbsPath);
|
|
100214
|
+
console.log(source_default.green("\n \u2713 Removed Startup script. Daemon will no longer auto-start."));
|
|
100215
|
+
console.log(source_default.gray(" Note: a currently running daemon is not affected. Stop with: adhdev daemon:stop"));
|
|
100216
|
+
}
|
|
100217
|
+
function isInstalledWindows() {
|
|
100218
|
+
return import_node_fs4.default.existsSync(getWindowsVbsPath());
|
|
100219
|
+
}
|
|
100220
|
+
function isAutoStartServiceInstalled(platform12 = import_node_os4.default.platform()) {
|
|
100221
|
+
if (platform12 === "darwin") return isInstalledDarwin();
|
|
100222
|
+
if (platform12 === "win32") return isInstalledWindows();
|
|
100223
|
+
return false;
|
|
100224
|
+
}
|
|
100225
|
+
function installAutoStartServiceForCurrentProcess(platform12 = import_node_os4.default.platform()) {
|
|
100226
|
+
const nodeExe = process.execPath;
|
|
100227
|
+
const cliExe = resolveCliPath();
|
|
100228
|
+
if (platform12 === "darwin") {
|
|
100229
|
+
installDarwin(nodeExe, cliExe);
|
|
100230
|
+
return true;
|
|
100231
|
+
}
|
|
100232
|
+
if (platform12 === "win32") {
|
|
100233
|
+
installWindows(nodeExe, cliExe);
|
|
100234
|
+
return true;
|
|
100235
|
+
}
|
|
100236
|
+
return false;
|
|
100237
|
+
}
|
|
100238
|
+
function registerServiceCommands(program2) {
|
|
100239
|
+
const svc = program2.command("service").description("\u{1F50C} Manage ADHDev as an OS background auto-start service");
|
|
100240
|
+
svc.command("install").description("Register ADHDev daemon to start automatically on login").action(async () => {
|
|
100241
|
+
console.log(source_default.bold("\n \u{1F680} Installing ADHDev Background Service"));
|
|
100242
|
+
const platform12 = import_node_os4.default.platform();
|
|
100243
|
+
const nodeExe = process.execPath;
|
|
100244
|
+
const cliExe = resolveCliPath();
|
|
100245
|
+
console.log(source_default.gray(` Node: ${nodeExe}`));
|
|
100246
|
+
console.log(source_default.gray(` CLI: ${cliExe}`));
|
|
100247
|
+
console.log(source_default.gray(` Platform: ${platform12}`));
|
|
100248
|
+
if (!installAutoStartServiceForCurrentProcess(platform12)) {
|
|
100249
|
+
console.log(source_default.yellow("\n \u26A0 Auto-start service install is not supported on this platform."));
|
|
100250
|
+
console.log(source_default.gray(" On Linux, create a systemd user unit manually:"));
|
|
100251
|
+
console.log(source_default.gray(" ~/.config/systemd/user/adhdev-daemon.service"));
|
|
100252
|
+
}
|
|
100253
|
+
console.log();
|
|
100254
|
+
});
|
|
100255
|
+
svc.command("uninstall").description("Remove the OS background service").action(async () => {
|
|
100256
|
+
console.log(source_default.bold("\n \u{1F5D1}\uFE0F Removing ADHDev Background Service"));
|
|
100257
|
+
const platform12 = import_node_os4.default.platform();
|
|
100258
|
+
if (platform12 === "darwin") {
|
|
100259
|
+
uninstallDarwin();
|
|
100260
|
+
} else if (platform12 === "win32") {
|
|
100261
|
+
uninstallWindows();
|
|
100262
|
+
} else {
|
|
100263
|
+
console.log(source_default.yellow("\n \u26A0 Not supported on this platform."));
|
|
100264
|
+
}
|
|
100265
|
+
console.log();
|
|
100266
|
+
});
|
|
100267
|
+
svc.command("status").description("Show service installation state and live daemon health").action(async () => {
|
|
100268
|
+
const platform12 = import_node_os4.default.platform();
|
|
100269
|
+
const installed = isAutoStartServiceInstalled(platform12);
|
|
100270
|
+
if (installed) {
|
|
100271
|
+
console.log(source_default.green("\n \u2713 Service is installed."));
|
|
100272
|
+
if (platform12 === "darwin") console.log(source_default.gray(` Plist: ${getDarwinPlistPath()}`));
|
|
100273
|
+
else console.log(source_default.gray(` Script: ${getWindowsVbsPath()}`));
|
|
100274
|
+
} else {
|
|
100275
|
+
console.log(source_default.gray("\n \u2717 Service is not installed. Run: adhdev service install"));
|
|
100276
|
+
}
|
|
100277
|
+
const health = await fetchHealth();
|
|
100278
|
+
if (health?.ok && health.pid) {
|
|
100279
|
+
const info = getProcessInfo(health.pid);
|
|
100280
|
+
if (info) {
|
|
100281
|
+
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}, uptime ${info.uptime}, ${info.memMB} MB`));
|
|
100282
|
+
} else {
|
|
100283
|
+
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}`));
|
|
100284
|
+
}
|
|
100285
|
+
} else {
|
|
100286
|
+
console.log(source_default.yellow(" \u2717 Daemon is not running."));
|
|
100287
|
+
}
|
|
100288
|
+
const outSize = import_node_fs4.default.existsSync(LOG_OUT) ? import_node_fs4.default.statSync(LOG_OUT).size : 0;
|
|
100289
|
+
const errSize = import_node_fs4.default.existsSync(LOG_ERR) ? import_node_fs4.default.statSync(LOG_ERR).size : 0;
|
|
100290
|
+
if (outSize > 0 || errSize > 0) {
|
|
100291
|
+
console.log(source_default.gray(` Logs: stdout ${formatBytes(outSize)}, stderr ${formatBytes(errSize)}`));
|
|
100292
|
+
}
|
|
100293
|
+
console.log();
|
|
100294
|
+
});
|
|
100295
|
+
svc.command("logs").description("View daemon service logs").option("--err", "Show stderr log instead of stdout").option("--clear", "Truncate all log files").option("-n, --lines <count>", "Number of lines to show", "30").action(async (options) => {
|
|
100296
|
+
if (options.clear) {
|
|
100297
|
+
for (const f of [LOG_OUT, LOG_ERR]) {
|
|
100298
|
+
if (import_node_fs4.default.existsSync(f)) import_node_fs4.default.writeFileSync(f, "", "utf-8");
|
|
100299
|
+
}
|
|
100300
|
+
console.log(source_default.green("\n \u2713 Logs cleared.\n"));
|
|
100301
|
+
return;
|
|
100302
|
+
}
|
|
100303
|
+
const logFile = options.err ? LOG_ERR : LOG_OUT;
|
|
100304
|
+
if (!import_node_fs4.default.existsSync(logFile)) {
|
|
100305
|
+
console.log(source_default.gray(`
|
|
100306
|
+
No log file found: ${logFile}
|
|
100307
|
+
`));
|
|
100308
|
+
return;
|
|
100309
|
+
}
|
|
100310
|
+
const lines = parseInt(options.lines, 10) || 30;
|
|
100311
|
+
console.log(source_default.gray(`
|
|
100312
|
+
\u2500\u2500 ${options.err ? "stderr" : "stdout"}: ${logFile} (last ${lines} lines) \u2500\u2500
|
|
100313
|
+
`));
|
|
100314
|
+
const content = import_node_fs4.default.readFileSync(logFile, "utf-8");
|
|
100315
|
+
const allLines = content.split("\n");
|
|
100316
|
+
const lastLines = allLines.slice(-lines).join("\n");
|
|
100317
|
+
if (lastLines.trim()) console.log(lastLines);
|
|
100318
|
+
console.log(source_default.gray("\n (watching for new output, Ctrl+C to stop)\n"));
|
|
100319
|
+
let offset = Buffer.byteLength(content, "utf-8");
|
|
100320
|
+
const watcher = import_node_fs4.default.watchFile(logFile, { interval: 500 }, () => {
|
|
100321
|
+
try {
|
|
100322
|
+
const stat5 = import_node_fs4.default.statSync(logFile);
|
|
100323
|
+
if (stat5.size > offset) {
|
|
100324
|
+
const fd = import_node_fs4.default.openSync(logFile, "r");
|
|
100325
|
+
const buf = Buffer.alloc(stat5.size - offset);
|
|
100326
|
+
import_node_fs4.default.readSync(fd, buf, 0, buf.length, offset);
|
|
100327
|
+
import_node_fs4.default.closeSync(fd);
|
|
100328
|
+
process.stdout.write(buf.toString("utf-8"));
|
|
100329
|
+
offset = stat5.size;
|
|
100330
|
+
} else if (stat5.size < offset) {
|
|
100331
|
+
offset = 0;
|
|
100332
|
+
}
|
|
100333
|
+
} catch {
|
|
100334
|
+
}
|
|
100335
|
+
});
|
|
100336
|
+
const cleanup = () => {
|
|
100337
|
+
import_node_fs4.default.unwatchFile(logFile);
|
|
100338
|
+
process.exit(0);
|
|
100339
|
+
};
|
|
100340
|
+
process.on("SIGINT", cleanup);
|
|
100341
|
+
process.on("SIGTERM", cleanup);
|
|
100342
|
+
});
|
|
100343
|
+
svc.command("restart").description("Restart the daemon process (service will auto-relaunch)").action(async () => {
|
|
100344
|
+
const platform12 = import_node_os4.default.platform();
|
|
100345
|
+
const installed = isAutoStartServiceInstalled(platform12);
|
|
100346
|
+
if (!installed) {
|
|
100347
|
+
console.log(source_default.yellow("\n \u26A0 Service is not installed. Use `adhdev daemon:restart` for manual restart."));
|
|
100348
|
+
console.log(source_default.gray(" Or install the service first: adhdev service install\n"));
|
|
100349
|
+
return;
|
|
100350
|
+
}
|
|
100351
|
+
rotateLogs();
|
|
100352
|
+
if (platform12 === "darwin") {
|
|
100353
|
+
console.log(source_default.cyan("\n Refreshing LaunchAgent definition and reloading service..."));
|
|
100354
|
+
installAutoStartServiceForCurrentProcess(platform12);
|
|
100355
|
+
console.log();
|
|
100356
|
+
return;
|
|
100357
|
+
}
|
|
100358
|
+
const health = await fetchHealth();
|
|
100359
|
+
if (!health?.pid) {
|
|
100360
|
+
console.log(source_default.yellow("\n \u26A0 Daemon is not currently running."));
|
|
100361
|
+
console.log(source_default.gray(" Start with: adhdev daemon\n"));
|
|
100362
|
+
return;
|
|
100363
|
+
}
|
|
100364
|
+
console.log(source_default.cyan(`
|
|
100365
|
+
Stopping daemon (PID ${health.pid})...`));
|
|
100366
|
+
try {
|
|
100367
|
+
process.kill(health.pid, "SIGTERM");
|
|
100368
|
+
} catch {
|
|
100369
|
+
console.log(source_default.yellow(" Could not send SIGTERM. Process may have already exited."));
|
|
100370
|
+
}
|
|
100371
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
100372
|
+
if (platform12 === "win32") {
|
|
100373
|
+
const vbsPath = getWindowsVbsPath();
|
|
100374
|
+
if (import_node_fs4.default.existsSync(vbsPath)) {
|
|
100375
|
+
try {
|
|
100376
|
+
(0, import_node_child_process4.execSync)(`wscript.exe "${vbsPath}"`, { stdio: "ignore", windowsHide: true });
|
|
100377
|
+
} catch {
|
|
100378
|
+
}
|
|
100379
|
+
}
|
|
100380
|
+
}
|
|
100381
|
+
let restarted = false;
|
|
100382
|
+
for (let i = 0; i < 8; i++) {
|
|
100383
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
100384
|
+
const newHealth = await fetchHealth();
|
|
100385
|
+
if (newHealth?.ok && newHealth.pid !== health.pid) {
|
|
100386
|
+
restarted = true;
|
|
100387
|
+
const info = getProcessInfo(newHealth.pid);
|
|
100388
|
+
console.log(source_default.green(` \u2713 Daemon restarted \u2014 new PID ${newHealth.pid}${info ? `, ${info.memMB} MB` : ""}`));
|
|
100389
|
+
break;
|
|
100390
|
+
}
|
|
100391
|
+
}
|
|
100392
|
+
if (!restarted) {
|
|
100393
|
+
console.log(source_default.yellow(" \u26A0 Daemon did not restart within 10s."));
|
|
100394
|
+
console.log(source_default.gray(" Check: adhdev service logs --err"));
|
|
100395
|
+
}
|
|
100396
|
+
console.log();
|
|
100397
|
+
});
|
|
100398
|
+
}
|
|
100399
|
+
function formatBytes(bytes) {
|
|
100400
|
+
if (bytes === 0) return "0 B";
|
|
100401
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
100402
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
100403
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
100404
|
+
}
|
|
100405
|
+
var import_node_fs4, import_node_path5, import_node_os4, import_node_child_process4, DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS2, LAUNCHD_LABEL, ADHDEV_DIR, LOG_OUT, LOG_ERR, MAX_LOG_SIZE2;
|
|
100406
|
+
var init_service_commands = __esm({
|
|
100407
|
+
"src/cli/service-commands.ts"() {
|
|
100408
|
+
"use strict";
|
|
100409
|
+
import_node_fs4 = __toESM(require("fs"));
|
|
100410
|
+
import_node_path5 = __toESM(require("path"));
|
|
100411
|
+
import_node_os4 = __toESM(require("os"));
|
|
100412
|
+
import_node_child_process4 = require("child_process");
|
|
100413
|
+
init_source();
|
|
100414
|
+
init_src();
|
|
100415
|
+
DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS2 = 1500;
|
|
100416
|
+
LAUNCHD_LABEL = "dev.adhf.daemon";
|
|
100417
|
+
ADHDEV_DIR = import_node_path5.default.join(import_node_os4.default.homedir(), ".adhdev");
|
|
100418
|
+
LOG_OUT = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.out");
|
|
100419
|
+
LOG_ERR = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.err");
|
|
100420
|
+
MAX_LOG_SIZE2 = 10 * 1024 * 1024;
|
|
100421
|
+
}
|
|
100422
|
+
});
|
|
100423
|
+
|
|
99642
100424
|
// ../../oss/packages/web-core/src/constants/supported.ts
|
|
99643
100425
|
var supported_exports = {};
|
|
99644
100426
|
__export(supported_exports, {
|
|
@@ -101612,7 +102394,7 @@ function formatDebugTraceEntryLine(entry) {
|
|
|
101612
102394
|
}
|
|
101613
102395
|
|
|
101614
102396
|
// src/cli/daemon-commands.ts
|
|
101615
|
-
var
|
|
102397
|
+
var DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3 = 1500;
|
|
101616
102398
|
var DEFAULT_TRACE_FOLLOW_INTERVAL_MS = 1500;
|
|
101617
102399
|
var DEFAULT_DAEMON_PORT_TEXT = String(DEFAULT_DAEMON_PORT);
|
|
101618
102400
|
var DEV_SERVER_PORT2 = 19280;
|
|
@@ -101640,6 +102422,15 @@ async function resolveConfiguredUpdateChannel() {
|
|
|
101640
102422
|
function releaseChannelLabel(channel) {
|
|
101641
102423
|
return `${channel} (${CHANNEL_NPM_TAG3[channel]})`;
|
|
101642
102424
|
}
|
|
102425
|
+
function buildDaemonRestartCommandArgv(options = {}) {
|
|
102426
|
+
const cliPath = options.cliPath || process.argv[1];
|
|
102427
|
+
const daemonPort = options.daemonPort || DEFAULT_DAEMON_PORT_TEXT;
|
|
102428
|
+
const platform12 = options.platform || process.platform;
|
|
102429
|
+
if (platform12 === "darwin" && options.serviceInstalled) {
|
|
102430
|
+
return [cliPath, "service", "install"];
|
|
102431
|
+
}
|
|
102432
|
+
return [cliPath, "daemon", "-p", daemonPort];
|
|
102433
|
+
}
|
|
101643
102434
|
async function persistReleaseChannel(channel) {
|
|
101644
102435
|
const { updateConfig: updateConfig2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
101645
102436
|
updateConfig2({ updateChannel: channel, serverUrl: CHANNEL_SERVER_URL3[channel] });
|
|
@@ -101650,7 +102441,7 @@ function hideCommand(command) {
|
|
|
101650
102441
|
}
|
|
101651
102442
|
async function fetchLocalDaemonHealth(port) {
|
|
101652
102443
|
const controller = new AbortController();
|
|
101653
|
-
const timer = setTimeout(() => controller.abort(),
|
|
102444
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3);
|
|
101654
102445
|
try {
|
|
101655
102446
|
const res = await fetch(`http://127.0.0.1:${port}/health`, { signal: controller.signal });
|
|
101656
102447
|
if (!res.ok) return null;
|
|
@@ -102016,6 +102807,9 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102016
102807
|
} else {
|
|
102017
102808
|
console.log(source_default.cyan(`
|
|
102018
102809
|
Upgrading v${currentVersion} \u2192 v${latest}...`));
|
|
102810
|
+
const { isAutoStartServiceInstalled: isAutoStartServiceInstalled2 } = await Promise.resolve().then(() => (init_service_commands(), service_commands_exports));
|
|
102811
|
+
const serviceInstalled = isAutoStartServiceInstalled2();
|
|
102812
|
+
const shouldRefreshInstalledService = options.restart !== false && process.platform === "darwin" && serviceInstalled;
|
|
102019
102813
|
const daemonWasRunning = options.restart !== false && isDaemonRunning2();
|
|
102020
102814
|
if (daemonWasRunning) {
|
|
102021
102815
|
stopDaemon2();
|
|
@@ -102027,10 +102821,22 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102027
102821
|
packageName: "adhdev",
|
|
102028
102822
|
targetVersion: latest,
|
|
102029
102823
|
parentPid: process.pid,
|
|
102030
|
-
restartArgv:
|
|
102824
|
+
restartArgv: shouldRefreshInstalledService ? buildDaemonRestartCommandArgv({
|
|
102825
|
+
cliPath: process.argv[1],
|
|
102826
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
102827
|
+
platform: process.platform,
|
|
102828
|
+
serviceInstalled
|
|
102829
|
+
}) : daemonWasRunning ? buildDaemonRestartCommandArgv({
|
|
102830
|
+
cliPath: process.argv[1],
|
|
102831
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
102832
|
+
platform: process.platform,
|
|
102833
|
+
serviceInstalled
|
|
102834
|
+
}) : [],
|
|
102031
102835
|
cwd: process.cwd()
|
|
102032
102836
|
});
|
|
102033
|
-
if (
|
|
102837
|
+
if (shouldRefreshInstalledService) {
|
|
102838
|
+
console.log(source_default.cyan(" Upgrading and refreshing background service in background..."));
|
|
102839
|
+
} else if (daemonWasRunning) {
|
|
102034
102840
|
console.log(source_default.cyan(" Upgrading and restarting daemon in background..."));
|
|
102035
102841
|
} else {
|
|
102036
102842
|
console.log(source_default.cyan(" Upgrading in background..."));
|
|
@@ -102042,29 +102848,44 @@ async function runDaemonUpgrade(options, pkgVersion3) {
|
|
|
102042
102848
|
return;
|
|
102043
102849
|
}
|
|
102044
102850
|
}
|
|
102045
|
-
if (options.restart !== false
|
|
102046
|
-
|
|
102047
|
-
|
|
102048
|
-
|
|
102049
|
-
|
|
102050
|
-
|
|
102051
|
-
|
|
102052
|
-
|
|
102053
|
-
|
|
102054
|
-
windowsHide: true,
|
|
102055
|
-
env: { ...process.env }
|
|
102056
|
-
});
|
|
102057
|
-
child.unref();
|
|
102058
|
-
await new Promise((r) => setTimeout(r, 3e3));
|
|
102851
|
+
if (options.restart !== false) {
|
|
102852
|
+
const { installAutoStartServiceForCurrentProcess: installAutoStartServiceForCurrentProcess2, isAutoStartServiceInstalled: isAutoStartServiceInstalled2 } = await Promise.resolve().then(() => (init_service_commands(), service_commands_exports));
|
|
102853
|
+
const serviceInstalled = isAutoStartServiceInstalled2();
|
|
102854
|
+
if (process.platform === "darwin" && serviceInstalled) {
|
|
102855
|
+
console.log(source_default.yellow("\n Refreshing LaunchAgent definition..."));
|
|
102856
|
+
installAutoStartServiceForCurrentProcess2(process.platform);
|
|
102857
|
+
console.log();
|
|
102858
|
+
return;
|
|
102859
|
+
}
|
|
102059
102860
|
if (isDaemonRunning2()) {
|
|
102060
|
-
console.log(source_default.
|
|
102861
|
+
console.log(source_default.yellow("\n Restarting daemon..."));
|
|
102862
|
+
stopDaemon2();
|
|
102863
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
102864
|
+
stopManagedSessionHostProcess2();
|
|
102865
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
102866
|
+
const child = spawn7(process.execPath, buildDaemonRestartCommandArgv({
|
|
102867
|
+
cliPath: process.argv[1],
|
|
102868
|
+
daemonPort: DEFAULT_DAEMON_PORT_TEXT,
|
|
102869
|
+
platform: process.platform,
|
|
102870
|
+
serviceInstalled
|
|
102871
|
+
}), {
|
|
102872
|
+
detached: true,
|
|
102873
|
+
stdio: "ignore",
|
|
102874
|
+
windowsHide: true,
|
|
102875
|
+
env: { ...process.env }
|
|
102876
|
+
});
|
|
102877
|
+
child.unref();
|
|
102878
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
102879
|
+
if (isDaemonRunning2()) {
|
|
102880
|
+
console.log(source_default.green(` \u2713 Daemon restarted with new version
|
|
102061
102881
|
`));
|
|
102062
|
-
|
|
102063
|
-
|
|
102882
|
+
} else {
|
|
102883
|
+
console.log(source_default.yellow(` \u26A0 Daemon not detected. Start manually: adhdev daemon
|
|
102064
102884
|
`));
|
|
102885
|
+
}
|
|
102886
|
+
} else {
|
|
102887
|
+
console.log(source_default.gray("\n Daemon was not running. Start with: adhdev daemon\n"));
|
|
102065
102888
|
}
|
|
102066
|
-
} else if (options.restart !== false) {
|
|
102067
|
-
console.log(source_default.gray("\n Daemon was not running. Start with: adhdev daemon\n"));
|
|
102068
102889
|
} else {
|
|
102069
102890
|
console.log(source_default.green("\n \u2713 Upgrade complete (daemon not restarted)\n"));
|
|
102070
102891
|
}
|
|
@@ -102235,7 +103056,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
|
|
|
102235
103056
|
}
|
|
102236
103057
|
try {
|
|
102237
103058
|
const controller = new AbortController();
|
|
102238
|
-
const timer = setTimeout(() => controller.abort(),
|
|
103059
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3);
|
|
102239
103060
|
const res = await fetch(`${DEV_SERVER_BASE_URL}/api/status`, { signal: controller.signal });
|
|
102240
103061
|
clearTimeout(timer);
|
|
102241
103062
|
if (res.ok) {
|
|
@@ -102782,373 +103603,8 @@ function buildDoctorAdvice(input) {
|
|
|
102782
103603
|
return advice;
|
|
102783
103604
|
}
|
|
102784
103605
|
|
|
102785
|
-
// src/cli/service-commands.ts
|
|
102786
|
-
var import_node_fs4 = __toESM(require("fs"));
|
|
102787
|
-
var import_node_path5 = __toESM(require("path"));
|
|
102788
|
-
var import_node_os4 = __toESM(require("os"));
|
|
102789
|
-
var import_node_child_process4 = require("child_process");
|
|
102790
|
-
init_source();
|
|
102791
|
-
init_src();
|
|
102792
|
-
var DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3 = 1500;
|
|
102793
|
-
var LAUNCHD_LABEL = "dev.adhf.daemon";
|
|
102794
|
-
var ADHDEV_DIR = import_node_path5.default.join(import_node_os4.default.homedir(), ".adhdev");
|
|
102795
|
-
var LOG_OUT = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.out");
|
|
102796
|
-
var LOG_ERR = import_node_path5.default.join(ADHDEV_DIR, "daemon-launchd.err");
|
|
102797
|
-
var MAX_LOG_SIZE2 = 10 * 1024 * 1024;
|
|
102798
|
-
function getDarwinPlistPath() {
|
|
102799
|
-
return import_node_path5.default.join(import_node_os4.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
102800
|
-
}
|
|
102801
|
-
function getWindowsStartupDir() {
|
|
102802
|
-
const appData = process.env.APPDATA || import_node_path5.default.join(import_node_os4.default.homedir(), "AppData", "Roaming");
|
|
102803
|
-
return import_node_path5.default.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
|
|
102804
|
-
}
|
|
102805
|
-
function getWindowsVbsPath() {
|
|
102806
|
-
return import_node_path5.default.join(getWindowsStartupDir(), "adhdev-daemon.vbs");
|
|
102807
|
-
}
|
|
102808
|
-
function resolveCliPath() {
|
|
102809
|
-
return import_node_fs4.default.realpathSync(process.argv[1]);
|
|
102810
|
-
}
|
|
102811
|
-
function ensureDir(dir) {
|
|
102812
|
-
if (!import_node_fs4.default.existsSync(dir)) import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
102813
|
-
}
|
|
102814
|
-
async function fetchHealth() {
|
|
102815
|
-
const controller = new AbortController();
|
|
102816
|
-
const timer = setTimeout(() => controller.abort(), DEFAULT_LOCAL_DAEMON_HEALTH_TIMEOUT_MS3);
|
|
102817
|
-
try {
|
|
102818
|
-
const res = await fetch(`http://127.0.0.1:${DEFAULT_DAEMON_PORT}/health`, { signal: controller.signal });
|
|
102819
|
-
if (!res.ok) return null;
|
|
102820
|
-
return await res.json();
|
|
102821
|
-
} catch {
|
|
102822
|
-
return null;
|
|
102823
|
-
} finally {
|
|
102824
|
-
clearTimeout(timer);
|
|
102825
|
-
}
|
|
102826
|
-
}
|
|
102827
|
-
function getProcessInfo(pid) {
|
|
102828
|
-
try {
|
|
102829
|
-
if (process.platform === "win32") {
|
|
102830
|
-
const out = (0, import_node_child_process4.execSync)(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { encoding: "utf-8" });
|
|
102831
|
-
const match = out.match(/"(\d[\d,]+)\sK"/);
|
|
102832
|
-
const memKB = match ? parseInt(match[1].replace(/,/g, ""), 10) : 0;
|
|
102833
|
-
return { uptime: "-", memMB: Math.round(memKB / 1024) };
|
|
102834
|
-
} else {
|
|
102835
|
-
const out = (0, import_node_child_process4.execSync)(`ps -o etime=,rss= -p ${pid}`, { encoding: "utf-8" }).trim();
|
|
102836
|
-
const parts = out.split(/\s+/);
|
|
102837
|
-
const etime = parts[0] || "-";
|
|
102838
|
-
const rssKB = parseInt(parts[1] || "0", 10);
|
|
102839
|
-
return { uptime: formatElapsed(etime), memMB: Math.round(rssKB / 1024) };
|
|
102840
|
-
}
|
|
102841
|
-
} catch {
|
|
102842
|
-
return null;
|
|
102843
|
-
}
|
|
102844
|
-
}
|
|
102845
|
-
function formatElapsed(etime) {
|
|
102846
|
-
const parts = etime.replace("-", ":").split(":").map(Number);
|
|
102847
|
-
if (parts.length === 4) return `${parts[0]}d ${parts[1]}h ${parts[2]}m`;
|
|
102848
|
-
if (parts.length === 3) return `${parts[0]}h ${parts[1]}m`;
|
|
102849
|
-
if (parts.length === 2) return `${parts[0]}m ${parts[1]}s`;
|
|
102850
|
-
return etime;
|
|
102851
|
-
}
|
|
102852
|
-
function rotateLogIfNeeded(logPath) {
|
|
102853
|
-
try {
|
|
102854
|
-
if (!import_node_fs4.default.existsSync(logPath)) return;
|
|
102855
|
-
const stat5 = import_node_fs4.default.statSync(logPath);
|
|
102856
|
-
if (stat5.size > MAX_LOG_SIZE2) {
|
|
102857
|
-
const rotated = logPath + ".old";
|
|
102858
|
-
if (import_node_fs4.default.existsSync(rotated)) import_node_fs4.default.unlinkSync(rotated);
|
|
102859
|
-
import_node_fs4.default.renameSync(logPath, rotated);
|
|
102860
|
-
import_node_fs4.default.writeFileSync(logPath, `[log rotated at ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
102861
|
-
`, "utf-8");
|
|
102862
|
-
}
|
|
102863
|
-
} catch {
|
|
102864
|
-
}
|
|
102865
|
-
}
|
|
102866
|
-
function rotateLogs() {
|
|
102867
|
-
rotateLogIfNeeded(LOG_OUT);
|
|
102868
|
-
rotateLogIfNeeded(LOG_ERR);
|
|
102869
|
-
}
|
|
102870
|
-
function buildPlist(nodeExe, cliExe) {
|
|
102871
|
-
const brewPrefix = import_node_fs4.default.existsSync("/opt/homebrew/bin") ? "/opt/homebrew/bin" : "/usr/local/bin";
|
|
102872
|
-
const nodeDir = import_node_path5.default.dirname(nodeExe);
|
|
102873
|
-
const pathEntries = /* @__PURE__ */ new Set([nodeDir, brewPrefix, "/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"]);
|
|
102874
|
-
const pathValue = Array.from(pathEntries).join(":");
|
|
102875
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
102876
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
102877
|
-
<plist version="1.0">
|
|
102878
|
-
<dict>
|
|
102879
|
-
<key>Label</key>
|
|
102880
|
-
<string>${LAUNCHD_LABEL}</string>
|
|
102881
|
-
<key>ProgramArguments</key>
|
|
102882
|
-
<array>
|
|
102883
|
-
<string>${nodeExe}</string>
|
|
102884
|
-
<string>${cliExe}</string>
|
|
102885
|
-
<string>daemon</string>
|
|
102886
|
-
</array>
|
|
102887
|
-
<key>RunAtLoad</key>
|
|
102888
|
-
<true/>
|
|
102889
|
-
<key>KeepAlive</key>
|
|
102890
|
-
<dict>
|
|
102891
|
-
<key>SuccessfulExit</key>
|
|
102892
|
-
<false/>
|
|
102893
|
-
</dict>
|
|
102894
|
-
<key>ThrottleInterval</key>
|
|
102895
|
-
<integer>30</integer>
|
|
102896
|
-
<key>StandardOutPath</key>
|
|
102897
|
-
<string>${LOG_OUT}</string>
|
|
102898
|
-
<key>StandardErrorPath</key>
|
|
102899
|
-
<string>${LOG_ERR}</string>
|
|
102900
|
-
<key>EnvironmentVariables</key>
|
|
102901
|
-
<dict>
|
|
102902
|
-
<key>PATH</key>
|
|
102903
|
-
<string>${pathValue}</string>
|
|
102904
|
-
</dict>
|
|
102905
|
-
</dict>
|
|
102906
|
-
</plist>`;
|
|
102907
|
-
}
|
|
102908
|
-
function installDarwin(nodeExe, cliExe) {
|
|
102909
|
-
const plistPath = getDarwinPlistPath();
|
|
102910
|
-
ensureDir(ADHDEV_DIR);
|
|
102911
|
-
ensureDir(import_node_path5.default.dirname(plistPath));
|
|
102912
|
-
import_node_fs4.default.writeFileSync(plistPath, buildPlist(nodeExe, cliExe), "utf-8");
|
|
102913
|
-
console.log(source_default.gray(` Plist: ${plistPath}`));
|
|
102914
|
-
try {
|
|
102915
|
-
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
102916
|
-
} catch {
|
|
102917
|
-
}
|
|
102918
|
-
try {
|
|
102919
|
-
(0, import_node_child_process4.execSync)(`launchctl load -w "${plistPath}"`, { stdio: "ignore" });
|
|
102920
|
-
console.log(source_default.green("\n \u2713 Registered as LaunchAgent \u2014 daemon will start on login."));
|
|
102921
|
-
console.log(source_default.gray(` Logs: ~/.adhdev/daemon-launchd.{out,err}`));
|
|
102922
|
-
} catch (e) {
|
|
102923
|
-
console.log(source_default.red(`
|
|
102924
|
-
\u2717 launchctl load failed: ${e.message}`));
|
|
102925
|
-
}
|
|
102926
|
-
}
|
|
102927
|
-
function uninstallDarwin() {
|
|
102928
|
-
const plistPath = getDarwinPlistPath();
|
|
102929
|
-
if (!import_node_fs4.default.existsSync(plistPath)) {
|
|
102930
|
-
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
102931
|
-
return;
|
|
102932
|
-
}
|
|
102933
|
-
try {
|
|
102934
|
-
(0, import_node_child_process4.execSync)(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
102935
|
-
} catch {
|
|
102936
|
-
}
|
|
102937
|
-
import_node_fs4.default.unlinkSync(plistPath);
|
|
102938
|
-
console.log(source_default.green("\n \u2713 Removed LaunchAgent. Daemon will no longer auto-start."));
|
|
102939
|
-
}
|
|
102940
|
-
function isInstalledDarwin() {
|
|
102941
|
-
return import_node_fs4.default.existsSync(getDarwinPlistPath());
|
|
102942
|
-
}
|
|
102943
|
-
function buildVbs(nodeExe, cliExe) {
|
|
102944
|
-
const logFile = import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log").replace(/\\/g, "\\\\");
|
|
102945
|
-
const escapedNodeExe = nodeExe.replace(/\\/g, "\\\\");
|
|
102946
|
-
const escapedCliExe = cliExe.replace(/\\/g, "\\\\");
|
|
102947
|
-
return `' ADHDev Daemon Auto-Start (generated by adhdev service install)
|
|
102948
|
-
Set WshShell = CreateObject("WScript.Shell")
|
|
102949
|
-
WshShell.Run "cmd.exe /c """"${escapedNodeExe}"""" """"${escapedCliExe}"""" daemon >> """"${logFile}"""" 2>&1", 0, False
|
|
102950
|
-
`;
|
|
102951
|
-
}
|
|
102952
|
-
function installWindows(nodeExe, cliExe) {
|
|
102953
|
-
const vbsPath = getWindowsVbsPath();
|
|
102954
|
-
ensureDir(ADHDEV_DIR);
|
|
102955
|
-
ensureDir(import_node_path5.default.dirname(vbsPath));
|
|
102956
|
-
import_node_fs4.default.writeFileSync(vbsPath, buildVbs(nodeExe, cliExe), "utf-8");
|
|
102957
|
-
console.log(source_default.gray(` Startup script: ${vbsPath}`));
|
|
102958
|
-
console.log(source_default.green("\n \u2713 Registered in Startup folder \u2014 daemon will start on login (hidden)."));
|
|
102959
|
-
console.log(source_default.gray(` Logs: ${import_node_path5.default.join(ADHDEV_DIR, "daemon-service.log")}`));
|
|
102960
|
-
console.log(source_default.gray(" To start now without rebooting, run: adhdev daemon"));
|
|
102961
|
-
}
|
|
102962
|
-
function uninstallWindows() {
|
|
102963
|
-
const vbsPath = getWindowsVbsPath();
|
|
102964
|
-
if (!import_node_fs4.default.existsSync(vbsPath)) {
|
|
102965
|
-
console.log(source_default.yellow("\n \u26A0 Service is not installed."));
|
|
102966
|
-
return;
|
|
102967
|
-
}
|
|
102968
|
-
import_node_fs4.default.unlinkSync(vbsPath);
|
|
102969
|
-
console.log(source_default.green("\n \u2713 Removed Startup script. Daemon will no longer auto-start."));
|
|
102970
|
-
console.log(source_default.gray(" Note: a currently running daemon is not affected. Stop with: adhdev daemon:stop"));
|
|
102971
|
-
}
|
|
102972
|
-
function isInstalledWindows() {
|
|
102973
|
-
return import_node_fs4.default.existsSync(getWindowsVbsPath());
|
|
102974
|
-
}
|
|
102975
|
-
function registerServiceCommands(program2) {
|
|
102976
|
-
const svc = program2.command("service").description("\u{1F50C} Manage ADHDev as an OS background auto-start service");
|
|
102977
|
-
svc.command("install").description("Register ADHDev daemon to start automatically on login").action(async () => {
|
|
102978
|
-
console.log(source_default.bold("\n \u{1F680} Installing ADHDev Background Service"));
|
|
102979
|
-
const platform12 = import_node_os4.default.platform();
|
|
102980
|
-
const nodeExe = process.execPath;
|
|
102981
|
-
const cliExe = resolveCliPath();
|
|
102982
|
-
console.log(source_default.gray(` Node: ${nodeExe}`));
|
|
102983
|
-
console.log(source_default.gray(` CLI: ${cliExe}`));
|
|
102984
|
-
console.log(source_default.gray(` Platform: ${platform12}`));
|
|
102985
|
-
if (platform12 === "darwin") {
|
|
102986
|
-
installDarwin(nodeExe, cliExe);
|
|
102987
|
-
} else if (platform12 === "win32") {
|
|
102988
|
-
installWindows(nodeExe, cliExe);
|
|
102989
|
-
} else {
|
|
102990
|
-
console.log(source_default.yellow("\n \u26A0 Auto-start service install is not supported on this platform."));
|
|
102991
|
-
console.log(source_default.gray(" On Linux, create a systemd user unit manually:"));
|
|
102992
|
-
console.log(source_default.gray(" ~/.config/systemd/user/adhdev-daemon.service"));
|
|
102993
|
-
}
|
|
102994
|
-
console.log();
|
|
102995
|
-
});
|
|
102996
|
-
svc.command("uninstall").description("Remove the OS background service").action(async () => {
|
|
102997
|
-
console.log(source_default.bold("\n \u{1F5D1}\uFE0F Removing ADHDev Background Service"));
|
|
102998
|
-
const platform12 = import_node_os4.default.platform();
|
|
102999
|
-
if (platform12 === "darwin") {
|
|
103000
|
-
uninstallDarwin();
|
|
103001
|
-
} else if (platform12 === "win32") {
|
|
103002
|
-
uninstallWindows();
|
|
103003
|
-
} else {
|
|
103004
|
-
console.log(source_default.yellow("\n \u26A0 Not supported on this platform."));
|
|
103005
|
-
}
|
|
103006
|
-
console.log();
|
|
103007
|
-
});
|
|
103008
|
-
svc.command("status").description("Show service installation state and live daemon health").action(async () => {
|
|
103009
|
-
const platform12 = import_node_os4.default.platform();
|
|
103010
|
-
const installed = platform12 === "darwin" ? isInstalledDarwin() : platform12 === "win32" ? isInstalledWindows() : false;
|
|
103011
|
-
if (installed) {
|
|
103012
|
-
console.log(source_default.green("\n \u2713 Service is installed."));
|
|
103013
|
-
if (platform12 === "darwin") console.log(source_default.gray(` Plist: ${getDarwinPlistPath()}`));
|
|
103014
|
-
else console.log(source_default.gray(` Script: ${getWindowsVbsPath()}`));
|
|
103015
|
-
} else {
|
|
103016
|
-
console.log(source_default.gray("\n \u2717 Service is not installed. Run: adhdev service install"));
|
|
103017
|
-
}
|
|
103018
|
-
const health = await fetchHealth();
|
|
103019
|
-
if (health?.ok && health.pid) {
|
|
103020
|
-
const info = getProcessInfo(health.pid);
|
|
103021
|
-
if (info) {
|
|
103022
|
-
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}, uptime ${info.uptime}, ${info.memMB} MB`));
|
|
103023
|
-
} else {
|
|
103024
|
-
console.log(source_default.green(` \u2713 Daemon running \u2014 PID ${health.pid}`));
|
|
103025
|
-
}
|
|
103026
|
-
} else {
|
|
103027
|
-
console.log(source_default.yellow(" \u2717 Daemon is not running."));
|
|
103028
|
-
}
|
|
103029
|
-
const outSize = import_node_fs4.default.existsSync(LOG_OUT) ? import_node_fs4.default.statSync(LOG_OUT).size : 0;
|
|
103030
|
-
const errSize = import_node_fs4.default.existsSync(LOG_ERR) ? import_node_fs4.default.statSync(LOG_ERR).size : 0;
|
|
103031
|
-
if (outSize > 0 || errSize > 0) {
|
|
103032
|
-
console.log(source_default.gray(` Logs: stdout ${formatBytes(outSize)}, stderr ${formatBytes(errSize)}`));
|
|
103033
|
-
}
|
|
103034
|
-
console.log();
|
|
103035
|
-
});
|
|
103036
|
-
svc.command("logs").description("View daemon service logs").option("--err", "Show stderr log instead of stdout").option("--clear", "Truncate all log files").option("-n, --lines <count>", "Number of lines to show", "30").action(async (options) => {
|
|
103037
|
-
if (options.clear) {
|
|
103038
|
-
for (const f of [LOG_OUT, LOG_ERR]) {
|
|
103039
|
-
if (import_node_fs4.default.existsSync(f)) import_node_fs4.default.writeFileSync(f, "", "utf-8");
|
|
103040
|
-
}
|
|
103041
|
-
console.log(source_default.green("\n \u2713 Logs cleared.\n"));
|
|
103042
|
-
return;
|
|
103043
|
-
}
|
|
103044
|
-
const logFile = options.err ? LOG_ERR : LOG_OUT;
|
|
103045
|
-
if (!import_node_fs4.default.existsSync(logFile)) {
|
|
103046
|
-
console.log(source_default.gray(`
|
|
103047
|
-
No log file found: ${logFile}
|
|
103048
|
-
`));
|
|
103049
|
-
return;
|
|
103050
|
-
}
|
|
103051
|
-
const lines = parseInt(options.lines, 10) || 30;
|
|
103052
|
-
console.log(source_default.gray(`
|
|
103053
|
-
\u2500\u2500 ${options.err ? "stderr" : "stdout"}: ${logFile} (last ${lines} lines) \u2500\u2500
|
|
103054
|
-
`));
|
|
103055
|
-
const content = import_node_fs4.default.readFileSync(logFile, "utf-8");
|
|
103056
|
-
const allLines = content.split("\n");
|
|
103057
|
-
const lastLines = allLines.slice(-lines).join("\n");
|
|
103058
|
-
if (lastLines.trim()) console.log(lastLines);
|
|
103059
|
-
console.log(source_default.gray("\n (watching for new output, Ctrl+C to stop)\n"));
|
|
103060
|
-
let offset = Buffer.byteLength(content, "utf-8");
|
|
103061
|
-
const watcher = import_node_fs4.default.watchFile(logFile, { interval: 500 }, () => {
|
|
103062
|
-
try {
|
|
103063
|
-
const stat5 = import_node_fs4.default.statSync(logFile);
|
|
103064
|
-
if (stat5.size > offset) {
|
|
103065
|
-
const fd = import_node_fs4.default.openSync(logFile, "r");
|
|
103066
|
-
const buf = Buffer.alloc(stat5.size - offset);
|
|
103067
|
-
import_node_fs4.default.readSync(fd, buf, 0, buf.length, offset);
|
|
103068
|
-
import_node_fs4.default.closeSync(fd);
|
|
103069
|
-
process.stdout.write(buf.toString("utf-8"));
|
|
103070
|
-
offset = stat5.size;
|
|
103071
|
-
} else if (stat5.size < offset) {
|
|
103072
|
-
offset = 0;
|
|
103073
|
-
}
|
|
103074
|
-
} catch {
|
|
103075
|
-
}
|
|
103076
|
-
});
|
|
103077
|
-
const cleanup = () => {
|
|
103078
|
-
import_node_fs4.default.unwatchFile(logFile);
|
|
103079
|
-
process.exit(0);
|
|
103080
|
-
};
|
|
103081
|
-
process.on("SIGINT", cleanup);
|
|
103082
|
-
process.on("SIGTERM", cleanup);
|
|
103083
|
-
});
|
|
103084
|
-
svc.command("restart").description("Restart the daemon process (service will auto-relaunch)").action(async () => {
|
|
103085
|
-
const platform12 = import_node_os4.default.platform();
|
|
103086
|
-
const installed = platform12 === "darwin" ? isInstalledDarwin() : platform12 === "win32" ? isInstalledWindows() : false;
|
|
103087
|
-
if (!installed) {
|
|
103088
|
-
console.log(source_default.yellow("\n \u26A0 Service is not installed. Use `adhdev daemon:restart` for manual restart."));
|
|
103089
|
-
console.log(source_default.gray(" Or install the service first: adhdev service install\n"));
|
|
103090
|
-
return;
|
|
103091
|
-
}
|
|
103092
|
-
rotateLogs();
|
|
103093
|
-
const health = await fetchHealth();
|
|
103094
|
-
if (!health?.pid) {
|
|
103095
|
-
console.log(source_default.yellow("\n \u26A0 Daemon is not currently running."));
|
|
103096
|
-
if (platform12 === "darwin") {
|
|
103097
|
-
console.log(source_default.gray(" Starting via launchctl..."));
|
|
103098
|
-
try {
|
|
103099
|
-
(0, import_node_child_process4.execSync)(`launchctl start ${LAUNCHD_LABEL}`, { stdio: "ignore" });
|
|
103100
|
-
console.log(source_default.green(" \u2713 Started.\n"));
|
|
103101
|
-
} catch {
|
|
103102
|
-
console.log(source_default.red(" \u2717 Failed to start. Check: adhdev service logs --err\n"));
|
|
103103
|
-
}
|
|
103104
|
-
} else {
|
|
103105
|
-
console.log(source_default.gray(" Start with: adhdev daemon\n"));
|
|
103106
|
-
}
|
|
103107
|
-
return;
|
|
103108
|
-
}
|
|
103109
|
-
console.log(source_default.cyan(`
|
|
103110
|
-
Stopping daemon (PID ${health.pid})...`));
|
|
103111
|
-
try {
|
|
103112
|
-
process.kill(health.pid, "SIGTERM");
|
|
103113
|
-
} catch {
|
|
103114
|
-
console.log(source_default.yellow(" Could not send SIGTERM. Process may have already exited."));
|
|
103115
|
-
}
|
|
103116
|
-
await new Promise((r) => setTimeout(r, 2e3));
|
|
103117
|
-
if (platform12 === "win32") {
|
|
103118
|
-
const vbsPath = getWindowsVbsPath();
|
|
103119
|
-
if (import_node_fs4.default.existsSync(vbsPath)) {
|
|
103120
|
-
try {
|
|
103121
|
-
(0, import_node_child_process4.execSync)(`wscript.exe "${vbsPath}"`, { stdio: "ignore", windowsHide: true });
|
|
103122
|
-
} catch {
|
|
103123
|
-
}
|
|
103124
|
-
}
|
|
103125
|
-
}
|
|
103126
|
-
let restarted = false;
|
|
103127
|
-
for (let i = 0; i < 8; i++) {
|
|
103128
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
103129
|
-
const newHealth = await fetchHealth();
|
|
103130
|
-
if (newHealth?.ok && newHealth.pid !== health.pid) {
|
|
103131
|
-
restarted = true;
|
|
103132
|
-
const info = getProcessInfo(newHealth.pid);
|
|
103133
|
-
console.log(source_default.green(` \u2713 Daemon restarted \u2014 new PID ${newHealth.pid}${info ? `, ${info.memMB} MB` : ""}`));
|
|
103134
|
-
break;
|
|
103135
|
-
}
|
|
103136
|
-
}
|
|
103137
|
-
if (!restarted) {
|
|
103138
|
-
console.log(source_default.yellow(" \u26A0 Daemon did not restart within 10s."));
|
|
103139
|
-
console.log(source_default.gray(" Check: adhdev service logs --err"));
|
|
103140
|
-
}
|
|
103141
|
-
console.log();
|
|
103142
|
-
});
|
|
103143
|
-
}
|
|
103144
|
-
function formatBytes(bytes) {
|
|
103145
|
-
if (bytes === 0) return "0 B";
|
|
103146
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
103147
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
103148
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
103149
|
-
}
|
|
103150
|
-
|
|
103151
103606
|
// src/cli/doctor-commands.ts
|
|
103607
|
+
init_service_commands();
|
|
103152
103608
|
function resolvePackageRoot() {
|
|
103153
103609
|
return path39.resolve(__dirname, "..", "..");
|
|
103154
103610
|
}
|
|
@@ -104640,6 +105096,9 @@ function registerCdpCommands(program2) {
|
|
|
104640
105096
|
});
|
|
104641
105097
|
}
|
|
104642
105098
|
|
|
105099
|
+
// src/cli/index.ts
|
|
105100
|
+
init_service_commands();
|
|
105101
|
+
|
|
104643
105102
|
// src/cli/mcp-commands.ts
|
|
104644
105103
|
var import_node_child_process5 = require("child_process");
|
|
104645
105104
|
var fs23 = __toESM(require("fs"));
|