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/cli/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,
@@ -2345,6 +2379,8 @@ var init_extension_provider_instance = __esm({
2345
2379
  this.detectTransition(newStatus, data);
2346
2380
  this.currentStatus = newStatus;
2347
2381
  }
2382
+ } else if (event === "stream_reset") {
2383
+ this.resetStreamState();
2348
2384
  } else if (event === "extension_connected") {
2349
2385
  this.ideType = data?.ideType || "";
2350
2386
  }
@@ -2424,6 +2460,30 @@ var init_extension_provider_instance = __esm({
2424
2460
  const title = typeof data?.title === "string" && data.title.trim() ? data.title.trim() : this.chatTitle;
2425
2461
  return title || this.agentName || this.provider.name;
2426
2462
  }
2463
+ resetStreamState() {
2464
+ if (this.currentStatus !== "idle") {
2465
+ this.detectTransition("idle", {
2466
+ title: this.chatTitle,
2467
+ agentName: this.agentName,
2468
+ extensionId: this.extensionId,
2469
+ messages: this.messages
2470
+ });
2471
+ }
2472
+ this.agentStreams = [];
2473
+ this.messages = [];
2474
+ this.activeModal = null;
2475
+ this.currentModel = "";
2476
+ this.currentMode = "";
2477
+ this.controlValues = {};
2478
+ this.currentStatus = "idle";
2479
+ this.chatId = null;
2480
+ this.chatTitle = null;
2481
+ this.agentName = "";
2482
+ this.extensionId = "";
2483
+ this.lastAgentStatus = "idle";
2484
+ this.generatingStartedAt = 0;
2485
+ this.monitor.reset();
2486
+ }
2427
2487
  };
2428
2488
  }
2429
2489
  });
@@ -2722,11 +2782,23 @@ var init_ide_provider_instance = __esm({
2722
2782
  } else if (event === "cdp_disconnected") {
2723
2783
  this.cachedChat = null;
2724
2784
  this.currentStatus = "idle";
2785
+ for (const ext of this.extensions.values()) {
2786
+ ext.onEvent("stream_reset");
2787
+ }
2725
2788
  } else if (event === "stream_update") {
2726
2789
  const extType = data?.extensionType;
2727
2790
  if (extType && this.extensions.has(extType)) {
2728
2791
  this.extensions.get(extType).onEvent("stream_update", data);
2729
2792
  }
2793
+ } else if (event === "stream_reset") {
2794
+ const extType = data?.extensionType;
2795
+ if (extType && this.extensions.has(extType)) {
2796
+ this.extensions.get(extType).onEvent("stream_reset");
2797
+ }
2798
+ } else if (event === "stream_reset_all") {
2799
+ for (const ext of this.extensions.values()) {
2800
+ ext.onEvent("stream_reset");
2801
+ }
2730
2802
  }
2731
2803
  }
2732
2804
  dispose() {
@@ -3411,6 +3483,55 @@ var init_initializer = __esm({
3411
3483
  });
3412
3484
 
3413
3485
  // ../../oss/packages/daemon-core/src/status/normalize.ts
3486
+ function truncateString(value, maxChars) {
3487
+ if (value.length <= maxChars) return value;
3488
+ if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));
3489
+ return `${value.slice(0, maxChars - 12)}...[truncated]`;
3490
+ }
3491
+ function truncateStringTail(value, maxChars) {
3492
+ if (value.length <= maxChars) return value;
3493
+ if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));
3494
+ return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;
3495
+ }
3496
+ function trimStructuredStrings(value, maxChars) {
3497
+ if (typeof value === "string") return truncateString(value, maxChars);
3498
+ if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));
3499
+ if (!value || typeof value !== "object") return value;
3500
+ return Object.fromEntries(
3501
+ Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)])
3502
+ );
3503
+ }
3504
+ function estimateBytes(value) {
3505
+ try {
3506
+ return JSON.stringify(value).length;
3507
+ } catch {
3508
+ return String(value ?? "").length;
3509
+ }
3510
+ }
3511
+ function trimMessageForStatus(message, stringLimit) {
3512
+ if (!message || typeof message !== "object") return message;
3513
+ return trimStructuredStrings(message, stringLimit);
3514
+ }
3515
+ function trimMessagesForStatus(messages) {
3516
+ if (!Array.isArray(messages) || messages.length === 0) return [];
3517
+ const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
3518
+ const kept = [];
3519
+ let totalBytes = 0;
3520
+ for (let i = recent.length - 1; i >= 0; i -= 1) {
3521
+ let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
3522
+ let size = estimateBytes(normalized);
3523
+ if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
3524
+ normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
3525
+ size = estimateBytes(normalized);
3526
+ }
3527
+ if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
3528
+ continue;
3529
+ }
3530
+ kept.push(normalized);
3531
+ totalBytes += size;
3532
+ }
3533
+ return kept.reverse();
3534
+ }
3414
3535
  function hasApprovalButtons(activeModal) {
3415
3536
  return (activeModal?.buttons?.length ?? 0) > 0;
3416
3537
  }
@@ -3437,10 +3558,19 @@ function normalizeActiveChatData(activeChat) {
3437
3558
  if (!activeChat) return activeChat;
3438
3559
  return {
3439
3560
  ...activeChat,
3440
- status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal })
3561
+ status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
3562
+ messages: trimMessagesForStatus(activeChat.messages),
3563
+ activeModal: activeChat.activeModal ? {
3564
+ message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
3565
+ buttons: (activeChat.activeModal.buttons || []).map(
3566
+ (button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
3567
+ )
3568
+ } : activeChat.activeModal,
3569
+ terminalHistory: activeChat.terminalHistory ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT) : activeChat.terminalHistory,
3570
+ inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
3441
3571
  };
3442
3572
  }
3443
- var WORKING_STATUSES;
3573
+ 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;
3444
3574
  var init_normalize = __esm({
3445
3575
  "../../oss/packages/daemon-core/src/status/normalize.ts"() {
3446
3576
  "use strict";
@@ -3452,6 +3582,14 @@ var init_normalize = __esm({
3452
3582
  "thinking",
3453
3583
  "active"
3454
3584
  ]);
3585
+ STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
3586
+ STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
3587
+ STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
3588
+ STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
3589
+ STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;
3590
+ STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
3591
+ STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
3592
+ STATUS_MODAL_BUTTON_LIMIT = 120;
3455
3593
  }
3456
3594
  });
3457
3595
 
@@ -3601,9 +3739,10 @@ function buildCliSession(state) {
3601
3739
  runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
3602
3740
  runtimeWriteOwner: state.runtime?.writeOwner || null,
3603
3741
  runtimeAttachedClients: state.runtime?.attachedClients || [],
3742
+ mode: state.mode,
3604
3743
  resume: state.resume,
3605
3744
  activeChat,
3606
- capabilities: PTY_SESSION_CAPABILITIES,
3745
+ capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES,
3607
3746
  controlValues: state.controlValues,
3608
3747
  providerControls: buildFallbackControls(
3609
3748
  state.providerControls
@@ -3673,7 +3812,7 @@ function buildSessionEntries(allStates, cdpManagers) {
3673
3812
  }
3674
3813
  return sessions;
3675
3814
  }
3676
- var IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES;
3815
+ var IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, CLI_CHAT_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES;
3677
3816
  var init_builders = __esm({
3678
3817
  "../../oss/packages/daemon-core/src/status/builders.ts"() {
3679
3818
  "use strict";
@@ -3706,6 +3845,11 @@ var init_builders = __esm({
3706
3845
  "terminal_io",
3707
3846
  "resize_terminal"
3708
3847
  ];
3848
+ CLI_CHAT_SESSION_CAPABILITIES = [
3849
+ "read_chat",
3850
+ "send_message",
3851
+ "resolve_action"
3852
+ ];
3709
3853
  ACP_SESSION_CAPABILITIES = [
3710
3854
  "read_chat",
3711
3855
  "send_message",
@@ -4830,6 +4974,13 @@ var init_cdp_commands = __esm({
4830
4974
  });
4831
4975
 
4832
4976
  // ../../oss/packages/daemon-core/src/commands/stream-commands.ts
4977
+ function getCliPresentationMode(h, targetSessionId) {
4978
+ if (!targetSessionId) return null;
4979
+ const instance = h.ctx.instanceManager?.getInstance(targetSessionId);
4980
+ if (instance?.category !== "cli") return null;
4981
+ const mode = instance.getPresentationMode?.();
4982
+ return mode === "chat" || mode === "terminal" ? mode : null;
4983
+ }
4833
4984
  async function handleFocusSession(h, args) {
4834
4985
  if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
4835
4986
  const sessionId = args?.targetSessionId || h.currentSession?.sessionId;
@@ -4840,6 +4991,9 @@ async function handleFocusSession(h, args) {
4840
4991
  function handlePtyInput(h, args) {
4841
4992
  const { cliType, data, targetSessionId } = args || {};
4842
4993
  if (!data) return { success: false, error: "data required" };
4994
+ if (getCliPresentationMode(h, targetSessionId) === "chat") {
4995
+ return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
4996
+ }
4843
4997
  const adapter = h.getCliAdapter(targetSessionId || cliType);
4844
4998
  if (!adapter || typeof adapter.writeRaw !== "function") {
4845
4999
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
@@ -4850,6 +5004,9 @@ function handlePtyInput(h, args) {
4850
5004
  function handlePtyResize(h, args) {
4851
5005
  const { cliType, cols, rows, force, targetSessionId } = args || {};
4852
5006
  if (!cols || !rows) return { success: false, error: "cols and rows required" };
5007
+ if (getCliPresentationMode(h, targetSessionId) === "chat") {
5008
+ return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
5009
+ }
4853
5010
  const adapter = h.getCliAdapter(targetSessionId || cliType);
4854
5011
  if (!adapter || typeof adapter.resize !== "function") {
4855
5012
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
@@ -18410,6 +18567,7 @@ var init_router = __esm({
18410
18567
  // ─── CLI / ACP commands ───
18411
18568
  case "launch_cli":
18412
18569
  case "stop_cli":
18570
+ case "set_cli_view_mode":
18413
18571
  case "agent_command": {
18414
18572
  return this.deps.cliManager.handleCliCommand(cmd, args);
18415
18573
  }
@@ -18762,6 +18920,20 @@ var init_reporter = __esm({
18762
18920
  ts() {
18763
18921
  return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
18764
18922
  }
18923
+ summarizeLargePayloadSessions(payload) {
18924
+ const sessions = Array.isArray(payload.sessions) ? payload.sessions : [];
18925
+ return sessions.map((session) => ({
18926
+ id: String(session?.id || ""),
18927
+ providerType: String(session?.providerType || ""),
18928
+ bytes: (() => {
18929
+ try {
18930
+ return JSON.stringify(session).length;
18931
+ } catch {
18932
+ return 0;
18933
+ }
18934
+ })()
18935
+ })).sort((a, b2) => b2.bytes - a.bytes).slice(0, 3).map((session) => `${session.providerType || "unknown"}:${session.id}=${session.bytes}b`).join(", ");
18936
+ }
18765
18937
  async sendUnifiedStatusReport(opts) {
18766
18938
  const { serverConn, p2p } = this.deps;
18767
18939
  if (!serverConn?.isConnected()) return;
@@ -18814,9 +18986,16 @@ var init_reporter = __esm({
18814
18986
  screenshotUsage: this.deps.getScreenshotUsage?.() || null,
18815
18987
  connectedExtensions: []
18816
18988
  };
18989
+ const payloadBytes = JSON.stringify(payload).length;
18817
18990
  const p2pSent = this.sendP2PPayload(payload);
18818
18991
  if (p2pSent) {
18819
- LOG.debug("P2P", `sent (${JSON.stringify(payload).length} bytes)`);
18992
+ LOG.debug("P2P", `sent (${payloadBytes} bytes)`);
18993
+ if (payloadBytes > 256 * 1024) {
18994
+ LOG.warn(
18995
+ "P2P",
18996
+ `large status payload (${payloadBytes} bytes) top sessions: ${this.summarizeLargePayloadSessions(payload) || "n/a"}`
18997
+ );
18998
+ }
18820
18999
  }
18821
19000
  if (opts?.p2pOnly) return;
18822
19001
  const wsPayload = {
@@ -18846,7 +19025,9 @@ var init_reporter = __esm({
18846
19025
  acpModes: session.acpModes
18847
19026
  })),
18848
19027
  p2p: payload.p2p,
18849
- timestamp: now
19028
+ timestamp: now,
19029
+ detectedIdes: payload.detectedIdes,
19030
+ availableProviders: payload.availableProviders
18850
19031
  };
18851
19032
  serverConn.sendMessage("status_report", wsPayload);
18852
19033
  LOG.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
@@ -19218,6 +19399,13 @@ var init_provider_cli_adapter = __esm({
19218
19399
  this.messages = [...this.committedMessages];
19219
19400
  this.structuredMessages = [...this.committedMessages];
19220
19401
  }
19402
+ normalizeParsedMessages(parsedMessages) {
19403
+ return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
19404
+ role: message.role,
19405
+ content: typeof message.content === "string" ? message.content : String(message.content || ""),
19406
+ timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : Date.now()
19407
+ }));
19408
+ }
19221
19409
  sliceFromOffset(text, start) {
19222
19410
  if (!text) return "";
19223
19411
  if (!Number.isFinite(start) || start <= 0) return text;
@@ -19614,6 +19802,15 @@ var init_provider_cli_adapter = __esm({
19614
19802
  this.onStatusChange?.();
19615
19803
  }
19616
19804
  commitCurrentTranscript() {
19805
+ const parsed = this.parseCurrentTranscript(
19806
+ this.committedMessages,
19807
+ this.responseBuffer,
19808
+ this.currentTurnScope
19809
+ );
19810
+ if (parsed && Array.isArray(parsed.messages)) {
19811
+ this.committedMessages = this.normalizeParsedMessages(parsed.messages);
19812
+ this.syncMessageViews();
19813
+ }
19617
19814
  }
19618
19815
  // ─── Script Execution ──────────────────────────
19619
19816
  runDetectStatus(text) {
@@ -19658,6 +19855,21 @@ var init_provider_cli_adapter = __esm({
19658
19855
  * Called by command handler / dashboard for rich content rendering.
19659
19856
  */
19660
19857
  getScriptParsedStatus() {
19858
+ const parsed = this.parseCurrentTranscript(
19859
+ this.committedMessages,
19860
+ this.responseBuffer,
19861
+ this.currentTurnScope
19862
+ );
19863
+ if (parsed && Array.isArray(parsed.messages)) {
19864
+ return {
19865
+ id: parsed.id || "cli_session",
19866
+ status: parsed.status || this.currentStatus,
19867
+ title: parsed.title || this.cliName,
19868
+ terminalHistory: this.terminalHistory,
19869
+ messages: parsed.messages,
19870
+ activeModal: parsed.activeModal ?? this.activeModal
19871
+ };
19872
+ }
19661
19873
  const messages = [...this.committedMessages];
19662
19874
  return {
19663
19875
  id: "cli_session",
@@ -20103,6 +20315,7 @@ var init_cli_provider_instance = __esm({
20103
20315
  this.cliArgs = cliArgs;
20104
20316
  this.type = provider.type;
20105
20317
  this.instanceId = instanceId || crypto3.randomUUID();
20318
+ this.presentationMode = "terminal";
20106
20319
  this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
20107
20320
  this.monitor = new StatusMonitor();
20108
20321
  this.historyWriter = new ChatHistoryWriter();
@@ -20121,6 +20334,7 @@ var init_cli_provider_instance = __esm({
20121
20334
  lastApprovalEventAt = 0;
20122
20335
  historyWriter;
20123
20336
  instanceId;
20337
+ presentationMode;
20124
20338
  // ─── Lifecycle ─────────────────────────────────
20125
20339
  async init(context) {
20126
20340
  this.context = context;
@@ -20145,6 +20359,7 @@ var init_cli_provider_instance = __esm({
20145
20359
  }
20146
20360
  getState() {
20147
20361
  const adapterStatus = this.adapter.getStatus();
20362
+ const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
20148
20363
  const runtime = this.adapter.getRuntimeMetadata();
20149
20364
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
20150
20365
  if (adapterStatus.terminalHistory?.trim()) {
@@ -20160,13 +20375,13 @@ var init_cli_provider_instance = __esm({
20160
20375
  name: this.provider.name,
20161
20376
  category: "cli",
20162
20377
  status: adapterStatus.status,
20163
- mode: "terminal",
20378
+ mode: this.presentationMode,
20164
20379
  activeChat: {
20165
20380
  id: `${this.type}_${this.workingDir}`,
20166
- title: `${this.provider.name} \xB7 ${dirName}`,
20167
- status: adapterStatus.status,
20168
- messages: [],
20169
- activeModal: adapterStatus.activeModal,
20381
+ title: parsedStatus?.title || `${this.provider.name} \xB7 ${dirName}`,
20382
+ status: parsedStatus?.status || adapterStatus.status,
20383
+ messages: Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [],
20384
+ activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
20170
20385
  terminalHistory: adapterStatus.terminalHistory,
20171
20386
  inputContent: ""
20172
20387
  },
@@ -20189,6 +20404,13 @@ var init_cli_provider_instance = __esm({
20189
20404
  providerControls: this.provider.controls
20190
20405
  };
20191
20406
  }
20407
+ setPresentationMode(mode) {
20408
+ if (this.presentationMode === mode) return;
20409
+ this.presentationMode = mode;
20410
+ }
20411
+ getPresentationMode() {
20412
+ return this.presentationMode;
20413
+ }
20192
20414
  onEvent(event, data) {
20193
20415
  if (event === "send_message" && data?.text) {
20194
20416
  void this.adapter.sendMessage(data.text).catch((e) => {
@@ -20449,7 +20671,7 @@ __export(util_exports, {
20449
20671
  getSizableOrigin: () => getSizableOrigin,
20450
20672
  hexToUint8Array: () => hexToUint8Array,
20451
20673
  isObject: () => isObject,
20452
- isPlainObject: () => isPlainObject,
20674
+ isPlainObject: () => isPlainObject2,
20453
20675
  issue: () => issue,
20454
20676
  joinValues: () => joinValues,
20455
20677
  jsonStringifyReplacer: () => jsonStringifyReplacer,
@@ -20618,7 +20840,7 @@ function slugify(input) {
20618
20840
  function isObject(data) {
20619
20841
  return typeof data === "object" && data !== null && !Array.isArray(data);
20620
20842
  }
20621
- function isPlainObject(o) {
20843
+ function isPlainObject2(o) {
20622
20844
  if (isObject(o) === false)
20623
20845
  return false;
20624
20846
  const ctor = o.constructor;
@@ -20635,7 +20857,7 @@ function isPlainObject(o) {
20635
20857
  return true;
20636
20858
  }
20637
20859
  function shallowClone(o) {
20638
- if (isPlainObject(o))
20860
+ if (isPlainObject2(o))
20639
20861
  return { ...o };
20640
20862
  if (Array.isArray(o))
20641
20863
  return [...o];
@@ -20771,7 +20993,7 @@ function omit(schema, mask) {
20771
20993
  return clone(schema, def);
20772
20994
  }
20773
20995
  function extend(schema, shape) {
20774
- if (!isPlainObject(shape)) {
20996
+ if (!isPlainObject2(shape)) {
20775
20997
  throw new Error("Invalid input to extend: expected a plain object");
20776
20998
  }
20777
20999
  const checks = schema._zod.def.checks;
@@ -20794,7 +21016,7 @@ function extend(schema, shape) {
20794
21016
  return clone(schema, def);
20795
21017
  }
20796
21018
  function safeExtend(schema, shape) {
20797
- if (!isPlainObject(shape)) {
21019
+ if (!isPlainObject2(shape)) {
20798
21020
  throw new Error("Invalid input to safeExtend: expected a plain object");
20799
21021
  }
20800
21022
  const def = mergeDefs(schema._zod.def, {
@@ -22277,7 +22499,7 @@ function mergeValues(a, b2) {
22277
22499
  if (a instanceof Date && b2 instanceof Date && +a === +b2) {
22278
22500
  return { valid: true, data: a };
22279
22501
  }
22280
- if (isPlainObject(a) && isPlainObject(b2)) {
22502
+ if (isPlainObject2(a) && isPlainObject2(b2)) {
22281
22503
  const bKeys = Object.keys(b2);
22282
22504
  const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
22283
22505
  const newObj = { ...a, ...b2 };
@@ -23472,7 +23694,7 @@ var init_schemas = __esm({
23472
23694
  $ZodType.init(inst, def);
23473
23695
  inst._zod.parse = (payload, ctx) => {
23474
23696
  const input = payload.value;
23475
- if (!isPlainObject(input)) {
23697
+ if (!isPlainObject2(input)) {
23476
23698
  payload.issues.push({
23477
23699
  expected: "record",
23478
23700
  code: "invalid_type",
@@ -37576,6 +37798,15 @@ var init_cli_manager = __esm({
37576
37798
  const hash2 = require("crypto").createHash("md5").update(require("path").resolve(dir)).digest("hex").slice(0, 8);
37577
37799
  return `${cliType}_${hash2}`;
37578
37800
  }
37801
+ getSessionPresentationMode(sessionId) {
37802
+ if (!sessionId) return null;
37803
+ const instance = this.deps.getInstanceManager()?.getInstance(sessionId);
37804
+ const mode = instance?.category === "cli" ? instance.getPresentationMode?.() : null;
37805
+ return mode === "chat" || mode === "terminal" ? mode : null;
37806
+ }
37807
+ isTerminalSession(sessionId) {
37808
+ return this.getSessionPresentationMode(sessionId) === "terminal";
37809
+ }
37579
37810
  persistRecentActivity(entry) {
37580
37811
  try {
37581
37812
  saveConfig(appendRecentActivity(loadConfig(), entry));
@@ -37754,6 +37985,7 @@ ${installInfo}`
37754
37985
  if (provider) {
37755
37986
  console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
37756
37987
  }
37988
+ const resolvedCliArgs = cliArgs;
37757
37989
  const instanceManager = this.deps.getInstanceManager();
37758
37990
  if (provider && instanceManager) {
37759
37991
  const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
@@ -37762,14 +37994,14 @@ ${installInfo}`
37762
37994
  normalizedType,
37763
37995
  cliType,
37764
37996
  resolvedDir,
37765
- cliArgs,
37997
+ resolvedCliArgs,
37766
37998
  resolvedProvider,
37767
37999
  {},
37768
38000
  false
37769
38001
  );
37770
38002
  console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
37771
38003
  } else {
37772
- const adapter = this.createAdapter(cliType, resolvedDir, cliArgs, key, false);
38004
+ const adapter = this.createAdapter(cliType, resolvedDir, resolvedCliArgs, key, false);
37773
38005
  try {
37774
38006
  await adapter.spawn();
37775
38007
  } catch (spawnErr) {
@@ -37919,6 +38151,14 @@ ${installInfo}`
37919
38151
  }
37920
38152
  return null;
37921
38153
  }
38154
+ findAdapterBySessionId(instanceKey) {
38155
+ if (!instanceKey) return null;
38156
+ let ik = instanceKey;
38157
+ const colonIdx = ik.lastIndexOf(":");
38158
+ if (colonIdx >= 0) ik = ik.substring(colonIdx + 1);
38159
+ const adapter = this.adapters.get(ik);
38160
+ return adapter ? { adapter, key: ik } : null;
38161
+ }
37922
38162
  // ─── CLI command handling ────────────────────────────
37923
38163
  async handleCliCommand(cmd, args) {
37924
38164
  switch (cmd) {
@@ -37969,6 +38209,23 @@ ${installInfo}`
37969
38209
  }
37970
38210
  return { success: true, cliType, dir, stopped: true, mode };
37971
38211
  }
38212
+ case "set_cli_view_mode": {
38213
+ const mode = args?.mode === "chat" ? "chat" : "terminal";
38214
+ const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId : "";
38215
+ const cliType = args?.cliType || args?.agentType || "";
38216
+ const dir = args?.dir || "";
38217
+ const found = this.findAdapterBySessionId(targetSessionId) || (cliType ? this.findAdapter(cliType, { instanceKey: targetSessionId, dir }) : null);
38218
+ if (!found) {
38219
+ return { success: false, error: "CLI session not found", code: "CLI_SESSION_NOT_FOUND" };
38220
+ }
38221
+ const instance = this.deps.getInstanceManager()?.getInstance(found.key);
38222
+ if (!(instance instanceof CliProviderInstance)) {
38223
+ return { success: false, error: "CLI instance not found", code: "CLI_INSTANCE_NOT_FOUND" };
38224
+ }
38225
+ instance.setPresentationMode(mode);
38226
+ this.deps.onStatusChange();
38227
+ return { success: true, id: found.key, mode };
38228
+ }
37972
38229
  case "restart_session": {
37973
38230
  const cliType = args?.cliType || args?.agentType || args?.ideType;
37974
38231
  const cfg = loadConfig();
@@ -38620,7 +38877,12 @@ var init_poller = __esm({
38620
38877
  } catch {
38621
38878
  }
38622
38879
  }
38623
- if (!resolvedActiveSessionId || !parentSessionId) continue;
38880
+ if (!resolvedActiveSessionId || !parentSessionId) {
38881
+ if (parentSessionId) {
38882
+ this.deps.onStreamsUpdated?.(ideType, []);
38883
+ }
38884
+ continue;
38885
+ }
38624
38886
  try {
38625
38887
  await agentStreamManager.syncActiveSession(cdp, parentSessionId);
38626
38888
  const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
@@ -38648,7 +38910,11 @@ var init_agent_stream = __esm({
38648
38910
  function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
38649
38911
  const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
38650
38912
  if (!ideInstance?.onEvent) return;
38913
+ const seenExtensionTypes = /* @__PURE__ */ new Set();
38651
38914
  for (const stream of streams) {
38915
+ if (typeof stream.agentType === "string" && stream.agentType) {
38916
+ seenExtensionTypes.add(stream.agentType);
38917
+ }
38652
38918
  ideInstance.onEvent("stream_update", {
38653
38919
  extensionType: stream.agentType,
38654
38920
  streams: [stream],
@@ -38665,6 +38931,16 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
38665
38931
  inputContent: stream.inputContent || ""
38666
38932
  });
38667
38933
  }
38934
+ const extensionTypes = ideInstance.getExtensionTypes?.() || [];
38935
+ if (streams.length === 0) {
38936
+ ideInstance.onEvent("stream_reset_all");
38937
+ return;
38938
+ }
38939
+ for (const extensionType of extensionTypes) {
38940
+ if (!seenExtensionTypes.has(extensionType)) {
38941
+ ideInstance.onEvent("stream_reset", { extensionType });
38942
+ }
38943
+ }
38668
38944
  }
38669
38945
  var init_forward = __esm({
38670
38946
  "../../oss/packages/daemon-core/src/agent-stream/forward.ts"() {
@@ -44408,13 +44684,8 @@ var init_server_connection = __esm({
44408
44684
  LOG.info("Server", `[ServerConn] Run 'adhdev setup' to re-authenticate.`);
44409
44685
  this.setState("disconnected");
44410
44686
  try {
44411
- const path18 = require("path");
44412
- const fs16 = require("fs");
44413
- const configPath = path18.join(process.env.HOME || process.env.USERPROFILE || "", ".adhdev", "config.json");
44414
- if (fs16.existsSync(configPath)) {
44415
- fs16.unlinkSync(configPath);
44416
- LOG.info("Server", `[ServerConn] Config file removed. Re-run 'adhdev setup'.`);
44417
- }
44687
+ resetConfig();
44688
+ LOG.info("Server", `[ServerConn] Config reset. Re-run 'adhdev setup'.`);
44418
44689
  } catch {
44419
44690
  }
44420
44691
  return;
@@ -44683,10 +44954,9 @@ ${e?.stack || ""}`);
44683
44954
  async fetchTurnCredentials() {
44684
44955
  try {
44685
44956
  const serverUrl = process.env.ADHDEV_SERVER_URL || "https://api.adhf.dev";
44686
- const configPath = path15.join(os18.homedir(), ".adhdev", "config.json");
44687
44957
  let token = "";
44688
44958
  try {
44689
- const config2 = JSON.parse(fs13.readFileSync(configPath, "utf-8"));
44959
+ const config2 = loadConfig();
44690
44960
  token = config2.machineSecret || "";
44691
44961
  } catch {
44692
44962
  }
@@ -44985,8 +45255,9 @@ ${e?.stack || ""}`);
44985
45255
  log(`pty_input: REJECTED \u2014 permission=${permission} peer=${peerId}`);
44986
45256
  return;
44987
45257
  }
44988
- if (this.ptyInputHandler && parsed.data) {
44989
- this.ptyInputHandler(parsed.cliType || "", parsed.data);
45258
+ const sessionId = parsed.sessionId || parsed.cliId || parsed.cliType || "";
45259
+ if (this.ptyInputHandler && parsed.data && sessionId) {
45260
+ this.ptyInputHandler(sessionId, parsed.data);
44990
45261
  }
44991
45262
  return;
44992
45263
  }
@@ -44996,8 +45267,9 @@ ${e?.stack || ""}`);
44996
45267
  log(`pty_resize: REJECTED \u2014 permission=${permission} peer=${peerId}`);
44997
45268
  return;
44998
45269
  }
44999
- if (this.ptyResizeHandler && parsed.cols && parsed.rows) {
45000
- this.ptyResizeHandler(parsed.cliType || "", parsed.cols, parsed.rows);
45270
+ const sessionId = parsed.sessionId || parsed.cliId || parsed.cliType || "";
45271
+ if (this.ptyResizeHandler && parsed.cols && parsed.rows && sessionId) {
45272
+ this.ptyResizeHandler(sessionId, parsed.cols, parsed.rows);
45001
45273
  }
45002
45274
  return;
45003
45275
  }
@@ -45025,8 +45297,8 @@ ${e?.stack || ""}`);
45025
45297
  return sentAny;
45026
45298
  }
45027
45299
  /** Broadcast PTY output to all connected peers */
45028
- broadcastPtyOutput(cliType, data) {
45029
- const msg = JSON.stringify({ type: "pty_output", cliType, data });
45300
+ broadcastPtyOutput(sessionId, data) {
45301
+ const msg = JSON.stringify({ type: "pty_output", sessionId, data });
45030
45302
  let sentAny = false;
45031
45303
  for (const peer of this.peers.values()) {
45032
45304
  if (peer.state !== "connected" || !peer.dataChannel) continue;
@@ -45660,7 +45932,7 @@ var init_adhdev_daemon = __esm({
45660
45932
  fs15 = __toESM(require("fs"));
45661
45933
  path17 = __toESM(require("path"));
45662
45934
  import_chalk2 = __toESM(require("chalk"));
45663
- pkgVersion = "0.7.40";
45935
+ pkgVersion = "0.7.42";
45664
45936
  if (pkgVersion === "unknown") {
45665
45937
  try {
45666
45938
  const possiblePaths = [
@@ -45705,6 +45977,16 @@ var init_adhdev_daemon = __esm({
45705
45977
  constructor() {
45706
45978
  this.localPort = 19222;
45707
45979
  }
45980
+ getCliPresentationMode(sessionId) {
45981
+ if (!sessionId || !this.components) return null;
45982
+ const instance = this.components.instanceManager.getInstance(sessionId);
45983
+ if (instance?.category !== "cli") return null;
45984
+ const mode = instance.getPresentationMode?.();
45985
+ return mode === "chat" || mode === "terminal" ? mode : null;
45986
+ }
45987
+ isTerminalCliSession(sessionId) {
45988
+ return this.getCliPresentationMode(sessionId) === "terminal";
45989
+ }
45708
45990
  async start(options = {}) {
45709
45991
  try {
45710
45992
  const { installGlobalInterceptor: installGlobalInterceptor2 } = require("./logging/logger");
@@ -45734,9 +46016,6 @@ ${err?.stack || ""}`);
45734
46016
  const authToken = config2.machineSecret;
45735
46017
  if (!authToken) {
45736
46018
  console.log(import_chalk2.default.red("\n\u2717 No machine secret found."));
45737
- if (config2.connectionToken) {
45738
- console.log(import_chalk2.default.yellow(" Legacy connectionToken detected \u2014 please re-run setup."));
45739
- }
45740
46019
  console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
45741
46020
  process.exit(1);
45742
46021
  }
@@ -45746,7 +46025,12 @@ ${err?.stack || ""}`);
45746
46025
  providerLogFn: LOG.forComponent("Provider").asLogFn(),
45747
46026
  cliManagerDeps: {
45748
46027
  getServerConn: () => this.serverConn,
45749
- getP2p: () => this.p2p,
46028
+ getP2p: () => ({
46029
+ broadcastPtyOutput: (key, data) => {
46030
+ if (!this.isTerminalCliSession(key)) return;
46031
+ this.p2p?.broadcastPtyOutput(key, data);
46032
+ }
46033
+ }),
45750
46034
  onStatusChange: () => this.statusReporter?.onStatusChange(),
45751
46035
  removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
45752
46036
  createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, attachExisting }) => new SessionHostPtyTransportFactory({
@@ -45823,14 +46107,16 @@ ${err?.stack || ""}`);
45823
46107
  return { id: req.id, success: result.success, entries: result.files, error: result.error };
45824
46108
  }
45825
46109
  });
45826
- this.p2p.onPtyInput((cliId, data) => {
45827
- const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
46110
+ this.p2p.onPtyInput((sessionId, data) => {
46111
+ if (!this.isTerminalCliSession(sessionId)) return;
46112
+ const found = this.components.cliManager.findAdapter(sessionId, { instanceKey: sessionId });
45828
46113
  if (found && typeof found.adapter.writeRaw === "function") {
45829
46114
  found.adapter.writeRaw(data);
45830
46115
  }
45831
46116
  });
45832
- this.p2p.onPtyResize((cliId, cols, rows) => {
45833
- const found = this.components.cliManager.findAdapter(cliId, { instanceKey: cliId });
46117
+ this.p2p.onPtyResize((sessionId, cols, rows) => {
46118
+ if (!this.isTerminalCliSession(sessionId)) return;
46119
+ const found = this.components.cliManager.findAdapter(sessionId, { instanceKey: sessionId });
45834
46120
  if (found && typeof found.adapter.resize === "function") {
45835
46121
  found.adapter.resize(cols, rows);
45836
46122
  }
@@ -46006,6 +46292,9 @@ ${err?.stack || ""}`);
46006
46292
  case "get_runtime_snapshot": {
46007
46293
  const sessionId = typeof data.sessionId === "string" ? data.sessionId : "";
46008
46294
  if (!sessionId) return { success: false, error: "sessionId is required" };
46295
+ if (!this.isTerminalCliSession(sessionId)) {
46296
+ return { success: false, error: "CLI session is not in terminal mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
46297
+ }
46009
46298
  if (!this.sessionHostEndpoint) return { success: false, error: "Session host unavailable" };
46010
46299
  const client = new SessionHostClient({ endpoint: this.sessionHostEndpoint });
46011
46300
  try {
@@ -46855,7 +47144,6 @@ function registerSetupCommands(program2, providerLoader) {
46855
47144
  console.log(import_chalk4.default.gray(` \u2022 ${ext}`));
46856
47145
  });
46857
47146
  console.log(` ${import_chalk4.default.bold("User:")} ${config2.userEmail || import_chalk4.default.gray("not logged in")}`);
46858
- console.log(` ${import_chalk4.default.bold("Auto-connect:")} ${config2.autoConnect ? import_chalk4.default.green("enabled") : import_chalk4.default.gray("disabled")}`);
46859
47147
  console.log(` ${import_chalk4.default.bold("Server:")} ${config2.serverUrl}`);
46860
47148
  console.log(` ${import_chalk4.default.bold("Setup date:")} ${config2.setupDate || "unknown"}`);
46861
47149
  console.log();
@@ -46951,7 +47239,6 @@ function registerSetupCommands(program2, providerLoader) {
46951
47239
  } catch {
46952
47240
  }
46953
47241
  const config2 = loadConfig2();
46954
- config2.apiToken = null;
46955
47242
  config2.machineSecret = void 0;
46956
47243
  config2.userEmail = null;
46957
47244
  config2.userName = null;