@adhdev/daemon-core 0.7.38 → 0.7.40

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.
Files changed (95) hide show
  1. package/dist/agent-stream/forward.d.ts +8 -0
  2. package/dist/agent-stream/index.d.ts +6 -0
  3. package/dist/agent-stream/manager.d.ts +59 -0
  4. package/dist/agent-stream/poller.d.ts +41 -0
  5. package/dist/agent-stream/provider-adapter.d.ts +29 -0
  6. package/dist/agent-stream/types.d.ts +62 -0
  7. package/dist/boot/daemon-lifecycle.d.ts +97 -0
  8. package/dist/cdp/devtools.d.ts +51 -0
  9. package/dist/cdp/initializer.d.ts +50 -0
  10. package/dist/cdp/manager.d.ts +145 -0
  11. package/dist/cdp/scanner.d.ts +58 -0
  12. package/dist/cdp/setup.d.ts +58 -0
  13. package/dist/cli-adapter-types.d.ts +25 -0
  14. package/dist/cli-adapters/provider-cli-adapter.d.ts +229 -0
  15. package/dist/cli-adapters/pty-transport.d.ts +43 -0
  16. package/dist/cli-adapters/session-host-transport.d.ts +19 -0
  17. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +12 -0
  18. package/dist/cli-adapters/terminal-backends/types.d.ts +14 -0
  19. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +13 -0
  20. package/dist/cli-adapters/terminal-screen.d.ts +27 -0
  21. package/dist/commands/cdp-commands.d.ts +15 -0
  22. package/dist/commands/chat-commands.d.ts +15 -0
  23. package/dist/commands/cli-manager.d.ts +82 -0
  24. package/dist/commands/handler.d.ts +101 -0
  25. package/dist/commands/router.d.ts +69 -0
  26. package/dist/commands/stream-commands.d.ts +13 -0
  27. package/dist/commands/workspace-commands.d.ts +11 -0
  28. package/dist/config/chat-history.d.ts +60 -0
  29. package/dist/config/config.d.ts +103 -0
  30. package/dist/config/recent-activity.d.ts +27 -0
  31. package/dist/config/workspaces.d.ts +82 -0
  32. package/dist/daemon/dev-auto-implement.d.ts +26 -0
  33. package/dist/daemon/dev-cdp-handlers.d.ts +22 -0
  34. package/dist/daemon/dev-cli-debug.d.ts +24 -0
  35. package/dist/daemon/dev-server-types.d.ts +43 -0
  36. package/dist/daemon/dev-server.d.ts +133 -0
  37. package/dist/daemon/scaffold-template.d.ts +32 -0
  38. package/dist/daemon-core.d.ts +36 -0
  39. package/dist/detection/cli-detector.d.ts +27 -0
  40. package/dist/detection/ide-detector.d.ts +34 -0
  41. package/dist/index.d.ts +72 -2499
  42. package/dist/index.js +673 -879
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +680 -884
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/installer.d.ts +50 -0
  47. package/dist/ipc-protocol.d.ts +111 -0
  48. package/dist/launch.d.ts +46 -0
  49. package/dist/logging/command-log.d.ts +31 -0
  50. package/dist/logging/logger.d.ts +87 -0
  51. package/dist/providers/acp-provider-instance.d.ts +101 -0
  52. package/dist/providers/cli-provider-instance.d.ts +43 -0
  53. package/dist/providers/contracts.d.ts +483 -0
  54. package/dist/providers/extension-provider-instance.d.ts +44 -0
  55. package/dist/providers/ide-provider-instance.d.ts +61 -0
  56. package/dist/providers/index.d.ts +5 -0
  57. package/dist/providers/provider-instance-manager.d.ts +84 -0
  58. package/dist/providers/provider-instance.d.ts +148 -0
  59. package/dist/providers/provider-loader.d.ts +270 -0
  60. package/dist/providers/status-monitor.d.ts +48 -0
  61. package/dist/providers/version-archive.d.ts +52 -0
  62. package/dist/session-host/runtime-support.d.ts +8 -0
  63. package/dist/sessions/registry.d.ts +24 -0
  64. package/dist/shared-types-extra.d.ts +29 -0
  65. package/dist/shared-types.d.ts +205 -0
  66. package/dist/status/builders.d.ts +33 -0
  67. package/dist/status/normalize.d.ts +14 -1
  68. package/dist/status/reporter.d.ts +69 -0
  69. package/dist/status/snapshot.d.ts +51 -0
  70. package/dist/system/host-memory.d.ts +19 -0
  71. package/dist/types.d.ts +123 -0
  72. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  73. package/package.json +3 -2
  74. package/src/commands/cli-manager.ts +1 -26
  75. package/src/commands/handler.ts +0 -31
  76. package/src/commands/router.ts +27 -34
  77. package/src/commands/stream-commands.ts +2 -4
  78. package/src/commands/workspace-commands.ts +9 -23
  79. package/src/config/config.ts +7 -81
  80. package/src/config/recent-activity.ts +24 -12
  81. package/src/config/workspaces.ts +0 -24
  82. package/src/index.ts +16 -15
  83. package/src/providers/provider-loader.ts +13 -5
  84. package/src/shared-types-extra.ts +34 -0
  85. package/src/shared-types.d.ts +4 -6
  86. package/src/shared-types.ts +17 -38
  87. package/src/status/builders.ts +12 -0
  88. package/src/status/reporter.ts +2 -1
  89. package/src/status/snapshot.ts +70 -87
  90. package/src/types.ts +3 -8
  91. package/dist/index.d.mts +0 -2504
  92. package/dist/normalize-DVI4Lo5I.d.mts +0 -947
  93. package/dist/normalize-DVI4Lo5I.d.ts +0 -947
  94. package/dist/status/normalize.d.mts +0 -1
  95. package/src/config/workspace-activity.ts +0 -65
@@ -18,14 +18,14 @@ import type { ProviderInstanceManager } from '../providers/provider-instance-man
18
18
  import { launchWithCdp, killIdeProcess, isIdeRunning } from '../launch.js';
19
19
  import { loadConfig, saveConfig, updateConfig } from '../config/config.js';
20
20
  import { resolveIdeLaunchWorkspace } from '../config/workspaces.js';
21
- import { appendWorkspaceActivity } from '../config/workspace-activity.js';
22
- import { addCliHistory } from '../config/config.js';
23
- import { appendRecentActivity, buildRecentActivityKey, markRecentSessionSeen } from '../config/recent-activity.js';
21
+ import { appendRecentActivity, markSessionSeen } from '../config/recent-activity.js';
24
22
  import { detectIDEs } from '../detection/ide-detector.js';
25
23
  import { SessionRegistry } from '../sessions/registry.js';
26
24
  import { LOG } from '../logging/logger.js';
27
25
  import { logCommand } from '../logging/command-log.js';
28
26
  import { getRecentLogs, LOG_PATH } from '../logging/logger.js';
27
+ import { buildSessionEntries } from '../status/builders.js';
28
+ import { getSessionCompletionMarker } from '../status/snapshot.js';
29
29
  import * as fs from 'fs';
30
30
 
31
31
  // ─── Types ───
@@ -63,6 +63,7 @@ const CHAT_COMMANDS = [
63
63
  'send_chat', 'new_chat', 'switch_chat', 'set_mode',
64
64
  'change_model',
65
65
  ];
66
+ const READ_DEBUG_ENABLED = process.argv.includes('--dev') || process.env.ADHDEV_READ_DEBUG === '1';
66
67
 
67
68
  export class DaemonCommandRouter {
68
69
  private deps: CommandRouterDeps;
@@ -208,17 +209,6 @@ export class DaemonCommandRouter {
208
209
  };
209
210
  LOG.info('LaunchIDE', `target=${ideKey || 'auto'}`);
210
211
  const result = await launchWithCdp(launchArgs);
211
- if (result.success && (result.ideId || ideKey)) {
212
- try {
213
- addCliHistory({
214
- category: 'ide',
215
- cliType: result.ideId || ideKey,
216
- dir: resolvedWorkspace || '',
217
- workspace: resolvedWorkspace || '',
218
- newWindow: args?.newWindow === true,
219
- });
220
- } catch { /* ignore history failure */ }
221
- }
222
212
 
223
213
  if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
224
214
  const logFn = this.deps.getCdpLogFn
@@ -241,11 +231,7 @@ export class DaemonCommandRouter {
241
231
  this.deps.onIdeConnected?.();
242
232
  if (result.success && resolvedWorkspace) {
243
233
  try {
244
- let next = appendWorkspaceActivity(loadConfig(), resolvedWorkspace, {
245
- kind: 'ide',
246
- agentType: result.ideId,
247
- });
248
- next = appendRecentActivity(next, {
234
+ const next = appendRecentActivity(loadConfig(), {
249
235
  kind: 'ide',
250
236
  providerType: result.ideId || ideKey,
251
237
  providerName: result.ideId || ideKey,
@@ -282,28 +268,35 @@ export class DaemonCommandRouter {
282
268
  return { success: true, userName: name };
283
269
  }
284
270
 
285
- case 'mark_recent_seen': {
286
- const kind = args?.kind;
287
- const providerType = args?.providerType;
288
- if (!kind || !providerType) {
289
- return { success: false, error: 'kind and providerType are required' };
271
+ case 'mark_session_seen': {
272
+ const sessionId = args?.sessionId;
273
+ if (!sessionId || typeof sessionId !== 'string') {
274
+ return { success: false, error: 'sessionId is required' };
290
275
  }
291
- const recentKey = args?.recentKey || buildRecentActivityKey({
292
- kind,
293
- providerType,
294
- workspace: args?.workspace || null,
295
- });
296
- const next = markRecentSessionSeen(
297
- loadConfig(),
298
- recentKey,
276
+ const currentConfig = loadConfig();
277
+ const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
278
+ const sessionEntries = buildSessionEntries(
279
+ this.deps.instanceManager.collectAllStates(),
280
+ this.deps.cdpManagers as Map<string, any>,
281
+ );
282
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
283
+ const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : '';
284
+ const next = markSessionSeen(
285
+ currentConfig,
286
+ sessionId,
299
287
  typeof args?.seenAt === 'number' ? args.seenAt : Date.now(),
288
+ completionMarker,
300
289
  );
290
+ if (READ_DEBUG_ENABLED) {
291
+ LOG.info('RecentRead', `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || '')} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || '-'}`);
292
+ }
301
293
  saveConfig(next);
302
294
  this.deps.onStatusChange?.();
303
295
  return {
304
296
  success: true,
305
- recentKey,
306
- seenAt: next.recentSessionReads?.[recentKey] || Date.now(),
297
+ sessionId,
298
+ seenAt: next.sessionReads?.[sessionId] || Date.now(),
299
+ completionMarker,
307
300
  };
308
301
  }
309
302
 
@@ -5,7 +5,6 @@
5
5
 
6
6
  import type { CommandResult, CommandHelpers } from './handler.js';
7
7
  import type { ProviderLoader } from '../providers/provider-loader.js';
8
- import { loadConfig } from '../config/config.js';
9
8
  import { LOG } from '../logging/logger.js';
10
9
 
11
10
  export async function handleFocusSession(h: CommandHelpers, args: any): Promise<CommandResult> {
@@ -193,14 +192,13 @@ export function handleGetIdeExtensions(h: CommandHelpers, args: any): CommandRes
193
192
  if (!loader) return { success: false, error: 'ProviderLoader not initialized' };
194
193
 
195
194
  const allExtProviders = loader.getByCategory?.('extension') || [];
196
- const config = loadConfig();
197
195
 
198
196
  if (ideType) {
199
197
  const extensions = allExtProviders.map(p => ({
200
198
  type: p.type,
201
199
  name: p.name,
202
200
  extensionId: p.extensionId,
203
- enabled: config.ideSettings?.[ideType]?.extensions?.[p.type]?.enabled === true,
201
+ enabled: loader.getIdeExtensionEnabledState?.(ideType, p.type) === true,
204
202
  }));
205
203
  return { success: true, ideType, extensions };
206
204
  }
@@ -212,7 +210,7 @@ export function handleGetIdeExtensions(h: CommandHelpers, args: any): CommandRes
212
210
  type: p.type,
213
211
  name: p.name,
214
212
  extensionId: p.extensionId,
215
- enabled: config.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true,
213
+ enabled: loader.getIdeExtensionEnabledState?.(ide, p.type) === true,
216
214
  }));
217
215
  }
218
216
  return { success: true, ideExtensions: result };
@@ -4,7 +4,6 @@
4
4
 
5
5
  import { loadConfig, saveConfig } from '../config/config.js';
6
6
  import * as W from '../config/workspaces.js';
7
- import { appendWorkspaceActivity, getWorkspaceActivity, removeActivityForPath } from '../config/workspace-activity.js';
8
7
 
9
8
  export type WorkspaceCommandResult = { success: boolean;[key: string]: unknown };
10
9
 
@@ -16,8 +15,6 @@ export function handleWorkspaceList(): WorkspaceCommandResult {
16
15
  workspaces: state.workspaces,
17
16
  defaultWorkspaceId: state.defaultWorkspaceId,
18
17
  defaultWorkspacePath: state.defaultWorkspacePath,
19
- legacyRecentPaths: config.recentCliWorkspaces || [],
20
- activity: getWorkspaceActivity(config, 25),
21
18
  };
22
19
  }
23
20
 
@@ -31,10 +28,9 @@ export function handleWorkspaceAdd(args: any): WorkspaceCommandResult {
31
28
  const result = W.addWorkspaceEntry(config, rawPath, label, { createIfMissing });
32
29
  if ('error' in result) return { success: false, error: result.error };
33
30
 
34
- let cfg = appendWorkspaceActivity(result.config, result.entry.path, {});
35
- saveConfig(cfg);
36
- const state = W.getWorkspaceState(cfg);
37
- return { success: true, entry: result.entry, ...state, activity: getWorkspaceActivity(cfg, 25) };
31
+ saveConfig(result.config);
32
+ const state = W.getWorkspaceState(result.config);
33
+ return { success: true, entry: result.entry, ...state };
38
34
  }
39
35
 
40
36
  export function handleWorkspaceRemove(args: any): WorkspaceCommandResult {
@@ -46,13 +42,9 @@ export function handleWorkspaceRemove(args: any): WorkspaceCommandResult {
46
42
  const result = W.removeWorkspaceEntry(config, id);
47
43
  if ('error' in result) return { success: false, error: result.error };
48
44
 
49
- let cfg = result.config;
50
- if (removed) {
51
- cfg = removeActivityForPath(cfg, removed.path);
52
- }
53
- saveConfig(cfg);
54
- const state = W.getWorkspaceState(cfg);
55
- return { success: true, removedId: id, ...state, activity: getWorkspaceActivity(cfg, 25) };
45
+ saveConfig(result.config);
46
+ const state = W.getWorkspaceState(result.config);
47
+ return { success: true, removedId: id, ...state };
56
48
  }
57
49
 
58
50
  export function handleWorkspaceSetDefault(args: any): WorkspaceCommandResult {
@@ -66,7 +58,6 @@ export function handleWorkspaceSetDefault(args: any): WorkspaceCommandResult {
66
58
  return {
67
59
  success: true,
68
60
  ...state,
69
- activity: getWorkspaceActivity(result.config, 25),
70
61
  };
71
62
  }
72
63
 
@@ -98,12 +89,7 @@ export function handleWorkspaceSetDefault(args: any): WorkspaceCommandResult {
98
89
  const result = W.setDefaultWorkspaceId(config, nextId);
99
90
  if ('error' in result) return { success: false, error: result.error };
100
91
 
101
- let out = result.config;
102
- const ap = W.getDefaultWorkspacePath(out);
103
- if (ap) {
104
- out = appendWorkspaceActivity(out, ap, { kind: 'default' });
105
- }
106
- saveConfig(out);
107
- const state = W.getWorkspaceState(out);
108
- return { success: true, ...state, activity: getWorkspaceActivity(out, 25) };
92
+ saveConfig(result.config);
93
+ const state = W.getWorkspaceState(result.config);
94
+ return { success: true, ...state };
109
95
  }
@@ -8,12 +8,9 @@ import { homedir } from 'os';
8
8
  import { join } from 'path';
9
9
  import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from 'fs';
10
10
  import { randomUUID } from 'crypto';
11
- import { migrateWorkspacesFromRecent } from './workspaces.js';
12
11
  import type { WorkspaceEntry } from './workspaces.js';
13
- import type { WorkspaceActivityEntry } from './workspace-activity.js';
14
12
  import type { RecentActivityEntry } from './recent-activity.js';
15
13
  export type { WorkspaceEntry } from './workspaces.js';
16
- export type { WorkspaceActivityEntry } from './workspace-activity.js';
17
14
  export type { RecentActivityEntry } from './recent-activity.js';
18
15
 
19
16
  export interface ADHDevConfig {
@@ -54,19 +51,18 @@ export interface ADHDevConfig {
54
51
 
55
52
  // Daemon: which IDEs to connect (empty = all)
56
53
  enabledIdes: string[];
57
- recentCliWorkspaces: string[];
58
54
 
59
55
  /** Saved workspaces for IDE/CLI/ACP launch (daemon-local) */
60
56
  workspaces?: WorkspaceEntry[];
61
57
  /** Default workspace id (from workspaces[]) — never used implicitly for launch */
62
58
  defaultWorkspaceId?: string | null;
63
59
 
64
- /** Recently used workspaces (IDE / CLI / ACP / default) for quick resume */
65
- recentWorkspaceActivity?: WorkspaceActivityEntry[];
66
60
  /** Unified recent activity across IDE / CLI / ACP launch flows */
67
61
  recentActivity?: RecentActivityEntry[];
68
- /** Last seen timestamps for machine-facing recent/session entries */
69
- recentSessionReads?: Record<string, number>;
62
+ /** Last seen timestamps for live sessions, keyed by sessionId */
63
+ sessionReads?: Record<string, number>;
64
+ /** Last seen completion marker for live sessions, keyed by sessionId */
65
+ sessionReadMarkers?: Record<string, string>;
70
66
 
71
67
  // Machine nickname (user-customizable label for this machine)
72
68
  machineNickname: string | null;
@@ -94,9 +90,6 @@ export interface ADHDevConfig {
94
90
  */
95
91
  registeredMachineId?: string;
96
92
 
97
- // CLI launch history
98
- cliHistory: CliHistoryEntry[];
99
-
100
93
  // Per-provider user config (public setting values)
101
94
  providerSettings: Record<string, Record<string, any>>;
102
95
 
@@ -113,18 +106,6 @@ export interface ADHDevConfig {
113
106
  providerDir?: string;
114
107
  }
115
108
 
116
- export interface CliHistoryEntry {
117
- category?: 'ide' | 'cli' | 'acp';
118
- cliType: string;
119
- dir: string;
120
- cliArgs?: string[];
121
- workspace?: string;
122
- newWindow?: boolean;
123
- model?: string;
124
- timestamp: number;
125
- label?: string;
126
- }
127
-
128
109
  const DEFAULT_CONFIG: ADHDevConfig = {
129
110
  serverUrl: 'https://api.adhf.dev',
130
111
  apiToken: null,
@@ -140,17 +121,15 @@ const DEFAULT_CONFIG: ADHDevConfig = {
140
121
  setupDate: null,
141
122
  configuredCLIs: [],
142
123
  enabledIdes: [],
143
- recentCliWorkspaces: [],
144
124
  workspaces: [],
145
125
  defaultWorkspaceId: null,
146
- recentWorkspaceActivity: [],
147
126
  recentActivity: [],
148
- recentSessionReads: {},
127
+ sessionReads: {},
128
+ sessionReadMarkers: {},
149
129
  machineNickname: null,
150
130
  machineId: undefined,
151
131
  machineSecret: null,
152
132
  registeredMachineId: undefined,
153
- cliHistory: [],
154
133
  providerSettings: {},
155
134
  ideSettings: {},
156
135
  disableUpstream: false,
@@ -227,18 +206,9 @@ export function loadConfig(): ADHDevConfig {
227
206
  (merged as ADHDevConfig).defaultWorkspaceId = merged.activeWorkspaceId;
228
207
  }
229
208
  delete (merged as any).activeWorkspaceId;
230
- const hadStoredWorkspaces = Array.isArray(parsed.workspaces) && parsed.workspaces.length > 0;
231
209
  const ensured = ensureMachineId(merged);
232
210
  const normalized = ensured.config as ADHDevConfig & { activeWorkspaceId?: string | null };
233
- migrateWorkspacesFromRecent(normalized);
234
-
235
- let configChanged = ensured.changed;
236
-
237
- if (!hadStoredWorkspaces && (normalized.workspaces?.length || 0) > 0) {
238
- configChanged = true;
239
- }
240
-
241
- if (configChanged) {
211
+ if (ensured.changed) {
242
212
  try {
243
213
  saveConfig(normalized);
244
214
  } catch { /* ignore */ }
@@ -318,47 +288,3 @@ export function generateConnectionToken(): string {
318
288
  }
319
289
  return token;
320
290
  }
321
- /**
322
- * Add launch to history (max 20, dedup by category+type+dir+args+workspace+model)
323
- */
324
- export function addCliHistory(entry: Omit<CliHistoryEntry, 'timestamp'>): void {
325
- const config = loadConfig();
326
- const history = config.cliHistory || [];
327
- const argsKey = (entry.cliArgs || []).join(' ');
328
- const category = entry.category || 'cli';
329
- const workspaceKey = entry.workspace || '';
330
- const modelKey = entry.model || '';
331
-
332
- // Remove duplicate (same category + type + dir + args + workspace + model)
333
- const filtered = history.filter(h => {
334
- const hArgsKey = (h.cliArgs || []).join(' ');
335
- return !(
336
- (h.category || 'cli') === category &&
337
- h.cliType === entry.cliType &&
338
- h.dir === entry.dir &&
339
- hArgsKey === argsKey &&
340
- (h.workspace || '') === workspaceKey &&
341
- (h.model || '') === modelKey
342
- );
343
- });
344
-
345
- // Add to front
346
- filtered.unshift({
347
- ...entry,
348
- category,
349
- timestamp: Date.now(),
350
- label: entry.label || (() => {
351
- const base = `${entry.cliType} · ${entry.dir.split('/').filter(Boolean).pop() || 'root'}`;
352
- const suffix: string[] = [];
353
- if (entry.workspace && entry.workspace !== entry.dir) suffix.push(entry.workspace.split('/').filter(Boolean).pop() || entry.workspace);
354
- if (entry.model) suffix.push(`model=${entry.model}`);
355
- if (argsKey) suffix.push(argsKey);
356
- if (entry.newWindow) suffix.push('new window');
357
- return suffix.length > 0 ? `${base} (${suffix.join(' · ')})` : base;
358
- })(),
359
- });
360
-
361
- // Keep max 20
362
- config.cliHistory = filtered.slice(0, 20);
363
- saveConfig(config);
364
- }
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Unified recent activity — machine-facing "pick up where you left off".
2
+ * Unified recent activity — launcher-facing "pick up where you launched".
3
3
  *
4
- * Unlike cliHistory or workspaceActivity, this is task/session oriented:
4
+ * Unlike live session state, this is launch oriented:
5
5
  * - one normalized row shape for IDE / CLI / ACP
6
6
  * - deduped by kind + providerType + workspace
7
- * - optionally linked to a live sessionId when known
7
+ * - used only for quick-launch shortcuts
8
8
  */
9
9
 
10
10
  import * as path from 'path';
@@ -18,7 +18,6 @@ export interface RecentActivityEntry {
18
18
  providerName: string;
19
19
  workspace?: string | null;
20
20
  currentModel?: string;
21
- sessionId?: string | null;
22
21
  title?: string;
23
22
  lastUsedAt: number;
24
23
  }
@@ -62,22 +61,35 @@ export function getRecentActivity(config: ADHDevConfig, limit = 20): RecentActiv
62
61
  .slice(0, limit);
63
62
  }
64
63
 
65
- export function getRecentSessionSeenAt(config: ADHDevConfig, recentKey: string): number {
66
- return config.recentSessionReads?.[recentKey] || 0;
64
+ export function getSessionSeenAt(config: ADHDevConfig, sessionId: string): number {
65
+ return config.sessionReads?.[sessionId] || 0;
67
66
  }
68
67
 
69
- export function markRecentSessionSeen(
68
+ export function getSessionSeenMarker(config: ADHDevConfig, sessionId: string): string {
69
+ return config.sessionReadMarkers?.[sessionId] || '';
70
+ }
71
+
72
+ export function markSessionSeen(
70
73
  config: ADHDevConfig,
71
- recentKey: string,
74
+ sessionId: string,
72
75
  seenAt = Date.now(),
76
+ completionMarker?: string | null,
73
77
  ): ADHDevConfig {
74
- const prev = config.recentSessionReads || {};
75
- const nextSeenAt = Math.max(prev[recentKey] || 0, seenAt);
78
+ const prev = config.sessionReads || {};
79
+ const nextSeenAt = Math.max(prev[sessionId] || 0, seenAt);
80
+ const prevMarkers = config.sessionReadMarkers || {};
81
+ const nextMarker = typeof completionMarker === 'string' ? completionMarker : '';
76
82
  return {
77
83
  ...config,
78
- recentSessionReads: {
84
+ sessionReads: {
79
85
  ...prev,
80
- [recentKey]: nextSeenAt,
86
+ [sessionId]: nextSeenAt,
81
87
  },
88
+ sessionReadMarkers: nextMarker
89
+ ? {
90
+ ...prevMarkers,
91
+ [sessionId]: nextMarker,
92
+ }
93
+ : prevMarkers,
82
94
  };
83
95
  }
@@ -42,30 +42,6 @@ export function defaultWorkspaceLabel(absPath: string): string {
42
42
  return base;
43
43
  }
44
44
 
45
- /**
46
- * Ensure config.workspaces exists; seed from recentCliWorkspaces once (same paths).
47
- */
48
- export function migrateWorkspacesFromRecent(config: ADHDevConfig): ADHDevConfig {
49
- if (!config.workspaces) config.workspaces = [];
50
- if (config.workspaces.length > 0) return config;
51
-
52
- const recent = config.recentCliWorkspaces || [];
53
- const now = Date.now();
54
- for (const raw of recent) {
55
- const abs = expandPath(raw);
56
- if (!abs || validateWorkspacePath(abs).ok !== true) continue;
57
- if (config.workspaces.some(w => path.resolve(w.path) === abs)) continue;
58
- config.workspaces.push({
59
- id: randomUUID(),
60
- path: abs,
61
- label: defaultWorkspaceLabel(abs),
62
- addedAt: now,
63
- });
64
- if (config.workspaces.length >= MAX_WORKSPACES) break;
65
- }
66
- return config;
67
- }
68
-
69
45
  export function getDefaultWorkspacePath(config: ADHDevConfig): string | null {
70
46
  const id = config.defaultWorkspaceId;
71
47
  if (!id) return null;
package/src/index.ts CHANGED
@@ -33,7 +33,6 @@ export type {
33
33
  MachineInfo,
34
34
  DetectedIdeInfo,
35
35
  WorkspaceEntry,
36
- WorkspaceActivity,
37
36
  ProviderStatus,
38
37
  ProviderErrorReason,
39
38
  ActiveChatData,
@@ -43,26 +42,28 @@ export type {
43
42
  ExtensionProviderState,
44
43
  } from './shared-types.js';
45
44
 
46
- export interface RecentSessionEntry {
47
- id: string;
48
- sessionId?: string | null;
49
- providerType: string;
50
- providerName: string;
51
- kind: 'ide' | 'cli' | 'acp';
52
- title: string;
53
- workspace?: string | null;
54
- currentModel?: string;
55
- status?: 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting' | 'panel_hidden' | 'not_monitored' | 'disconnected';
56
- lastUsedAt: number;
57
- }
45
+ // These types live in shared-types-extra.ts — imported directly because
46
+ // rollup-dts cannot resolve re-exports from shared-types.ts for them.
47
+ import type { RuntimeWriteOwner as _RuntimeWriteOwner } from './shared-types-extra.js';
48
+ import type { RuntimeAttachedClient as _RuntimeAttachedClient } from './shared-types-extra.js';
49
+ import type { RecentLaunchEntry as _RecentLaunchEntry } from './shared-types.js';
50
+ import type { TerminalBackendStatus as _TerminalBackendStatus } from './shared-types-extra.js';
51
+ export type RuntimeWriteOwner = _RuntimeWriteOwner;
52
+ export type RuntimeAttachedClient = _RuntimeAttachedClient;
53
+ export type RecentLaunchEntry = _RecentLaunchEntry;
54
+ export type TerminalBackendStatus = _TerminalBackendStatus;
55
+
56
+ // Type aliases — rollup-dts cannot bundle re-exported type aliases at all.
57
+ // Canonical definition lives in shared-types-extra.ts — keep these in sync.
58
+ export type SessionStatus = 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting' | 'panel_hidden' | 'not_monitored' | 'disconnected';
59
+ export type RecentSessionBucket = 'needs_attention' | 'working' | 'task_complete' | 'idle';
58
60
 
59
61
  // ── Core Interface ──
60
62
  export type { IDaemonCore, DaemonCoreOptions } from './daemon-core.js';
61
63
 
62
64
  // ── Config ──
63
- export { loadConfig, saveConfig, resetConfig, isSetupComplete, addCliHistory, markSetupComplete, updateConfig } from './config/config.js';
65
+ export { loadConfig, saveConfig, resetConfig, isSetupComplete, markSetupComplete, updateConfig } from './config/config.js';
64
66
  export { getWorkspaceState } from './config/workspaces.js';
65
- export { getWorkspaceActivity } from './config/workspace-activity.js';
66
67
  export { appendRecentActivity, getRecentActivity } from './config/recent-activity.js';
67
68
  export type { RecentActivityEntry } from './config/recent-activity.js';
68
69
 
@@ -284,16 +284,24 @@ export class ProviderLoader {
284
284
  isEnabled(type: string, ideType?: string): boolean {
285
285
  if (!ideType) return true;
286
286
  try {
287
- const { loadConfig } = require('../config/config.js');
288
- const config = loadConfig();
289
- const baseIdeType = ideType.split('_')[0];
290
- const val = config.ideSettings?.[baseIdeType]?.extensions?.[type]?.enabled;
291
- return val === true; // undefined → false (default inactive)
287
+ return this.getIdeExtensionEnabledState(ideType, type);
292
288
  } catch {
293
289
  return false;
294
290
  }
295
291
  }
296
292
 
293
+ /**
294
+ * Resolve per-IDE extension enabled state using the same normalization
295
+ * that runtime attach/remove uses.
296
+ */
297
+ getIdeExtensionEnabledState(ideType: string, extensionType: string): boolean {
298
+ const { loadConfig } = require('../config/config.js');
299
+ const config = loadConfig();
300
+ const baseIdeType = ideType.split('_')[0];
301
+ const val = config.ideSettings?.[baseIdeType]?.extensions?.[extensionType]?.enabled;
302
+ return val === true;
303
+ }
304
+
297
305
  /**
298
306
  * Save IDE extension enabled setting
299
307
  */
@@ -0,0 +1,34 @@
1
+ /**
2
+ * ADHDev Shared Types — Additional cross-package type definitions
3
+ *
4
+ * Extracted common sub-types previously inlined across multiple packages.
5
+ * Separated from shared-types.ts due to rollup-dts bundling constraints.
6
+ *
7
+ * IMPORTANT: This file must remain runtime-free (types only).
8
+ */
9
+
10
+ /** Runtime terminal write-owner descriptor */
11
+ export interface RuntimeWriteOwner {
12
+ clientId: string;
13
+ ownerType: 'agent' | 'user';
14
+ }
15
+
16
+ /** Runtime attached client descriptor */
17
+ export interface RuntimeAttachedClient {
18
+ clientId: string;
19
+ type: 'daemon' | 'web' | 'local-terminal';
20
+ readOnly: boolean;
21
+ }
22
+
23
+ /** Session status union (used by SessionEntry.status, legacy recent-launch metadata, etc.) */
24
+ export type SessionStatus = 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting' | 'panel_hidden' | 'not_monitored' | 'disconnected';
25
+
26
+ /** Inbox bucket categories for recent sessions */
27
+ export type RecentSessionBucket = 'needs_attention' | 'working' | 'task_complete' | 'idle';
28
+
29
+ /** Terminal backend status */
30
+ export interface TerminalBackendStatus {
31
+ backend: 'xterm' | 'ghostty-vt';
32
+ preference: 'auto' | 'xterm' | 'ghostty-vt';
33
+ ghosttyAvailable: boolean;
34
+ }
@@ -147,17 +147,15 @@ export interface WorkspaceActivity {
147
147
  kind?: string;
148
148
  agentType?: string;
149
149
  }
150
- export interface RecentSessionEntry {
150
+ export interface RecentLaunchEntry {
151
151
  id: string;
152
- sessionId?: string | null;
153
152
  providerType: string;
154
153
  providerName: string;
155
154
  kind: 'ide' | 'cli' | 'acp';
156
- title: string;
155
+ title?: string;
157
156
  workspace?: string | null;
158
157
  currentModel?: string;
159
- status?: SessionEntry['status'];
160
- lastUsedAt: number;
158
+ lastLaunchedAt: number;
161
159
  }
162
160
  export interface StatusReportPayload {
163
161
  /** Daemon instance ID */
@@ -188,5 +186,5 @@ export interface StatusReportPayload {
188
186
  defaultWorkspaceId?: string | null;
189
187
  defaultWorkspacePath?: string | null;
190
188
  workspaceActivity?: WorkspaceActivity[];
191
- recentSessions?: RecentSessionEntry[];
189
+ recentLaunches?: RecentLaunchEntry[];
192
190
  }