@adhdev/daemon-core 0.8.34 → 0.8.36
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/boot/daemon-lifecycle.d.ts +4 -0
- package/dist/commands/router.d.ts +3 -0
- package/dist/config/config.d.ts +5 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +585 -256
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +584 -256
- package/dist/index.mjs.map +1 -1
- package/dist/shared-types.d.ts +286 -16
- package/dist/status/builders.d.ts +5 -1
- package/dist/status/normalize.d.ts +11 -1
- package/dist/status/normalize.js +36 -16
- package/dist/status/normalize.js.map +1 -1
- package/dist/status/normalize.mjs +35 -16
- package/dist/status/normalize.mjs.map +1 -1
- package/dist/status/reporter.d.ts +7 -0
- package/dist/status/snapshot.d.ts +5 -5
- package/dist/types.d.ts +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/agent-stream/forward.d.ts +8 -0
- package/src/agent-stream/index.d.ts +6 -0
- package/src/agent-stream/manager.d.ts +60 -0
- package/src/agent-stream/poller.d.ts +41 -0
- package/src/agent-stream/provider-adapter.d.ts +36 -0
- package/src/agent-stream/types.d.ts +68 -0
- package/src/boot/daemon-lifecycle.d.ts +100 -0
- package/src/boot/daemon-lifecycle.ts +7 -0
- package/src/cdp/devtools.d.ts +51 -0
- package/src/cdp/initializer.d.ts +50 -0
- package/src/cdp/manager.d.ts +147 -0
- package/src/cdp/scanner.d.ts +58 -0
- package/src/cdp/setup.d.ts +58 -0
- package/src/cli-adapter-types.d.ts +57 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +177 -0
- package/src/cli-adapters/provider-cli-adapter.ts +115 -91
- package/src/cli-adapters/provider-cli-config.d.ts +30 -0
- package/src/cli-adapters/provider-cli-parse.d.ts +42 -0
- package/src/cli-adapters/provider-cli-runtime.d.ts +29 -0
- package/src/cli-adapters/provider-cli-shared.d.ts +158 -0
- package/src/cli-adapters/pty-transport.d.ts +48 -0
- package/src/cli-adapters/session-host-transport.d.ts +20 -0
- package/src/cli-adapters/spawn-env.d.ts +8 -0
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +16 -0
- package/src/cli-adapters/terminal-backends/types.d.ts +18 -0
- package/src/cli-adapters/terminal-backends/xterm-backend.d.ts +17 -0
- package/src/cli-adapters/terminal-screen.d.ts +33 -0
- package/src/commands/cdp-commands.d.ts +15 -0
- package/src/commands/chat-commands.d.ts +15 -0
- package/src/commands/chat-commands.ts +192 -17
- package/src/commands/cli-manager.d.ts +94 -0
- package/src/commands/handler.d.ts +103 -0
- package/src/commands/router.d.ts +98 -0
- package/src/commands/router.ts +25 -0
- package/src/commands/stream-commands.d.ts +14 -0
- package/src/commands/stream-commands.ts +14 -10
- package/src/commands/upgrade-helper.d.ts +10 -0
- package/src/commands/workspace-commands.d.ts +11 -0
- package/src/config/chat-history.d.ts +99 -0
- package/src/config/config.d.ts +14 -0
- package/src/config/config.ts +8 -0
- package/src/config/recent-activity.d.ts +29 -0
- package/src/config/saved-sessions.d.ts +22 -0
- package/src/config/state-store.d.ts +32 -0
- package/src/config/workspaces.d.ts +0 -1
- package/src/daemon/dev-auto-implement.d.ts +43 -0
- package/src/daemon/dev-cdp-handlers.d.ts +22 -0
- package/src/daemon/dev-cli-debug.d.ts +106 -0
- package/src/daemon/dev-server-types.d.ts +43 -0
- package/src/daemon/dev-server.d.ts +140 -0
- package/src/daemon/scaffold-template.d.ts +32 -0
- package/src/daemon-core.d.ts +36 -0
- package/src/detection/cli-detector.d.ts +31 -0
- package/src/detection/ide-detector.d.ts +35 -0
- package/src/index.d.ts +83 -0
- package/src/index.ts +34 -1
- package/src/installer.d.ts +50 -0
- package/src/ipc-protocol.d.ts +111 -0
- package/src/launch.d.ts +46 -0
- package/src/logging/command-log.d.ts +31 -0
- package/src/logging/logger.d.ts +89 -0
- package/src/providers/acp-provider-instance.d.ts +102 -0
- package/src/providers/approval-utils.d.ts +7 -0
- package/src/providers/cli-provider-instance.d.ts +86 -0
- package/src/providers/contracts.d.ts +193 -1
- package/src/providers/control-effects.d.ts +4 -0
- package/src/providers/extension-provider-instance.d.ts +61 -0
- package/src/providers/ide-provider-instance.d.ts +70 -0
- package/src/providers/provider-instance-manager.d.ts +84 -0
- package/src/providers/provider-instance.d.ts +7 -1
- package/src/providers/provider-loader.d.ts +299 -0
- package/src/providers/status-monitor.d.ts +48 -0
- package/src/providers/version-archive.d.ts +52 -0
- package/src/session-host/runtime-support.d.ts +8 -0
- package/src/sessions/reconcile.d.ts +22 -0
- package/src/sessions/registry.d.ts +24 -0
- package/src/shared-types-extra.d.ts +29 -0
- package/src/shared-types.d.ts +204 -38
- package/src/shared-types.ts +319 -16
- package/src/status/builders.d.ts +33 -0
- package/src/status/builders.ts +110 -54
- package/src/status/normalize.ts +54 -19
- package/src/status/reporter.d.ts +69 -0
- package/src/status/reporter.ts +104 -26
- package/src/status/snapshot.d.ts +58 -0
- package/src/status/snapshot.ts +79 -41
- package/src/system/host-memory.d.ts +19 -0
- package/src/types.d.ts +3 -7
- package/src/types.ts +1 -1
package/src/status/reporter.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { LOG } from '../logging/logger.js';
|
|
9
9
|
import type { DaemonCdpManager } from '../cdp/manager.js';
|
|
10
10
|
import type { MachineInfo } from '../shared-types.js';
|
|
11
|
+
import type { CloudStatusReportPayload, DaemonStatusEventPayload } from '../shared-types.js';
|
|
11
12
|
import { buildSessionEntries } from './builders.js';
|
|
12
13
|
import { buildStatusSnapshot } from './snapshot.js';
|
|
13
14
|
import type {
|
|
@@ -22,7 +23,15 @@ import type {
|
|
|
22
23
|
export interface StatusReporterDeps {
|
|
23
24
|
serverConn: { isConnected(): boolean; sendMessage(type: string, data: any): void; getUserPlan(): string } | null;
|
|
24
25
|
cdpManagers: Map<string, DaemonCdpManager>;
|
|
25
|
-
p2p: {
|
|
26
|
+
p2p: {
|
|
27
|
+
isConnected: boolean;
|
|
28
|
+
isAvailable: boolean;
|
|
29
|
+
connectionState: string;
|
|
30
|
+
connectedPeerCount: number;
|
|
31
|
+
screenshotActive: boolean;
|
|
32
|
+
sendStatus(data: any): void;
|
|
33
|
+
sendStatusEvent(event: DaemonStatusEventPayload): void;
|
|
34
|
+
} | null;
|
|
26
35
|
providerLoader: { resolve(type: string): any; getAll(): any[] };
|
|
27
36
|
detectedIdes: any[];
|
|
28
37
|
instanceId: string;
|
|
@@ -38,6 +47,7 @@ export class DaemonStatusReporter {
|
|
|
38
47
|
private lastStatusSentAt = 0;
|
|
39
48
|
private statusPendingThrottle = false;
|
|
40
49
|
private lastP2PStatusHash = '';
|
|
50
|
+
private lastServerStatusHash = '';
|
|
41
51
|
private lastStatusSummary = '';
|
|
42
52
|
|
|
43
53
|
private statusTimer: NodeJS.Timeout | null = null;
|
|
@@ -52,12 +62,12 @@ export class DaemonStatusReporter {
|
|
|
52
62
|
|
|
53
63
|
startReporting(): void {
|
|
54
64
|
setTimeout(() => {
|
|
55
|
-
this.sendUnifiedStatusReport().catch(e => LOG.warn('Status', `Initial report failed: ${e?.message}`));
|
|
65
|
+
this.sendUnifiedStatusReport({ forceServer: true, reason: 'initial' }).catch(e => LOG.warn('Status', `Initial report failed: ${e?.message}`));
|
|
56
66
|
}, 2000);
|
|
57
67
|
|
|
58
68
|
const scheduleServerReport = () => {
|
|
59
69
|
this.statusTimer = setTimeout(() => {
|
|
60
|
-
this.sendUnifiedStatusReport().catch(e => LOG.warn('Status', `Periodic report failed: ${e?.message}`));
|
|
70
|
+
this.sendUnifiedStatusReport({ forceServer: true, reason: 'periodic' }).catch(e => LOG.warn('Status', `Periodic report failed: ${e?.message}`));
|
|
61
71
|
scheduleServerReport();
|
|
62
72
|
}, 30_000);
|
|
63
73
|
};
|
|
@@ -93,10 +103,73 @@ export class DaemonStatusReporter {
|
|
|
93
103
|
}
|
|
94
104
|
}
|
|
95
105
|
|
|
106
|
+
private toDaemonStatusEventName(value: unknown): DaemonStatusEventPayload['event'] | null {
|
|
107
|
+
switch (value) {
|
|
108
|
+
case 'agent:generating_started':
|
|
109
|
+
case 'agent:waiting_approval':
|
|
110
|
+
case 'agent:generating_completed':
|
|
111
|
+
case 'agent:stopped':
|
|
112
|
+
case 'monitor:long_generating':
|
|
113
|
+
return value;
|
|
114
|
+
default:
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private buildServerStatusEvent(event: Record<string, unknown>): DaemonStatusEventPayload | null {
|
|
120
|
+
const eventName = this.toDaemonStatusEventName(event.event);
|
|
121
|
+
if (!eventName) return null;
|
|
122
|
+
|
|
123
|
+
// Provider UI effects can carry arbitrary text content and are not required
|
|
124
|
+
// for server-side routing, push, or dashboard session targeting.
|
|
125
|
+
if (eventName.startsWith('provider:')) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const payload: DaemonStatusEventPayload = {
|
|
130
|
+
event: eventName,
|
|
131
|
+
timestamp: typeof event.timestamp === 'number' && Number.isFinite(event.timestamp)
|
|
132
|
+
? event.timestamp
|
|
133
|
+
: Date.now(),
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
if (typeof event.targetSessionId === 'string' && event.targetSessionId.trim()) {
|
|
137
|
+
payload.targetSessionId = event.targetSessionId.trim();
|
|
138
|
+
}
|
|
139
|
+
const providerType = typeof event.providerType === 'string' && event.providerType.trim()
|
|
140
|
+
? event.providerType.trim()
|
|
141
|
+
: (typeof event.ideType === 'string' && event.ideType.trim() ? event.ideType.trim() : '');
|
|
142
|
+
if (providerType) {
|
|
143
|
+
payload.providerType = providerType;
|
|
144
|
+
}
|
|
145
|
+
if (typeof event.duration === 'number' && Number.isFinite(event.duration)) {
|
|
146
|
+
payload.duration = event.duration;
|
|
147
|
+
}
|
|
148
|
+
if (typeof event.elapsedSec === 'number' && Number.isFinite(event.elapsedSec)) {
|
|
149
|
+
payload.elapsedSec = event.elapsedSec;
|
|
150
|
+
}
|
|
151
|
+
if (typeof event.modalMessage === 'string' && event.modalMessage.trim()) {
|
|
152
|
+
payload.modalMessage = event.modalMessage;
|
|
153
|
+
}
|
|
154
|
+
if (Array.isArray(event.modalButtons)) {
|
|
155
|
+
const modalButtons = event.modalButtons
|
|
156
|
+
.filter((button): button is string => typeof button === 'string' && button.trim().length > 0);
|
|
157
|
+
if (modalButtons.length > 0) {
|
|
158
|
+
payload.modalButtons = modalButtons;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return payload;
|
|
163
|
+
}
|
|
164
|
+
|
|
96
165
|
emitStatusEvent(event: Record<string, unknown>): void {
|
|
97
166
|
LOG.info('StatusEvent', `${event.event} (${event.providerType || event.ideType || ''})`);
|
|
98
|
-
|
|
99
|
-
|
|
167
|
+
const serverEvent = this.buildServerStatusEvent(event);
|
|
168
|
+
if (!serverEvent) return;
|
|
169
|
+
// Dashboard delivery is P2P-only, but the server still receives the event
|
|
170
|
+
// for push notifications, webhook dispatch, and audit-side effects.
|
|
171
|
+
this.deps.p2p?.sendStatusEvent(serverEvent);
|
|
172
|
+
this.deps.serverConn?.sendMessage('status_event', serverEvent);
|
|
100
173
|
}
|
|
101
174
|
|
|
102
175
|
removeAgentTracking(_key: string): void { /* Managed by Instance itself */ }
|
|
@@ -135,7 +208,7 @@ export class DaemonStatusReporter {
|
|
|
135
208
|
.join(', ');
|
|
136
209
|
}
|
|
137
210
|
|
|
138
|
-
async sendUnifiedStatusReport(opts?: { p2pOnly?: boolean }): Promise<void> {
|
|
211
|
+
async sendUnifiedStatusReport(opts?: { p2pOnly?: boolean; forceServer?: boolean; reason?: string }): Promise<void> {
|
|
139
212
|
const { serverConn, p2p } = this.deps;
|
|
140
213
|
if (!serverConn?.isConnected()) return;
|
|
141
214
|
this.lastStatusSentAt = Date.now();
|
|
@@ -188,7 +261,6 @@ export class DaemonStatusReporter {
|
|
|
188
261
|
detectedIdes: this.deps.detectedIdes || [],
|
|
189
262
|
instanceId: this.deps.instanceId,
|
|
190
263
|
version: this.deps.daemonVersion || 'unknown',
|
|
191
|
-
daemonMode: true,
|
|
192
264
|
timestamp: now,
|
|
193
265
|
p2p: {
|
|
194
266
|
available: p2p?.isAvailable || false,
|
|
@@ -196,9 +268,9 @@ export class DaemonStatusReporter {
|
|
|
196
268
|
peers: p2p?.connectedPeerCount || 0,
|
|
197
269
|
screenshotActive: p2p?.screenshotActive || false,
|
|
198
270
|
},
|
|
271
|
+
profile: 'live',
|
|
199
272
|
}),
|
|
200
273
|
screenshotUsage: this.deps.getScreenshotUsage?.() || null,
|
|
201
|
-
connectedExtensions: [],
|
|
202
274
|
};
|
|
203
275
|
|
|
204
276
|
// ═══ P2P transmit ═══
|
|
@@ -216,51 +288,57 @@ export class DaemonStatusReporter {
|
|
|
216
288
|
|
|
217
289
|
// ═══ Server transmit (minimal routing meta only) ═══
|
|
218
290
|
if (opts?.p2pOnly) return;
|
|
219
|
-
|
|
220
|
-
|
|
291
|
+
// Server relay only needs compact session metadata for routing, compact status,
|
|
292
|
+
// initial_state fallback, and lightweight API/session inspection.
|
|
293
|
+
const wsPayload: CloudStatusReportPayload = {
|
|
221
294
|
sessions: sessions.map((session) => ({
|
|
222
295
|
id: session.id,
|
|
223
296
|
parentId: session.parentId,
|
|
224
297
|
providerType: session.providerType,
|
|
225
|
-
providerName: session.providerName,
|
|
298
|
+
providerName: session.providerName || session.providerType,
|
|
226
299
|
kind: session.kind,
|
|
227
300
|
transport: session.transport,
|
|
228
301
|
status: session.status,
|
|
229
|
-
workspace: session.workspace,
|
|
302
|
+
workspace: session.workspace ?? null,
|
|
230
303
|
title: session.title,
|
|
231
304
|
cdpConnected: session.cdpConnected,
|
|
232
305
|
currentModel: session.currentModel,
|
|
233
306
|
currentPlan: session.currentPlan,
|
|
234
307
|
currentAutoApprove: session.currentAutoApprove,
|
|
235
|
-
lastUpdated: session.lastUpdated,
|
|
236
|
-
unread: session.unread,
|
|
237
|
-
lastSeenAt: session.lastSeenAt,
|
|
238
|
-
inboxBucket: session.inboxBucket,
|
|
239
|
-
surfaceHidden: session.surfaceHidden,
|
|
240
|
-
controlValues: session.controlValues,
|
|
241
|
-
providerControls: session.providerControls,
|
|
242
|
-
acpConfigOptions: session.acpConfigOptions,
|
|
243
|
-
acpModes: session.acpModes,
|
|
244
308
|
})),
|
|
245
309
|
p2p: payload.p2p,
|
|
246
310
|
timestamp: now,
|
|
247
|
-
detectedIdes: payload.detectedIdes,
|
|
248
|
-
availableProviders: payload.availableProviders,
|
|
249
311
|
};
|
|
312
|
+
const wsHash = this.simpleHash(JSON.stringify({
|
|
313
|
+
...wsPayload,
|
|
314
|
+
timestamp: undefined,
|
|
315
|
+
}));
|
|
316
|
+
if (!opts?.forceServer && wsHash === this.lastServerStatusHash) {
|
|
317
|
+
LOG.debug('Server', `skip duplicate status_report${opts?.reason ? ` (${opts.reason})` : ''}`);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
this.lastServerStatusHash = wsHash;
|
|
250
321
|
serverConn.sendMessage('status_report', wsPayload);
|
|
251
|
-
LOG.debug('Server', `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
|
|
322
|
+
LOG.debug('Server', `sent status_report (${JSON.stringify(wsPayload).length} bytes)${opts?.reason ? ` [${opts.reason}]` : ''}`);
|
|
252
323
|
}
|
|
253
324
|
|
|
254
325
|
// ─── P2P ─────────────────────────────────────────
|
|
255
326
|
|
|
256
327
|
private sendP2PPayload(payload: { timestamp?: number; system?: unknown; machine?: MachineInfo; [key: string]: unknown }): boolean {
|
|
257
328
|
const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
|
|
329
|
+
const sessions = Array.isArray(hashTarget.sessions)
|
|
330
|
+
? hashTarget.sessions.map((session) => {
|
|
331
|
+
if (!session || typeof session !== 'object') return session;
|
|
332
|
+
const { lastUpdated: _lu, ...stableSession } = session as Record<string, unknown>;
|
|
333
|
+
return stableSession;
|
|
334
|
+
})
|
|
335
|
+
: hashTarget.sessions;
|
|
258
336
|
const hashPayload = hashTarget.machine
|
|
259
337
|
? (() => {
|
|
260
338
|
const { freeMem: _f, availableMem: _a, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
|
|
261
|
-
return { ...hashTarget, machine: stableMachine };
|
|
339
|
+
return { ...hashTarget, sessions, machine: stableMachine };
|
|
262
340
|
})()
|
|
263
|
-
: hashTarget;
|
|
341
|
+
: { ...hashTarget, sessions };
|
|
264
342
|
const h = this.simpleHash(JSON.stringify(hashPayload));
|
|
265
343
|
if (h !== this.lastP2PStatusHash) {
|
|
266
344
|
this.lastP2PStatusHash = h;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared status snapshot builders.
|
|
3
|
+
*
|
|
4
|
+
* Used by:
|
|
5
|
+
* - DaemonStatusReporter (cloud)
|
|
6
|
+
* - daemon-standalone HTTP/WS status responses
|
|
7
|
+
*/
|
|
8
|
+
import type { DaemonCdpManager } from '../cdp/manager.js';
|
|
9
|
+
import type { ProviderState } from '../providers/provider-instance.js';
|
|
10
|
+
import type { AvailableProviderInfo, StatusReportPayload } from '../shared-types.js';
|
|
11
|
+
export interface StatusSnapshotOptions {
|
|
12
|
+
allStates: ProviderState[];
|
|
13
|
+
cdpManagers: Map<string, DaemonCdpManager>;
|
|
14
|
+
providerLoader: {
|
|
15
|
+
getAll(): Array<{
|
|
16
|
+
type: string;
|
|
17
|
+
icon?: string;
|
|
18
|
+
displayName?: string;
|
|
19
|
+
category: 'ide' | 'extension' | 'cli' | 'acp';
|
|
20
|
+
}>;
|
|
21
|
+
getAvailableProviderInfos?: () => Array<{
|
|
22
|
+
type: string;
|
|
23
|
+
icon?: string;
|
|
24
|
+
displayName?: string;
|
|
25
|
+
category: 'ide' | 'extension' | 'cli' | 'acp';
|
|
26
|
+
installed?: boolean;
|
|
27
|
+
detectedPath?: string | null;
|
|
28
|
+
}>;
|
|
29
|
+
};
|
|
30
|
+
detectedIdes: Array<{
|
|
31
|
+
id: string;
|
|
32
|
+
name?: string;
|
|
33
|
+
displayName?: string;
|
|
34
|
+
installed?: boolean;
|
|
35
|
+
path?: string;
|
|
36
|
+
}>;
|
|
37
|
+
instanceId: string;
|
|
38
|
+
version: string;
|
|
39
|
+
daemonMode: boolean;
|
|
40
|
+
timestamp?: number;
|
|
41
|
+
p2p?: StatusReportPayload['p2p'];
|
|
42
|
+
machineNickname?: string | null;
|
|
43
|
+
}
|
|
44
|
+
export interface StatusSnapshot extends StatusReportPayload {
|
|
45
|
+
availableProviders: AvailableProviderInfo[];
|
|
46
|
+
}
|
|
47
|
+
export declare function getSessionCompletionMarker(session: {
|
|
48
|
+
activeChat?: {
|
|
49
|
+
messages?: Array<{
|
|
50
|
+
role?: string;
|
|
51
|
+
id?: string;
|
|
52
|
+
index?: number;
|
|
53
|
+
receivedAt?: number | string;
|
|
54
|
+
_turnKey?: string;
|
|
55
|
+
}> | null;
|
|
56
|
+
} | null;
|
|
57
|
+
}): string;
|
|
58
|
+
export declare function buildStatusSnapshot(options: StatusSnapshotOptions): StatusSnapshot;
|
package/src/status/snapshot.ts
CHANGED
|
@@ -15,11 +15,12 @@ import { getHostMemorySnapshot } from '../system/host-memory.js';
|
|
|
15
15
|
import { getTerminalBackendRuntimeStatus } from '../cli-adapters/terminal-screen.js';
|
|
16
16
|
import { LOG } from '../logging/logger.js';
|
|
17
17
|
import type { DaemonCdpManager } from '../cdp/manager.js';
|
|
18
|
-
import { buildSessionEntries, isCdpConnected } from './builders.js';
|
|
18
|
+
import { buildSessionEntries, isCdpConnected, type SessionEntryProfile } from './builders.js';
|
|
19
19
|
import type { ProviderState } from '../providers/provider-instance.js';
|
|
20
20
|
import type {
|
|
21
21
|
AvailableProviderInfo,
|
|
22
22
|
DetectedIdeInfo,
|
|
23
|
+
MachineInfo,
|
|
23
24
|
RecentLaunchEntry,
|
|
24
25
|
RecentSessionBucket,
|
|
25
26
|
SessionEntry,
|
|
@@ -54,15 +55,13 @@ export interface StatusSnapshotOptions {
|
|
|
54
55
|
}>;
|
|
55
56
|
instanceId: string;
|
|
56
57
|
version: string;
|
|
57
|
-
daemonMode: boolean;
|
|
58
58
|
timestamp?: number;
|
|
59
59
|
p2p?: StatusReportPayload['p2p'];
|
|
60
60
|
machineNickname?: string | null;
|
|
61
|
+
profile?: SessionEntryProfile;
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
export
|
|
64
|
-
availableProviders: AvailableProviderInfo[];
|
|
65
|
-
}
|
|
64
|
+
export type StatusSnapshot = StatusReportPayload;
|
|
66
65
|
|
|
67
66
|
const READ_DEBUG_ENABLED = process.argv.includes('--dev') || process.env.ADHDEV_READ_DEBUG === '1';
|
|
68
67
|
|
|
@@ -103,6 +102,41 @@ function buildAvailableProviders(
|
|
|
103
102
|
}));
|
|
104
103
|
}
|
|
105
104
|
|
|
105
|
+
export function buildMachineInfo(profile: 'full' | 'live' | 'metadata' = 'full'): MachineInfo {
|
|
106
|
+
const base: MachineInfo = {
|
|
107
|
+
hostname: os.hostname(),
|
|
108
|
+
platform: os.platform(),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (profile === 'live') {
|
|
112
|
+
return base;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (profile === 'metadata') {
|
|
116
|
+
const memSnap = getHostMemorySnapshot();
|
|
117
|
+
return {
|
|
118
|
+
...base,
|
|
119
|
+
arch: os.arch(),
|
|
120
|
+
cpus: os.cpus().length,
|
|
121
|
+
totalMem: memSnap.totalMem,
|
|
122
|
+
release: os.release(),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const memSnap = getHostMemorySnapshot();
|
|
127
|
+
return {
|
|
128
|
+
...base,
|
|
129
|
+
arch: os.arch(),
|
|
130
|
+
cpus: os.cpus().length,
|
|
131
|
+
totalMem: memSnap.totalMem,
|
|
132
|
+
freeMem: memSnap.freeMem,
|
|
133
|
+
availableMem: memSnap.availableMem,
|
|
134
|
+
loadavg: os.loadavg(),
|
|
135
|
+
uptime: os.uptime(),
|
|
136
|
+
release: os.release(),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
106
140
|
function parseMessageTime(value: unknown): number {
|
|
107
141
|
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
108
142
|
if (typeof value === 'string') {
|
|
@@ -207,28 +241,39 @@ function buildRecentLaunches(
|
|
|
207
241
|
}
|
|
208
242
|
|
|
209
243
|
export function buildStatusSnapshot(options: StatusSnapshotOptions): StatusSnapshot {
|
|
244
|
+
const profile = options.profile || 'full';
|
|
210
245
|
const cfg = loadConfig();
|
|
211
246
|
const state = loadState();
|
|
212
247
|
const wsState = getWorkspaceState(cfg);
|
|
213
|
-
const memSnap = getHostMemorySnapshot();
|
|
214
248
|
const recentActivity = getRecentActivity(state, 20);
|
|
215
|
-
const
|
|
249
|
+
const unreadSourceSessions = buildSessionEntries(
|
|
216
250
|
options.allStates,
|
|
217
251
|
options.cdpManagers,
|
|
252
|
+
{ profile: 'full' },
|
|
218
253
|
);
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
254
|
+
const sessions = profile === 'full'
|
|
255
|
+
? unreadSourceSessions
|
|
256
|
+
: buildSessionEntries(
|
|
257
|
+
options.allStates,
|
|
258
|
+
options.cdpManagers,
|
|
259
|
+
{ profile },
|
|
260
|
+
);
|
|
261
|
+
const sessionsById = new Map(sessions.map((session) => [session.id, session]));
|
|
262
|
+
for (const sourceSession of unreadSourceSessions) {
|
|
263
|
+
const session = sessionsById.get(sourceSession.id);
|
|
264
|
+
if (!session) continue;
|
|
265
|
+
const lastSeenAt = getSessionSeenAt(state, sourceSession.id);
|
|
266
|
+
const seenCompletionMarker = getSessionSeenMarker(state, sourceSession.id);
|
|
267
|
+
const lastUsedAt = getSessionLastUsedAt(sourceSession);
|
|
268
|
+
const completionMarker = getSessionCompletionMarker(sourceSession);
|
|
269
|
+
const { unread, inboxBucket } = sourceSession.surfaceHidden
|
|
225
270
|
? { unread: false, inboxBucket: 'idle' as RecentSessionBucket }
|
|
226
271
|
: getUnreadState(
|
|
227
|
-
getSessionMessageUpdatedAt(
|
|
228
|
-
|
|
272
|
+
getSessionMessageUpdatedAt(sourceSession) > 0,
|
|
273
|
+
sourceSession.status,
|
|
229
274
|
lastUsedAt,
|
|
230
275
|
lastSeenAt,
|
|
231
|
-
getLastMessageRole(
|
|
276
|
+
getLastMessageRole(sourceSession),
|
|
232
277
|
completionMarker,
|
|
233
278
|
seenCompletionMarker,
|
|
234
279
|
);
|
|
@@ -238,39 +283,32 @@ export function buildStatusSnapshot(options: StatusSnapshotOptions): StatusSnaps
|
|
|
238
283
|
if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== 'idle' || session.providerType.includes('codex'))) {
|
|
239
284
|
LOG.info(
|
|
240
285
|
'RecentRead',
|
|
241
|
-
`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(
|
|
286
|
+
`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(sourceSession)} msgUpdatedAt=${getSessionMessageUpdatedAt(sourceSession)}`,
|
|
242
287
|
);
|
|
243
288
|
}
|
|
244
289
|
}
|
|
245
|
-
const
|
|
290
|
+
const includeMachineMetadata = profile !== 'live';
|
|
291
|
+
const terminalBackend = includeMachineMetadata
|
|
292
|
+
? getTerminalBackendRuntimeStatus()
|
|
293
|
+
: undefined;
|
|
246
294
|
|
|
247
295
|
return {
|
|
248
296
|
instanceId: options.instanceId,
|
|
249
|
-
version: options.version,
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
hostname: os.hostname(),
|
|
253
|
-
platform: os.platform(),
|
|
254
|
-
arch: os.arch(),
|
|
255
|
-
cpus: os.cpus().length,
|
|
256
|
-
totalMem: memSnap.totalMem,
|
|
257
|
-
freeMem: memSnap.freeMem,
|
|
258
|
-
availableMem: memSnap.availableMem,
|
|
259
|
-
loadavg: os.loadavg(),
|
|
260
|
-
uptime: os.uptime(),
|
|
261
|
-
release: os.release(),
|
|
262
|
-
},
|
|
263
|
-
machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
|
|
297
|
+
...(includeMachineMetadata ? { version: options.version } : {}),
|
|
298
|
+
machine: buildMachineInfo(profile),
|
|
299
|
+
...(includeMachineMetadata ? { machineNickname: options.machineNickname ?? cfg.machineNickname ?? null } : {}),
|
|
264
300
|
timestamp: options.timestamp ?? Date.now(),
|
|
265
|
-
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
266
301
|
...(options.p2p ? { p2p: options.p2p } : {}),
|
|
267
302
|
sessions,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
303
|
+
...(terminalBackend ? { terminalBackend } : {}),
|
|
304
|
+
...(includeMachineMetadata && {
|
|
305
|
+
detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
|
|
306
|
+
workspaces: wsState.workspaces,
|
|
307
|
+
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
308
|
+
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
309
|
+
terminalSizingMode: cfg.terminalSizingMode || 'measured',
|
|
310
|
+
recentLaunches: buildRecentLaunches(recentActivity),
|
|
311
|
+
availableProviders: buildAvailableProviders(options.providerLoader),
|
|
312
|
+
}),
|
|
275
313
|
};
|
|
276
314
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host memory metrics — macOS-aware "available" memory.
|
|
3
|
+
*
|
|
4
|
+
* Node's os.freemem() on darwin reports only the tiny truly-free pool; most RAM
|
|
5
|
+
* sits in inactive/file-backed cache that the OS can reclaim. Dashboard "used %"
|
|
6
|
+
* based on (total - freemem) looks ~99% almost always — misleading.
|
|
7
|
+
*
|
|
8
|
+
* On macOS we parse `vm_stat` and approximate available bytes as:
|
|
9
|
+
* (free + inactive + speculative + purgeable [+ file_backed]) × page size
|
|
10
|
+
* (aligned with common Activity Monitor–style interpretations.)
|
|
11
|
+
*/
|
|
12
|
+
export interface HostMemorySnapshot {
|
|
13
|
+
totalMem: number;
|
|
14
|
+
/** Raw kernel "free" — small on macOS; kept for debugging / API compat */
|
|
15
|
+
freeMem: number;
|
|
16
|
+
/** Use this for UI "used %" — on darwin from vm_stat; else equals freeMem */
|
|
17
|
+
availableMem: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function getHostMemorySnapshot(): HostMemorySnapshot;
|
package/src/types.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Shared types referenced by daemon-core, daemon-standalone, and web-core.
|
|
5
5
|
* When modifying this file, also update interface contracts in AGENT_PROTOCOL.md.
|
|
6
6
|
*/
|
|
7
|
-
import type { StatusReportPayload } from './shared-types.js';
|
|
7
|
+
import type { StatusReportPayload, AvailableProviderInfo } from './shared-types.js';
|
|
8
8
|
/** Full status response from /api/v1/status and WS events */
|
|
9
9
|
export interface StatusResponse extends StatusReportPayload {
|
|
10
10
|
/** For standalone API compat */
|
|
@@ -15,7 +15,7 @@ export interface StatusResponse extends StatusReportPayload {
|
|
|
15
15
|
/** User display name from config */
|
|
16
16
|
userName?: string;
|
|
17
17
|
/** Available providers */
|
|
18
|
-
availableProviders:
|
|
18
|
+
availableProviders: AvailableProviderInfo[];
|
|
19
19
|
/** System info (legacy compat) */
|
|
20
20
|
system?: SystemInfo;
|
|
21
21
|
}
|
|
@@ -111,11 +111,7 @@ export interface DetectedIde {
|
|
|
111
111
|
installed: boolean;
|
|
112
112
|
running: boolean;
|
|
113
113
|
}
|
|
114
|
-
export interface ProviderInfo {
|
|
115
|
-
type: string;
|
|
116
|
-
icon: string;
|
|
117
|
-
displayName: string;
|
|
118
|
-
category: string;
|
|
114
|
+
export interface ProviderInfo extends AvailableProviderInfo {
|
|
119
115
|
}
|
|
120
116
|
/** Flattened agent entry from /api/v1/agents */
|
|
121
117
|
export interface AgentEntry {
|
package/src/types.ts
CHANGED
|
@@ -18,7 +18,7 @@ export interface StatusResponse extends StatusReportPayload {
|
|
|
18
18
|
/** User display name from config */
|
|
19
19
|
userName?: string;
|
|
20
20
|
/** Available providers */
|
|
21
|
-
availableProviders
|
|
21
|
+
availableProviders?: AvailableProviderInfo[];
|
|
22
22
|
/** System info (legacy compat) */
|
|
23
23
|
system?: SystemInfo;
|
|
24
24
|
}
|