@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.mjs
CHANGED
|
@@ -170,7 +170,8 @@ var init_config = __esm({
|
|
|
170
170
|
workspaces: [],
|
|
171
171
|
defaultWorkspaceId: null,
|
|
172
172
|
recentActivity: [],
|
|
173
|
-
|
|
173
|
+
sessionReads: {},
|
|
174
|
+
sessionReadMarkers: {},
|
|
174
175
|
machineNickname: null,
|
|
175
176
|
machineId: void 0,
|
|
176
177
|
machineSecret: null,
|
|
@@ -2044,18 +2045,27 @@ function appendRecentActivity(config, entry) {
|
|
|
2044
2045
|
function getRecentActivity(config, limit = 20) {
|
|
2045
2046
|
return [...config.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
|
|
2046
2047
|
}
|
|
2047
|
-
function
|
|
2048
|
-
return config.
|
|
2048
|
+
function getSessionSeenAt(config, sessionId) {
|
|
2049
|
+
return config.sessionReads?.[sessionId] || 0;
|
|
2049
2050
|
}
|
|
2050
|
-
function
|
|
2051
|
-
|
|
2052
|
-
|
|
2051
|
+
function getSessionSeenMarker(config, sessionId) {
|
|
2052
|
+
return config.sessionReadMarkers?.[sessionId] || "";
|
|
2053
|
+
}
|
|
2054
|
+
function markSessionSeen(config, sessionId, seenAt = Date.now(), completionMarker) {
|
|
2055
|
+
const prev = config.sessionReads || {};
|
|
2056
|
+
const nextSeenAt = Math.max(prev[sessionId] || 0, seenAt);
|
|
2057
|
+
const prevMarkers = config.sessionReadMarkers || {};
|
|
2058
|
+
const nextMarker = typeof completionMarker === "string" ? completionMarker : "";
|
|
2053
2059
|
return {
|
|
2054
2060
|
...config,
|
|
2055
|
-
|
|
2061
|
+
sessionReads: {
|
|
2056
2062
|
...prev,
|
|
2057
|
-
[
|
|
2058
|
-
}
|
|
2063
|
+
[sessionId]: nextSeenAt
|
|
2064
|
+
},
|
|
2065
|
+
sessionReadMarkers: nextMarker ? {
|
|
2066
|
+
...prevMarkers,
|
|
2067
|
+
[sessionId]: nextMarker
|
|
2068
|
+
} : prevMarkers
|
|
2059
2069
|
};
|
|
2060
2070
|
}
|
|
2061
2071
|
|
|
@@ -4979,6 +4989,8 @@ function buildCliSession(state) {
|
|
|
4979
4989
|
runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
|
|
4980
4990
|
runtimeWriteOwner: state.runtime?.writeOwner || null,
|
|
4981
4991
|
runtimeAttachedClients: state.runtime?.attachedClients || [],
|
|
4992
|
+
launchMode: state.launchMode,
|
|
4993
|
+
mode: state.mode,
|
|
4982
4994
|
resume: state.resume,
|
|
4983
4995
|
activeChat,
|
|
4984
4996
|
capabilities: PTY_SESSION_CAPABILITIES,
|
|
@@ -8385,6 +8397,149 @@ cleanOldFiles();
|
|
|
8385
8397
|
|
|
8386
8398
|
// src/commands/router.ts
|
|
8387
8399
|
init_logger();
|
|
8400
|
+
|
|
8401
|
+
// src/status/snapshot.ts
|
|
8402
|
+
init_config();
|
|
8403
|
+
import * as os10 from "os";
|
|
8404
|
+
init_terminal_screen();
|
|
8405
|
+
init_logger();
|
|
8406
|
+
var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
8407
|
+
function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
8408
|
+
return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
|
|
8409
|
+
id: ide.id,
|
|
8410
|
+
type: ide.id,
|
|
8411
|
+
name: ide.displayName || ide.name || ide.id,
|
|
8412
|
+
running: isCdpConnected(cdpManagers, ide.id),
|
|
8413
|
+
...ide.path ? { path: ide.path } : {}
|
|
8414
|
+
}));
|
|
8415
|
+
}
|
|
8416
|
+
function buildAvailableProviders(providerLoader) {
|
|
8417
|
+
return providerLoader.getAll().map((provider) => ({
|
|
8418
|
+
type: provider.type,
|
|
8419
|
+
name: provider.displayName || provider.type,
|
|
8420
|
+
displayName: provider.displayName || provider.type,
|
|
8421
|
+
icon: provider.icon || "\u{1F4BB}",
|
|
8422
|
+
category: provider.category
|
|
8423
|
+
}));
|
|
8424
|
+
}
|
|
8425
|
+
function parseMessageTime(value) {
|
|
8426
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
8427
|
+
if (typeof value === "string") {
|
|
8428
|
+
const parsed = Date.parse(value);
|
|
8429
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
8430
|
+
}
|
|
8431
|
+
return 0;
|
|
8432
|
+
}
|
|
8433
|
+
function getSessionMessageUpdatedAt(session) {
|
|
8434
|
+
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8435
|
+
if (!lastMessage) return 0;
|
|
8436
|
+
return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
|
|
8437
|
+
}
|
|
8438
|
+
function getSessionCompletionMarker(session) {
|
|
8439
|
+
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8440
|
+
if (!lastMessage) return "";
|
|
8441
|
+
const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
|
|
8442
|
+
if (role === "user" || role === "human") return "";
|
|
8443
|
+
if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
|
|
8444
|
+
if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
|
|
8445
|
+
if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
|
|
8446
|
+
const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
|
|
8447
|
+
return timestamp > 0 ? `ts:${timestamp}` : "";
|
|
8448
|
+
}
|
|
8449
|
+
function getSessionLastUsedAt(session) {
|
|
8450
|
+
return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
|
|
8451
|
+
}
|
|
8452
|
+
function getLastMessageRole(session) {
|
|
8453
|
+
const role = session.activeChat?.messages?.at?.(-1)?.role;
|
|
8454
|
+
return typeof role === "string" ? role : "";
|
|
8455
|
+
}
|
|
8456
|
+
function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
|
|
8457
|
+
if (status === "waiting_approval") {
|
|
8458
|
+
return { unread: false, inboxBucket: "needs_attention" };
|
|
8459
|
+
}
|
|
8460
|
+
if (status === "generating" || status === "starting") {
|
|
8461
|
+
return { unread: false, inboxBucket: "working" };
|
|
8462
|
+
}
|
|
8463
|
+
const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
|
|
8464
|
+
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
8465
|
+
}
|
|
8466
|
+
function buildRecentLaunches(recentActivity) {
|
|
8467
|
+
return recentActivity.map((item) => ({
|
|
8468
|
+
id: item.id,
|
|
8469
|
+
providerType: item.providerType,
|
|
8470
|
+
providerName: item.providerName,
|
|
8471
|
+
kind: item.kind,
|
|
8472
|
+
title: item.title || item.providerName,
|
|
8473
|
+
workspace: item.workspace,
|
|
8474
|
+
currentModel: item.currentModel,
|
|
8475
|
+
lastLaunchedAt: item.lastUsedAt
|
|
8476
|
+
})).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
|
|
8477
|
+
}
|
|
8478
|
+
function buildStatusSnapshot(options) {
|
|
8479
|
+
const cfg = loadConfig();
|
|
8480
|
+
const wsState = getWorkspaceState(cfg);
|
|
8481
|
+
const memSnap = getHostMemorySnapshot();
|
|
8482
|
+
const recentActivity = getRecentActivity(cfg, 20);
|
|
8483
|
+
const sessions = buildSessionEntries(
|
|
8484
|
+
options.allStates,
|
|
8485
|
+
options.cdpManagers
|
|
8486
|
+
);
|
|
8487
|
+
for (const session of sessions) {
|
|
8488
|
+
const lastSeenAt = getSessionSeenAt(cfg, session.id);
|
|
8489
|
+
const seenCompletionMarker = getSessionSeenMarker(cfg, session.id);
|
|
8490
|
+
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8491
|
+
const completionMarker = getSessionCompletionMarker(session);
|
|
8492
|
+
const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
|
|
8493
|
+
getSessionMessageUpdatedAt(session) > 0,
|
|
8494
|
+
session.status,
|
|
8495
|
+
lastUsedAt,
|
|
8496
|
+
lastSeenAt,
|
|
8497
|
+
getLastMessageRole(session),
|
|
8498
|
+
completionMarker,
|
|
8499
|
+
seenCompletionMarker
|
|
8500
|
+
);
|
|
8501
|
+
session.lastSeenAt = lastSeenAt;
|
|
8502
|
+
session.unread = unread;
|
|
8503
|
+
session.inboxBucket = inboxBucket;
|
|
8504
|
+
if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
|
|
8505
|
+
LOG.info(
|
|
8506
|
+
"RecentRead",
|
|
8507
|
+
`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)}`
|
|
8508
|
+
);
|
|
8509
|
+
}
|
|
8510
|
+
}
|
|
8511
|
+
const terminalBackend = getTerminalBackendRuntimeStatus();
|
|
8512
|
+
return {
|
|
8513
|
+
instanceId: options.instanceId,
|
|
8514
|
+
version: options.version,
|
|
8515
|
+
daemonMode: options.daemonMode,
|
|
8516
|
+
machine: {
|
|
8517
|
+
hostname: os10.hostname(),
|
|
8518
|
+
platform: os10.platform(),
|
|
8519
|
+
arch: os10.arch(),
|
|
8520
|
+
cpus: os10.cpus().length,
|
|
8521
|
+
totalMem: memSnap.totalMem,
|
|
8522
|
+
freeMem: memSnap.freeMem,
|
|
8523
|
+
availableMem: memSnap.availableMem,
|
|
8524
|
+
loadavg: os10.loadavg(),
|
|
8525
|
+
uptime: os10.uptime(),
|
|
8526
|
+
release: os10.release()
|
|
8527
|
+
},
|
|
8528
|
+
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
8529
|
+
timestamp: options.timestamp ?? Date.now(),
|
|
8530
|
+
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
8531
|
+
...options.p2p ? { p2p: options.p2p } : {},
|
|
8532
|
+
sessions,
|
|
8533
|
+
workspaces: wsState.workspaces,
|
|
8534
|
+
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
8535
|
+
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
8536
|
+
recentLaunches: buildRecentLaunches(recentActivity),
|
|
8537
|
+
terminalBackend,
|
|
8538
|
+
availableProviders: buildAvailableProviders(options.providerLoader)
|
|
8539
|
+
};
|
|
8540
|
+
}
|
|
8541
|
+
|
|
8542
|
+
// src/commands/router.ts
|
|
8388
8543
|
import * as fs7 from "fs";
|
|
8389
8544
|
var CHAT_COMMANDS = [
|
|
8390
8545
|
"send_chat",
|
|
@@ -8393,6 +8548,7 @@ var CHAT_COMMANDS = [
|
|
|
8393
8548
|
"set_mode",
|
|
8394
8549
|
"change_model"
|
|
8395
8550
|
];
|
|
8551
|
+
var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
8396
8552
|
var DaemonCommandRouter = class {
|
|
8397
8553
|
deps;
|
|
8398
8554
|
constructor(deps) {
|
|
@@ -8563,28 +8719,35 @@ var DaemonCommandRouter = class {
|
|
|
8563
8719
|
updateConfig({ userName: name });
|
|
8564
8720
|
return { success: true, userName: name };
|
|
8565
8721
|
}
|
|
8566
|
-
case "
|
|
8567
|
-
const
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
return { success: false, error: "kind and providerType are required" };
|
|
8722
|
+
case "mark_session_seen": {
|
|
8723
|
+
const sessionId = args?.sessionId;
|
|
8724
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
8725
|
+
return { success: false, error: "sessionId is required" };
|
|
8571
8726
|
}
|
|
8572
|
-
const
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8727
|
+
const currentConfig = loadConfig();
|
|
8728
|
+
const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
|
|
8729
|
+
const sessionEntries = buildSessionEntries(
|
|
8730
|
+
this.deps.instanceManager.collectAllStates(),
|
|
8731
|
+
this.deps.cdpManagers
|
|
8732
|
+
);
|
|
8733
|
+
const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
|
|
8734
|
+
const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : "";
|
|
8735
|
+
const next = markSessionSeen(
|
|
8736
|
+
currentConfig,
|
|
8737
|
+
sessionId,
|
|
8738
|
+
typeof args?.seenAt === "number" ? args.seenAt : Date.now(),
|
|
8739
|
+
completionMarker
|
|
8581
8740
|
);
|
|
8741
|
+
if (READ_DEBUG_ENABLED2) {
|
|
8742
|
+
LOG.info("RecentRead", `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || "")} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || "-"}`);
|
|
8743
|
+
}
|
|
8582
8744
|
saveConfig(next);
|
|
8583
8745
|
this.deps.onStatusChange?.();
|
|
8584
8746
|
return {
|
|
8585
8747
|
success: true,
|
|
8586
|
-
|
|
8587
|
-
seenAt: next.
|
|
8748
|
+
sessionId,
|
|
8749
|
+
seenAt: next.sessionReads?.[sessionId] || Date.now(),
|
|
8750
|
+
completionMarker
|
|
8588
8751
|
};
|
|
8589
8752
|
}
|
|
8590
8753
|
// ─── Daemon Self-Upgrade ───
|
|
@@ -8701,194 +8864,6 @@ var DaemonCommandRouter = class {
|
|
|
8701
8864
|
|
|
8702
8865
|
// src/status/reporter.ts
|
|
8703
8866
|
init_logger();
|
|
8704
|
-
|
|
8705
|
-
// src/status/snapshot.ts
|
|
8706
|
-
init_config();
|
|
8707
|
-
import * as os10 from "os";
|
|
8708
|
-
init_terminal_screen();
|
|
8709
|
-
function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
|
|
8710
|
-
return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
|
|
8711
|
-
id: ide.id,
|
|
8712
|
-
type: ide.id,
|
|
8713
|
-
name: ide.displayName || ide.name || ide.id,
|
|
8714
|
-
running: isCdpConnected(cdpManagers, ide.id),
|
|
8715
|
-
...ide.path ? { path: ide.path } : {}
|
|
8716
|
-
}));
|
|
8717
|
-
}
|
|
8718
|
-
function buildAvailableProviders(providerLoader) {
|
|
8719
|
-
return providerLoader.getAll().map((provider) => ({
|
|
8720
|
-
type: provider.type,
|
|
8721
|
-
name: provider.displayName || provider.type,
|
|
8722
|
-
displayName: provider.displayName || provider.type,
|
|
8723
|
-
icon: provider.icon || "\u{1F4BB}",
|
|
8724
|
-
category: provider.category
|
|
8725
|
-
}));
|
|
8726
|
-
}
|
|
8727
|
-
function parseMessageTime(value) {
|
|
8728
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
8729
|
-
if (typeof value === "string") {
|
|
8730
|
-
const parsed = Date.parse(value);
|
|
8731
|
-
if (Number.isFinite(parsed)) return parsed;
|
|
8732
|
-
}
|
|
8733
|
-
return 0;
|
|
8734
|
-
}
|
|
8735
|
-
function getSessionMessageUpdatedAt(session) {
|
|
8736
|
-
const lastMessage = session.activeChat?.messages?.at?.(-1);
|
|
8737
|
-
if (!lastMessage) return 0;
|
|
8738
|
-
return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
|
|
8739
|
-
}
|
|
8740
|
-
function getSessionLastUsedAt(session) {
|
|
8741
|
-
return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
|
|
8742
|
-
}
|
|
8743
|
-
function getSessionKind(session) {
|
|
8744
|
-
return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
|
|
8745
|
-
}
|
|
8746
|
-
function getLastMessageRole(session) {
|
|
8747
|
-
const role = session.activeChat?.messages?.at?.(-1)?.role;
|
|
8748
|
-
return typeof role === "string" ? role : "";
|
|
8749
|
-
}
|
|
8750
|
-
function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
|
|
8751
|
-
if (status === "waiting_approval") {
|
|
8752
|
-
return { unread: false, inboxBucket: "needs_attention" };
|
|
8753
|
-
}
|
|
8754
|
-
if (status === "generating" || status === "starting") {
|
|
8755
|
-
return { unread: false, inboxBucket: "working" };
|
|
8756
|
-
}
|
|
8757
|
-
const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
|
|
8758
|
-
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
8759
|
-
}
|
|
8760
|
-
function buildRecentSessions(sessions, recentActivity, readState) {
|
|
8761
|
-
const visibleKeys = /* @__PURE__ */ new Set();
|
|
8762
|
-
const hiddenKeys = /* @__PURE__ */ new Set();
|
|
8763
|
-
const live = sessions.filter((session) => !session.surfaceHidden && session.status !== "stopped").map((session) => {
|
|
8764
|
-
const kind = getSessionKind(session);
|
|
8765
|
-
const recentKey = buildRecentActivityKey({
|
|
8766
|
-
kind,
|
|
8767
|
-
providerType: session.providerType,
|
|
8768
|
-
workspace: session.workspace
|
|
8769
|
-
});
|
|
8770
|
-
const lastSeenAt = readState[recentKey] || 0;
|
|
8771
|
-
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8772
|
-
const { unread, inboxBucket } = getUnreadState(
|
|
8773
|
-
getSessionMessageUpdatedAt(session) > 0,
|
|
8774
|
-
session.status,
|
|
8775
|
-
lastUsedAt,
|
|
8776
|
-
lastSeenAt,
|
|
8777
|
-
getLastMessageRole(session)
|
|
8778
|
-
);
|
|
8779
|
-
return {
|
|
8780
|
-
id: session.id,
|
|
8781
|
-
recentKey,
|
|
8782
|
-
sessionId: session.id,
|
|
8783
|
-
providerType: session.providerType,
|
|
8784
|
-
providerName: session.providerName,
|
|
8785
|
-
kind,
|
|
8786
|
-
title: session.activeChat?.title || session.title || session.providerName,
|
|
8787
|
-
workspace: session.workspace,
|
|
8788
|
-
currentModel: session.currentModel,
|
|
8789
|
-
status: session.status,
|
|
8790
|
-
lastUsedAt,
|
|
8791
|
-
unread,
|
|
8792
|
-
lastSeenAt,
|
|
8793
|
-
inboxBucket,
|
|
8794
|
-
surfaceHidden: false
|
|
8795
|
-
};
|
|
8796
|
-
});
|
|
8797
|
-
for (const item of live) {
|
|
8798
|
-
visibleKeys.add(`${item.kind}:${item.providerType}:${item.workspace || ""}`);
|
|
8799
|
-
}
|
|
8800
|
-
for (const session of sessions) {
|
|
8801
|
-
if (!session.surfaceHidden) continue;
|
|
8802
|
-
hiddenKeys.add(`${getSessionKind(session)}:${session.providerType}:${session.workspace || ""}`);
|
|
8803
|
-
}
|
|
8804
|
-
const persisted = recentActivity.filter((item) => {
|
|
8805
|
-
const key = `${item.kind}:${item.providerType}:${item.workspace || ""}`;
|
|
8806
|
-
return !visibleKeys.has(key) && !hiddenKeys.has(key);
|
|
8807
|
-
}).map((item) => {
|
|
8808
|
-
const lastSeenAt = readState[item.id] || 0;
|
|
8809
|
-
const unread = item.lastUsedAt > lastSeenAt;
|
|
8810
|
-
return {
|
|
8811
|
-
id: item.id,
|
|
8812
|
-
recentKey: item.id,
|
|
8813
|
-
sessionId: item.sessionId || null,
|
|
8814
|
-
providerType: item.providerType,
|
|
8815
|
-
providerName: item.providerName,
|
|
8816
|
-
kind: item.kind,
|
|
8817
|
-
title: item.title || item.providerName,
|
|
8818
|
-
workspace: item.workspace,
|
|
8819
|
-
currentModel: item.currentModel,
|
|
8820
|
-
lastUsedAt: item.lastUsedAt,
|
|
8821
|
-
unread,
|
|
8822
|
-
lastSeenAt,
|
|
8823
|
-
inboxBucket: unread ? "task_complete" : "idle",
|
|
8824
|
-
surfaceHidden: false
|
|
8825
|
-
};
|
|
8826
|
-
});
|
|
8827
|
-
return [...live, ...persisted].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, 12);
|
|
8828
|
-
}
|
|
8829
|
-
function buildStatusSnapshot(options) {
|
|
8830
|
-
const cfg = loadConfig();
|
|
8831
|
-
const wsState = getWorkspaceState(cfg);
|
|
8832
|
-
const memSnap = getHostMemorySnapshot();
|
|
8833
|
-
const recentActivity = getRecentActivity(cfg, 20);
|
|
8834
|
-
const sessions = buildSessionEntries(
|
|
8835
|
-
options.allStates,
|
|
8836
|
-
options.cdpManagers
|
|
8837
|
-
);
|
|
8838
|
-
const readState = cfg.recentSessionReads || {};
|
|
8839
|
-
for (const session of sessions) {
|
|
8840
|
-
const kind = getSessionKind(session);
|
|
8841
|
-
const recentKey = buildRecentActivityKey({
|
|
8842
|
-
kind,
|
|
8843
|
-
providerType: session.providerType,
|
|
8844
|
-
workspace: session.workspace
|
|
8845
|
-
});
|
|
8846
|
-
const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
|
|
8847
|
-
const lastUsedAt = getSessionLastUsedAt(session);
|
|
8848
|
-
const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
|
|
8849
|
-
getSessionMessageUpdatedAt(session) > 0,
|
|
8850
|
-
session.status,
|
|
8851
|
-
lastUsedAt,
|
|
8852
|
-
lastSeenAt,
|
|
8853
|
-
getLastMessageRole(session)
|
|
8854
|
-
);
|
|
8855
|
-
session.recentKey = recentKey;
|
|
8856
|
-
session.lastSeenAt = lastSeenAt;
|
|
8857
|
-
session.unread = unread;
|
|
8858
|
-
session.inboxBucket = inboxBucket;
|
|
8859
|
-
}
|
|
8860
|
-
const terminalBackend = getTerminalBackendRuntimeStatus();
|
|
8861
|
-
return {
|
|
8862
|
-
instanceId: options.instanceId,
|
|
8863
|
-
version: options.version,
|
|
8864
|
-
daemonMode: options.daemonMode,
|
|
8865
|
-
machine: {
|
|
8866
|
-
hostname: os10.hostname(),
|
|
8867
|
-
platform: os10.platform(),
|
|
8868
|
-
arch: os10.arch(),
|
|
8869
|
-
cpus: os10.cpus().length,
|
|
8870
|
-
totalMem: memSnap.totalMem,
|
|
8871
|
-
freeMem: memSnap.freeMem,
|
|
8872
|
-
availableMem: memSnap.availableMem,
|
|
8873
|
-
loadavg: os10.loadavg(),
|
|
8874
|
-
uptime: os10.uptime(),
|
|
8875
|
-
release: os10.release()
|
|
8876
|
-
},
|
|
8877
|
-
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
8878
|
-
timestamp: options.timestamp ?? Date.now(),
|
|
8879
|
-
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
8880
|
-
...options.p2p ? { p2p: options.p2p } : {},
|
|
8881
|
-
sessions,
|
|
8882
|
-
workspaces: wsState.workspaces,
|
|
8883
|
-
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
8884
|
-
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
8885
|
-
recentSessions: buildRecentSessions(sessions, recentActivity, readState),
|
|
8886
|
-
terminalBackend,
|
|
8887
|
-
availableProviders: buildAvailableProviders(options.providerLoader)
|
|
8888
|
-
};
|
|
8889
|
-
}
|
|
8890
|
-
|
|
8891
|
-
// src/status/reporter.ts
|
|
8892
8867
|
var DaemonStatusReporter = class {
|
|
8893
8868
|
deps;
|
|
8894
8869
|
log;
|
|
@@ -9036,7 +9011,7 @@ var DaemonStatusReporter = class {
|
|
|
9036
9011
|
currentModel: session.currentModel,
|
|
9037
9012
|
currentPlan: session.currentPlan,
|
|
9038
9013
|
currentAutoApprove: session.currentAutoApprove,
|
|
9039
|
-
|
|
9014
|
+
lastUpdated: session.lastUpdated,
|
|
9040
9015
|
unread: session.unread,
|
|
9041
9016
|
lastSeenAt: session.lastSeenAt,
|
|
9042
9017
|
inboxBucket: session.inboxBucket,
|
|
@@ -9093,12 +9068,14 @@ init_provider_cli_adapter();
|
|
|
9093
9068
|
import * as crypto3 from "crypto";
|
|
9094
9069
|
init_logger();
|
|
9095
9070
|
var CliProviderInstance = class {
|
|
9096
|
-
constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory) {
|
|
9071
|
+
constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, launchModeId) {
|
|
9097
9072
|
this.provider = provider;
|
|
9098
9073
|
this.workingDir = workingDir;
|
|
9099
9074
|
this.cliArgs = cliArgs;
|
|
9100
9075
|
this.type = provider.type;
|
|
9101
9076
|
this.instanceId = instanceId || crypto3.randomUUID();
|
|
9077
|
+
this.launchMode = launchModeId && provider.launchModes?.find((m) => m.id === launchModeId) || null;
|
|
9078
|
+
this.resolvedOutputFormat = this.resolveOutputFormat();
|
|
9102
9079
|
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
|
|
9103
9080
|
this.monitor = new StatusMonitor();
|
|
9104
9081
|
this.historyWriter = new ChatHistoryWriter();
|
|
@@ -9117,6 +9094,26 @@ var CliProviderInstance = class {
|
|
|
9117
9094
|
lastApprovalEventAt = 0;
|
|
9118
9095
|
historyWriter;
|
|
9119
9096
|
instanceId;
|
|
9097
|
+
launchMode;
|
|
9098
|
+
resolvedOutputFormat;
|
|
9099
|
+
/**
|
|
9100
|
+
* Determine output rendering format from:
|
|
9101
|
+
* 1. launchMode.outputFormat (explicit override)
|
|
9102
|
+
* 2. launchOptions[].outputFormatMap — check actual args for matching values
|
|
9103
|
+
* 3. Default: 'terminal'
|
|
9104
|
+
*/
|
|
9105
|
+
resolveOutputFormat() {
|
|
9106
|
+
if (this.launchMode?.outputFormat) return this.launchMode.outputFormat;
|
|
9107
|
+
if (this.provider.launchOptions?.length) {
|
|
9108
|
+
for (const opt of this.provider.launchOptions) {
|
|
9109
|
+
if (!opt.outputFormatMap) continue;
|
|
9110
|
+
for (const [val, fmt] of Object.entries(opt.outputFormatMap)) {
|
|
9111
|
+
if (this.cliArgs.includes(val)) return fmt;
|
|
9112
|
+
}
|
|
9113
|
+
}
|
|
9114
|
+
}
|
|
9115
|
+
return "terminal";
|
|
9116
|
+
}
|
|
9120
9117
|
// ─── Lifecycle ─────────────────────────────────
|
|
9121
9118
|
async init(context) {
|
|
9122
9119
|
this.context = context;
|
|
@@ -9156,7 +9153,8 @@ var CliProviderInstance = class {
|
|
|
9156
9153
|
name: this.provider.name,
|
|
9157
9154
|
category: "cli",
|
|
9158
9155
|
status: adapterStatus.status,
|
|
9159
|
-
mode: "terminal",
|
|
9156
|
+
mode: this.resolvedOutputFormat === "stream-json" ? "chat" : "terminal",
|
|
9157
|
+
launchMode: this.launchMode?.id,
|
|
9160
9158
|
activeChat: {
|
|
9161
9159
|
id: `${this.type}_${this.workingDir}`,
|
|
9162
9160
|
title: `${this.provider.name} \xB7 ${dirName}`,
|
|
@@ -10303,12 +10301,12 @@ var DaemonCliManager = class {
|
|
|
10303
10301
|
}
|
|
10304
10302
|
}, 3e3);
|
|
10305
10303
|
}
|
|
10306
|
-
async registerCliInstance(key, normalizedType, cliType, resolvedDir, cliArgs, provider, settings, attachExisting = false) {
|
|
10304
|
+
async registerCliInstance(key, normalizedType, cliType, resolvedDir, cliArgs, provider, settings, attachExisting = false, launchModeId) {
|
|
10307
10305
|
const instanceManager = this.deps.getInstanceManager();
|
|
10308
10306
|
const sessionRegistry = this.deps.getSessionRegistry?.() || null;
|
|
10309
10307
|
if (!instanceManager) throw new Error("InstanceManager not available");
|
|
10310
10308
|
const transportFactory = this.getTransportFactory(key, normalizedType, resolvedDir, cliArgs, attachExisting);
|
|
10311
|
-
const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key, transportFactory);
|
|
10309
|
+
const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key, transportFactory, launchModeId);
|
|
10312
10310
|
try {
|
|
10313
10311
|
await instanceManager.addInstance(key, cliInstance, {
|
|
10314
10312
|
serverConn: this.deps.getServerConn(),
|
|
@@ -10334,7 +10332,7 @@ var DaemonCliManager = class {
|
|
|
10334
10332
|
this.startCliExitMonitor(key, cliType);
|
|
10335
10333
|
}
|
|
10336
10334
|
// ─── Session start/management ──────────────────────────────
|
|
10337
|
-
async startSession(cliType, workingDir, cliArgs, initialModel) {
|
|
10335
|
+
async startSession(cliType, workingDir, cliArgs, initialModel, launchMode, launchOptionValues) {
|
|
10338
10336
|
const trimmed = (workingDir || "").trim();
|
|
10339
10337
|
if (!trimmed) throw new Error("working directory required");
|
|
10340
10338
|
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path10.resolve(trimmed);
|
|
@@ -10426,6 +10424,29 @@ ${installInfo}`
|
|
|
10426
10424
|
if (provider) {
|
|
10427
10425
|
console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
10428
10426
|
}
|
|
10427
|
+
let resolvedCliArgs = cliArgs;
|
|
10428
|
+
let resolvedLaunchMode = launchMode;
|
|
10429
|
+
const activeMode = provider?.launchModes?.length ? launchMode ? provider.launchModes.find((m) => m.id === launchMode) : provider.launchModes.find((m) => m.default) : void 0;
|
|
10430
|
+
if (activeMode) {
|
|
10431
|
+
resolvedLaunchMode = activeMode.id;
|
|
10432
|
+
}
|
|
10433
|
+
if (provider?.launchArgBuilder) {
|
|
10434
|
+
const defaults = {};
|
|
10435
|
+
for (const opt of provider.launchOptions || []) {
|
|
10436
|
+
if (opt.default !== void 0) defaults[opt.id] = opt.default;
|
|
10437
|
+
}
|
|
10438
|
+
const modeOptions = activeMode?.options || {};
|
|
10439
|
+
const userOptions = launchOptionValues || {};
|
|
10440
|
+
const merged = { ...defaults, ...modeOptions, ...userOptions };
|
|
10441
|
+
const extraArgs = provider.launchArgBuilder(merged);
|
|
10442
|
+
if (extraArgs.length) {
|
|
10443
|
+
resolvedCliArgs = [...cliArgs || [], ...extraArgs];
|
|
10444
|
+
console.log(colorize("cyan", ` \u{1F680} Launch options applied: ${extraArgs.join(" ")}`));
|
|
10445
|
+
}
|
|
10446
|
+
} else if (activeMode?.extraArgs?.length) {
|
|
10447
|
+
resolvedCliArgs = [...cliArgs || [], ...activeMode.extraArgs];
|
|
10448
|
+
console.log(colorize("cyan", ` \u{1F680} Launch mode '${activeMode.name}': appending args ${activeMode.extraArgs.join(" ")}`));
|
|
10449
|
+
}
|
|
10429
10450
|
const instanceManager = this.deps.getInstanceManager();
|
|
10430
10451
|
if (provider && instanceManager) {
|
|
10431
10452
|
const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
|
|
@@ -10434,14 +10455,15 @@ ${installInfo}`
|
|
|
10434
10455
|
normalizedType,
|
|
10435
10456
|
cliType,
|
|
10436
10457
|
resolvedDir,
|
|
10437
|
-
|
|
10458
|
+
resolvedCliArgs,
|
|
10438
10459
|
resolvedProvider,
|
|
10439
10460
|
{},
|
|
10440
|
-
false
|
|
10461
|
+
false,
|
|
10462
|
+
resolvedLaunchMode
|
|
10441
10463
|
);
|
|
10442
10464
|
console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
10443
10465
|
} else {
|
|
10444
|
-
const adapter = this.createAdapter(cliType, resolvedDir,
|
|
10466
|
+
const adapter = this.createAdapter(cliType, resolvedDir, resolvedCliArgs, key, false);
|
|
10445
10467
|
try {
|
|
10446
10468
|
await adapter.spawn();
|
|
10447
10469
|
} catch (spawnErr) {
|
|
@@ -10549,7 +10571,8 @@ ${installInfo}`
|
|
|
10549
10571
|
record.cliArgs,
|
|
10550
10572
|
resolvedProvider,
|
|
10551
10573
|
{},
|
|
10552
|
-
true
|
|
10574
|
+
true,
|
|
10575
|
+
record.launchMode
|
|
10553
10576
|
);
|
|
10554
10577
|
restored += 1;
|
|
10555
10578
|
LOG.info("CLI", `\u267B Restored hosted runtime: ${record.runtimeKey || record.runtimeId} (${record.displayName || record.workspace})`);
|
|
@@ -10619,7 +10642,7 @@ ${installInfo}`
|
|
|
10619
10642
|
const dir = resolved.path;
|
|
10620
10643
|
const launchSource = resolved.source;
|
|
10621
10644
|
if (!cliType) throw new Error("cliType required");
|
|
10622
|
-
await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel);
|
|
10645
|
+
await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel, args?.launchMode, args?.launchOptionValues);
|
|
10623
10646
|
let newKey = null;
|
|
10624
10647
|
for (const [k, adapter] of this.adapters) {
|
|
10625
10648
|
if (adapter.cliType === cliType && adapter.workingDir === dir) {
|