@adhdev/daemon-core 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
@@ -33,7 +33,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
33
33
  // src/config/config.ts
34
34
  var config_exports = {};
35
35
  __export(config_exports, {
36
- generateConnectionToken: () => generateConnectionToken,
37
36
  generateMachineId: () => generateMachineId,
38
37
  getConfigDir: () => getConfigDir,
39
38
  isSetupComplete: () => isSetupComplete,
@@ -44,6 +43,57 @@ __export(config_exports, {
44
43
  saveConfig: () => saveConfig,
45
44
  updateConfig: () => updateConfig
46
45
  });
46
+ function isPlainObject(value) {
47
+ return !!value && typeof value === "object" && !Array.isArray(value);
48
+ }
49
+ function asStringArray(value) {
50
+ if (!Array.isArray(value)) return [];
51
+ return value.filter((item) => typeof item === "string");
52
+ }
53
+ function asNullableString(value) {
54
+ return typeof value === "string" ? value : null;
55
+ }
56
+ function asOptionalString(value) {
57
+ return typeof value === "string" && value.trim() ? value : void 0;
58
+ }
59
+ function asBoolean(value, fallback) {
60
+ return typeof value === "boolean" ? value : fallback;
61
+ }
62
+ function normalizeConfig(raw) {
63
+ const parsed = isPlainObject(raw) ? raw : {};
64
+ const legacySessionReads = isPlainObject(parsed.recentSessionReads) ? parsed.recentSessionReads : {};
65
+ const sessionReads = isPlainObject(parsed.sessionReads) ? parsed.sessionReads : {};
66
+ const mergedSessionReads = Object.fromEntries(
67
+ Object.entries({ ...legacySessionReads, ...sessionReads }).filter(([, value]) => typeof value === "number" && Number.isFinite(value))
68
+ );
69
+ const sessionReadMarkers = Object.fromEntries(
70
+ Object.entries(isPlainObject(parsed.sessionReadMarkers) ? parsed.sessionReadMarkers : {}).filter(([, value]) => typeof value === "string")
71
+ );
72
+ return {
73
+ serverUrl: typeof parsed.serverUrl === "string" && parsed.serverUrl.trim() ? parsed.serverUrl : DEFAULT_CONFIG.serverUrl,
74
+ selectedIde: asNullableString(parsed.selectedIde),
75
+ configuredIdes: asStringArray(parsed.configuredIdes),
76
+ installedExtensions: asStringArray(parsed.installedExtensions),
77
+ userEmail: asNullableString(parsed.userEmail),
78
+ userName: asNullableString(parsed.userName),
79
+ setupCompleted: asBoolean(parsed.setupCompleted, DEFAULT_CONFIG.setupCompleted),
80
+ setupDate: asNullableString(parsed.setupDate),
81
+ enabledIdes: asStringArray(parsed.enabledIdes),
82
+ workspaces: Array.isArray(parsed.workspaces) ? parsed.workspaces : [],
83
+ defaultWorkspaceId: asNullableString(parsed.defaultWorkspaceId) ?? asNullableString(parsed.activeWorkspaceId),
84
+ recentActivity: Array.isArray(parsed.recentActivity) ? parsed.recentActivity : [],
85
+ sessionReads: mergedSessionReads,
86
+ sessionReadMarkers,
87
+ machineNickname: asNullableString(parsed.machineNickname),
88
+ machineId: asOptionalString(parsed.machineId),
89
+ machineSecret: parsed.machineSecret === null ? null : asOptionalString(parsed.machineSecret),
90
+ registeredMachineId: asOptionalString(parsed.registeredMachineId),
91
+ providerSettings: isPlainObject(parsed.providerSettings) ? parsed.providerSettings : {},
92
+ ideSettings: isPlainObject(parsed.ideSettings) ? parsed.ideSettings : {},
93
+ disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
94
+ providerDir: asOptionalString(parsed.providerDir)
95
+ };
96
+ }
47
97
  function generateMachineId() {
48
98
  return `${MACHINE_ID_PREFIX}${(0, import_crypto.randomUUID)().replace(/-/g, "")}`;
49
99
  }
@@ -87,14 +137,10 @@ function loadConfig() {
87
137
  try {
88
138
  const raw = (0, import_fs.readFileSync)(configPath, "utf-8");
89
139
  const parsed = JSON.parse(raw);
90
- const merged = { ...DEFAULT_CONFIG, ...parsed };
91
- if (merged.defaultWorkspaceId == null && merged.activeWorkspaceId != null) {
92
- merged.defaultWorkspaceId = merged.activeWorkspaceId;
93
- }
94
- delete merged.activeWorkspaceId;
95
- const ensured = ensureMachineId(merged);
140
+ const normalizedInput = normalizeConfig(parsed);
141
+ const ensured = ensureMachineId(normalizedInput);
96
142
  const normalized = ensured.config;
97
- if (ensured.changed) {
143
+ if (ensured.changed || JSON.stringify(parsed) !== JSON.stringify(normalized)) {
98
144
  try {
99
145
  saveConfig(normalized);
100
146
  } catch {
@@ -109,10 +155,11 @@ function loadConfig() {
109
155
  function saveConfig(config) {
110
156
  const configPath = getConfigPath();
111
157
  const dir = getConfigDir();
158
+ const normalized = normalizeConfig(config);
112
159
  if (!(0, import_fs.existsSync)(dir)) {
113
160
  (0, import_fs.mkdirSync)(dir, { recursive: true, mode: 448 });
114
161
  }
115
- (0, import_fs.writeFileSync)(configPath, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
162
+ (0, import_fs.writeFileSync)(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
116
163
  try {
117
164
  (0, import_fs.chmodSync)(configPath, 384);
118
165
  } catch {
@@ -141,14 +188,6 @@ function isSetupComplete() {
141
188
  function resetConfig() {
142
189
  saveConfig({ ...DEFAULT_CONFIG });
143
190
  }
144
- function generateConnectionToken() {
145
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
146
- let token = "db_";
147
- for (let i = 0; i < 32; i++) {
148
- token += chars.charAt(Math.floor(Math.random() * chars.length));
149
- }
150
- return token;
151
- }
152
191
  var import_os, import_path, import_fs, import_crypto, DEFAULT_CONFIG, MACHINE_ID_PREFIX;
153
192
  var init_config = __esm({
154
193
  "src/config/config.ts"() {
@@ -159,18 +198,13 @@ var init_config = __esm({
159
198
  import_crypto = require("crypto");
160
199
  DEFAULT_CONFIG = {
161
200
  serverUrl: "https://api.adhf.dev",
162
- apiToken: null,
163
- connectionToken: null,
164
201
  selectedIde: null,
165
202
  configuredIdes: [],
166
203
  installedExtensions: [],
167
- autoConnect: true,
168
- notifications: true,
169
204
  userEmail: null,
170
205
  userName: null,
171
206
  setupCompleted: false,
172
207
  setupDate: null,
173
- configuredCLIs: [],
174
208
  enabledIdes: [],
175
209
  workspaces: [],
176
210
  defaultWorkspaceId: null,
@@ -983,6 +1017,13 @@ var init_provider_cli_adapter = __esm({
983
1017
  this.messages = [...this.committedMessages];
984
1018
  this.structuredMessages = [...this.committedMessages];
985
1019
  }
1020
+ normalizeParsedMessages(parsedMessages) {
1021
+ return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
1022
+ role: message.role,
1023
+ content: typeof message.content === "string" ? message.content : String(message.content || ""),
1024
+ timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : Date.now()
1025
+ }));
1026
+ }
986
1027
  sliceFromOffset(text, start) {
987
1028
  if (!text) return "";
988
1029
  if (!Number.isFinite(start) || start <= 0) return text;
@@ -1379,6 +1420,15 @@ var init_provider_cli_adapter = __esm({
1379
1420
  this.onStatusChange?.();
1380
1421
  }
1381
1422
  commitCurrentTranscript() {
1423
+ const parsed = this.parseCurrentTranscript(
1424
+ this.committedMessages,
1425
+ this.responseBuffer,
1426
+ this.currentTurnScope
1427
+ );
1428
+ if (parsed && Array.isArray(parsed.messages)) {
1429
+ this.committedMessages = this.normalizeParsedMessages(parsed.messages);
1430
+ this.syncMessageViews();
1431
+ }
1382
1432
  }
1383
1433
  // ─── Script Execution ──────────────────────────
1384
1434
  runDetectStatus(text) {
@@ -1423,6 +1473,21 @@ var init_provider_cli_adapter = __esm({
1423
1473
  * Called by command handler / dashboard for rich content rendering.
1424
1474
  */
1425
1475
  getScriptParsedStatus() {
1476
+ const parsed = this.parseCurrentTranscript(
1477
+ this.committedMessages,
1478
+ this.responseBuffer,
1479
+ this.currentTurnScope
1480
+ );
1481
+ if (parsed && Array.isArray(parsed.messages)) {
1482
+ return {
1483
+ id: parsed.id || "cli_session",
1484
+ status: parsed.status || this.currentStatus,
1485
+ title: parsed.title || this.cliName,
1486
+ terminalHistory: this.terminalHistory,
1487
+ messages: parsed.messages,
1488
+ activeModal: parsed.activeModal ?? this.activeModal
1489
+ };
1490
+ }
1426
1491
  const messages = [...this.committedMessages];
1427
1492
  return {
1428
1493
  id: "cli_session",
@@ -3823,6 +3888,8 @@ var ExtensionProviderInstance = class {
3823
3888
  this.detectTransition(newStatus, data);
3824
3889
  this.currentStatus = newStatus;
3825
3890
  }
3891
+ } else if (event === "stream_reset") {
3892
+ this.resetStreamState();
3826
3893
  } else if (event === "extension_connected") {
3827
3894
  this.ideType = data?.ideType || "";
3828
3895
  }
@@ -3902,6 +3969,30 @@ var ExtensionProviderInstance = class {
3902
3969
  const title = typeof data?.title === "string" && data.title.trim() ? data.title.trim() : this.chatTitle;
3903
3970
  return title || this.agentName || this.provider.name;
3904
3971
  }
3972
+ resetStreamState() {
3973
+ if (this.currentStatus !== "idle") {
3974
+ this.detectTransition("idle", {
3975
+ title: this.chatTitle,
3976
+ agentName: this.agentName,
3977
+ extensionId: this.extensionId,
3978
+ messages: this.messages
3979
+ });
3980
+ }
3981
+ this.agentStreams = [];
3982
+ this.messages = [];
3983
+ this.activeModal = null;
3984
+ this.currentModel = "";
3985
+ this.currentMode = "";
3986
+ this.controlValues = {};
3987
+ this.currentStatus = "idle";
3988
+ this.chatId = null;
3989
+ this.chatTitle = null;
3990
+ this.agentName = "";
3991
+ this.extensionId = "";
3992
+ this.lastAgentStatus = "idle";
3993
+ this.generatingStartedAt = 0;
3994
+ this.monitor.reset();
3995
+ }
3905
3996
  };
3906
3997
 
3907
3998
  // src/config/chat-history.ts
@@ -4184,11 +4275,23 @@ var IdeProviderInstance = class {
4184
4275
  } else if (event === "cdp_disconnected") {
4185
4276
  this.cachedChat = null;
4186
4277
  this.currentStatus = "idle";
4278
+ for (const ext of this.extensions.values()) {
4279
+ ext.onEvent("stream_reset");
4280
+ }
4187
4281
  } else if (event === "stream_update") {
4188
4282
  const extType = data?.extensionType;
4189
4283
  if (extType && this.extensions.has(extType)) {
4190
4284
  this.extensions.get(extType).onEvent("stream_update", data);
4191
4285
  }
4286
+ } else if (event === "stream_reset") {
4287
+ const extType = data?.extensionType;
4288
+ if (extType && this.extensions.has(extType)) {
4289
+ this.extensions.get(extType).onEvent("stream_reset");
4290
+ }
4291
+ } else if (event === "stream_reset_all") {
4292
+ for (const ext of this.extensions.values()) {
4293
+ ext.onEvent("stream_reset");
4294
+ }
4192
4295
  }
4193
4296
  }
4194
4297
  dispose() {
@@ -4855,6 +4958,63 @@ var WORKING_STATUSES = /* @__PURE__ */ new Set([
4855
4958
  "thinking",
4856
4959
  "active"
4857
4960
  ]);
4961
+ var STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
4962
+ var STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
4963
+ var STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
4964
+ var STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
4965
+ var STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;
4966
+ var STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
4967
+ var STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
4968
+ var STATUS_MODAL_BUTTON_LIMIT = 120;
4969
+ function truncateString(value, maxChars) {
4970
+ if (value.length <= maxChars) return value;
4971
+ if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));
4972
+ return `${value.slice(0, maxChars - 12)}...[truncated]`;
4973
+ }
4974
+ function truncateStringTail(value, maxChars) {
4975
+ if (value.length <= maxChars) return value;
4976
+ if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));
4977
+ return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;
4978
+ }
4979
+ function trimStructuredStrings(value, maxChars) {
4980
+ if (typeof value === "string") return truncateString(value, maxChars);
4981
+ if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));
4982
+ if (!value || typeof value !== "object") return value;
4983
+ return Object.fromEntries(
4984
+ Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)])
4985
+ );
4986
+ }
4987
+ function estimateBytes(value) {
4988
+ try {
4989
+ return JSON.stringify(value).length;
4990
+ } catch {
4991
+ return String(value ?? "").length;
4992
+ }
4993
+ }
4994
+ function trimMessageForStatus(message, stringLimit) {
4995
+ if (!message || typeof message !== "object") return message;
4996
+ return trimStructuredStrings(message, stringLimit);
4997
+ }
4998
+ function trimMessagesForStatus(messages) {
4999
+ if (!Array.isArray(messages) || messages.length === 0) return [];
5000
+ const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
5001
+ const kept = [];
5002
+ let totalBytes = 0;
5003
+ for (let i = recent.length - 1; i >= 0; i -= 1) {
5004
+ let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
5005
+ let size = estimateBytes(normalized);
5006
+ if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
5007
+ normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
5008
+ size = estimateBytes(normalized);
5009
+ }
5010
+ if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
5011
+ continue;
5012
+ }
5013
+ kept.push(normalized);
5014
+ totalBytes += size;
5015
+ }
5016
+ return kept.reverse();
5017
+ }
4858
5018
  function hasApprovalButtons(activeModal) {
4859
5019
  return (activeModal?.buttons?.length ?? 0) > 0;
4860
5020
  }
@@ -4881,7 +5041,16 @@ function normalizeActiveChatData(activeChat) {
4881
5041
  if (!activeChat) return activeChat;
4882
5042
  return {
4883
5043
  ...activeChat,
4884
- status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal })
5044
+ status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
5045
+ messages: trimMessagesForStatus(activeChat.messages),
5046
+ activeModal: activeChat.activeModal ? {
5047
+ message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
5048
+ buttons: (activeChat.activeModal.buttons || []).map(
5049
+ (button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
5050
+ )
5051
+ } : activeChat.activeModal,
5052
+ terminalHistory: activeChat.terminalHistory ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT) : activeChat.terminalHistory,
5053
+ inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
4885
5054
  };
4886
5055
  }
4887
5056
 
@@ -4979,6 +5148,11 @@ var PTY_SESSION_CAPABILITIES = [
4979
5148
  "terminal_io",
4980
5149
  "resize_terminal"
4981
5150
  ];
5151
+ var CLI_CHAT_SESSION_CAPABILITIES = [
5152
+ "read_chat",
5153
+ "send_message",
5154
+ "resolve_action"
5155
+ ];
4982
5156
  var ACP_SESSION_CAPABILITIES = [
4983
5157
  "read_chat",
4984
5158
  "send_message",
@@ -5068,9 +5242,10 @@ function buildCliSession(state) {
5068
5242
  runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
5069
5243
  runtimeWriteOwner: state.runtime?.writeOwner || null,
5070
5244
  runtimeAttachedClients: state.runtime?.attachedClients || [],
5245
+ mode: state.mode,
5071
5246
  resume: state.resume,
5072
5247
  activeChat,
5073
- capabilities: PTY_SESSION_CAPABILITIES,
5248
+ capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES,
5074
5249
  controlValues: state.controlValues,
5075
5250
  providerControls: buildFallbackControls(
5076
5251
  state.providerControls
@@ -6244,6 +6419,13 @@ async function handleFileListBrowse(h, args) {
6244
6419
 
6245
6420
  // src/commands/stream-commands.ts
6246
6421
  init_logger();
6422
+ function getCliPresentationMode(h, targetSessionId) {
6423
+ if (!targetSessionId) return null;
6424
+ const instance = h.ctx.instanceManager?.getInstance(targetSessionId);
6425
+ if (instance?.category !== "cli") return null;
6426
+ const mode = instance.getPresentationMode?.();
6427
+ return mode === "chat" || mode === "terminal" ? mode : null;
6428
+ }
6247
6429
  async function handleFocusSession(h, args) {
6248
6430
  if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
6249
6431
  const sessionId = args?.targetSessionId || h.currentSession?.sessionId;
@@ -6254,6 +6436,9 @@ async function handleFocusSession(h, args) {
6254
6436
  function handlePtyInput(h, args) {
6255
6437
  const { cliType, data, targetSessionId } = args || {};
6256
6438
  if (!data) return { success: false, error: "data required" };
6439
+ if (getCliPresentationMode(h, targetSessionId) === "chat") {
6440
+ return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
6441
+ }
6257
6442
  const adapter = h.getCliAdapter(targetSessionId || cliType);
6258
6443
  if (!adapter || typeof adapter.writeRaw !== "function") {
6259
6444
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
@@ -6264,6 +6449,9 @@ function handlePtyInput(h, args) {
6264
6449
  function handlePtyResize(h, args) {
6265
6450
  const { cliType, cols, rows, force, targetSessionId } = args || {};
6266
6451
  if (!cols || !rows) return { success: false, error: "cols and rows required" };
6452
+ if (getCliPresentationMode(h, targetSessionId) === "chat") {
6453
+ return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
6454
+ }
6267
6455
  const adapter = h.getCliAdapter(targetSessionId || cliType);
6268
6456
  if (!adapter || typeof adapter.resize !== "function") {
6269
6457
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
@@ -8671,6 +8859,7 @@ var DaemonCommandRouter = class {
8671
8859
  // ─── CLI / ACP commands ───
8672
8860
  case "launch_cli":
8673
8861
  case "stop_cli":
8862
+ case "set_cli_view_mode":
8674
8863
  case "agent_command": {
8675
8864
  return this.deps.cliManager.handleCliCommand(cmd, args);
8676
8865
  }
@@ -9015,6 +9204,20 @@ var DaemonStatusReporter = class {
9015
9204
  ts() {
9016
9205
  return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
9017
9206
  }
9207
+ summarizeLargePayloadSessions(payload) {
9208
+ const sessions = Array.isArray(payload.sessions) ? payload.sessions : [];
9209
+ return sessions.map((session) => ({
9210
+ id: String(session?.id || ""),
9211
+ providerType: String(session?.providerType || ""),
9212
+ bytes: (() => {
9213
+ try {
9214
+ return JSON.stringify(session).length;
9215
+ } catch {
9216
+ return 0;
9217
+ }
9218
+ })()
9219
+ })).sort((a, b) => b.bytes - a.bytes).slice(0, 3).map((session) => `${session.providerType || "unknown"}:${session.id}=${session.bytes}b`).join(", ");
9220
+ }
9018
9221
  async sendUnifiedStatusReport(opts) {
9019
9222
  const { serverConn, p2p } = this.deps;
9020
9223
  if (!serverConn?.isConnected()) return;
@@ -9067,9 +9270,16 @@ var DaemonStatusReporter = class {
9067
9270
  screenshotUsage: this.deps.getScreenshotUsage?.() || null,
9068
9271
  connectedExtensions: []
9069
9272
  };
9273
+ const payloadBytes = JSON.stringify(payload).length;
9070
9274
  const p2pSent = this.sendP2PPayload(payload);
9071
9275
  if (p2pSent) {
9072
- LOG.debug("P2P", `sent (${JSON.stringify(payload).length} bytes)`);
9276
+ LOG.debug("P2P", `sent (${payloadBytes} bytes)`);
9277
+ if (payloadBytes > 256 * 1024) {
9278
+ LOG.warn(
9279
+ "P2P",
9280
+ `large status payload (${payloadBytes} bytes) top sessions: ${this.summarizeLargePayloadSessions(payload) || "n/a"}`
9281
+ );
9282
+ }
9073
9283
  }
9074
9284
  if (opts?.p2pOnly) return;
9075
9285
  const wsPayload = {
@@ -9099,7 +9309,9 @@ var DaemonStatusReporter = class {
9099
9309
  acpModes: session.acpModes
9100
9310
  })),
9101
9311
  p2p: payload.p2p,
9102
- timestamp: now
9312
+ timestamp: now,
9313
+ detectedIdes: payload.detectedIdes,
9314
+ availableProviders: payload.availableProviders
9103
9315
  };
9104
9316
  serverConn.sendMessage("status_report", wsPayload);
9105
9317
  LOG.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
@@ -9151,6 +9363,7 @@ var CliProviderInstance = class {
9151
9363
  this.cliArgs = cliArgs;
9152
9364
  this.type = provider.type;
9153
9365
  this.instanceId = instanceId || crypto3.randomUUID();
9366
+ this.presentationMode = "terminal";
9154
9367
  this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
9155
9368
  this.monitor = new StatusMonitor();
9156
9369
  this.historyWriter = new ChatHistoryWriter();
@@ -9169,6 +9382,7 @@ var CliProviderInstance = class {
9169
9382
  lastApprovalEventAt = 0;
9170
9383
  historyWriter;
9171
9384
  instanceId;
9385
+ presentationMode;
9172
9386
  // ─── Lifecycle ─────────────────────────────────
9173
9387
  async init(context) {
9174
9388
  this.context = context;
@@ -9193,6 +9407,7 @@ var CliProviderInstance = class {
9193
9407
  }
9194
9408
  getState() {
9195
9409
  const adapterStatus = this.adapter.getStatus();
9410
+ const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
9196
9411
  const runtime = this.adapter.getRuntimeMetadata();
9197
9412
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
9198
9413
  if (adapterStatus.terminalHistory?.trim()) {
@@ -9208,13 +9423,13 @@ var CliProviderInstance = class {
9208
9423
  name: this.provider.name,
9209
9424
  category: "cli",
9210
9425
  status: adapterStatus.status,
9211
- mode: "terminal",
9426
+ mode: this.presentationMode,
9212
9427
  activeChat: {
9213
9428
  id: `${this.type}_${this.workingDir}`,
9214
- title: `${this.provider.name} \xB7 ${dirName}`,
9215
- status: adapterStatus.status,
9216
- messages: [],
9217
- activeModal: adapterStatus.activeModal,
9429
+ title: parsedStatus?.title || `${this.provider.name} \xB7 ${dirName}`,
9430
+ status: parsedStatus?.status || adapterStatus.status,
9431
+ messages: Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [],
9432
+ activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
9218
9433
  terminalHistory: adapterStatus.terminalHistory,
9219
9434
  inputContent: ""
9220
9435
  },
@@ -9237,6 +9452,13 @@ var CliProviderInstance = class {
9237
9452
  providerControls: this.provider.controls
9238
9453
  };
9239
9454
  }
9455
+ setPresentationMode(mode) {
9456
+ if (this.presentationMode === mode) return;
9457
+ this.presentationMode = mode;
9458
+ }
9459
+ getPresentationMode() {
9460
+ return this.presentationMode;
9461
+ }
9240
9462
  onEvent(event, data) {
9241
9463
  if (event === "send_message" && data?.text) {
9242
9464
  void this.adapter.sendMessage(data.text).catch((e) => {
@@ -10295,6 +10517,15 @@ var DaemonCliManager = class {
10295
10517
  const hash = require("crypto").createHash("md5").update(require("path").resolve(dir)).digest("hex").slice(0, 8);
10296
10518
  return `${cliType}_${hash}`;
10297
10519
  }
10520
+ getSessionPresentationMode(sessionId) {
10521
+ if (!sessionId) return null;
10522
+ const instance = this.deps.getInstanceManager()?.getInstance(sessionId);
10523
+ const mode = instance?.category === "cli" ? instance.getPresentationMode?.() : null;
10524
+ return mode === "chat" || mode === "terminal" ? mode : null;
10525
+ }
10526
+ isTerminalSession(sessionId) {
10527
+ return this.getSessionPresentationMode(sessionId) === "terminal";
10528
+ }
10298
10529
  persistRecentActivity(entry) {
10299
10530
  try {
10300
10531
  saveConfig(appendRecentActivity(loadConfig(), entry));
@@ -10473,6 +10704,7 @@ ${installInfo}`
10473
10704
  if (provider) {
10474
10705
  console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
10475
10706
  }
10707
+ const resolvedCliArgs = cliArgs;
10476
10708
  const instanceManager = this.deps.getInstanceManager();
10477
10709
  if (provider && instanceManager) {
10478
10710
  const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
@@ -10481,14 +10713,14 @@ ${installInfo}`
10481
10713
  normalizedType,
10482
10714
  cliType,
10483
10715
  resolvedDir,
10484
- cliArgs,
10716
+ resolvedCliArgs,
10485
10717
  resolvedProvider,
10486
10718
  {},
10487
10719
  false
10488
10720
  );
10489
10721
  console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
10490
10722
  } else {
10491
- const adapter = this.createAdapter(cliType, resolvedDir, cliArgs, key, false);
10723
+ const adapter = this.createAdapter(cliType, resolvedDir, resolvedCliArgs, key, false);
10492
10724
  try {
10493
10725
  await adapter.spawn();
10494
10726
  } catch (spawnErr) {
@@ -10638,6 +10870,14 @@ ${installInfo}`
10638
10870
  }
10639
10871
  return null;
10640
10872
  }
10873
+ findAdapterBySessionId(instanceKey) {
10874
+ if (!instanceKey) return null;
10875
+ let ik = instanceKey;
10876
+ const colonIdx = ik.lastIndexOf(":");
10877
+ if (colonIdx >= 0) ik = ik.substring(colonIdx + 1);
10878
+ const adapter = this.adapters.get(ik);
10879
+ return adapter ? { adapter, key: ik } : null;
10880
+ }
10641
10881
  // ─── CLI command handling ────────────────────────────
10642
10882
  async handleCliCommand(cmd, args) {
10643
10883
  switch (cmd) {
@@ -10688,6 +10928,23 @@ ${installInfo}`
10688
10928
  }
10689
10929
  return { success: true, cliType, dir, stopped: true, mode };
10690
10930
  }
10931
+ case "set_cli_view_mode": {
10932
+ const mode = args?.mode === "chat" ? "chat" : "terminal";
10933
+ const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId : "";
10934
+ const cliType = args?.cliType || args?.agentType || "";
10935
+ const dir = args?.dir || "";
10936
+ const found = this.findAdapterBySessionId(targetSessionId) || (cliType ? this.findAdapter(cliType, { instanceKey: targetSessionId, dir }) : null);
10937
+ if (!found) {
10938
+ return { success: false, error: "CLI session not found", code: "CLI_SESSION_NOT_FOUND" };
10939
+ }
10940
+ const instance = this.deps.getInstanceManager()?.getInstance(found.key);
10941
+ if (!(instance instanceof CliProviderInstance)) {
10942
+ return { success: false, error: "CLI instance not found", code: "CLI_INSTANCE_NOT_FOUND" };
10943
+ }
10944
+ instance.setPresentationMode(mode);
10945
+ this.deps.onStatusChange();
10946
+ return { success: true, id: found.key, mode };
10947
+ }
10691
10948
  case "restart_session": {
10692
10949
  const cliType = args?.cliType || args?.agentType || args?.ideType;
10693
10950
  const cfg = loadConfig();
@@ -11306,7 +11563,12 @@ var AgentStreamPoller = class {
11306
11563
  } catch {
11307
11564
  }
11308
11565
  }
11309
- if (!resolvedActiveSessionId || !parentSessionId) continue;
11566
+ if (!resolvedActiveSessionId || !parentSessionId) {
11567
+ if (parentSessionId) {
11568
+ this.deps.onStreamsUpdated?.(ideType, []);
11569
+ }
11570
+ continue;
11571
+ }
11310
11572
  try {
11311
11573
  await agentStreamManager.syncActiveSession(cdp, parentSessionId);
11312
11574
  const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
@@ -11321,7 +11583,11 @@ var AgentStreamPoller = class {
11321
11583
  function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
11322
11584
  const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
11323
11585
  if (!ideInstance?.onEvent) return;
11586
+ const seenExtensionTypes = /* @__PURE__ */ new Set();
11324
11587
  for (const stream of streams) {
11588
+ if (typeof stream.agentType === "string" && stream.agentType) {
11589
+ seenExtensionTypes.add(stream.agentType);
11590
+ }
11325
11591
  ideInstance.onEvent("stream_update", {
11326
11592
  extensionType: stream.agentType,
11327
11593
  streams: [stream],
@@ -11338,6 +11604,16 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
11338
11604
  inputContent: stream.inputContent || ""
11339
11605
  });
11340
11606
  }
11607
+ const extensionTypes = ideInstance.getExtensionTypes?.() || [];
11608
+ if (streams.length === 0) {
11609
+ ideInstance.onEvent("stream_reset_all");
11610
+ return;
11611
+ }
11612
+ for (const extensionType of extensionTypes) {
11613
+ if (!seenExtensionTypes.has(extensionType)) {
11614
+ ideInstance.onEvent("stream_reset", { extensionType });
11615
+ }
11616
+ }
11341
11617
  }
11342
11618
 
11343
11619
  // src/providers/provider-instance-manager.ts