@adhdev/daemon-standalone 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
@@ -18296,7 +18296,6 @@ var __copyProps2 = (to, from, except, desc) => {
18296
18296
  var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
18297
18297
  var config_exports = {};
18298
18298
  __export2(config_exports, {
18299
- generateConnectionToken: () => generateConnectionToken,
18300
18299
  generateMachineId: () => generateMachineId,
18301
18300
  getConfigDir: () => getConfigDir,
18302
18301
  isSetupComplete: () => isSetupComplete,
@@ -18307,6 +18306,57 @@ __export2(config_exports, {
18307
18306
  saveConfig: () => saveConfig,
18308
18307
  updateConfig: () => updateConfig
18309
18308
  });
18309
+ function isPlainObject2(value) {
18310
+ return !!value && typeof value === "object" && !Array.isArray(value);
18311
+ }
18312
+ function asStringArray(value) {
18313
+ if (!Array.isArray(value)) return [];
18314
+ return value.filter((item) => typeof item === "string");
18315
+ }
18316
+ function asNullableString(value) {
18317
+ return typeof value === "string" ? value : null;
18318
+ }
18319
+ function asOptionalString(value) {
18320
+ return typeof value === "string" && value.trim() ? value : void 0;
18321
+ }
18322
+ function asBoolean(value, fallback) {
18323
+ return typeof value === "boolean" ? value : fallback;
18324
+ }
18325
+ function normalizeConfig(raw) {
18326
+ const parsed = isPlainObject2(raw) ? raw : {};
18327
+ const legacySessionReads = isPlainObject2(parsed.recentSessionReads) ? parsed.recentSessionReads : {};
18328
+ const sessionReads = isPlainObject2(parsed.sessionReads) ? parsed.sessionReads : {};
18329
+ const mergedSessionReads = Object.fromEntries(
18330
+ Object.entries({ ...legacySessionReads, ...sessionReads }).filter(([, value]) => typeof value === "number" && Number.isFinite(value))
18331
+ );
18332
+ const sessionReadMarkers = Object.fromEntries(
18333
+ Object.entries(isPlainObject2(parsed.sessionReadMarkers) ? parsed.sessionReadMarkers : {}).filter(([, value]) => typeof value === "string")
18334
+ );
18335
+ return {
18336
+ serverUrl: typeof parsed.serverUrl === "string" && parsed.serverUrl.trim() ? parsed.serverUrl : DEFAULT_CONFIG.serverUrl,
18337
+ selectedIde: asNullableString(parsed.selectedIde),
18338
+ configuredIdes: asStringArray(parsed.configuredIdes),
18339
+ installedExtensions: asStringArray(parsed.installedExtensions),
18340
+ userEmail: asNullableString(parsed.userEmail),
18341
+ userName: asNullableString(parsed.userName),
18342
+ setupCompleted: asBoolean(parsed.setupCompleted, DEFAULT_CONFIG.setupCompleted),
18343
+ setupDate: asNullableString(parsed.setupDate),
18344
+ enabledIdes: asStringArray(parsed.enabledIdes),
18345
+ workspaces: Array.isArray(parsed.workspaces) ? parsed.workspaces : [],
18346
+ defaultWorkspaceId: asNullableString(parsed.defaultWorkspaceId) ?? asNullableString(parsed.activeWorkspaceId),
18347
+ recentActivity: Array.isArray(parsed.recentActivity) ? parsed.recentActivity : [],
18348
+ sessionReads: mergedSessionReads,
18349
+ sessionReadMarkers,
18350
+ machineNickname: asNullableString(parsed.machineNickname),
18351
+ machineId: asOptionalString(parsed.machineId),
18352
+ machineSecret: parsed.machineSecret === null ? null : asOptionalString(parsed.machineSecret),
18353
+ registeredMachineId: asOptionalString(parsed.registeredMachineId),
18354
+ providerSettings: isPlainObject2(parsed.providerSettings) ? parsed.providerSettings : {},
18355
+ ideSettings: isPlainObject2(parsed.ideSettings) ? parsed.ideSettings : {},
18356
+ disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
18357
+ providerDir: asOptionalString(parsed.providerDir)
18358
+ };
18359
+ }
18310
18360
  function generateMachineId() {
18311
18361
  return `${MACHINE_ID_PREFIX}${(0, import_crypto2.randomUUID)().replace(/-/g, "")}`;
18312
18362
  }
@@ -18350,14 +18400,10 @@ function loadConfig() {
18350
18400
  try {
18351
18401
  const raw = (0, import_fs.readFileSync)(configPath, "utf-8");
18352
18402
  const parsed = JSON.parse(raw);
18353
- const merged = { ...DEFAULT_CONFIG, ...parsed };
18354
- if (merged.defaultWorkspaceId == null && merged.activeWorkspaceId != null) {
18355
- merged.defaultWorkspaceId = merged.activeWorkspaceId;
18356
- }
18357
- delete merged.activeWorkspaceId;
18358
- const ensured = ensureMachineId(merged);
18403
+ const normalizedInput = normalizeConfig(parsed);
18404
+ const ensured = ensureMachineId(normalizedInput);
18359
18405
  const normalized = ensured.config;
18360
- if (ensured.changed) {
18406
+ if (ensured.changed || JSON.stringify(parsed) !== JSON.stringify(normalized)) {
18361
18407
  try {
18362
18408
  saveConfig(normalized);
18363
18409
  } catch {
@@ -18372,10 +18418,11 @@ function loadConfig() {
18372
18418
  function saveConfig(config2) {
18373
18419
  const configPath = getConfigPath();
18374
18420
  const dir = getConfigDir();
18421
+ const normalized = normalizeConfig(config2);
18375
18422
  if (!(0, import_fs.existsSync)(dir)) {
18376
18423
  (0, import_fs.mkdirSync)(dir, { recursive: true, mode: 448 });
18377
18424
  }
18378
- (0, import_fs.writeFileSync)(configPath, JSON.stringify(config2, null, 2), { encoding: "utf-8", mode: 384 });
18425
+ (0, import_fs.writeFileSync)(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
18379
18426
  try {
18380
18427
  (0, import_fs.chmodSync)(configPath, 384);
18381
18428
  } catch {
@@ -18404,14 +18451,6 @@ function isSetupComplete() {
18404
18451
  function resetConfig() {
18405
18452
  saveConfig({ ...DEFAULT_CONFIG });
18406
18453
  }
18407
- function generateConnectionToken() {
18408
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
18409
- let token = "db_";
18410
- for (let i = 0; i < 32; i++) {
18411
- token += chars.charAt(Math.floor(Math.random() * chars.length));
18412
- }
18413
- return token;
18414
- }
18415
18454
  var DEFAULT_CONFIG;
18416
18455
  var MACHINE_ID_PREFIX;
18417
18456
  var init_config = __esm2({
@@ -18419,18 +18458,13 @@ var init_config = __esm2({
18419
18458
  "use strict";
18420
18459
  DEFAULT_CONFIG = {
18421
18460
  serverUrl: "https://api.adhf.dev",
18422
- apiToken: null,
18423
- connectionToken: null,
18424
18461
  selectedIde: null,
18425
18462
  configuredIdes: [],
18426
18463
  installedExtensions: [],
18427
- autoConnect: true,
18428
- notifications: true,
18429
18464
  userEmail: null,
18430
18465
  userName: null,
18431
18466
  setupCompleted: false,
18432
18467
  setupDate: null,
18433
- configuredCLIs: [],
18434
18468
  enabledIdes: [],
18435
18469
  workspaces: [],
18436
18470
  defaultWorkspaceId: null,
@@ -19242,6 +19276,13 @@ var init_provider_cli_adapter = __esm2({
19242
19276
  this.messages = [...this.committedMessages];
19243
19277
  this.structuredMessages = [...this.committedMessages];
19244
19278
  }
19279
+ normalizeParsedMessages(parsedMessages) {
19280
+ return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
19281
+ role: message.role,
19282
+ content: typeof message.content === "string" ? message.content : String(message.content || ""),
19283
+ timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : Date.now()
19284
+ }));
19285
+ }
19245
19286
  sliceFromOffset(text, start) {
19246
19287
  if (!text) return "";
19247
19288
  if (!Number.isFinite(start) || start <= 0) return text;
@@ -19638,6 +19679,15 @@ var init_provider_cli_adapter = __esm2({
19638
19679
  this.onStatusChange?.();
19639
19680
  }
19640
19681
  commitCurrentTranscript() {
19682
+ const parsed = this.parseCurrentTranscript(
19683
+ this.committedMessages,
19684
+ this.responseBuffer,
19685
+ this.currentTurnScope
19686
+ );
19687
+ if (parsed && Array.isArray(parsed.messages)) {
19688
+ this.committedMessages = this.normalizeParsedMessages(parsed.messages);
19689
+ this.syncMessageViews();
19690
+ }
19641
19691
  }
19642
19692
  // ─── Script Execution ──────────────────────────
19643
19693
  runDetectStatus(text) {
@@ -19682,6 +19732,21 @@ var init_provider_cli_adapter = __esm2({
19682
19732
  * Called by command handler / dashboard for rich content rendering.
19683
19733
  */
19684
19734
  getScriptParsedStatus() {
19735
+ const parsed = this.parseCurrentTranscript(
19736
+ this.committedMessages,
19737
+ this.responseBuffer,
19738
+ this.currentTurnScope
19739
+ );
19740
+ if (parsed && Array.isArray(parsed.messages)) {
19741
+ return {
19742
+ id: parsed.id || "cli_session",
19743
+ status: parsed.status || this.currentStatus,
19744
+ title: parsed.title || this.cliName,
19745
+ terminalHistory: this.terminalHistory,
19746
+ messages: parsed.messages,
19747
+ activeModal: parsed.activeModal ?? this.activeModal
19748
+ };
19749
+ }
19685
19750
  const messages = [...this.committedMessages];
19686
19751
  return {
19687
19752
  id: "cli_session",
@@ -21971,6 +22036,8 @@ var ExtensionProviderInstance = class {
21971
22036
  this.detectTransition(newStatus, data);
21972
22037
  this.currentStatus = newStatus;
21973
22038
  }
22039
+ } else if (event === "stream_reset") {
22040
+ this.resetStreamState();
21974
22041
  } else if (event === "extension_connected") {
21975
22042
  this.ideType = data?.ideType || "";
21976
22043
  }
@@ -22050,6 +22117,30 @@ var ExtensionProviderInstance = class {
22050
22117
  const title = typeof data?.title === "string" && data.title.trim() ? data.title.trim() : this.chatTitle;
22051
22118
  return title || this.agentName || this.provider.name;
22052
22119
  }
22120
+ resetStreamState() {
22121
+ if (this.currentStatus !== "idle") {
22122
+ this.detectTransition("idle", {
22123
+ title: this.chatTitle,
22124
+ agentName: this.agentName,
22125
+ extensionId: this.extensionId,
22126
+ messages: this.messages
22127
+ });
22128
+ }
22129
+ this.agentStreams = [];
22130
+ this.messages = [];
22131
+ this.activeModal = null;
22132
+ this.currentModel = "";
22133
+ this.currentMode = "";
22134
+ this.controlValues = {};
22135
+ this.currentStatus = "idle";
22136
+ this.chatId = null;
22137
+ this.chatTitle = null;
22138
+ this.agentName = "";
22139
+ this.extensionId = "";
22140
+ this.lastAgentStatus = "idle";
22141
+ this.generatingStartedAt = 0;
22142
+ this.monitor.reset();
22143
+ }
22053
22144
  };
22054
22145
  var HISTORY_DIR = path4.join(os5.homedir(), ".adhdev", "history");
22055
22146
  var RETAIN_DAYS = 30;
@@ -22325,11 +22416,23 @@ var IdeProviderInstance = class {
22325
22416
  } else if (event === "cdp_disconnected") {
22326
22417
  this.cachedChat = null;
22327
22418
  this.currentStatus = "idle";
22419
+ for (const ext of this.extensions.values()) {
22420
+ ext.onEvent("stream_reset");
22421
+ }
22328
22422
  } else if (event === "stream_update") {
22329
22423
  const extType = data?.extensionType;
22330
22424
  if (extType && this.extensions.has(extType)) {
22331
22425
  this.extensions.get(extType).onEvent("stream_update", data);
22332
22426
  }
22427
+ } else if (event === "stream_reset") {
22428
+ const extType = data?.extensionType;
22429
+ if (extType && this.extensions.has(extType)) {
22430
+ this.extensions.get(extType).onEvent("stream_reset");
22431
+ }
22432
+ } else if (event === "stream_reset_all") {
22433
+ for (const ext of this.extensions.values()) {
22434
+ ext.onEvent("stream_reset");
22435
+ }
22333
22436
  }
22334
22437
  }
22335
22438
  dispose() {
@@ -22836,6 +22939,63 @@ var WORKING_STATUSES = /* @__PURE__ */ new Set([
22836
22939
  "thinking",
22837
22940
  "active"
22838
22941
  ]);
22942
+ var STATUS_ACTIVE_CHAT_MESSAGE_LIMIT = 60;
22943
+ var STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT = 96 * 1024;
22944
+ var STATUS_ACTIVE_CHAT_STRING_LIMIT = 4 * 1024;
22945
+ var STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT = 1024;
22946
+ var STATUS_TERMINAL_HISTORY_LIMIT = 8 * 1024;
22947
+ var STATUS_INPUT_CONTENT_LIMIT = 2 * 1024;
22948
+ var STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
22949
+ var STATUS_MODAL_BUTTON_LIMIT = 120;
22950
+ function truncateString(value, maxChars) {
22951
+ if (value.length <= maxChars) return value;
22952
+ if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));
22953
+ return `${value.slice(0, maxChars - 12)}...[truncated]`;
22954
+ }
22955
+ function truncateStringTail(value, maxChars) {
22956
+ if (value.length <= maxChars) return value;
22957
+ if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));
22958
+ return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;
22959
+ }
22960
+ function trimStructuredStrings(value, maxChars) {
22961
+ if (typeof value === "string") return truncateString(value, maxChars);
22962
+ if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));
22963
+ if (!value || typeof value !== "object") return value;
22964
+ return Object.fromEntries(
22965
+ Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)])
22966
+ );
22967
+ }
22968
+ function estimateBytes(value) {
22969
+ try {
22970
+ return JSON.stringify(value).length;
22971
+ } catch {
22972
+ return String(value ?? "").length;
22973
+ }
22974
+ }
22975
+ function trimMessageForStatus(message, stringLimit) {
22976
+ if (!message || typeof message !== "object") return message;
22977
+ return trimStructuredStrings(message, stringLimit);
22978
+ }
22979
+ function trimMessagesForStatus(messages) {
22980
+ if (!Array.isArray(messages) || messages.length === 0) return [];
22981
+ const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
22982
+ const kept = [];
22983
+ let totalBytes = 0;
22984
+ for (let i = recent.length - 1; i >= 0; i -= 1) {
22985
+ let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
22986
+ let size = estimateBytes(normalized);
22987
+ if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
22988
+ normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
22989
+ size = estimateBytes(normalized);
22990
+ }
22991
+ if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
22992
+ continue;
22993
+ }
22994
+ kept.push(normalized);
22995
+ totalBytes += size;
22996
+ }
22997
+ return kept.reverse();
22998
+ }
22839
22999
  function hasApprovalButtons(activeModal) {
22840
23000
  return (activeModal?.buttons?.length ?? 0) > 0;
22841
23001
  }
@@ -22856,7 +23016,16 @@ function normalizeActiveChatData(activeChat) {
22856
23016
  if (!activeChat) return activeChat;
22857
23017
  return {
22858
23018
  ...activeChat,
22859
- status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal })
23019
+ status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),
23020
+ messages: trimMessagesForStatus(activeChat.messages),
23021
+ activeModal: activeChat.activeModal ? {
23022
+ message: truncateString(activeChat.activeModal.message || "", STATUS_MODAL_MESSAGE_LIMIT),
23023
+ buttons: (activeChat.activeModal.buttons || []).map(
23024
+ (button) => truncateString(String(button || ""), STATUS_MODAL_BUTTON_LIMIT)
23025
+ )
23026
+ } : activeChat.activeModal,
23027
+ terminalHistory: activeChat.terminalHistory ? truncateStringTail(activeChat.terminalHistory, STATUS_TERMINAL_HISTORY_LIMIT) : activeChat.terminalHistory,
23028
+ inputContent: activeChat.inputContent ? truncateString(activeChat.inputContent, STATUS_INPUT_CONTENT_LIMIT) : activeChat.inputContent
22860
23029
  };
22861
23030
  }
22862
23031
  function findCdpManager(cdpManagers, key) {
@@ -22944,6 +23113,11 @@ var PTY_SESSION_CAPABILITIES = [
22944
23113
  "terminal_io",
22945
23114
  "resize_terminal"
22946
23115
  ];
23116
+ var CLI_CHAT_SESSION_CAPABILITIES = [
23117
+ "read_chat",
23118
+ "send_message",
23119
+ "resolve_action"
23120
+ ];
22947
23121
  var ACP_SESSION_CAPABILITIES = [
22948
23122
  "read_chat",
22949
23123
  "send_message",
@@ -23033,9 +23207,10 @@ function buildCliSession(state) {
23033
23207
  runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
23034
23208
  runtimeWriteOwner: state.runtime?.writeOwner || null,
23035
23209
  runtimeAttachedClients: state.runtime?.attachedClients || [],
23210
+ mode: state.mode,
23036
23211
  resume: state.resume,
23037
23212
  activeChat,
23038
- capabilities: PTY_SESSION_CAPABILITIES,
23213
+ capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES,
23039
23214
  controlValues: state.controlValues,
23040
23215
  providerControls: buildFallbackControls(
23041
23216
  state.providerControls
@@ -24198,6 +24373,13 @@ async function handleFileListBrowse(h, args) {
24198
24373
  return handleFileList(h, args);
24199
24374
  }
24200
24375
  init_logger();
24376
+ function getCliPresentationMode(h, targetSessionId) {
24377
+ if (!targetSessionId) return null;
24378
+ const instance = h.ctx.instanceManager?.getInstance(targetSessionId);
24379
+ if (instance?.category !== "cli") return null;
24380
+ const mode = instance.getPresentationMode?.();
24381
+ return mode === "chat" || mode === "terminal" ? mode : null;
24382
+ }
24201
24383
  async function handleFocusSession(h, args) {
24202
24384
  if (!h.agentStream || !h.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
24203
24385
  const sessionId = args?.targetSessionId || h.currentSession?.sessionId;
@@ -24208,6 +24390,9 @@ async function handleFocusSession(h, args) {
24208
24390
  function handlePtyInput(h, args) {
24209
24391
  const { cliType, data, targetSessionId } = args || {};
24210
24392
  if (!data) return { success: false, error: "data required" };
24393
+ if (getCliPresentationMode(h, targetSessionId) === "chat") {
24394
+ return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
24395
+ }
24211
24396
  const adapter = h.getCliAdapter(targetSessionId || cliType);
24212
24397
  if (!adapter || typeof adapter.writeRaw !== "function") {
24213
24398
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
@@ -24218,6 +24403,9 @@ function handlePtyInput(h, args) {
24218
24403
  function handlePtyResize(h, args) {
24219
24404
  const { cliType, cols, rows, force, targetSessionId } = args || {};
24220
24405
  if (!cols || !rows) return { success: false, error: "cols and rows required" };
24406
+ if (getCliPresentationMode(h, targetSessionId) === "chat") {
24407
+ return { success: false, error: "CLI session is in chat mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" };
24408
+ }
24221
24409
  const adapter = h.getCliAdapter(targetSessionId || cliType);
24222
24410
  if (!adapter || typeof adapter.resize !== "function") {
24223
24411
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
@@ -26564,6 +26752,7 @@ var DaemonCommandRouter = class {
26564
26752
  // ─── CLI / ACP commands ───
26565
26753
  case "launch_cli":
26566
26754
  case "stop_cli":
26755
+ case "set_cli_view_mode":
26567
26756
  case "agent_command": {
26568
26757
  return this.deps.cliManager.handleCliCommand(cmd, args);
26569
26758
  }
@@ -26844,6 +27033,7 @@ var CliProviderInstance = class {
26844
27033
  this.cliArgs = cliArgs;
26845
27034
  this.type = provider.type;
26846
27035
  this.instanceId = instanceId || crypto3.randomUUID();
27036
+ this.presentationMode = "terminal";
26847
27037
  this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
26848
27038
  this.monitor = new StatusMonitor();
26849
27039
  this.historyWriter = new ChatHistoryWriter();
@@ -26862,6 +27052,7 @@ var CliProviderInstance = class {
26862
27052
  lastApprovalEventAt = 0;
26863
27053
  historyWriter;
26864
27054
  instanceId;
27055
+ presentationMode;
26865
27056
  // ─── Lifecycle ─────────────────────────────────
26866
27057
  async init(context) {
26867
27058
  this.context = context;
@@ -26886,6 +27077,7 @@ var CliProviderInstance = class {
26886
27077
  }
26887
27078
  getState() {
26888
27079
  const adapterStatus = this.adapter.getStatus();
27080
+ const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
26889
27081
  const runtime = this.adapter.getRuntimeMetadata();
26890
27082
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
26891
27083
  if (adapterStatus.terminalHistory?.trim()) {
@@ -26901,13 +27093,13 @@ var CliProviderInstance = class {
26901
27093
  name: this.provider.name,
26902
27094
  category: "cli",
26903
27095
  status: adapterStatus.status,
26904
- mode: "terminal",
27096
+ mode: this.presentationMode,
26905
27097
  activeChat: {
26906
27098
  id: `${this.type}_${this.workingDir}`,
26907
- title: `${this.provider.name} \xB7 ${dirName}`,
26908
- status: adapterStatus.status,
26909
- messages: [],
26910
- activeModal: adapterStatus.activeModal,
27099
+ title: parsedStatus?.title || `${this.provider.name} \xB7 ${dirName}`,
27100
+ status: parsedStatus?.status || adapterStatus.status,
27101
+ messages: Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [],
27102
+ activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
26911
27103
  terminalHistory: adapterStatus.terminalHistory,
26912
27104
  inputContent: ""
26913
27105
  },
@@ -26930,6 +27122,13 @@ var CliProviderInstance = class {
26930
27122
  providerControls: this.provider.controls
26931
27123
  };
26932
27124
  }
27125
+ setPresentationMode(mode) {
27126
+ if (this.presentationMode === mode) return;
27127
+ this.presentationMode = mode;
27128
+ }
27129
+ getPresentationMode() {
27130
+ return this.presentationMode;
27131
+ }
26933
27132
  onEvent(event, data) {
26934
27133
  if (event === "send_message" && data?.text) {
26935
27134
  void this.adapter.sendMessage(data.text).catch((e) => {
@@ -27977,6 +28176,15 @@ var DaemonCliManager = class {
27977
28176
  const hash2 = __require("crypto").createHash("md5").update(__require("path").resolve(dir)).digest("hex").slice(0, 8);
27978
28177
  return `${cliType}_${hash2}`;
27979
28178
  }
28179
+ getSessionPresentationMode(sessionId) {
28180
+ if (!sessionId) return null;
28181
+ const instance = this.deps.getInstanceManager()?.getInstance(sessionId);
28182
+ const mode = instance?.category === "cli" ? instance.getPresentationMode?.() : null;
28183
+ return mode === "chat" || mode === "terminal" ? mode : null;
28184
+ }
28185
+ isTerminalSession(sessionId) {
28186
+ return this.getSessionPresentationMode(sessionId) === "terminal";
28187
+ }
27980
28188
  persistRecentActivity(entry) {
27981
28189
  try {
27982
28190
  saveConfig(appendRecentActivity(loadConfig(), entry));
@@ -28155,6 +28363,7 @@ ${installInfo}`
28155
28363
  if (provider) {
28156
28364
  console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
28157
28365
  }
28366
+ const resolvedCliArgs = cliArgs;
28158
28367
  const instanceManager = this.deps.getInstanceManager();
28159
28368
  if (provider && instanceManager) {
28160
28369
  const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
@@ -28163,14 +28372,14 @@ ${installInfo}`
28163
28372
  normalizedType,
28164
28373
  cliType,
28165
28374
  resolvedDir,
28166
- cliArgs,
28375
+ resolvedCliArgs,
28167
28376
  resolvedProvider,
28168
28377
  {},
28169
28378
  false
28170
28379
  );
28171
28380
  console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
28172
28381
  } else {
28173
- const adapter = this.createAdapter(cliType, resolvedDir, cliArgs, key, false);
28382
+ const adapter = this.createAdapter(cliType, resolvedDir, resolvedCliArgs, key, false);
28174
28383
  try {
28175
28384
  await adapter.spawn();
28176
28385
  } catch (spawnErr) {
@@ -28320,6 +28529,14 @@ ${installInfo}`
28320
28529
  }
28321
28530
  return null;
28322
28531
  }
28532
+ findAdapterBySessionId(instanceKey) {
28533
+ if (!instanceKey) return null;
28534
+ let ik = instanceKey;
28535
+ const colonIdx = ik.lastIndexOf(":");
28536
+ if (colonIdx >= 0) ik = ik.substring(colonIdx + 1);
28537
+ const adapter = this.adapters.get(ik);
28538
+ return adapter ? { adapter, key: ik } : null;
28539
+ }
28323
28540
  // ─── CLI command handling ────────────────────────────
28324
28541
  async handleCliCommand(cmd, args) {
28325
28542
  switch (cmd) {
@@ -28370,6 +28587,23 @@ ${installInfo}`
28370
28587
  }
28371
28588
  return { success: true, cliType, dir, stopped: true, mode };
28372
28589
  }
28590
+ case "set_cli_view_mode": {
28591
+ const mode = args?.mode === "chat" ? "chat" : "terminal";
28592
+ const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId : "";
28593
+ const cliType = args?.cliType || args?.agentType || "";
28594
+ const dir = args?.dir || "";
28595
+ const found = this.findAdapterBySessionId(targetSessionId) || (cliType ? this.findAdapter(cliType, { instanceKey: targetSessionId, dir }) : null);
28596
+ if (!found) {
28597
+ return { success: false, error: "CLI session not found", code: "CLI_SESSION_NOT_FOUND" };
28598
+ }
28599
+ const instance = this.deps.getInstanceManager()?.getInstance(found.key);
28600
+ if (!(instance instanceof CliProviderInstance)) {
28601
+ return { success: false, error: "CLI instance not found", code: "CLI_INSTANCE_NOT_FOUND" };
28602
+ }
28603
+ instance.setPresentationMode(mode);
28604
+ this.deps.onStatusChange();
28605
+ return { success: true, id: found.key, mode };
28606
+ }
28373
28607
  case "restart_session": {
28374
28608
  const cliType = args?.cliType || args?.agentType || args?.ideType;
28375
28609
  const cfg = loadConfig();
@@ -28978,7 +29212,12 @@ var AgentStreamPoller = class {
28978
29212
  } catch {
28979
29213
  }
28980
29214
  }
28981
- if (!resolvedActiveSessionId || !parentSessionId) continue;
29215
+ if (!resolvedActiveSessionId || !parentSessionId) {
29216
+ if (parentSessionId) {
29217
+ this.deps.onStreamsUpdated?.(ideType, []);
29218
+ }
29219
+ continue;
29220
+ }
28982
29221
  try {
28983
29222
  await agentStreamManager.syncActiveSession(cdp, parentSessionId);
28984
29223
  const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
@@ -28991,7 +29230,11 @@ var AgentStreamPoller = class {
28991
29230
  function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
28992
29231
  const ideInstance = instanceManager.getInstance(`ide:${ideType}`);
28993
29232
  if (!ideInstance?.onEvent) return;
29233
+ const seenExtensionTypes = /* @__PURE__ */ new Set();
28994
29234
  for (const stream of streams) {
29235
+ if (typeof stream.agentType === "string" && stream.agentType) {
29236
+ seenExtensionTypes.add(stream.agentType);
29237
+ }
28995
29238
  ideInstance.onEvent("stream_update", {
28996
29239
  extensionType: stream.agentType,
28997
29240
  streams: [stream],
@@ -29008,6 +29251,16 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
29008
29251
  inputContent: stream.inputContent || ""
29009
29252
  });
29010
29253
  }
29254
+ const extensionTypes = ideInstance.getExtensionTypes?.() || [];
29255
+ if (streams.length === 0) {
29256
+ ideInstance.onEvent("stream_reset_all");
29257
+ return;
29258
+ }
29259
+ for (const extensionType of extensionTypes) {
29260
+ if (!seenExtensionTypes.has(extensionType)) {
29261
+ ideInstance.onEvent("stream_reset", { extensionType });
29262
+ }
29263
+ }
29011
29264
  }
29012
29265
  init_logger();
29013
29266
  var ProviderInstanceManager = class {
@@ -34283,6 +34536,16 @@ var StandaloneServer = class {
34283
34536
  await client.connect();
34284
34537
  return client;
34285
34538
  }
34539
+ getCliPresentationMode(sessionId) {
34540
+ if (!sessionId || !this.components) return null;
34541
+ const instance = this.components.instanceManager.getInstance(sessionId);
34542
+ if (instance?.category !== "cli") return null;
34543
+ const mode = instance.getPresentationMode?.();
34544
+ return mode === "chat" || mode === "terminal" ? mode : null;
34545
+ }
34546
+ isTerminalCliSession(sessionId) {
34547
+ return this.getCliPresentationMode(sessionId) === "terminal";
34548
+ }
34286
34549
  async start(options = {}) {
34287
34550
  const port = options.port || DEFAULT_PORT;
34288
34551
  const host = options.host || "127.0.0.1";
@@ -34294,8 +34557,8 @@ var StandaloneServer = class {
34294
34557
  getServerConn: () => null,
34295
34558
  getP2p: () => ({
34296
34559
  broadcastPtyOutput: (key, data) => {
34297
- if (this.clients.size === 0) return;
34298
- const msg = JSON.stringify({ type: "pty_output", cliId: key, data });
34560
+ if (this.clients.size === 0 || !this.isTerminalCliSession(key)) return;
34561
+ const msg = JSON.stringify({ type: "pty_output", sessionId: key, data });
34299
34562
  for (const client of this.clients) {
34300
34563
  if (client.readyState === 1) {
34301
34564
  client.send(msg);
@@ -34509,6 +34772,11 @@ var StandaloneServer = class {
34509
34772
  return;
34510
34773
  }
34511
34774
  if (action === "snapshot" && method === "GET") {
34775
+ if (!this.isTerminalCliSession(sessionId)) {
34776
+ res.writeHead(409, { "Content-Type": "application/json" });
34777
+ res.end(JSON.stringify({ error: "CLI session is not in terminal mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" }));
34778
+ return;
34779
+ }
34512
34780
  void (async () => {
34513
34781
  const client = await this.createSessionHostClient();
34514
34782
  try {
@@ -34630,6 +34898,11 @@ var StandaloneServer = class {
34630
34898
  req.on("aborted", cleanup);
34631
34899
  }
34632
34900
  async handleRuntimeEvents(req, res, sessionId) {
34901
+ if (!this.isTerminalCliSession(sessionId)) {
34902
+ res.writeHead(409, { "Content-Type": "application/json" });
34903
+ res.end(JSON.stringify({ error: "CLI session is not in terminal mode", code: "CLI_VIEW_MODE_NOT_TERMINAL" }));
34904
+ return;
34905
+ }
34633
34906
  const client = await this.createSessionHostClient();
34634
34907
  res.writeHead(200, {
34635
34908
  "Content-Type": "text/event-stream",
@@ -34649,6 +34922,7 @@ var StandaloneServer = class {
34649
34922
  }
34650
34923
  const writeEvent = (event) => {
34651
34924
  if (event.sessionId !== sessionId) return;
34925
+ if (!this.isTerminalCliSession(sessionId)) return;
34652
34926
  res.write(`event: ${event.type}
34653
34927
  `);
34654
34928
  res.write(`data: ${JSON.stringify(event)}
@@ -34736,7 +35010,7 @@ var StandaloneServer = class {
34736
35010
  const states = this.components.instanceManager.collectAllStates();
34737
35011
  for (const state of states) {
34738
35012
  const sessionId = typeof state?.instanceId === "string" ? state.instanceId : "";
34739
- if (!sessionId || state?.category !== "cli") continue;
35013
+ if (!sessionId || state?.category !== "cli" || state?.mode !== "terminal") continue;
34740
35014
  const snapshot = await client.request({
34741
35015
  type: "get_snapshot",
34742
35016
  payload: { sessionId }