adhdev 0.7.40 → 0.7.42

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/index.js CHANGED
@@ -34,7 +34,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
34
34
  // ../../oss/packages/daemon-core/src/config/config.ts
35
35
  var config_exports = {};
36
36
  __export(config_exports, {
37
- generateConnectionToken: () => generateConnectionToken,
38
37
  generateMachineId: () => generateMachineId,
39
38
  getConfigDir: () => getConfigDir,
40
39
  isSetupComplete: () => isSetupComplete,
@@ -45,6 +44,57 @@ __export(config_exports, {
45
44
  saveConfig: () => saveConfig,
46
45
  updateConfig: () => updateConfig
47
46
  });
47
+ function isPlainObject(value) {
48
+ return !!value && typeof value === "object" && !Array.isArray(value);
49
+ }
50
+ function asStringArray(value) {
51
+ if (!Array.isArray(value)) return [];
52
+ return value.filter((item) => typeof item === "string");
53
+ }
54
+ function asNullableString(value) {
55
+ return typeof value === "string" ? value : null;
56
+ }
57
+ function asOptionalString(value) {
58
+ return typeof value === "string" && value.trim() ? value : void 0;
59
+ }
60
+ function asBoolean(value, fallback) {
61
+ return typeof value === "boolean" ? value : fallback;
62
+ }
63
+ function normalizeConfig(raw) {
64
+ const parsed = isPlainObject(raw) ? raw : {};
65
+ const legacySessionReads = isPlainObject(parsed.recentSessionReads) ? parsed.recentSessionReads : {};
66
+ const sessionReads = isPlainObject(parsed.sessionReads) ? parsed.sessionReads : {};
67
+ const mergedSessionReads = Object.fromEntries(
68
+ Object.entries({ ...legacySessionReads, ...sessionReads }).filter(([, value]) => typeof value === "number" && Number.isFinite(value))
69
+ );
70
+ const sessionReadMarkers = Object.fromEntries(
71
+ Object.entries(isPlainObject(parsed.sessionReadMarkers) ? parsed.sessionReadMarkers : {}).filter(([, value]) => typeof value === "string")
72
+ );
73
+ return {
74
+ serverUrl: typeof parsed.serverUrl === "string" && parsed.serverUrl.trim() ? parsed.serverUrl : DEFAULT_CONFIG.serverUrl,
75
+ selectedIde: asNullableString(parsed.selectedIde),
76
+ configuredIdes: asStringArray(parsed.configuredIdes),
77
+ installedExtensions: asStringArray(parsed.installedExtensions),
78
+ userEmail: asNullableString(parsed.userEmail),
79
+ userName: asNullableString(parsed.userName),
80
+ setupCompleted: asBoolean(parsed.setupCompleted, DEFAULT_CONFIG.setupCompleted),
81
+ setupDate: asNullableString(parsed.setupDate),
82
+ enabledIdes: asStringArray(parsed.enabledIdes),
83
+ workspaces: Array.isArray(parsed.workspaces) ? parsed.workspaces : [],
84
+ defaultWorkspaceId: asNullableString(parsed.defaultWorkspaceId) ?? asNullableString(parsed.activeWorkspaceId),
85
+ recentActivity: Array.isArray(parsed.recentActivity) ? parsed.recentActivity : [],
86
+ sessionReads: mergedSessionReads,
87
+ sessionReadMarkers,
88
+ machineNickname: asNullableString(parsed.machineNickname),
89
+ machineId: asOptionalString(parsed.machineId),
90
+ machineSecret: parsed.machineSecret === null ? null : asOptionalString(parsed.machineSecret),
91
+ registeredMachineId: asOptionalString(parsed.registeredMachineId),
92
+ providerSettings: isPlainObject(parsed.providerSettings) ? parsed.providerSettings : {},
93
+ ideSettings: isPlainObject(parsed.ideSettings) ? parsed.ideSettings : {},
94
+ disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
95
+ providerDir: asOptionalString(parsed.providerDir)
96
+ };
97
+ }
48
98
  function generateMachineId() {
49
99
  return `${MACHINE_ID_PREFIX}${(0, import_crypto.randomUUID)().replace(/-/g, "")}`;
50
100
  }
@@ -88,14 +138,10 @@ function loadConfig() {
88
138
  try {
89
139
  const raw = (0, import_fs.readFileSync)(configPath, "utf-8");
90
140
  const parsed = JSON.parse(raw);
91
- const merged = { ...DEFAULT_CONFIG, ...parsed };
92
- if (merged.defaultWorkspaceId == null && merged.activeWorkspaceId != null) {
93
- merged.defaultWorkspaceId = merged.activeWorkspaceId;
94
- }
95
- delete merged.activeWorkspaceId;
96
- const ensured = ensureMachineId(merged);
141
+ const normalizedInput = normalizeConfig(parsed);
142
+ const ensured = ensureMachineId(normalizedInput);
97
143
  const normalized = ensured.config;
98
- if (ensured.changed) {
144
+ if (ensured.changed || JSON.stringify(parsed) !== JSON.stringify(normalized)) {
99
145
  try {
100
146
  saveConfig(normalized);
101
147
  } catch {
@@ -110,10 +156,11 @@ function loadConfig() {
110
156
  function saveConfig(config2) {
111
157
  const configPath = getConfigPath();
112
158
  const dir = getConfigDir();
159
+ const normalized = normalizeConfig(config2);
113
160
  if (!(0, import_fs.existsSync)(dir)) {
114
161
  (0, import_fs.mkdirSync)(dir, { recursive: true, mode: 448 });
115
162
  }
116
- (0, import_fs.writeFileSync)(configPath, JSON.stringify(config2, null, 2), { encoding: "utf-8", mode: 384 });
163
+ (0, import_fs.writeFileSync)(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
117
164
  try {
118
165
  (0, import_fs.chmodSync)(configPath, 384);
119
166
  } catch {
@@ -142,14 +189,6 @@ function isSetupComplete() {
142
189
  function resetConfig() {
143
190
  saveConfig({ ...DEFAULT_CONFIG });
144
191
  }
145
- function generateConnectionToken() {
146
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
147
- let token = "db_";
148
- for (let i = 0; i < 32; i++) {
149
- token += chars.charAt(Math.floor(Math.random() * chars.length));
150
- }
151
- return token;
152
- }
153
192
  var import_os, import_path, import_fs, import_crypto, DEFAULT_CONFIG, MACHINE_ID_PREFIX;
154
193
  var init_config = __esm({
155
194
  "../../oss/packages/daemon-core/src/config/config.ts"() {
@@ -160,18 +199,13 @@ var init_config = __esm({
160
199
  import_crypto = require("crypto");
161
200
  DEFAULT_CONFIG = {
162
201
  serverUrl: "https://api.adhf.dev",
163
- apiToken: null,
164
- connectionToken: null,
165
202
  selectedIde: null,
166
203
  configuredIdes: [],
167
204
  installedExtensions: [],
168
- autoConnect: true,
169
- notifications: true,
170
205
  userEmail: null,
171
206
  userName: null,
172
207
  setupCompleted: false,
173
208
  setupDate: null,
174
- configuredCLIs: [],
175
209
  enabledIdes: [],
176
210
  workspaces: [],
177
211
  defaultWorkspaceId: null,
@@ -2338,6 +2372,8 @@ var init_extension_provider_instance = __esm({
2338
2372
  this.detectTransition(newStatus, data);
2339
2373
  this.currentStatus = newStatus;
2340
2374
  }
2375
+ } else if (event === "stream_reset") {
2376
+ this.resetStreamState();
2341
2377
  } else if (event === "extension_connected") {
2342
2378
  this.ideType = data?.ideType || "";
2343
2379
  }
@@ -2417,6 +2453,30 @@ var init_extension_provider_instance = __esm({
2417
2453
  const title = typeof data?.title === "string" && data.title.trim() ? data.title.trim() : this.chatTitle;
2418
2454
  return title || this.agentName || this.provider.name;
2419
2455
  }
2456
+ resetStreamState() {
2457
+ if (this.currentStatus !== "idle") {
2458
+ this.detectTransition("idle", {
2459
+ title: this.chatTitle,
2460
+ agentName: this.agentName,
2461
+ extensionId: this.extensionId,
2462
+ messages: this.messages
2463
+ });
2464
+ }
2465
+ this.agentStreams = [];
2466
+ this.messages = [];
2467
+ this.activeModal = null;
2468
+ this.currentModel = "";
2469
+ this.currentMode = "";
2470
+ this.controlValues = {};
2471
+ this.currentStatus = "idle";
2472
+ this.chatId = null;
2473
+ this.chatTitle = null;
2474
+ this.agentName = "";
2475
+ this.extensionId = "";
2476
+ this.lastAgentStatus = "idle";
2477
+ this.generatingStartedAt = 0;
2478
+ this.monitor.reset();
2479
+ }
2420
2480
  };
2421
2481
  }
2422
2482
  });
@@ -2715,11 +2775,23 @@ var init_ide_provider_instance = __esm({
2715
2775
  } else if (event === "cdp_disconnected") {
2716
2776
  this.cachedChat = null;
2717
2777
  this.currentStatus = "idle";
2778
+ for (const ext of this.extensions.values()) {
2779
+ ext.onEvent("stream_reset");
2780
+ }
2718
2781
  } else if (event === "stream_update") {
2719
2782
  const extType = data?.extensionType;
2720
2783
  if (extType && this.extensions.has(extType)) {
2721
2784
  this.extensions.get(extType).onEvent("stream_update", data);
2722
2785
  }
2786
+ } else if (event === "stream_reset") {
2787
+ const extType = data?.extensionType;
2788
+ if (extType && this.extensions.has(extType)) {
2789
+ this.extensions.get(extType).onEvent("stream_reset");
2790
+ }
2791
+ } else if (event === "stream_reset_all") {
2792
+ for (const ext of this.extensions.values()) {
2793
+ ext.onEvent("stream_reset");
2794
+ }
2723
2795
  }
2724
2796
  }
2725
2797
  dispose() {
@@ -3251,6 +3323,55 @@ var init_initializer = __esm({
3251
3323
  });
3252
3324
 
3253
3325
  // ../../oss/packages/daemon-core/src/status/normalize.ts
3326
+ function truncateString(value, maxChars) {
3327
+ if (value.length <= maxChars) return value;
3328
+ if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));
3329
+ return `${value.slice(0, maxChars - 12)}...[truncated]`;
3330
+ }
3331
+ function truncateStringTail(value, maxChars) {
3332
+ if (value.length <= maxChars) return value;
3333
+ if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));
3334
+ return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;
3335
+ }
3336
+ function trimStructuredStrings(value, maxChars) {
3337
+ if (typeof value === "string") return truncateString(value, maxChars);
3338
+ if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));
3339
+ if (!value || typeof value !== "object") return value;
3340
+ return Object.fromEntries(
3341
+ Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)])
3342
+ );
3343
+ }
3344
+ function estimateBytes(value) {
3345
+ try {
3346
+ return JSON.stringify(value).length;
3347
+ } catch {
3348
+ return String(value ?? "").length;
3349
+ }
3350
+ }
3351
+ function trimMessageForStatus(message, stringLimit) {
3352
+ if (!message || typeof message !== "object") return message;
3353
+ return trimStructuredStrings(message, stringLimit);
3354
+ }
3355
+ function trimMessagesForStatus(messages) {
3356
+ if (!Array.isArray(messages) || messages.length === 0) return [];
3357
+ const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
3358
+ const kept = [];
3359
+ let totalBytes = 0;
3360
+ for (let i = recent.length - 1; i >= 0; i -= 1) {
3361
+ let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
3362
+ let size = estimateBytes(normalized);
3363
+ if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
3364
+ normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
3365
+ size = estimateBytes(normalized);
3366
+ }
3367
+ if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
3368
+ continue;
3369
+ }
3370
+ kept.push(normalized);
3371
+ totalBytes += size;
3372
+ }
3373
+ return kept.reverse();
3374
+ }
3254
3375
  function hasApprovalButtons(activeModal) {
3255
3376
  return (activeModal?.buttons?.length ?? 0) > 0;
3256
3377
  }
@@ -3271,10 +3392,19 @@ function normalizeActiveChatData(activeChat) {
3271
3392
  if (!activeChat) return activeChat;
3272
3393
  return {
3273
3394
  ...activeChat,
3274
- status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal })
3395
+ status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
3396
+ messages: trimMessagesForStatus(activeChat.messages),
3397
+ activeModal: activeChat.activeModal ? {
3398
+ message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
3399
+ buttons: (activeChat.activeModal.buttons || []).map(
3400
+ (button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
3401
+ )
3402
+ } : activeChat.activeModal,
3403
+ terminalHistory: activeChat.terminalHistory ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT) : activeChat.terminalHistory,
3404
+ inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
3275
3405
  };
3276
3406
  }
3277
- var WORKING_STATUSES;
3407
+ var WORKING_STATUSES, STATUS_ACTIVE_CHAT_MESSAGE_LIMIT, STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT, STATUS_ACTIVE_CHAT_STRING_LIMIT, STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT, STATUS_TERMINAL_HISTORY_LIMIT, STATUS_INPUT_CONTENT_LIMIT, STATUS_MODAL_MESSAGE_LIMIT, STATUS_MODAL_BUTTON_LIMIT;
3278
3408
  var init_normalize = __esm({
3279
3409
  "../../oss/packages/daemon-core/src/status/normalize.ts"() {
3280
3410
  "use strict";
@@ -3286,6 +3416,14 @@ var init_normalize = __esm({
3286
3416
  "thinking",
3287
3417
  "active"
3288
3418
  ]);
3419
+ STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
3420
+ STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
3421
+ STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
3422
+ STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
3423
+ STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;
3424
+ STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
3425
+ STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
3426
+ STATUS_MODAL_BUTTON_LIMIT = 120;
3289
3427
  }
3290
3428
  });
3291
3429
 
@@ -3427,9 +3565,10 @@ function buildCliSession(state) {
3427
3565
  runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
3428
3566
  runtimeWriteOwner: state.runtime?.writeOwner || null,
3429
3567
  runtimeAttachedClients: state.runtime?.attachedClients || [],
3568
+ mode: state.mode,
3430
3569
  resume: state.resume,
3431
3570
  activeChat,
3432
- capabilities: PTY_SESSION_CAPABILITIES,
3571
+ capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES,
3433
3572
  controlValues: state.controlValues,
3434
3573
  providerControls: buildFallbackControls(
3435
3574
  state.providerControls
@@ -3499,7 +3638,7 @@ function buildSessionEntries(allStates, cdpManagers) {
3499
3638
  }
3500
3639
  return sessions;
3501
3640
  }
3502
- var IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES;
3641
+ var IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, CLI_CHAT_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES;
3503
3642
  var init_builders = __esm({
3504
3643
  "../../oss/packages/daemon-core/src/status/builders.ts"() {
3505
3644
  "use strict";
@@ -3532,6 +3671,11 @@ var init_builders = __esm({
3532
3671
  "terminal_io",
3533
3672
  "resize_terminal"
3534
3673
  ];
3674
+ CLI_CHAT_SESSION_CAPABILITIES = [
3675
+ "read_chat",
3676
+ "send_message",
3677
+ "resolve_action"
3678
+ ];
3535
3679
  ACP_SESSION_CAPABILITIES = [
3536
3680
  "read_chat",
3537
3681
  "send_message",
@@ -4656,6 +4800,13 @@ var init_cdp_commands = __esm({
4656
4800
  });
4657
4801
 
4658
4802
  // ../../oss/packages/daemon-core/src/commands/stream-commands.ts
4803
+ function getCliPresentationMode(h, targetSessionId) {
4804
+ if (!targetSessionId) return null;
4805
+ const instance = h.ctx.instanceManager?.getInstance(targetSessionId);
4806
+ if (instance?.category !== "cli") return null;
4807
+ const mode = instance.getPresentationMode?.();
4808
+ return mode === "chat" || mode === "terminal" ? mode : null;
4809
+ }
4659
4810
  async function handleFocusSession(h, args) {
4660
4811
  if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
4661
4812
  const sessionId = args?.targetSessionId || h.currentSession?.sessionId;
@@ -4666,6 +4817,9 @@ async function handleFocusSession(h, args) {
4666
4817
  function handlePtyInput(h, args) {
4667
4818
  const { cliType, data, targetSessionId } = args || {};
4668
4819
  if (!data) return { success: false, error: "data required" };
4820
+ if (getCliPresentationMode(h, targetSessionId) === "chat") {
4821
+ return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
4822
+ }
4669
4823
  const adapter = h.getCliAdapter(targetSessionId || cliType);
4670
4824
  if (!adapter || typeof adapter.writeRaw !== "function") {
4671
4825
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
@@ -4676,6 +4830,9 @@ function handlePtyInput(h, args) {
4676
4830
  function handlePtyResize(h, args) {
4677
4831
  const { cliType, cols, rows, force, targetSessionId } = args || {};
4678
4832
  if (!cols || !rows) return { success: false, error: "cols and rows required" };
4833
+ if (getCliPresentationMode(h, targetSessionId) === "chat") {
4834
+ return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
4835
+ }
4679
4836
  const adapter = h.getCliAdapter(targetSessionId || cliType);
4680
4837
  if (!adapter || typeof adapter.resize !== "function") {
4681
4838
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
@@ -18208,6 +18365,7 @@ var init_router = __esm({
18208
18365
  // ─── CLI / ACP commands ───
18209
18366
  case "launch_cli":
18210
18367
  case "stop_cli":
18368
+ case "set_cli_view_mode":
18211
18369
  case "agent_command": {
18212
18370
  return this.deps.cliManager.handleCliCommand(cmd, args);
18213
18371
  }
@@ -18560,6 +18718,20 @@ var init_reporter = __esm({
18560
18718
  ts() {
18561
18719
  return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
18562
18720
  }
18721
+ summarizeLargePayloadSessions(payload) {
18722
+ const sessions = Array.isArray(payload.sessions) ? payload.sessions : [];
18723
+ return sessions.map((session) => ({
18724
+ id: String(session?.id || ""),
18725
+ providerType: String(session?.providerType || ""),
18726
+ bytes: (() => {
18727
+ try {
18728
+ return JSON.stringify(session).length;
18729
+ } catch {
18730
+ return 0;
18731
+ }
18732
+ })()
18733
+ })).sort((a, b2) => b2.bytes - a.bytes).slice(0, 3).map((session) => `${session.providerType || "unknown"}:${session.id}=${session.bytes}b`).join(", ");
18734
+ }
18563
18735
  async sendUnifiedStatusReport(opts) {
18564
18736
  const { serverConn, p2p } = this.deps;
18565
18737
  if (!serverConn?.isConnected()) return;
@@ -18612,9 +18784,16 @@ var init_reporter = __esm({
18612
18784
  screenshotUsage: this.deps.getScreenshotUsage?.() || null,
18613
18785
  connectedExtensions: []
18614
18786
  };
18787
+ const payloadBytes = JSON.stringify(payload).length;
18615
18788
  const p2pSent = this.sendP2PPayload(payload);
18616
18789
  if (p2pSent) {
18617
- LOG.debug("P2P", `sent (${JSON.stringify(payload).length} bytes)`);
18790
+ LOG.debug("P2P", `sent (${payloadBytes} bytes)`);
18791
+ if (payloadBytes > 256 * 1024) {
18792
+ LOG.warn(
18793
+ "P2P",
18794
+ `large status payload (${payloadBytes} bytes) top sessions: ${this.summarizeLargePayloadSessions(payload) || "n/a"}`
18795
+ );
18796
+ }
18618
18797
  }
18619
18798
  if (opts?.p2pOnly) return;
18620
18799
  const wsPayload = {
@@ -18644,7 +18823,9 @@ var init_reporter = __esm({
18644
18823
  acpModes: session.acpModes
18645
18824
  })),
18646
18825
  p2p: payload.p2p,
18647
- timestamp: now
18826
+ timestamp: now,
18827
+ detectedIdes: payload.detectedIdes,
18828
+ availableProviders: payload.availableProviders
18648
18829
  };
18649
18830
  serverConn.sendMessage("status_report", wsPayload);
18650
18831
  LOG.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
@@ -19016,6 +19197,13 @@ var init_provider_cli_adapter = __esm({
19016
19197
  this.messages = [...this.committedMessages];
19017
19198
  this.structuredMessages = [...this.committedMessages];
19018
19199
  }
19200
+ normalizeParsedMessages(parsedMessages) {
19201
+ return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
19202
+ role: message.role,
19203
+ content: typeof message.content === "string" ? message.content : String(message.content || ""),
19204
+ timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : Date.now()
19205
+ }));
19206
+ }
19019
19207
  sliceFromOffset(text, start) {
19020
19208
  if (!text) return "";
19021
19209
  if (!Number.isFinite(start) || start <= 0) return text;
@@ -19412,6 +19600,15 @@ var init_provider_cli_adapter = __esm({
19412
19600
  this.onStatusChange?.();
19413
19601
  }
19414
19602
  commitCurrentTranscript() {
19603
+ const parsed = this.parseCurrentTranscript(
19604
+ this.committedMessages,
19605
+ this.responseBuffer,
19606
+ this.currentTurnScope
19607
+ );
19608
+ if (parsed && Array.isArray(parsed.messages)) {
19609
+ this.committedMessages = this.normalizeParsedMessages(parsed.messages);
19610
+ this.syncMessageViews();
19611
+ }
19415
19612
  }
19416
19613
  // ─── Script Execution ──────────────────────────
19417
19614
  runDetectStatus(text) {
@@ -19456,6 +19653,21 @@ var init_provider_cli_adapter = __esm({
19456
19653
  * Called by command handler / dashboard for rich content rendering.
19457
19654
  */
19458
19655
  getScriptParsedStatus() {
19656
+ const parsed = this.parseCurrentTranscript(
19657
+ this.committedMessages,
19658
+ this.responseBuffer,
19659
+ this.currentTurnScope
19660
+ );
19661
+ if (parsed && Array.isArray(parsed.messages)) {
19662
+ return {
19663
+ id: parsed.id || "cli_session",
19664
+ status: parsed.status || this.currentStatus,
19665
+ title: parsed.title || this.cliName,
19666
+ terminalHistory: this.terminalHistory,
19667
+ messages: parsed.messages,
19668
+ activeModal: parsed.activeModal ?? this.activeModal
19669
+ };
19670
+ }
19459
19671
  const messages = [...this.committedMessages];
19460
19672
  return {
19461
19673
  id: "cli_session",
@@ -19901,6 +20113,7 @@ var init_cli_provider_instance = __esm({
19901
20113
  this.cliArgs = cliArgs;
19902
20114
  this.type = provider.type;
19903
20115
  this.instanceId = instanceId || crypto3.randomUUID();
20116
+ this.presentationMode = "terminal";
19904
20117
  this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
19905
20118
  this.monitor = new StatusMonitor();
19906
20119
  this.historyWriter = new ChatHistoryWriter();
@@ -19919,6 +20132,7 @@ var init_cli_provider_instance = __esm({
19919
20132
  lastApprovalEventAt = 0;
19920
20133
  historyWriter;
19921
20134
  instanceId;
20135
+ presentationMode;
19922
20136
  // ─── Lifecycle ─────────────────────────────────
19923
20137
  async init(context) {
19924
20138
  this.context = context;
@@ -19943,6 +20157,7 @@ var init_cli_provider_instance = __esm({
19943
20157
  }
19944
20158
  getState() {
19945
20159
  const adapterStatus = this.adapter.getStatus();
20160
+ const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
19946
20161
  const runtime = this.adapter.getRuntimeMetadata();
19947
20162
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
19948
20163
  if (adapterStatus.terminalHistory?.trim()) {
@@ -19958,13 +20173,13 @@ var init_cli_provider_instance = __esm({
19958
20173
  name: this.provider.name,
19959
20174
  category: "cli",
19960
20175
  status: adapterStatus.status,
19961
- mode: "terminal",
20176
+ mode: this.presentationMode,
19962
20177
  activeChat: {
19963
20178
  id: `${this.type}_${this.workingDir}`,
19964
- title: `${this.provider.name} \xB7 ${dirName}`,
19965
- status: adapterStatus.status,
19966
- messages: [],
19967
- activeModal: adapterStatus.activeModal,
20179
+ title: parsedStatus?.title || `${this.provider.name} \xB7 ${dirName}`,
20180
+ status: parsedStatus?.status || adapterStatus.status,
20181
+ messages: Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [],
20182
+ activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
19968
20183
  terminalHistory: adapterStatus.terminalHistory,
19969
20184
  inputContent: ""
19970
20185
  },
@@ -19987,6 +20202,13 @@ var init_cli_provider_instance = __esm({
19987
20202
  providerControls: this.provider.controls
19988
20203
  };
19989
20204
  }
20205
+ setPresentationMode(mode) {
20206
+ if (this.presentationMode === mode) return;
20207
+ this.presentationMode = mode;
20208
+ }
20209
+ getPresentationMode() {
20210
+ return this.presentationMode;
20211
+ }
19990
20212
  onEvent(event, data) {
19991
20213
  if (event === "send_message" && data?.text) {
19992
20214
  void this.adapter.sendMessage(data.text).catch((e) => {
@@ -20247,7 +20469,7 @@ __export(util_exports, {
20247
20469
  getSizableOrigin: () => getSizableOrigin,
20248
20470
  hexToUint8Array: () => hexToUint8Array,
20249
20471
  isObject: () => isObject,
20250
- isPlainObject: () => isPlainObject,
20472
+ isPlainObject: () => isPlainObject2,
20251
20473
  issue: () => issue,
20252
20474
  joinValues: () => joinValues,
20253
20475
  jsonStringifyReplacer: () => jsonStringifyReplacer,
@@ -20416,7 +20638,7 @@ function slugify(input) {
20416
20638
  function isObject(data) {
20417
20639
  return typeof data === "object" && data !== null && !Array.isArray(data);
20418
20640
  }
20419
- function isPlainObject(o) {
20641
+ function isPlainObject2(o) {
20420
20642
  if (isObject(o) === false)
20421
20643
  return false;
20422
20644
  const ctor = o.constructor;
@@ -20433,7 +20655,7 @@ function isPlainObject(o) {
20433
20655
  return true;
20434
20656
  }
20435
20657
  function shallowClone(o) {
20436
- if (isPlainObject(o))
20658
+ if (isPlainObject2(o))
20437
20659
  return { ...o };
20438
20660
  if (Array.isArray(o))
20439
20661
  return [...o];
@@ -20569,7 +20791,7 @@ function omit(schema, mask) {
20569
20791
  return clone(schema, def);
20570
20792
  }
20571
20793
  function extend(schema, shape) {
20572
- if (!isPlainObject(shape)) {
20794
+ if (!isPlainObject2(shape)) {
20573
20795
  throw new Error("Invalid input to extend: expected a plain object");
20574
20796
  }
20575
20797
  const checks = schema._zod.def.checks;
@@ -20592,7 +20814,7 @@ function extend(schema, shape) {
20592
20814
  return clone(schema, def);
20593
20815
  }
20594
20816
  function safeExtend(schema, shape) {
20595
- if (!isPlainObject(shape)) {
20817
+ if (!isPlainObject2(shape)) {
20596
20818
  throw new Error("Invalid input to safeExtend: expected a plain object");
20597
20819
  }
20598
20820
  const def = mergeDefs(schema._zod.def, {
@@ -22075,7 +22297,7 @@ function mergeValues(a, b2) {
22075
22297
  if (a instanceof Date && b2 instanceof Date && +a === +b2) {
22076
22298
  return { valid: true, data: a };
22077
22299
  }
22078
- if (isPlainObject(a) && isPlainObject(b2)) {
22300
+ if (isPlainObject2(a) && isPlainObject2(b2)) {
22079
22301
  const bKeys = Object.keys(b2);
22080
22302
  const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
22081
22303
  const newObj = { ...a, ...b2 };
@@ -23270,7 +23492,7 @@ var init_schemas = __esm({
23270
23492
  $ZodType.init(inst, def);
23271
23493
  inst._zod.parse = (payload, ctx) => {
23272
23494
  const input = payload.value;
23273
- if (!isPlainObject(input)) {
23495
+ if (!isPlainObject2(input)) {
23274
23496
  payload.issues.push({
23275
23497
  expected: "record",
23276
23498
  code: "invalid_type",
@@ -37374,6 +37596,15 @@ var init_cli_manager = __esm({
37374
37596
  const hash2 = require("crypto").createHash("md5").update(require("path").resolve(dir)).digest("hex").slice(0, 8);
37375
37597
  return `${cliType}_${hash2}`;
37376
37598
  }
37599
+ getSessionPresentationMode(sessionId) {
37600
+ if (!sessionId) return null;
37601
+ const instance = this.deps.getInstanceManager()?.getInstance(sessionId);
37602
+ const mode = instance?.category === "cli" ? instance.getPresentationMode?.() : null;
37603
+ return mode === "chat" || mode === "terminal" ? mode : null;
37604
+ }
37605
+ isTerminalSession(sessionId) {
37606
+ return this.getSessionPresentationMode(sessionId) === "terminal";
37607
+ }
37377
37608
  persistRecentActivity(entry) {
37378
37609
  try {
37379
37610
  saveConfig(appendRecentActivity(loadConfig(), entry));
@@ -37552,6 +37783,7 @@ ${installInfo}`
37552
37783
  if (provider) {
37553
37784
  console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
37554
37785
  }
37786
+ const resolvedCliArgs = cliArgs;
37555
37787
  const instanceManager = this.deps.getInstanceManager();
37556
37788
  if (provider && instanceManager) {
37557
37789
  const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
@@ -37560,14 +37792,14 @@ ${installInfo}`
37560
37792
  normalizedType,
37561
37793
  cliType,
37562
37794
  resolvedDir,
37563
- cliArgs,
37795
+ resolvedCliArgs,
37564
37796
  resolvedProvider,
37565
37797
  {},
37566
37798
  false
37567
37799
  );
37568
37800
  console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
37569
37801
  } else {
37570
- const adapter = this.createAdapter(cliType, resolvedDir, cliArgs, key, false);
37802
+ const adapter = this.createAdapter(cliType, resolvedDir, resolvedCliArgs, key, false);
37571
37803
  try {
37572
37804
  await adapter.spawn();
37573
37805
  } catch (spawnErr) {
@@ -37717,6 +37949,14 @@ ${installInfo}`
37717
37949
  }
37718
37950
  return null;
37719
37951
  }
37952
+ findAdapterBySessionId(instanceKey) {
37953
+ if (!instanceKey) return null;
37954
+ let ik = instanceKey;
37955
+ const colonIdx = ik.lastIndexOf(":");
37956
+ if (colonIdx >= 0) ik = ik.substring(colonIdx + 1);
37957
+ const adapter = this.adapters.get(ik);
37958
+ return adapter ? { adapter, key: ik } : null;
37959
+ }
37720
37960
  // ─── CLI command handling ────────────────────────────
37721
37961
  async handleCliCommand(cmd, args) {
37722
37962
  switch (cmd) {
@@ -37767,6 +38007,23 @@ ${installInfo}`
37767
38007
  }
37768
38008
  return { success: true, cliType, dir, stopped: true, mode };
37769
38009
  }
38010
+ case "set_cli_view_mode": {
38011
+ const mode = args?.mode === "chat" ? "chat" : "terminal";
38012
+ const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId : "";
38013
+ const cliType = args?.cliType || args?.agentType || "";
38014
+ const dir = args?.dir || "";
38015
+ const found = this.findAdapterBySessionId(targetSessionId) || (cliType ? this.findAdapter(cliType, { instanceKey: targetSessionId, dir }) : null);
38016
+ if (!found) {
38017
+ return { success: false, error: "CLI session not found", code: "CLI_SESSION_NOT_FOUND" };
38018
+ }
38019
+ const instance = this.deps.getInstanceManager()?.getInstance(found.key);
38020
+ if (!(instance instanceof CliProviderInstance)) {
38021
+ return { success: false, error: "CLI instance not found", code: "CLI_INSTANCE_NOT_FOUND" };
38022
+ }
38023
+ instance.setPresentationMode(mode);
38024
+ this.deps.onStatusChange();
38025
+ return { success: true, id: found.key, mode };
38026
+ }
37770
38027
  case "restart_session": {
37771
38028
  const cliType = args?.cliType || args?.agentType || args?.ideType;
37772
38029
  const cfg = loadConfig();
@@ -38417,7 +38674,12 @@ var init_poller = __esm({
38417
38674
  } catch {
38418
38675
  }
38419
38676
  }
38420
- if (!resolvedActiveSessionId || !parentSessionId) continue;
38677
+ if (!resolvedActiveSessionId || !parentSessionId) {
38678
+ if (parentSessionId) {
38679
+ this.deps.onStreamsUpdated?.(ideType, []);
38680
+ }
38681
+ continue;
38682
+ }
38421
38683
  try {
38422
38684
  await agentStreamManager.syncActiveSession(cdp, parentSessionId);
38423
38685
  const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
@@ -38445,7 +38707,11 @@ var init_agent_stream = __esm({
38445
38707
  function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
38446
38708
  const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
38447
38709
  if (!ideInstance?.onEvent) return;
38710
+ const seenExtensionTypes = /* @__PURE__ */ new Set();
38448
38711
  for (const stream of streams) {
38712
+ if (typeof stream.agentType === "string" && stream.agentType) {
38713
+ seenExtensionTypes.add(stream.agentType);
38714
+ }
38449
38715
  ideInstance.onEvent("stream_update", {
38450
38716
  extensionType: stream.agentType,
38451
38717
  streams: [stream],
@@ -38462,6 +38728,16 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
38462
38728
  inputContent: stream.inputContent || ""
38463
38729
  });
38464
38730
  }
38731
+ const extensionTypes = ideInstance.getExtensionTypes?.() || [];
38732
+ if (streams.length === 0) {
38733
+ ideInstance.onEvent("stream_reset_all");
38734
+ return;
38735
+ }
38736
+ for (const extensionType of extensionTypes) {
38737
+ if (!seenExtensionTypes.has(extensionType)) {
38738
+ ideInstance.onEvent("stream_reset", { extensionType });
38739
+ }
38740
+ }
38465
38741
  }
38466
38742
  var init_forward = __esm({
38467
38743
  "../../oss/packages/daemon-core/src/agent-stream/forward.ts"() {
@@ -43942,13 +44218,8 @@ var init_server_connection = __esm({
43942
44218
  LOG.info("Server", `[ServerConn] Run 'adhdev setup' to re-authenticate.`);
43943
44219
  this.setState("disconnected");
43944
44220
  try {
43945
- const path18 = require("path");
43946
- const fs16 = require("fs");
43947
- const configPath = path18.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "config.json");
43948
- if (fs16.existsSync(configPath)) {
43949
- fs16.unlinkSync(configPath);
43950
- LOG.info("Server", `[ServerConn] Config file removed. Re-run 'adhdev setup'.`);
43951
- }
44221
+ resetConfig();
44222
+ LOG.info("Server", `[ServerConn] Config reset. Re-run 'adhdev setup'.`);
43952
44223
  } catch {
43953
44224
  }
43954
44225
  return;
@@ -44217,10 +44488,9 @@ ${e?.stack || ""}`);
44217
44488
  async fetchTurnCredentials() {
44218
44489
  try {
44219
44490
  const serverUrl = process.env.ADHDEV_SERVER_URL || "https://api.adhf.dev";
44220
- const configPath = path15.join(os18.homedir(), ".adhdev", "config.json");
44221
44491
  let token = "";
44222
44492
  try {
44223
- const config2 = JSON.parse(fs13.readFileSync(configPath, "utf-8"));
44493
+ const config2 = loadConfig();
44224
44494
  token = config2.machineSecret || "";
44225
44495
  } catch {
44226
44496
  }
@@ -44519,8 +44789,9 @@ ${e?.stack || ""}`);
44519
44789
  log(`pty_input: REJECTED \u2014 permission=${permission} peer=${peerId}`);
44520
44790
  return;
44521
44791
  }
44522
- if (this.ptyInputHandler && parsed.data) {
44523
- this.ptyInputHandler(parsed.cliType || "", parsed.data);
44792
+ const sessionId = parsed.sessionId || parsed.cliId || parsed.cliType || "";
44793
+ if (this.ptyInputHandler && parsed.data && sessionId) {
44794
+ this.ptyInputHandler(sessionId, parsed.data);
44524
44795
  }
44525
44796
  return;
44526
44797
  }
@@ -44530,8 +44801,9 @@ ${e?.stack || ""}`);
44530
44801
  log(`pty_resize: REJECTED \u2014 permission=${permission} peer=${peerId}`);
44531
44802
  return;
44532
44803
  }
44533
- if (this.ptyResizeHandler && parsed.cols && parsed.rows) {
44534
- this.ptyResizeHandler(parsed.cliType || "", parsed.cols, parsed.rows);
44804
+ const sessionId = parsed.sessionId || parsed.cliId || parsed.cliType || "";
44805
+ if (this.ptyResizeHandler && parsed.cols && parsed.rows && sessionId) {
44806
+ this.ptyResizeHandler(sessionId, parsed.cols, parsed.rows);
44535
44807
  }
44536
44808
  return;
44537
44809
  }
@@ -44559,8 +44831,8 @@ ${e?.stack || ""}`);
44559
44831
  return sentAny;
44560
44832
  }
44561
44833
  /** Broadcast PTY output to all connected peers */
44562
- broadcastPtyOutput(cliType, data) {
44563
- const msg = JSON.stringify({ type: "pty_output", cliType, data });
44834
+ broadcastPtyOutput(sessionId, data) {
44835
+ const msg = JSON.stringify({ type: "pty_output", sessionId, data });
44564
44836
  let sentAny = false;
44565
44837
  for (const peer of this.peers.values()) {
44566
44838
  if (peer.state !== "connected" || !peer.dataChannel) continue;
@@ -45141,7 +45413,7 @@ var init_adhdev_daemon = __esm({
45141
45413
  fs15 = __toESM(require("fs"));
45142
45414
  path17 = __toESM(require("path"));
45143
45415
  import_chalk2 = __toESM(require("chalk"));
45144
- pkgVersion = "0.7.40";
45416
+ pkgVersion = "0.7.42";
45145
45417
  if (pkgVersion === "unknown") {
45146
45418
  try {
45147
45419
  const possiblePaths = [
@@ -45186,6 +45458,16 @@ var init_adhdev_daemon = __esm({
45186
45458
  constructor() {
45187
45459
  this.localPort = 19222;
45188
45460
  }
45461
+ getCliPresentationMode(sessionId) {
45462
+ if (!sessionId || !this.components) return null;
45463
+ const instance = this.components.instanceManager.getInstance(sessionId);
45464
+ if (instance?.category !== "cli") return null;
45465
+ const mode = instance.getPresentationMode?.();
45466
+ return mode === "chat" || mode === "terminal" ? mode : null;
45467
+ }
45468
+ isTerminalCliSession(sessionId) {
45469
+ return this.getCliPresentationMode(sessionId) === "terminal";
45470
+ }
45189
45471
  async start(options = {}) {
45190
45472
  try {
45191
45473
  const { installGlobalInterceptor: installGlobalInterceptor2 } = require("./logging/logger");
@@ -45215,9 +45497,6 @@ ${err?.stack || ""}`);
45215
45497
  const authToken = config2.machineSecret;
45216
45498
  if (!authToken) {
45217
45499
  console.log(import_chalk2.default.red("\n\u2717 No machine secret found."));
45218
- if (config2.connectionToken) {
45219
- console.log(import_chalk2.default.yellow(" Legacy connectionToken detected \u2014 please re-run setup."));
45220
- }
45221
45500
  console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
45222
45501
  process.exit(1);
45223
45502
  }
@@ -45227,7 +45506,12 @@ ${err?.stack || ""}`);
45227
45506
  providerLogFn: LOG.forComponent("Provider").asLogFn(),
45228
45507
  cliManagerDeps: {
45229
45508
  getServerConn: () => this.serverConn,
45230
- getP2p: () => this.p2p,
45509
+ getP2p: () => ({
45510
+ broadcastPtyOutput: (key, data) => {
45511
+ if (!this.isTerminalCliSession(key)) return;
45512
+ this.p2p?.broadcastPtyOutput(key, data);
45513
+ }
45514
+ }),
45231
45515
  onStatusChange: () => this.statusReporter?.onStatusChange(),
45232
45516
  removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
45233
45517
  createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, attachExisting }) => new SessionHostPtyTransportFactory({
@@ -45304,14 +45588,16 @@ ${err?.stack || ""}`);
45304
45588
  return { id: req.id, success: result.success, entries: result.files, error: result.error };
45305
45589
  }
45306
45590
  });
45307
- this.p2p.onPtyInput((cliId, data) => {
45308
- const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45591
+ this.p2p.onPtyInput((sessionId, data) => {
45592
+ if (!this.isTerminalCliSession(sessionId)) return;
45593
+ const found = this.components.cliManager.findAdapter(sessionId, { instanceKey: sessionId });
45309
45594
  if (found && typeof found.adapter.writeRaw === "function") {
45310
45595
  found.adapter.writeRaw(data);
45311
45596
  }
45312
45597
  });
45313
- this.p2p.onPtyResize((cliId, cols, rows) => {
45314
- const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
45598
+ this.p2p.onPtyResize((sessionId, cols, rows) => {
45599
+ if (!this.isTerminalCliSession(sessionId)) return;
45600
+ const found = this.components.cliManager.findAdapter(sessionId, { instanceKey: sessionId });
45315
45601
  if (found && typeof found.adapter.resize === "function") {
45316
45602
  found.adapter.resize(cols, rows);
45317
45603
  }
@@ -45487,6 +45773,9 @@ ${err?.stack || ""}`);
45487
45773
  case "get_runtime_snapshot": {
45488
45774
  const sessionId = typeof data.sessionId === "string" ? data.sessionId : "";
45489
45775
  if (!sessionId) return { success: false, error: "sessionId is required" };
45776
+ if (!this.isTerminalCliSession(sessionId)) {
45777
+ return { success: false, error: "CLI session is not in terminal mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
45778
+ }
45490
45779
  if (!this.sessionHostEndpoint) return { success: false, error: "Session host unavailable" };
45491
45780
  const client = new SessionHostClient({ endpoint: this.sessionHostEndpoint });
45492
45781
  try {