@adhdev/daemon-standalone 0.7.39 → 0.7.41

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
@@ -18114,8 +18114,8 @@ function watch(paths, options = {}) {
18114
18114
  var fs6 = __toESM(require("fs"), 1);
18115
18115
  var path8 = __toESM(require("path"), 1);
18116
18116
  var os9 = __toESM(require("os"), 1);
18117
- var fs7 = __toESM(require("fs"), 1);
18118
18117
  var os10 = __toESM(require("os"), 1);
18118
+ var fs7 = __toESM(require("fs"), 1);
18119
18119
  var os13 = __toESM(require("os"), 1);
18120
18120
  var path10 = __toESM(require("path"), 1);
18121
18121
  var crypto4 = __toESM(require("crypto"), 1);
@@ -18435,7 +18435,8 @@ var init_config = __esm2({
18435
18435
  workspaces: [],
18436
18436
  defaultWorkspaceId: null,
18437
18437
  recentActivity: [],
18438
- recentSessionReads: {},
18438
+ sessionReads: {},
18439
+ sessionReadMarkers: {},
18439
18440
  machineNickname: null,
18440
18441
  machineId: void 0,
18441
18442
  machineSecret: null,
@@ -20297,18 +20298,27 @@ function appendRecentActivity(config2, entry) {
20297
20298
  function getRecentActivity(config2, limit = 20) {
20298
20299
  return [...config2.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
20299
20300
  }
20300
- function getRecentSessionSeenAt(config2, recentKey) {
20301
- return config2.recentSessionReads?.[recentKey] || 0;
20301
+ function getSessionSeenAt(config2, sessionId) {
20302
+ return config2.sessionReads?.[sessionId] || 0;
20302
20303
  }
20303
- function markRecentSessionSeen(config2, recentKey, seenAt = Date.now()) {
20304
- const prev = config2.recentSessionReads || {};
20305
- const nextSeenAt = Math.max(prev[recentKey] || 0, seenAt);
20304
+ function getSessionSeenMarker(config2, sessionId) {
20305
+ return config2.sessionReadMarkers?.[sessionId] || "";
20306
+ }
20307
+ function markSessionSeen(config2, sessionId, seenAt = Date.now(), completionMarker) {
20308
+ const prev = config2.sessionReads || {};
20309
+ const nextSeenAt = Math.max(prev[sessionId] || 0, seenAt);
20310
+ const prevMarkers = config2.sessionReadMarkers || {};
20311
+ const nextMarker = typeof completionMarker === "string" ? completionMarker : "";
20306
20312
  return {
20307
20313
  ...config2,
20308
- recentSessionReads: {
20314
+ sessionReads: {
20309
20315
  ...prev,
20310
- [recentKey]: nextSeenAt
20311
- }
20316
+ [sessionId]: nextSeenAt
20317
+ },
20318
+ sessionReadMarkers: nextMarker ? {
20319
+ ...prevMarkers,
20320
+ [sessionId]: nextMarker
20321
+ } : prevMarkers
20312
20322
  };
20313
20323
  }
20314
20324
  var BUILTIN_IDE_DEFINITIONS = [];
@@ -23023,6 +23033,8 @@ function buildCliSession(state) {
23023
23033
  runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
23024
23034
  runtimeWriteOwner: state.runtime?.writeOwner || null,
23025
23035
  runtimeAttachedClients: state.runtime?.attachedClients || [],
23036
+ launchMode: state.launchMode,
23037
+ mode: state.mode,
23026
23038
  resume: state.resume,
23027
23039
  activeChat,
23028
23040
  capabilities: PTY_SESSION_CAPABILITIES,
@@ -26363,6 +26375,144 @@ function logCommand(entry) {
26363
26375
  }
26364
26376
  cleanOldFiles();
26365
26377
  init_logger();
26378
+ init_config();
26379
+ init_terminal_screen();
26380
+ init_logger();
26381
+ var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
26382
+ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
26383
+ return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
26384
+ id: ide.id,
26385
+ type: ide.id,
26386
+ name: ide.displayName || ide.name || ide.id,
26387
+ running: isCdpConnected(cdpManagers, ide.id),
26388
+ ...ide.path ? { path: ide.path } : {}
26389
+ }));
26390
+ }
26391
+ function buildAvailableProviders(providerLoader) {
26392
+ return providerLoader.getAll().map((provider) => ({
26393
+ type: provider.type,
26394
+ name: provider.displayName || provider.type,
26395
+ displayName: provider.displayName || provider.type,
26396
+ icon: provider.icon || "\u{1F4BB}",
26397
+ category: provider.category
26398
+ }));
26399
+ }
26400
+ function parseMessageTime(value) {
26401
+ if (typeof value === "number" && Number.isFinite(value)) return value;
26402
+ if (typeof value === "string") {
26403
+ const parsed = Date.parse(value);
26404
+ if (Number.isFinite(parsed)) return parsed;
26405
+ }
26406
+ return 0;
26407
+ }
26408
+ function getSessionMessageUpdatedAt(session) {
26409
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
26410
+ if (!lastMessage) return 0;
26411
+ return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
26412
+ }
26413
+ function getSessionCompletionMarker(session) {
26414
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
26415
+ if (!lastMessage) return "";
26416
+ const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
26417
+ if (role === "user" || role === "human") return "";
26418
+ if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
26419
+ if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
26420
+ if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
26421
+ const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
26422
+ return timestamp > 0 ? `ts:${timestamp}` : "";
26423
+ }
26424
+ function getSessionLastUsedAt(session) {
26425
+ return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
26426
+ }
26427
+ function getLastMessageRole(session) {
26428
+ const role = session.activeChat?.messages?.at?.(-1)?.role;
26429
+ return typeof role === "string" ? role : "";
26430
+ }
26431
+ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole, completionMarker, seenCompletionMarker) {
26432
+ if (status === "waiting_approval") {
26433
+ return { unread: false, inboxBucket: "needs_attention" };
26434
+ }
26435
+ if (status === "generating" || status === "starting") {
26436
+ return { unread: false, inboxBucket: "working" };
26437
+ }
26438
+ const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
26439
+ return { unread, inboxBucket: unread ? "task_complete" : "idle" };
26440
+ }
26441
+ function buildRecentLaunches(recentActivity) {
26442
+ return recentActivity.map((item) => ({
26443
+ id: item.id,
26444
+ providerType: item.providerType,
26445
+ providerName: item.providerName,
26446
+ kind: item.kind,
26447
+ title: item.title || item.providerName,
26448
+ workspace: item.workspace,
26449
+ currentModel: item.currentModel,
26450
+ lastLaunchedAt: item.lastUsedAt
26451
+ })).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
26452
+ }
26453
+ function buildStatusSnapshot(options) {
26454
+ const cfg = loadConfig();
26455
+ const wsState = getWorkspaceState(cfg);
26456
+ const memSnap = getHostMemorySnapshot();
26457
+ const recentActivity = getRecentActivity(cfg, 20);
26458
+ const sessions = buildSessionEntries(
26459
+ options.allStates,
26460
+ options.cdpManagers
26461
+ );
26462
+ for (const session of sessions) {
26463
+ const lastSeenAt = getSessionSeenAt(cfg, session.id);
26464
+ const seenCompletionMarker = getSessionSeenMarker(cfg, session.id);
26465
+ const lastUsedAt = getSessionLastUsedAt(session);
26466
+ const completionMarker = getSessionCompletionMarker(session);
26467
+ const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
26468
+ getSessionMessageUpdatedAt(session) > 0,
26469
+ session.status,
26470
+ lastUsedAt,
26471
+ lastSeenAt,
26472
+ getLastMessageRole(session),
26473
+ completionMarker,
26474
+ seenCompletionMarker
26475
+ );
26476
+ session.lastSeenAt = lastSeenAt;
26477
+ session.unread = unread;
26478
+ session.inboxBucket = inboxBucket;
26479
+ if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
26480
+ LOG.info(
26481
+ "RecentRead",
26482
+ `snapshot session id=${session.id} provider=${session.providerType} status=${String(session.status || "")} bucket=${inboxBucket} unread=${String(unread)} lastSeenAt=${lastSeenAt} completionMarker=${completionMarker || "-"} seenMarker=${seenCompletionMarker || "-"} lastUpdated=${String(session.lastUpdated || 0)} lastUsedAt=${lastUsedAt} lastRole=${getLastMessageRole(session)} msgUpdatedAt=${getSessionMessageUpdatedAt(session)}`
26483
+ );
26484
+ }
26485
+ }
26486
+ const terminalBackend = getTerminalBackendRuntimeStatus();
26487
+ return {
26488
+ instanceId: options.instanceId,
26489
+ version: options.version,
26490
+ daemonMode: options.daemonMode,
26491
+ machine: {
26492
+ hostname: os10.hostname(),
26493
+ platform: os10.platform(),
26494
+ arch: os10.arch(),
26495
+ cpus: os10.cpus().length,
26496
+ totalMem: memSnap.totalMem,
26497
+ freeMem: memSnap.freeMem,
26498
+ availableMem: memSnap.availableMem,
26499
+ loadavg: os10.loadavg(),
26500
+ uptime: os10.uptime(),
26501
+ release: os10.release()
26502
+ },
26503
+ machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
26504
+ timestamp: options.timestamp ?? Date.now(),
26505
+ detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
26506
+ ...options.p2p ? { p2p: options.p2p } : {},
26507
+ sessions,
26508
+ workspaces: wsState.workspaces,
26509
+ defaultWorkspaceId: wsState.defaultWorkspaceId,
26510
+ defaultWorkspacePath: wsState.defaultWorkspacePath,
26511
+ recentLaunches: buildRecentLaunches(recentActivity),
26512
+ terminalBackend,
26513
+ availableProviders: buildAvailableProviders(options.providerLoader)
26514
+ };
26515
+ }
26366
26516
  var CHAT_COMMANDS = [
26367
26517
  "send_chat",
26368
26518
  "new_chat",
@@ -26370,6 +26520,7 @@ var CHAT_COMMANDS = [
26370
26520
  "set_mode",
26371
26521
  "change_model"
26372
26522
  ];
26523
+ var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
26373
26524
  var DaemonCommandRouter = class {
26374
26525
  deps;
26375
26526
  constructor(deps) {
@@ -26540,28 +26691,35 @@ var DaemonCommandRouter = class {
26540
26691
  updateConfig({ userName: name });
26541
26692
  return { success: true, userName: name };
26542
26693
  }
26543
- case "mark_recent_seen": {
26544
- const kind = args?.kind;
26545
- const providerType = args?.providerType;
26546
- if (!kind || !providerType) {
26547
- return { success: false, error: "kind and providerType are required" };
26694
+ case "mark_session_seen": {
26695
+ const sessionId = args?.sessionId;
26696
+ if (!sessionId || typeof sessionId !== "string") {
26697
+ return { success: false, error: "sessionId is required" };
26548
26698
  }
26549
- const recentKey = args?.recentKey || buildRecentActivityKey({
26550
- kind,
26551
- providerType,
26552
- workspace: args?.workspace || null
26553
- });
26554
- const next = markRecentSessionSeen(
26555
- loadConfig(),
26556
- recentKey,
26557
- typeof args?.seenAt === "number" ? args.seenAt : Date.now()
26699
+ const currentConfig = loadConfig();
26700
+ const prevSeenAt = currentConfig.sessionReads?.[sessionId] || 0;
26701
+ const sessionEntries = buildSessionEntries(
26702
+ this.deps.instanceManager.collectAllStates(),
26703
+ this.deps.cdpManagers
26704
+ );
26705
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
26706
+ const completionMarker = targetSession ? getSessionCompletionMarker(targetSession) : "";
26707
+ const next = markSessionSeen(
26708
+ currentConfig,
26709
+ sessionId,
26710
+ typeof args?.seenAt === "number" ? args.seenAt : Date.now(),
26711
+ completionMarker
26558
26712
  );
26713
+ if (READ_DEBUG_ENABLED2) {
26714
+ LOG.info("RecentRead", `mark_session_seen sessionId=${sessionId} seenAt=${String(args?.seenAt || "")} prevSeenAt=${String(prevSeenAt)} nextSeenAt=${String(next.sessionReads?.[sessionId] || 0)} marker=${completionMarker || "-"}`);
26715
+ }
26559
26716
  saveConfig(next);
26560
26717
  this.deps.onStatusChange?.();
26561
26718
  return {
26562
26719
  success: true,
26563
- recentKey,
26564
- seenAt: next.recentSessionReads?.[recentKey] || Date.now()
26720
+ sessionId,
26721
+ seenAt: next.sessionReads?.[sessionId] || Date.now(),
26722
+ completionMarker
26565
26723
  };
26566
26724
  }
26567
26725
  // ─── Daemon Self-Upgrade ───
@@ -26676,201 +26834,20 @@ var DaemonCommandRouter = class {
26676
26834
  }
26677
26835
  };
26678
26836
  init_logger();
26679
- init_config();
26680
- init_terminal_screen();
26681
- function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
26682
- return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
26683
- id: ide.id,
26684
- type: ide.id,
26685
- name: ide.displayName || ide.name || ide.id,
26686
- running: isCdpConnected(cdpManagers, ide.id),
26687
- ...ide.path ? { path: ide.path } : {}
26688
- }));
26689
- }
26690
- function buildAvailableProviders(providerLoader) {
26691
- return providerLoader.getAll().map((provider) => ({
26692
- type: provider.type,
26693
- name: provider.displayName || provider.type,
26694
- displayName: provider.displayName || provider.type,
26695
- icon: provider.icon || "\u{1F4BB}",
26696
- category: provider.category
26697
- }));
26698
- }
26699
- function parseMessageTime(value) {
26700
- if (typeof value === "number" && Number.isFinite(value)) return value;
26701
- if (typeof value === "string") {
26702
- const parsed = Date.parse(value);
26703
- if (Number.isFinite(parsed)) return parsed;
26704
- }
26705
- return 0;
26706
- }
26707
- function getSessionMessageUpdatedAt(session) {
26708
- const lastMessage = session.activeChat?.messages?.at?.(-1);
26709
- if (!lastMessage) return 0;
26710
- return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
26711
- }
26712
- function getSessionLastUsedAt(session) {
26713
- return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
26714
- }
26715
- function getSessionKind(session) {
26716
- return session.transport === "cdp-page" || session.transport === "cdp-webview" ? "ide" : session.transport === "acp" ? "acp" : "cli";
26717
- }
26718
- function getLastMessageRole(session) {
26719
- const role = session.activeChat?.messages?.at?.(-1)?.role;
26720
- return typeof role === "string" ? role : "";
26721
- }
26722
- function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRole) {
26723
- if (status === "waiting_approval") {
26724
- return { unread: false, inboxBucket: "needs_attention" };
26725
- }
26726
- if (status === "generating" || status === "starting") {
26727
- return { unread: false, inboxBucket: "working" };
26728
- }
26729
- const unread = hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
26730
- return { unread, inboxBucket: unread ? "task_complete" : "idle" };
26731
- }
26732
- function buildRecentSessions(sessions, recentActivity, readState) {
26733
- const visibleKeys = /* @__PURE__ */ new Set();
26734
- const hiddenKeys = /* @__PURE__ */ new Set();
26735
- const live = sessions.filter((session) => !session.surfaceHidden && session.status !== "stopped").map((session) => {
26736
- const kind = getSessionKind(session);
26737
- const recentKey = buildRecentActivityKey({
26738
- kind,
26739
- providerType: session.providerType,
26740
- workspace: session.workspace
26741
- });
26742
- const lastSeenAt = readState[recentKey] || 0;
26743
- const lastUsedAt = getSessionLastUsedAt(session);
26744
- const { unread, inboxBucket } = getUnreadState(
26745
- getSessionMessageUpdatedAt(session) > 0,
26746
- session.status,
26747
- lastUsedAt,
26748
- lastSeenAt,
26749
- getLastMessageRole(session)
26750
- );
26751
- return {
26752
- id: session.id,
26753
- recentKey,
26754
- sessionId: session.id,
26755
- providerType: session.providerType,
26756
- providerName: session.providerName,
26757
- kind,
26758
- title: session.activeChat?.title || session.title || session.providerName,
26759
- workspace: session.workspace,
26760
- currentModel: session.currentModel,
26761
- status: session.status,
26762
- lastUsedAt,
26763
- unread,
26764
- lastSeenAt,
26765
- inboxBucket,
26766
- surfaceHidden: false
26767
- };
26768
- });
26769
- for (const item of live) {
26770
- visibleKeys.add(`${item.kind}:${item.providerType}:${item.workspace || ""}`);
26771
- }
26772
- for (const session of sessions) {
26773
- if (!session.surfaceHidden) continue;
26774
- hiddenKeys.add(`${getSessionKind(session)}:${session.providerType}:${session.workspace || ""}`);
26775
- }
26776
- const persisted = recentActivity.filter((item) => {
26777
- const key = `${item.kind}:${item.providerType}:${item.workspace || ""}`;
26778
- return !visibleKeys.has(key) && !hiddenKeys.has(key);
26779
- }).map((item) => {
26780
- const lastSeenAt = readState[item.id] || 0;
26781
- const unread = item.lastUsedAt > lastSeenAt;
26782
- return {
26783
- id: item.id,
26784
- recentKey: item.id,
26785
- sessionId: item.sessionId || null,
26786
- providerType: item.providerType,
26787
- providerName: item.providerName,
26788
- kind: item.kind,
26789
- title: item.title || item.providerName,
26790
- workspace: item.workspace,
26791
- currentModel: item.currentModel,
26792
- lastUsedAt: item.lastUsedAt,
26793
- unread,
26794
- lastSeenAt,
26795
- inboxBucket: unread ? "task_complete" : "idle",
26796
- surfaceHidden: false
26797
- };
26798
- });
26799
- return [...live, ...persisted].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, 12);
26800
- }
26801
- function buildStatusSnapshot(options) {
26802
- const cfg = loadConfig();
26803
- const wsState = getWorkspaceState(cfg);
26804
- const memSnap = getHostMemorySnapshot();
26805
- const recentActivity = getRecentActivity(cfg, 20);
26806
- const sessions = buildSessionEntries(
26807
- options.allStates,
26808
- options.cdpManagers
26809
- );
26810
- const readState = cfg.recentSessionReads || {};
26811
- for (const session of sessions) {
26812
- const kind = getSessionKind(session);
26813
- const recentKey = buildRecentActivityKey({
26814
- kind,
26815
- providerType: session.providerType,
26816
- workspace: session.workspace
26817
- });
26818
- const lastSeenAt = getRecentSessionSeenAt(cfg, recentKey);
26819
- const lastUsedAt = getSessionLastUsedAt(session);
26820
- const { unread, inboxBucket } = session.surfaceHidden ? { unread: false, inboxBucket: "idle" } : getUnreadState(
26821
- getSessionMessageUpdatedAt(session) > 0,
26822
- session.status,
26823
- lastUsedAt,
26824
- lastSeenAt,
26825
- getLastMessageRole(session)
26826
- );
26827
- session.recentKey = recentKey;
26828
- session.lastSeenAt = lastSeenAt;
26829
- session.unread = unread;
26830
- session.inboxBucket = inboxBucket;
26831
- }
26832
- const terminalBackend = getTerminalBackendRuntimeStatus();
26833
- return {
26834
- instanceId: options.instanceId,
26835
- version: options.version,
26836
- daemonMode: options.daemonMode,
26837
- machine: {
26838
- hostname: os10.hostname(),
26839
- platform: os10.platform(),
26840
- arch: os10.arch(),
26841
- cpus: os10.cpus().length,
26842
- totalMem: memSnap.totalMem,
26843
- freeMem: memSnap.freeMem,
26844
- availableMem: memSnap.availableMem,
26845
- loadavg: os10.loadavg(),
26846
- uptime: os10.uptime(),
26847
- release: os10.release()
26848
- },
26849
- machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
26850
- timestamp: options.timestamp ?? Date.now(),
26851
- detectedIdes: buildDetectedIdeInfos(options.detectedIdes, options.cdpManagers),
26852
- ...options.p2p ? { p2p: options.p2p } : {},
26853
- sessions,
26854
- workspaces: wsState.workspaces,
26855
- defaultWorkspaceId: wsState.defaultWorkspaceId,
26856
- defaultWorkspacePath: wsState.defaultWorkspacePath,
26857
- recentSessions: buildRecentSessions(sessions, recentActivity, readState),
26858
- terminalBackend,
26859
- availableProviders: buildAvailableProviders(options.providerLoader)
26860
- };
26861
- }
26862
26837
  init_logger();
26863
26838
  init_provider_cli_adapter();
26864
26839
  init_config();
26865
26840
  init_provider_cli_adapter();
26866
26841
  init_logger();
26867
26842
  var CliProviderInstance = class {
26868
- constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory) {
26843
+ constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, launchModeId) {
26869
26844
  this.provider = provider;
26870
26845
  this.workingDir = workingDir;
26871
26846
  this.cliArgs = cliArgs;
26872
26847
  this.type = provider.type;
26873
26848
  this.instanceId = instanceId || crypto3.randomUUID();
26849
+ this.launchMode = launchModeId && provider.launchModes?.find((m) => m.id === launchModeId) || null;
26850
+ this.resolvedOutputFormat = this.resolveOutputFormat();
26874
26851
  this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
26875
26852
  this.monitor = new StatusMonitor();
26876
26853
  this.historyWriter = new ChatHistoryWriter();
@@ -26889,6 +26866,26 @@ var CliProviderInstance = class {
26889
26866
  lastApprovalEventAt = 0;
26890
26867
  historyWriter;
26891
26868
  instanceId;
26869
+ launchMode;
26870
+ resolvedOutputFormat;
26871
+ /**
26872
+ * Determine output rendering format from:
26873
+ * 1. launchMode.outputFormat (explicit override)
26874
+ * 2. launchOptions[].outputFormatMap — check actual args for matching values
26875
+ * 3. Default: 'terminal'
26876
+ */
26877
+ resolveOutputFormat() {
26878
+ if (this.launchMode?.outputFormat) return this.launchMode.outputFormat;
26879
+ if (this.provider.launchOptions?.length) {
26880
+ for (const opt of this.provider.launchOptions) {
26881
+ if (!opt.outputFormatMap) continue;
26882
+ for (const [val, fmt] of Object.entries(opt.outputFormatMap)) {
26883
+ if (this.cliArgs.includes(val)) return fmt;
26884
+ }
26885
+ }
26886
+ }
26887
+ return "terminal";
26888
+ }
26892
26889
  // ─── Lifecycle ─────────────────────────────────
26893
26890
  async init(context) {
26894
26891
  this.context = context;
@@ -26928,7 +26925,8 @@ var CliProviderInstance = class {
26928
26925
  name: this.provider.name,
26929
26926
  category: "cli",
26930
26927
  status: adapterStatus.status,
26931
- mode: "terminal",
26928
+ mode: this.resolvedOutputFormat === "stream-json" ? "chat" : "terminal",
26929
+ launchMode: this.launchMode?.id,
26932
26930
  activeChat: {
26933
26931
  id: `${this.type}_${this.workingDir}`,
26934
26932
  title: `${this.provider.name} \xB7 ${dirName}`,
@@ -28059,12 +28057,12 @@ var DaemonCliManager = class {
28059
28057
  }
28060
28058
  }, 3e3);
28061
28059
  }
28062
- async registerCliInstance(key, normalizedType, cliType, resolvedDir, cliArgs, provider, settings, attachExisting = false) {
28060
+ async registerCliInstance(key, normalizedType, cliType, resolvedDir, cliArgs, provider, settings, attachExisting = false, launchModeId) {
28063
28061
  const instanceManager = this.deps.getInstanceManager();
28064
28062
  const sessionRegistry = this.deps.getSessionRegistry?.() || null;
28065
28063
  if (!instanceManager) throw new Error("InstanceManager not available");
28066
28064
  const transportFactory = this.getTransportFactory(key, normalizedType, resolvedDir, cliArgs, attachExisting);
28067
- const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key, transportFactory);
28065
+ const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key, transportFactory, launchModeId);
28068
28066
  try {
28069
28067
  await instanceManager.addInstance(key, cliInstance, {
28070
28068
  serverConn: this.deps.getServerConn(),
@@ -28090,7 +28088,7 @@ var DaemonCliManager = class {
28090
28088
  this.startCliExitMonitor(key, cliType);
28091
28089
  }
28092
28090
  // ─── Session start/management ──────────────────────────────
28093
- async startSession(cliType, workingDir, cliArgs, initialModel) {
28091
+ async startSession(cliType, workingDir, cliArgs, initialModel, launchMode, launchOptionValues) {
28094
28092
  const trimmed = (workingDir || "").trim();
28095
28093
  if (!trimmed) throw new Error("working directory required");
28096
28094
  const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path10.resolve(trimmed);
@@ -28182,6 +28180,29 @@ ${installInfo}`
28182
28180
  if (provider) {
28183
28181
  console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
28184
28182
  }
28183
+ let resolvedCliArgs = cliArgs;
28184
+ let resolvedLaunchMode = launchMode;
28185
+ const activeMode = provider?.launchModes?.length ? launchMode ? provider.launchModes.find((m) => m.id === launchMode) : provider.launchModes.find((m) => m.default) : void 0;
28186
+ if (activeMode) {
28187
+ resolvedLaunchMode = activeMode.id;
28188
+ }
28189
+ if (provider?.launchArgBuilder) {
28190
+ const defaults = {};
28191
+ for (const opt of provider.launchOptions || []) {
28192
+ if (opt.default !== void 0) defaults[opt.id] = opt.default;
28193
+ }
28194
+ const modeOptions = activeMode?.options || {};
28195
+ const userOptions = launchOptionValues || {};
28196
+ const merged = { ...defaults, ...modeOptions, ...userOptions };
28197
+ const extraArgs = provider.launchArgBuilder(merged);
28198
+ if (extraArgs.length) {
28199
+ resolvedCliArgs = [...cliArgs || [], ...extraArgs];
28200
+ console.log(colorize("cyan", ` \u{1F680} Launch options applied: ${extraArgs.join(" ")}`));
28201
+ }
28202
+ } else if (activeMode?.extraArgs?.length) {
28203
+ resolvedCliArgs = [...cliArgs || [], ...activeMode.extraArgs];
28204
+ console.log(colorize("cyan", ` \u{1F680} Launch mode '${activeMode.name}': appending args ${activeMode.extraArgs.join(" ")}`));
28205
+ }
28185
28206
  const instanceManager = this.deps.getInstanceManager();
28186
28207
  if (provider && instanceManager) {
28187
28208
  const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
@@ -28190,14 +28211,15 @@ ${installInfo}`
28190
28211
  normalizedType,
28191
28212
  cliType,
28192
28213
  resolvedDir,
28193
- cliArgs,
28214
+ resolvedCliArgs,
28194
28215
  resolvedProvider,
28195
28216
  {},
28196
- false
28217
+ false,
28218
+ resolvedLaunchMode
28197
28219
  );
28198
28220
  console.log(colorize("green", ` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
28199
28221
  } else {
28200
- const adapter = this.createAdapter(cliType, resolvedDir, cliArgs, key, false);
28222
+ const adapter = this.createAdapter(cliType, resolvedDir, resolvedCliArgs, key, false);
28201
28223
  try {
28202
28224
  await adapter.spawn();
28203
28225
  } catch (spawnErr) {
@@ -28305,7 +28327,8 @@ ${installInfo}`
28305
28327
  record2.cliArgs,
28306
28328
  resolvedProvider,
28307
28329
  {},
28308
- true
28330
+ true,
28331
+ record2.launchMode
28309
28332
  );
28310
28333
  restored += 1;
28311
28334
  LOG.info("CLI", `\u267B Restored hosted runtime: ${record2.runtimeKey || record2.runtimeId} (${record2.displayName || record2.workspace})`);
@@ -28375,7 +28398,7 @@ ${installInfo}`
28375
28398
  const dir = resolved.path;
28376
28399
  const launchSource = resolved.source;
28377
28400
  if (!cliType) throw new Error("cliType required");
28378
- await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel);
28401
+ await this.startSession(cliType, dir, args?.cliArgs, args?.initialModel, args?.launchMode, args?.launchOptionValues);
28379
28402
  let newKey = null;
28380
28403
  for (const [k, adapter] of this.adapters) {
28381
28404
  if (adapter.cliType === cliType && adapter.workingDir === dir) {