@adhdev/daemon-core 0.7.39 → 0.7.41
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/commands/cli-manager.d.ts +2 -1
- package/dist/config/config.d.ts +4 -2
- package/dist/config/recent-activity.d.ts +6 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +247 -224
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +247 -224
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +10 -1
- package/dist/providers/contracts.d.ts +79 -0
- package/dist/providers/provider-instance.d.ts +2 -0
- package/dist/shared-types-extra.d.ts +1 -1
- package/dist/shared-types.d.ts +8 -12
- package/dist/status/snapshot.d.ts +13 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/commands/cli-manager.ts +43 -5
- package/src/commands/router.ts +26 -16
- package/src/config/config.ts +6 -3
- package/src/config/recent-activity.ts +24 -12
- package/src/index.ts +2 -2
- package/src/providers/cli-provider-instance.ts +29 -2
- package/src/providers/contracts.ts +80 -0
- package/src/providers/provider-instance.ts +2 -0
- package/src/shared-types-extra.ts +1 -1
- package/src/shared-types.d.ts +4 -6
- package/src/shared-types.ts +8 -12
- package/src/status/builders.ts +2 -0
- package/src/status/reporter.ts +1 -1
- package/src/status/snapshot.ts +61 -91
package/dist/index.js
CHANGED
|
@@ -175,7 +175,8 @@ var init_config = __esm({
|
|
|
175
175
|
workspaces: [],
|
|
176
176
|
defaultWorkspaceId: null,
|
|
177
177
|
recentActivity: [],
|
|
178
|
-
|
|
178
|
+
sessionReads: {},
|
|
179
|
+
sessionReadMarkers: {},
|
|
179
180
|
machineNickname: null,
|
|
180
181
|
machineId: void 0,
|
|
181
182
|
machineSecret: null,
|
|
@@ -2123,18 +2124,27 @@ function appendRecentActivity(config, entry) {
|
|
|
2123
2124
|
function getRecentActivity(config, limit = 20) {
|
|
2124
2125
|
return [...config.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
|
|
2125
2126
|
}
|
|
2126
|
-
function
|
|
2127
|
-
return config.
|
|
2127
|
+
function getSessionSeenAt(config, sessionId) {
|
|
2128
|
+
return config.sessionReads?.[sessionId] || 0;
|
|
2128
2129
|
}
|
|
2129
|
-
function
|
|
2130
|
-
|
|
2131
|
-
|
|
2130
|
+
function getSessionSeenMarker(config, sessionId) {
|
|
2131
|
+
return config.sessionReadMarkers?.[sessionId] || "";
|
|
2132
|
+
}
|
|
2133
|
+
function markSessionSeen(config, sessionId, seenAt = Date.now(), completionMarker) {
|
|
2134
|
+
const prev = config.sessionReads || {};
|
|
2135
|
+
const nextSeenAt = Math.max(prev[sessionId] || 0, seenAt);
|
|
2136
|
+
const prevMarkers = config.sessionReadMarkers || {};
|
|
2137
|
+
const nextMarker = typeof completionMarker === "string" ? completionMarker : "";
|
|
2132
2138
|
return {
|
|
2133
2139
|
...config,
|
|
2134
|
-
|
|
2140
|
+
sessionReads: {
|
|
2135
2141
|
...prev,
|
|
2136
|
-
[
|
|
2137
|
-
}
|
|
2142
|
+
[sessionId]: nextSeenAt
|
|
2143
|
+
},
|
|
2144
|
+
sessionReadMarkers: nextMarker ? {
|
|
2145
|
+
...prevMarkers,
|
|
2146
|
+
[sessionId]: nextMarker
|
|
2147
|
+
} : prevMarkers
|
|
2138
2148
|
};
|
|
2139
2149
|
}
|
|
2140
2150
|
|
|
@@ -5058,6 +5068,8 @@ function buildCliSession(state) {
|
|
|
5058
5068
|
runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
|
|
5059
5069
|
runtimeWriteOwner: state.runtime?.writeOwner || null,
|
|
5060
5070
|
runtimeAttachedClients: state.runtime?.attachedClients || [],
|
|
5071
|
+
launchMode: state.launchMode,
|
|
5072
|
+
mode: state.mode,
|
|
5061
5073
|
resume: state.resume,
|
|
5062
5074
|
activeChat,
|
|
5063
5075
|
capabilities: PTY_SESSION_CAPABILITIES,
|
|
@@ -8464,6 +8476,149 @@ cleanOldFiles();
|
|
|
8464
8476
|
|
|
8465
8477
|
// src/commands/router.ts
|
|
8466
8478
|
init_logger();
|
|
8479
|
+
|
|
8480
|
+
// src/status/snapshot.ts
|
|
8481
|
+
var os10 = __toESM(require("os"));
|
|
8482
|
+
init_config();
|
|
8483
|
+
init_terminal_screen();
|
|
8484
|
+
init_logger();
|
|
8485
|
+
var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
8486
|
+
function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
8487
|
+
return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
|
|
8488
|
+
id: ide.id,
|
|
8489
|
+
type: ide.id,
|
|
8490
|
+
name: ide.displayName || ide.name || ide.id,
|
|
8491
|
+
running: isCdpConnected(cdpManagers, ide.id),
|
|
8492
|
+
...ide.path ? { path: ide.path } : {}
|
|
8493
|
+
}));
|
|
8494
|
+
}
|
|
8495
|
+
function buildAvailableProviders(providerLoader) {
|
|
8496
|
+
return providerLoader.getAll().map((provider) => ({
|
|
8497
|
+
type: provider.type,
|
|
8498
|
+
name: provider.displayName || provider.type,
|
|
8499
|
+
displayName: provider.displayName || provider.type,
|
|
8500
|
+
icon: provider.icon || "\u{1F4BB}",
|
|
8501
|
+
category: provider.category
|
|
8502
|
+
}));
|
|
8503
|
+
}
|
|
8504
|
+
function parseMessageTime(value) {
|
|
8505
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
8506
|
+
if (typeof value === "string") {
|
|
8507
|
+
const parsed = Date.parse(value);
|
|
8508
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
8509
|
+
}
|
|
8510
|
+
return 0;
|
|
8511
|
+
}
|
|
8512
|
+
function getSessionMessageUpdatedAt(session) {
|
|
8513
|
+
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8514
|
+
if (!lastMessage) return 0;
|
|
8515
|
+
return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
|
|
8516
|
+
}
|
|
8517
|
+
function getSessionCompletionMarker(session) {
|
|
8518
|
+
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8519
|
+
if (!lastMessage) return "";
|
|
8520
|
+
const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
|
|
8521
|
+
if (role === "user" || role === "human") return "";
|
|
8522
|
+
if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
|
|
8523
|
+
if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
|
|
8524
|
+
if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
|
|
8525
|
+
const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
|
|
8526
|
+
return timestamp > 0 ? `ts:${timestamp}` : "";
|
|
8527
|
+
}
|
|
8528
|
+
function getSessionLastUsedAt(session) {
|
|
8529
|
+
return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
|
|
8530
|
+
}
|
|
8531
|
+
function getLastMessageRole(session) {
|
|
8532
|
+
const role = session.activeChat?.messages?.at?.(-1)?.role;
|
|
8533
|
+
return typeof role === "string" ? role : "";
|
|
8534
|
+
}
|
|
8535
|
+
function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
|
|
8536
|
+
if (status === "waiting_approval") {
|
|
8537
|
+
return { unread: false, inboxBucket: "needs_attention" };
|
|
8538
|
+
}
|
|
8539
|
+
if (status === "generating" || status === "starting") {
|
|
8540
|
+
return { unread: false, inboxBucket: "working" };
|
|
8541
|
+
}
|
|
8542
|
+
const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
|
|
8543
|
+
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
8544
|
+
}
|
|
8545
|
+
function buildRecentLaunches(recentActivity) {
|
|
8546
|
+
return recentActivity.map((item) => ({
|
|
8547
|
+
id: item.id,
|
|
8548
|
+
providerType: item.providerType,
|
|
8549
|
+
providerName: item.providerName,
|
|
8550
|
+
kind: item.kind,
|
|
8551
|
+
title: item.title || item.providerName,
|
|
8552
|
+
workspace: item.workspace,
|
|
8553
|
+
currentModel: item.currentModel,
|
|
8554
|
+
lastLaunchedAt: item.lastUsedAt
|
|
8555
|
+
})).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
|
|
8556
|
+
}
|
|
8557
|
+
function buildStatusSnapshot(options) {
|
|
8558
|
+
const cfg = loadConfig();
|
|
8559
|
+
const wsState = getWorkspaceState(cfg);
|
|
8560
|
+
const memSnap = getHostMemorySnapshot();
|
|
8561
|
+
const recentActivity = getRecentActivity(cfg, 20);
|
|
8562
|
+
const sessions = buildSessionEntries(
|
|
8563
|
+
options.allStates,
|
|
8564
|
+
options.cdpManagers
|
|
8565
|
+
);
|
|
8566
|
+
for (const session of sessions) {
|
|
8567
|
+
const lastSeenAt = getSessionSeenAt(cfg, session.id);
|
|
8568
|
+
const seenCompletionMarker = getSessionSeenMarker(cfg, session.id);
|
|
8569
|
+
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8570
|
+
const completionMarker = getSessionCompletionMarker(session);
|
|
8571
|
+
const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
|
|
8572
|
+
getSessionMessageUpdatedAt(session) > 0,
|
|
8573
|
+
session.status,
|
|
8574
|
+
lastUsedAt,
|
|
8575
|
+
lastSeenAt,
|
|
8576
|
+
getLastMessageRole(session),
|
|
8577
|
+
completionMarker,
|
|
8578
|
+
seenCompletionMarker
|
|
8579
|
+
);
|
|
8580
|
+
session.lastSeenAt = lastSeenAt;
|
|
8581
|
+
session.unread = unread;
|
|
8582
|
+
session.inboxBucket = inboxBucket;
|
|
8583
|
+
if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
|
|
8584
|
+
LOG.info(
|
|
8585
|
+
"RecentRead",
|
|
8586
|
+
`snapshot session id=${session.id} provider=${session.providerType} status=${String(session.status || "")} bucket=${inboxBucket} unread=${String(unread)} lastSeenAt=${lastSeenAt} completionMarker=${completionMarker || "-"} seenMarker=${seenCompletionMarker || "-"} lastUpdated=${String(session.lastUpdated || 0)} lastUsedAt=${lastUsedAt} lastRole=${getLastMessageRole(session)} msgUpdatedAt=${getSessionMessageUpdatedAt(session)}`
|
|
8587
|
+
);
|
|
8588
|
+
}
|
|
8589
|
+
}
|
|
8590
|
+
const terminalBackend = getTerminalBackendRuntimeStatus();
|
|
8591
|
+
return {
|
|
8592
|
+
instanceId: options.instanceId,
|
|
8593
|
+
version: options.version,
|
|
8594
|
+
daemonMode: options.daemonMode,
|
|
8595
|
+
machine: {
|
|
8596
|
+
hostname: os10.hostname(),
|
|
8597
|
+
platform: os10.platform(),
|
|
8598
|
+
arch: os10.arch(),
|
|
8599
|
+
cpus: os10.cpus().length,
|
|
8600
|
+
totalMem: memSnap.totalMem,
|
|
8601
|
+
freeMem: memSnap.freeMem,
|
|
8602
|
+
availableMem: memSnap.availableMem,
|
|
8603
|
+
loadavg: os10.loadavg(),
|
|
8604
|
+
uptime: os10.uptime(),
|
|
8605
|
+
release: os10.release()
|
|
8606
|
+
},
|
|
8607
|
+
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
8608
|
+
timestamp: options.timestamp ?? Date.now(),
|
|
8609
|
+
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
8610
|
+
...options.p2p ? { p2p: options.p2p } : {},
|
|
8611
|
+
sessions,
|
|
8612
|
+
workspaces: wsState.workspaces,
|
|
8613
|
+
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
8614
|
+
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
8615
|
+
recentLaunches: buildRecentLaunches(recentActivity),
|
|
8616
|
+
terminalBackend,
|
|
8617
|
+
availableProviders: buildAvailableProviders(options.providerLoader)
|
|
8618
|
+
};
|
|
8619
|
+
}
|
|
8620
|
+
|
|
8621
|
+
// src/commands/router.ts
|
|
8467
8622
|
var fs7 = __toESM(require("fs"));
|
|
8468
8623
|
var CHAT_COMMANDS = [
|
|
8469
8624
|
"send_chat",
|
|
@@ -8472,6 +8627,7 @@ var CHAT_COMMANDS = [
|
|
|
8472
8627
|
"set_mode",
|
|
8473
8628
|
"change_model"
|
|
8474
8629
|
];
|
|
8630
|
+
var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
8475
8631
|
var DaemonCommandRouter = class {
|
|
8476
8632
|
deps;
|
|
8477
8633
|
constructor(deps) {
|
|
@@ -8642,28 +8798,35 @@ var DaemonCommandRouter = class {
|
|
|
8642
8798
|
updateConfig({ userName: name });
|
|
8643
8799
|
return { success: true, userName: name };
|
|
8644
8800
|
}
|
|
8645
|
-
case "
|
|
8646
|
-
const
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
return { success: false, error: "kind and providerType are required" };
|
|
8801
|
+
case "mark_session_seen": {
|
|
8802
|
+
const sessionId = args?.sessionId;
|
|
8803
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
8804
|
+
return { success: false, error: "sessionId is required" };
|
|
8650
8805
|
}
|
|
8651
|
-
const
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8806
|
+
const currentConfig = loadConfig();
|
|
8807
|
+
const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
|
|
8808
|
+
const sessionEntries = buildSessionEntries(
|
|
8809
|
+
this.deps.instanceManager.collectAllStates(),
|
|
8810
|
+
this.deps.cdpManagers
|
|
8811
|
+
);
|
|
8812
|
+
const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
|
|
8813
|
+
const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : "";
|
|
8814
|
+
const next = markSessionSeen(
|
|
8815
|
+
currentConfig,
|
|
8816
|
+
sessionId,
|
|
8817
|
+
typeof args?.seenAt === "number" ? args.seenAt : Date.now(),
|
|
8818
|
+
completionMarker
|
|
8660
8819
|
);
|
|
8820
|
+
if (READ_DEBUG_ENABLED2) {
|
|
8821
|
+
LOG.info("RecentRead", `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || "")} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || "-"}`);
|
|
8822
|
+
}
|
|
8661
8823
|
saveConfig(next);
|
|
8662
8824
|
this.deps.onStatusChange?.();
|
|
8663
8825
|
return {
|
|
8664
8826
|
success: true,
|
|
8665
|
-
|
|
8666
|
-
seenAt: next.
|
|
8827
|
+
sessionId,
|
|
8828
|
+
seenAt: next.sessionReads?.[sessionId] || Date.now(),
|
|
8829
|
+
completionMarker
|
|
8667
8830
|
};
|
|
8668
8831
|
}
|
|
8669
8832
|
// ─── Daemon Self-Upgrade ───
|
|
@@ -8780,194 +8943,6 @@ var DaemonCommandRouter = class {
|
|
|
8780
8943
|
|
|
8781
8944
|
// src/status/reporter.ts
|
|
8782
8945
|
init_logger();
|
|
8783
|
-
|
|
8784
|
-
// src/status/snapshot.ts
|
|
8785
|
-
var os10 = __toESM(require("os"));
|
|
8786
|
-
init_config();
|
|
8787
|
-
init_terminal_screen();
|
|
8788
|
-
function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
8789
|
-
return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
|
|
8790
|
-
id: ide.id,
|
|
8791
|
-
type: ide.id,
|
|
8792
|
-
name: ide.displayName || ide.name || ide.id,
|
|
8793
|
-
running: isCdpConnected(cdpManagers, ide.id),
|
|
8794
|
-
...ide.path ? { path: ide.path } : {}
|
|
8795
|
-
}));
|
|
8796
|
-
}
|
|
8797
|
-
function buildAvailableProviders(providerLoader) {
|
|
8798
|
-
return providerLoader.getAll().map((provider) => ({
|
|
8799
|
-
type: provider.type,
|
|
8800
|
-
name: provider.displayName || provider.type,
|
|
8801
|
-
displayName: provider.displayName || provider.type,
|
|
8802
|
-
icon: provider.icon || "\u{1F4BB}",
|
|
8803
|
-
category: provider.category
|
|
8804
|
-
}));
|
|
8805
|
-
}
|
|
8806
|
-
function parseMessageTime(value) {
|
|
8807
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
8808
|
-
if (typeof value === "string") {
|
|
8809
|
-
const parsed = Date.parse(value);
|
|
8810
|
-
if (Number.isFinite(parsed)) return parsed;
|
|
8811
|
-
}
|
|
8812
|
-
return 0;
|
|
8813
|
-
}
|
|
8814
|
-
function getSessionMessageUpdatedAt(session) {
|
|
8815
|
-
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8816
|
-
if (!lastMessage) return 0;
|
|
8817
|
-
return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
|
|
8818
|
-
}
|
|
8819
|
-
function getSessionLastUsedAt(session) {
|
|
8820
|
-
return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
|
|
8821
|
-
}
|
|
8822
|
-
function getSessionKind(session) {
|
|
8823
|
-
return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
|
|
8824
|
-
}
|
|
8825
|
-
function getLastMessageRole(session) {
|
|
8826
|
-
const role = session.activeChat?.messages?.at?.(-1)?.role;
|
|
8827
|
-
return typeof role === "string" ? role : "";
|
|
8828
|
-
}
|
|
8829
|
-
function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
|
|
8830
|
-
if (status === "waiting_approval") {
|
|
8831
|
-
return { unread: false, inboxBucket: "needs_attention" };
|
|
8832
|
-
}
|
|
8833
|
-
if (status === "generating" || status === "starting") {
|
|
8834
|
-
return { unread: false, inboxBucket: "working" };
|
|
8835
|
-
}
|
|
8836
|
-
const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
|
|
8837
|
-
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
8838
|
-
}
|
|
8839
|
-
function buildRecentSessions(sessions, recentActivity, readState) {
|
|
8840
|
-
const visibleKeys = /* @__PURE__ */ new Set();
|
|
8841
|
-
const hiddenKeys = /* @__PURE__ */ new Set();
|
|
8842
|
-
const live = sessions.filter((session) => !session.surfaceHidden && session.status !== "stopped").map((session) => {
|
|
8843
|
-
const kind = getSessionKind(session);
|
|
8844
|
-
const recentKey = buildRecentActivityKey({
|
|
8845
|
-
kind,
|
|
8846
|
-
providerType: session.providerType,
|
|
8847
|
-
workspace: session.workspace
|
|
8848
|
-
});
|
|
8849
|
-
const lastSeenAt = readState[recentKey] || 0;
|
|
8850
|
-
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8851
|
-
const { unread, inboxBucket } = getUnreadState(
|
|
8852
|
-
getSessionMessageUpdatedAt(session) > 0,
|
|
8853
|
-
session.status,
|
|
8854
|
-
lastUsedAt,
|
|
8855
|
-
lastSeenAt,
|
|
8856
|
-
getLastMessageRole(session)
|
|
8857
|
-
);
|
|
8858
|
-
return {
|
|
8859
|
-
id: session.id,
|
|
8860
|
-
recentKey,
|
|
8861
|
-
sessionId: session.id,
|
|
8862
|
-
providerType: session.providerType,
|
|
8863
|
-
providerName: session.providerName,
|
|
8864
|
-
kind,
|
|
8865
|
-
title: session.activeChat?.title || session.title || session.providerName,
|
|
8866
|
-
workspace: session.workspace,
|
|
8867
|
-
currentModel: session.currentModel,
|
|
8868
|
-
status: session.status,
|
|
8869
|
-
lastUsedAt,
|
|
8870
|
-
unread,
|
|
8871
|
-
lastSeenAt,
|
|
8872
|
-
inboxBucket,
|
|
8873
|
-
surfaceHidden: false
|
|
8874
|
-
};
|
|
8875
|
-
});
|
|
8876
|
-
for (const item of live) {
|
|
8877
|
-
visibleKeys.add(`${item.kind}:${item.providerType}:${item.workspace || ""}`);
|
|
8878
|
-
}
|
|
8879
|
-
for (const session of sessions) {
|
|
8880
|
-
if (!session.surfaceHidden) continue;
|
|
8881
|
-
hiddenKeys.add(`${getSessionKind(session)}:${session.providerType}:${session.workspace || ""}`);
|
|
8882
|
-
}
|
|
8883
|
-
const persisted = recentActivity.filter((item) => {
|
|
8884
|
-
const key = `${item.kind}:${item.providerType}:${item.workspace || ""}`;
|
|
8885
|
-
return !visibleKeys.has(key) && !hiddenKeys.has(key);
|
|
8886
|
-
}).map((item) => {
|
|
8887
|
-
const lastSeenAt = readState[item.id] || 0;
|
|
8888
|
-
const unread = item.lastUsedAt > lastSeenAt;
|
|
8889
|
-
return {
|
|
8890
|
-
id: item.id,
|
|
8891
|
-
recentKey: item.id,
|
|
8892
|
-
sessionId: item.sessionId || null,
|
|
8893
|
-
providerType: item.providerType,
|
|
8894
|
-
providerName: item.providerName,
|
|
8895
|
-
kind: item.kind,
|
|
8896
|
-
title: item.title || item.providerName,
|
|
8897
|
-
workspace: item.workspace,
|
|
8898
|
-
currentModel: item.currentModel,
|
|
8899
|
-
lastUsedAt: item.lastUsedAt,
|
|
8900
|
-
unread,
|
|
8901
|
-
lastSeenAt,
|
|
8902
|
-
inboxBucket: unread ? "task_complete" : "idle",
|
|
8903
|
-
surfaceHidden: false
|
|
8904
|
-
};
|
|
8905
|
-
});
|
|
8906
|
-
return [...live, ...persisted].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, 12);
|
|
8907
|
-
}
|
|
8908
|
-
function buildStatusSnapshot(options) {
|
|
8909
|
-
const cfg = loadConfig();
|
|
8910
|
-
const wsState = getWorkspaceState(cfg);
|
|
8911
|
-
const memSnap = getHostMemorySnapshot();
|
|
8912
|
-
const recentActivity = getRecentActivity(cfg, 20);
|
|
8913
|
-
const sessions = buildSessionEntries(
|
|
8914
|
-
options.allStates,
|
|
8915
|
-
options.cdpManagers
|
|
8916
|
-
);
|
|
8917
|
-
const readState = cfg.recentSessionReads || {};
|
|
8918
|
-
for (const session of sessions) {
|
|
8919
|
-
const kind = getSessionKind(session);
|
|
8920
|
-
const recentKey = buildRecentActivityKey({
|
|
8921
|
-
kind,
|
|
8922
|
-
providerType: session.providerType,
|
|
8923
|
-
workspace: session.workspace
|
|
8924
|
-
});
|
|
8925
|
-
const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
|
|
8926
|
-
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8927
|
-
const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
|
|
8928
|
-
getSessionMessageUpdatedAt(session) > 0,
|
|
8929
|
-
session.status,
|
|
8930
|
-
lastUsedAt,
|
|
8931
|
-
lastSeenAt,
|
|
8932
|
-
getLastMessageRole(session)
|
|
8933
|
-
);
|
|
8934
|
-
session.recentKey = recentKey;
|
|
8935
|
-
session.lastSeenAt = lastSeenAt;
|
|
8936
|
-
session.unread = unread;
|
|
8937
|
-
session.inboxBucket = inboxBucket;
|
|
8938
|
-
}
|
|
8939
|
-
const terminalBackend = getTerminalBackendRuntimeStatus();
|
|
8940
|
-
return {
|
|
8941
|
-
instanceId: options.instanceId,
|
|
8942
|
-
version: options.version,
|
|
8943
|
-
daemonMode: options.daemonMode,
|
|
8944
|
-
machine: {
|
|
8945
|
-
hostname: os10.hostname(),
|
|
8946
|
-
platform: os10.platform(),
|
|
8947
|
-
arch: os10.arch(),
|
|
8948
|
-
cpus: os10.cpus().length,
|
|
8949
|
-
totalMem: memSnap.totalMem,
|
|
8950
|
-
freeMem: memSnap.freeMem,
|
|
8951
|
-
availableMem: memSnap.availableMem,
|
|
8952
|
-
loadavg: os10.loadavg(),
|
|
8953
|
-
uptime: os10.uptime(),
|
|
8954
|
-
release: os10.release()
|
|
8955
|
-
},
|
|
8956
|
-
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
8957
|
-
timestamp: options.timestamp ?? Date.now(),
|
|
8958
|
-
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
8959
|
-
...options.p2p ? { p2p: options.p2p } : {},
|
|
8960
|
-
sessions,
|
|
8961
|
-
workspaces: wsState.workspaces,
|
|
8962
|
-
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
8963
|
-
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
8964
|
-
recentSessions: buildRecentSessions(sessions, recentActivity, readState),
|
|
8965
|
-
terminalBackend,
|
|
8966
|
-
availableProviders: buildAvailableProviders(options.providerLoader)
|
|
8967
|
-
};
|
|
8968
|
-
}
|
|
8969
|
-
|
|
8970
|
-
// src/status/reporter.ts
|
|
8971
8946
|
var DaemonStatusReporter = class {
|
|
8972
8947
|
deps;
|
|
8973
8948
|
log;
|
|
@@ -9115,7 +9090,7 @@ var DaemonStatusReporter = class {
|
|
|
9115
9090
|
currentModel: session.currentModel,
|
|
9116
9091
|
currentPlan: session.currentPlan,
|
|
9117
9092
|
currentAutoApprove: session.currentAutoApprove,
|
|
9118
|
-
|
|
9093
|
+
lastUpdated: session.lastUpdated,
|
|
9119
9094
|
unread: session.unread,
|
|
9120
9095
|
lastSeenAt: session.lastSeenAt,
|
|
9121
9096
|
inboxBucket: session.inboxBucket,
|
|
@@ -9172,12 +9147,14 @@ var crypto3 = __toESM(require("crypto"));
|
|
|
9172
9147
|
init_provider_cli_adapter();
|
|
9173
9148
|
init_logger();
|
|
9174
9149
|
var CliProviderInstance = class {
|
|
9175
|
-
constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory) {
|
|
9150
|
+
constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, launchModeId) {
|
|
9176
9151
|
this.provider = provider;
|
|
9177
9152
|
this.workingDir = workingDir;
|
|
9178
9153
|
this.cliArgs = cliArgs;
|
|
9179
9154
|
this.type = provider.type;
|
|
9180
9155
|
this.instanceId = instanceId || crypto3.randomUUID();
|
|
9156
|
+
this.launchMode = launchModeId && provider.launchModes?.find((m) => m.id === launchModeId) || null;
|
|
9157
|
+
this.resolvedOutputFormat = this.resolveOutputFormat();
|
|
9181
9158
|
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
|
|
9182
9159
|
this.monitor = new StatusMonitor();
|
|
9183
9160
|
this.historyWriter = new ChatHistoryWriter();
|
|
@@ -9196,6 +9173,26 @@ var CliProviderInstance = class {
|
|
|
9196
9173
|
lastApprovalEventAt = 0;
|
|
9197
9174
|
historyWriter;
|
|
9198
9175
|
instanceId;
|
|
9176
|
+
launchMode;
|
|
9177
|
+
resolvedOutputFormat;
|
|
9178
|
+
/**
|
|
9179
|
+
* Determine output rendering format from:
|
|
9180
|
+
* 1. launchMode.outputFormat (explicit override)
|
|
9181
|
+
* 2. launchOptions[].outputFormatMap — check actual args for matching values
|
|
9182
|
+
* 3. Default: 'terminal'
|
|
9183
|
+
*/
|
|
9184
|
+
resolveOutputFormat() {
|
|
9185
|
+
if (this.launchMode?.outputFormat) return this.launchMode.outputFormat;
|
|
9186
|
+
if (this.provider.launchOptions?.length) {
|
|
9187
|
+
for (const opt of this.provider.launchOptions) {
|
|
9188
|
+
if (!opt.outputFormatMap) continue;
|
|
9189
|
+
for (const [val, fmt] of Object.entries(opt.outputFormatMap)) {
|
|
9190
|
+
if (this.cliArgs.includes(val)) return fmt;
|
|
9191
|
+
}
|
|
9192
|
+
}
|
|
9193
|
+
}
|
|
9194
|
+
return "terminal";
|
|
9195
|
+
}
|
|
9199
9196
|
// ─── Lifecycle ─────────────────────────────────
|
|
9200
9197
|
async init(context) {
|
|
9201
9198
|
this.context = context;
|
|
@@ -9235,7 +9232,8 @@ var CliProviderInstance = class {
|
|
|
9235
9232
|
name: this.provider.name,
|
|
9236
9233
|
category: "cli",
|
|
9237
9234
|
status: adapterStatus.status,
|
|
9238
|
-
mode: "terminal",
|
|
9235
|
+
mode: this.resolvedOutputFormat === "stream-json" ? "chat" : "terminal",
|
|
9236
|
+
launchMode: this.launchMode?.id,
|
|
9239
9237
|
activeChat: {
|
|
9240
9238
|
id: `${this.type}_${this.workingDir}`,
|
|
9241
9239
|
title: `${this.provider.name} \xB7 ${dirName}`,
|
|
@@ -10377,12 +10375,12 @@ var DaemonCliManager = class {
|
|
|
10377
10375
|
}
|
|
10378
10376
|
}, 3e3);
|
|
10379
10377
|
}
|
|
10380
|
-
async registerCliInstance(key, normalizedType, cliType, resolvedDir, cliArgs, provider, settings, attachExisting = false) {
|
|
10378
|
+
async registerCliInstance(key, normalizedType, cliType, resolvedDir, cliArgs, provider, settings, attachExisting = false, launchModeId) {
|
|
10381
10379
|
const instanceManager = this.deps.getInstanceManager();
|
|
10382
10380
|
const sessionRegistry = this.deps.getSessionRegistry?.() || null;
|
|
10383
10381
|
if (!instanceManager) throw new Error("InstanceManager not available");
|
|
10384
10382
|
const transportFactory = this.getTransportFactory(key, normalizedType, resolvedDir, cliArgs, attachExisting);
|
|
10385
|
-
const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key, transportFactory);
|
|
10383
|
+
const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key, transportFactory, launchModeId);
|
|
10386
10384
|
try {
|
|
10387
10385
|
await instanceManager.addInstance(key, cliInstance, {
|
|
10388
10386
|
serverConn: this.deps.getServerConn(),
|
|
@@ -10408,7 +10406,7 @@ var DaemonCliManager = class {
|
|
|
10408
10406
|
this.startCliExitMonitor(key, cliType);
|
|
10409
10407
|
}
|
|
10410
10408
|
// ─── Session start/management ──────────────────────────────
|
|
10411
|
-
async startSession(cliType, workingDir, cliArgs, initialModel) {
|
|
10409
|
+
async startSession(cliType, workingDir, cliArgs, initialModel, launchMode, launchOptionValues) {
|
|
10412
10410
|
const trimmed = (workingDir || "").trim();
|
|
10413
10411
|
if (!trimmed) throw new Error("working directory required");
|
|
10414
10412
|
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path10.resolve(trimmed);
|
|
@@ -10500,6 +10498,29 @@ ${installInfo}`
|
|
|
10500
10498
|
if (provider) {
|
|
10501
10499
|
console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
10502
10500
|
}
|
|
10501
|
+
let resolvedCliArgs = cliArgs;
|
|
10502
|
+
let resolvedLaunchMode = launchMode;
|
|
10503
|
+
const activeMode = provider?.launchModes?.length ? launchMode ? provider.launchModes.find((m) => m.id === launchMode) : provider.launchModes.find((m) => m.default) : void 0;
|
|
10504
|
+
if (activeMode) {
|
|
10505
|
+
resolvedLaunchMode = activeMode.id;
|
|
10506
|
+
}
|
|
10507
|
+
if (provider?.launchArgBuilder) {
|
|
10508
|
+
const defaults = {};
|
|
10509
|
+
for (const opt of provider.launchOptions || []) {
|
|
10510
|
+
if (opt.default !== void 0) defaults[opt.id] = opt.default;
|
|
10511
|
+
}
|
|
10512
|
+
const modeOptions = activeMode?.options || {};
|
|
10513
|
+
const userOptions = launchOptionValues || {};
|
|
10514
|
+
const merged = { ...defaults, ...modeOptions, ...userOptions };
|
|
10515
|
+
const extraArgs = provider.launchArgBuilder(merged);
|
|
10516
|
+
if (extraArgs.length) {
|
|
10517
|
+
resolvedCliArgs = [...cliArgs || [], ...extraArgs];
|
|
10518
|
+
console.log(colorize("cyan", ` \u{1F680} Launch options applied: ${extraArgs.join(" ")}`));
|
|
10519
|
+
}
|
|
10520
|
+
} else if (activeMode?.extraArgs?.length) {
|
|
10521
|
+
resolvedCliArgs = [...cliArgs || [], ...activeMode.extraArgs];
|
|
10522
|
+
console.log(colorize("cyan", ` \u{1F680} Launch mode '${activeMode.name}': appending args ${activeMode.extraArgs.join(" ")}`));
|
|
10523
|
+
}
|
|
10503
10524
|
const instanceManager = this.deps.getInstanceManager();
|
|
10504
10525
|
if (provider && instanceManager) {
|
|
10505
10526
|
const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
|
|
@@ -10508,14 +10529,15 @@ ${installInfo}`
|
|
|
10508
10529
|
normalizedType,
|
|
10509
10530
|
cliType,
|
|
10510
10531
|
resolvedDir,
|
|
10511
|
-
|
|
10532
|
+
resolvedCliArgs,
|
|
10512
10533
|
resolvedProvider,
|
|
10513
10534
|
{},
|
|
10514
|
-
false
|
|
10535
|
+
false,
|
|
10536
|
+
resolvedLaunchMode
|
|
10515
10537
|
);
|
|
10516
10538
|
console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
10517
10539
|
} else {
|
|
10518
|
-
const adapter = this.createAdapter(cliType, resolvedDir,
|
|
10540
|
+
const adapter = this.createAdapter(cliType, resolvedDir, resolvedCliArgs, key, false);
|
|
10519
10541
|
try {
|
|
10520
10542
|
await adapter.spawn();
|
|
10521
10543
|
} catch (spawnErr) {
|
|
@@ -10623,7 +10645,8 @@ ${installInfo}`
|
|
|
10623
10645
|
record.cliArgs,
|
|
10624
10646
|
resolvedProvider,
|
|
10625
10647
|
{},
|
|
10626
|
-
true
|
|
10648
|
+
true,
|
|
10649
|
+
record.launchMode
|
|
10627
10650
|
);
|
|
10628
10651
|
restored += 1;
|
|
10629
10652
|
LOG.info("CLI", `\u267B Restored hosted runtime: ${record.runtimeKey || record.runtimeId} (${record.displayName || record.workspace})`);
|
|
@@ -10693,7 +10716,7 @@ ${installInfo}`
|
|
|
10693
10716
|
const dir = resolved.path;
|
|
10694
10717
|
const launchSource = resolved.source;
|
|
10695
10718
|
if (!cliType) throw new Error("cliType required");
|
|
10696
|
-
await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel);
|
|
10719
|
+
await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel, args?.launchMode, args?.launchOptionValues);
|
|
10697
10720
|
let newKey = null;
|
|
10698
10721
|
for (const [k, adapter] of this.adapters) {
|
|
10699
10722
|
if (adapter.cliType === cliType && adapter.workingDir === dir) {
|