reasonix 0.52.0 → 0.53.0

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.
Files changed (143) hide show
  1. package/README.md +1 -0
  2. package/README.zh-CN.md +1 -0
  3. package/dashboard/dist/app.css +1 -1
  4. package/dashboard/dist/app.js +13 -13
  5. package/dashboard/dist/app.js.map +1 -1
  6. package/dist/cli/{acp-NEUYWGUU.js → acp-ABNDGEYC.js} +63 -30
  7. package/dist/cli/acp-ABNDGEYC.js.map +1 -0
  8. package/dist/cli/chat-377YZV56.js +49 -0
  9. package/dist/cli/{chunk-FY5UERSG.js → chunk-2WZT27GR.js} +9 -9
  10. package/dist/cli/{chunk-B4MOGWHW.js → chunk-4EHRIP5U.js} +7 -7
  11. package/dist/cli/chunk-4EHRIP5U.js.map +1 -0
  12. package/dist/cli/{chunk-RCC73DWQ.js → chunk-4SBXAHR6.js} +4 -4
  13. package/dist/cli/{chunk-5YLEKX2V.js → chunk-4V4TKQMB.js} +4 -4
  14. package/dist/cli/{chunk-5YLEKX2V.js.map → chunk-4V4TKQMB.js.map} +1 -1
  15. package/dist/cli/chunk-7ZO6H6ZK.js +54 -0
  16. package/dist/cli/chunk-7ZO6H6ZK.js.map +1 -0
  17. package/dist/cli/{chunk-3OXD5CBM.js → chunk-A6GSOADP.js} +17870 -16070
  18. package/dist/cli/chunk-A6GSOADP.js.map +1 -0
  19. package/dist/cli/{chunk-Z663GVUB.js → chunk-APOSDBAU.js} +3 -3
  20. package/dist/cli/{chunk-CTRM32BP.js → chunk-B5JISV5I.js} +2 -2
  21. package/dist/cli/{chunk-HNZ4727T.js → chunk-DFHI2MRB.js} +412 -152
  22. package/dist/cli/chunk-DFHI2MRB.js.map +1 -0
  23. package/dist/cli/{chunk-CGVW5W7N.js → chunk-EPIHGOM3.js} +14 -14
  24. package/dist/cli/{chunk-CGVW5W7N.js.map → chunk-EPIHGOM3.js.map} +1 -1
  25. package/dist/cli/{chunk-77JIQ7SL.js → chunk-EQFZIHKJ.js} +8 -8
  26. package/dist/cli/chunk-EQFZIHKJ.js.map +1 -0
  27. package/dist/cli/{chunk-XNMXVL6C.js → chunk-FB27YXPX.js} +2 -2
  28. package/dist/cli/{chunk-ARBGTNHM.js → chunk-FK7NXDRP.js} +2 -2
  29. package/dist/cli/{chunk-AOYUW3HR.js → chunk-GCNBIWK7.js} +22 -2
  30. package/dist/cli/chunk-GCNBIWK7.js.map +1 -0
  31. package/dist/cli/{chunk-XBYHNZ5Z.js → chunk-GMQVINZK.js} +13 -5
  32. package/dist/cli/chunk-GMQVINZK.js.map +1 -0
  33. package/dist/cli/{chunk-MVLPXZAA.js → chunk-GOASYYZ4.js} +43 -11
  34. package/dist/cli/{chunk-MVLPXZAA.js.map → chunk-GOASYYZ4.js.map} +1 -1
  35. package/dist/cli/{chunk-WPY7AFS6.js → chunk-I4SH5Z7S.js} +2 -2
  36. package/dist/cli/{chunk-MW64SQUE.js → chunk-J26XOB2T.js} +2 -2
  37. package/dist/cli/{chunk-DLTE4GBY.js → chunk-J4MYMBJ7.js} +3 -3
  38. package/dist/cli/{chunk-CFJY64UA.js → chunk-LRO63VNK.js} +2 -2
  39. package/dist/cli/{chunk-XUZHBQSM.js → chunk-MQJR7YQ2.js} +2 -2
  40. package/dist/cli/{chunk-CPCUMMSR.js → chunk-NVI4XPOQ.js} +3 -3
  41. package/dist/cli/{chunk-RHQOGG43.js → chunk-OHSVEXFF.js} +3 -3
  42. package/dist/cli/chunk-OHSVEXFF.js.map +1 -0
  43. package/dist/cli/{chunk-AMSK3ZLB.js → chunk-P5SUHDUQ.js} +2 -2
  44. package/dist/cli/{chunk-GFJJEW3Z.js → chunk-QSKDP3OS.js} +55 -5
  45. package/dist/cli/chunk-QSKDP3OS.js.map +1 -0
  46. package/dist/cli/{chunk-D6WRFR6V.js → chunk-R7JMQMLD.js} +6 -5
  47. package/dist/cli/chunk-R7JMQMLD.js.map +1 -0
  48. package/dist/cli/{chunk-VVPV5HU6.js → chunk-RRZIIMAF.js} +2 -2
  49. package/dist/cli/{chunk-GNRKXRRE.js → chunk-S3QII236.js} +369 -359
  50. package/dist/cli/{chunk-GNRKXRRE.js.map → chunk-S3QII236.js.map} +1 -1
  51. package/dist/cli/{chunk-HI6THNAZ.js → chunk-TGP7JGHN.js} +32 -14
  52. package/dist/cli/chunk-TGP7JGHN.js.map +1 -0
  53. package/dist/cli/{chunk-CLHMV6OL.js → chunk-U7G72DHQ.js} +83 -42
  54. package/dist/cli/chunk-U7G72DHQ.js.map +1 -0
  55. package/dist/cli/{chunk-OMNRXZNA.js → chunk-URAI4YRL.js} +2 -2
  56. package/dist/cli/{chunk-6QBUXA73.js → chunk-V4AXMN4X.js} +2 -2
  57. package/dist/cli/{chunk-2W4F3RIZ.js → chunk-XHP6NYOT.js} +3 -2
  58. package/dist/cli/{chunk-2W4F3RIZ.js.map → chunk-XHP6NYOT.js.map} +1 -1
  59. package/dist/cli/{code-WN6D4VZO.js → code-JPFZJYVW.js} +34 -34
  60. package/dist/cli/{commands-DHETOY7O.js → commands-IUL2CLKH.js} +4 -4
  61. package/dist/cli/{commit-BBUYAKZV.js → commit-JT7LYBTL.js} +3 -3
  62. package/dist/cli/{config-KV7VV5LG.js → config-T4RWI5NG.js} +6 -2
  63. package/dist/cli/{desktop-LJVXWXNF.js → desktop-AUBW2SLL.js} +122 -38
  64. package/dist/cli/desktop-AUBW2SLL.js.map +1 -0
  65. package/dist/cli/devtools-O5HOMAGZ.js +3 -0
  66. package/dist/cli/diff-NINZHUJR.js +165 -0
  67. package/dist/cli/diff-NINZHUJR.js.map +1 -0
  68. package/dist/cli/{doctor-GI5LOEZL.js → doctor-OMAYGY4F.js} +10 -10
  69. package/dist/cli/{events-LBKMLFM4.js → events-5IVFJ4H3.js} +5 -5
  70. package/dist/cli/index.js +38 -38
  71. package/dist/cli/{mcp-DKEJK5ND.js → mcp-ECGJACAP.js} +3 -3
  72. package/dist/cli/{mcp-browse-V7KWDY32.js → mcp-browse-NGEOHVJB.js} +15 -15
  73. package/dist/cli/mcp-browse-NGEOHVJB.js.map +1 -0
  74. package/dist/cli/{mcp-inspect-MTABNHVM.js → mcp-inspect-ZIMNRG7G.js} +5 -5
  75. package/dist/cli/{prompt-ATI7DKHF.js → prompt-JCC3A7AA.js} +5 -5
  76. package/dist/cli/{prune-sessions-YQQSZTZS.js → prune-sessions-TE4BJYO2.js} +4 -4
  77. package/dist/cli/{replay-ZJQ4I4CJ.js → replay-2UUTCRTG.js} +29 -29
  78. package/dist/cli/replay-2UUTCRTG.js.map +1 -0
  79. package/dist/cli/{run-HFPRNWJY.js → run-ABQYOPVM.js} +22 -22
  80. package/dist/cli/{server-UHKO2VVM.js → server-MPCXIW2O.js} +27 -25
  81. package/dist/cli/{server-UHKO2VVM.js.map → server-MPCXIW2O.js.map} +1 -1
  82. package/dist/cli/{sessions-IQEWWUH3.js → sessions-YBPRGIAF.js} +16 -16
  83. package/dist/cli/{setup-5BYKCL62.js → setup-A34LF2QE.js} +42 -42
  84. package/dist/cli/setup-A34LF2QE.js.map +1 -0
  85. package/dist/cli/{stats-OFCGOQMZ.js → stats-GKG5JZQX.js} +6 -6
  86. package/dist/cli/stats-GKG5JZQX.js.map +1 -0
  87. package/dist/cli/{version-EODUFAAI.js → version-JD6QSM4X.js} +16 -16
  88. package/dist/index.d.ts +36 -5
  89. package/dist/index.js +443 -73
  90. package/dist/index.js.map +1 -1
  91. package/package.json +7 -2
  92. package/dist/cli/acp-NEUYWGUU.js.map +0 -1
  93. package/dist/cli/chat-QA6IVFJD.js +0 -49
  94. package/dist/cli/chunk-3OXD5CBM.js.map +0 -1
  95. package/dist/cli/chunk-77JIQ7SL.js.map +0 -1
  96. package/dist/cli/chunk-AOYUW3HR.js.map +0 -1
  97. package/dist/cli/chunk-B4MOGWHW.js.map +0 -1
  98. package/dist/cli/chunk-CLHMV6OL.js.map +0 -1
  99. package/dist/cli/chunk-D6WRFR6V.js.map +0 -1
  100. package/dist/cli/chunk-GFJJEW3Z.js.map +0 -1
  101. package/dist/cli/chunk-HI6THNAZ.js.map +0 -1
  102. package/dist/cli/chunk-HNZ4727T.js.map +0 -1
  103. package/dist/cli/chunk-I3NE5S63.js +0 -54
  104. package/dist/cli/chunk-I3NE5S63.js.map +0 -1
  105. package/dist/cli/chunk-RHQOGG43.js.map +0 -1
  106. package/dist/cli/chunk-XBYHNZ5Z.js.map +0 -1
  107. package/dist/cli/desktop-LJVXWXNF.js.map +0 -1
  108. package/dist/cli/diff-2JHMQAHI.js +0 -165
  109. package/dist/cli/diff-2JHMQAHI.js.map +0 -1
  110. package/dist/cli/mcp-browse-V7KWDY32.js.map +0 -1
  111. package/dist/cli/replay-ZJQ4I4CJ.js.map +0 -1
  112. package/dist/cli/setup-5BYKCL62.js.map +0 -1
  113. /package/dist/cli/{chat-QA6IVFJD.js.map → chat-377YZV56.js.map} +0 -0
  114. /package/dist/cli/{chunk-FY5UERSG.js.map → chunk-2WZT27GR.js.map} +0 -0
  115. /package/dist/cli/{chunk-RCC73DWQ.js.map → chunk-4SBXAHR6.js.map} +0 -0
  116. /package/dist/cli/{chunk-Z663GVUB.js.map → chunk-APOSDBAU.js.map} +0 -0
  117. /package/dist/cli/{chunk-CTRM32BP.js.map → chunk-B5JISV5I.js.map} +0 -0
  118. /package/dist/cli/{chunk-XNMXVL6C.js.map → chunk-FB27YXPX.js.map} +0 -0
  119. /package/dist/cli/{chunk-ARBGTNHM.js.map → chunk-FK7NXDRP.js.map} +0 -0
  120. /package/dist/cli/{chunk-WPY7AFS6.js.map → chunk-I4SH5Z7S.js.map} +0 -0
  121. /package/dist/cli/{chunk-MW64SQUE.js.map → chunk-J26XOB2T.js.map} +0 -0
  122. /package/dist/cli/{chunk-DLTE4GBY.js.map → chunk-J4MYMBJ7.js.map} +0 -0
  123. /package/dist/cli/{chunk-CFJY64UA.js.map → chunk-LRO63VNK.js.map} +0 -0
  124. /package/dist/cli/{chunk-XUZHBQSM.js.map → chunk-MQJR7YQ2.js.map} +0 -0
  125. /package/dist/cli/{chunk-CPCUMMSR.js.map → chunk-NVI4XPOQ.js.map} +0 -0
  126. /package/dist/cli/{chunk-AMSK3ZLB.js.map → chunk-P5SUHDUQ.js.map} +0 -0
  127. /package/dist/cli/{chunk-VVPV5HU6.js.map → chunk-RRZIIMAF.js.map} +0 -0
  128. /package/dist/cli/{chunk-OMNRXZNA.js.map → chunk-URAI4YRL.js.map} +0 -0
  129. /package/dist/cli/{chunk-6QBUXA73.js.map → chunk-V4AXMN4X.js.map} +0 -0
  130. /package/dist/cli/{code-WN6D4VZO.js.map → code-JPFZJYVW.js.map} +0 -0
  131. /package/dist/cli/{commands-DHETOY7O.js.map → commands-IUL2CLKH.js.map} +0 -0
  132. /package/dist/cli/{commit-BBUYAKZV.js.map → commit-JT7LYBTL.js.map} +0 -0
  133. /package/dist/cli/{config-KV7VV5LG.js.map → config-T4RWI5NG.js.map} +0 -0
  134. /package/dist/cli/{doctor-GI5LOEZL.js.map → devtools-O5HOMAGZ.js.map} +0 -0
  135. /package/dist/cli/{prompt-ATI7DKHF.js.map → doctor-OMAYGY4F.js.map} +0 -0
  136. /package/dist/cli/{events-LBKMLFM4.js.map → events-5IVFJ4H3.js.map} +0 -0
  137. /package/dist/cli/{mcp-DKEJK5ND.js.map → mcp-ECGJACAP.js.map} +0 -0
  138. /package/dist/cli/{mcp-inspect-MTABNHVM.js.map → mcp-inspect-ZIMNRG7G.js.map} +0 -0
  139. /package/dist/cli/{stats-OFCGOQMZ.js.map → prompt-JCC3A7AA.js.map} +0 -0
  140. /package/dist/cli/{prune-sessions-YQQSZTZS.js.map → prune-sessions-TE4BJYO2.js.map} +0 -0
  141. /package/dist/cli/{run-HFPRNWJY.js.map → run-ABQYOPVM.js.map} +0 -0
  142. /package/dist/cli/{sessions-IQEWWUH3.js.map → sessions-YBPRGIAF.js.map} +0 -0
  143. /package/dist/cli/{version-EODUFAAI.js.map → version-JD6QSM4X.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/cli/commands/desktop.ts","../../src/desktop/login-shell-path.ts","../../src/desktop/qq-settings.ts","../../src/desktop/qq-turn-routing.ts","../../src/session-import.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { existsSync, statSync, writeSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { stdin } from \"node:process\";\nimport { createInterface } from \"node:readline\";\nimport { toApprovalPrompt } from \"@reasonix/core-utils\";\nimport {\n type FileWithStats,\n listDirectory,\n listFilesWithStatsAsync,\n parseAtQuery,\n rankPickerCandidates,\n} from \"../../at-mentions.js\";\nimport { pickPrimaryBalance } from \"../../client.js\";\nimport { codeSystemPrompt } from \"../../code/prompt.js\";\nimport { applyPlanMode, buildCodeToolset } from \"../../code/setup.js\";\nimport {\n DEFAULT_MODEL,\n type DesktopOpenTab,\n type EditMode,\n bridgeEndpointEnv,\n isPlausibleKey,\n isReasoningEffort,\n loadApiKey,\n loadDesktopOpenTabs,\n loadEditMode,\n loadEditor,\n loadEndpoint,\n loadExaApiKey,\n loadMetasoApiKey,\n loadModel,\n loadPerplexityApiKey,\n loadQQConfig,\n loadReasoningEffort,\n loadRecentWorkspaces,\n loadResolvedSkillPaths,\n loadShowSystemEvents,\n loadSubagentModels,\n loadTavilyApiKey,\n loadWorkspaceDir,\n pushRecentWorkspace,\n readConfig,\n webSearchEngine as readWebSearchEngine,\n saveApiKey,\n saveBaseUrl,\n saveDesktopOpenTabs,\n saveEditMode,\n saveEditor,\n saveModel,\n saveReasoningEffort,\n saveShowSystemEvents,\n saveSubagentModels,\n saveWorkspaceDir,\n writeConfig,\n} from \"../../config.js\";\nimport { Eventizer } from \"../../core/eventize.js\";\nimport type { Event as KernelEvent } from \"../../core/events.js\";\nimport {\n type CheckpointVerdict,\n type ChoiceVerdict,\n type ConfirmationChoice,\n type PlanVerdict,\n type RevisionVerdict,\n pauseGate,\n} from \"../../core/pause-gate.js\";\nimport { autoResolveVerdict } from \"../../core/pause-policy.js\";\nimport { augmentProcessPath } from \"../../desktop/login-shell-path.js\";\nimport {\n type MemoryEntryDetail,\n type MemoryEntryInfo,\n collectMemoryEntriesForWorkspace,\n readMemoryEntryDetail,\n} from \"../../desktop/memory-browser.js\";\nimport {\n loadDesktopQQState,\n saveDesktopQQSettings,\n setDesktopQQEnabled,\n} from \"../../desktop/qq-settings.js\";\nimport {\n clearQQTurnRouting,\n createQQTurnRoutingState,\n markQQTurnFinished,\n markQQTurnStarted,\n setQQPendingInteraction,\n shouldRouteQQForTab,\n takeQQPendingInteraction,\n} from \"../../desktop/qq-turn-routing.js\";\nimport { loadDotenv } from \"../../env.js\";\nimport { CacheFirstLoop, DeepSeekClient, ImmutablePrefix } from \"../../index.js\";\nimport { parseMcpSpec } from \"../../mcp/spec.js\";\nimport {\n deleteSession,\n listSessionsForWorkspace,\n loadSessionMessages,\n loadSessionMeta,\n patchSessionMeta,\n patchSessionWorkspaceIfMissing,\n sessionPath,\n timestampSuffix,\n} from \"../../memory/session.js\";\nimport { QQChannel } from \"../../qq/channel.js\";\nimport {\n type ExternalSessionSource,\n discoverExternalSessionApps,\n importExternalSession,\n importExternalSessions,\n} from \"../../session-import.js\";\nimport { SkillStore } from \"../../skills.js\";\nimport { countTokensBounded } from \"../../tokenizer.js\";\nimport type { ChoiceOption } from \"../../tools/choice.js\";\nimport type { ChatMessage } from \"../../types.js\";\nimport { VERSION } from \"../../version.js\";\nimport { type McpRuntime, createMcpRuntime } from \"./mcp-runtime.js\";\n\nexport interface DesktopOptions {\n model: string;\n budgetUsd?: number;\n /** Root directory the agent's filesystem tools operate inside. Defaults to cwd. */\n dir?: string;\n}\n\ntype InMessage = { tabId?: string } & (\n | { cmd: \"user_input\"; text: string }\n | { cmd: \"abort\" }\n | { cmd: \"confirm_response\"; id: number; response: ConfirmationChoice }\n | { cmd: \"choice_response\"; id: number; response: ChoiceVerdict }\n | { cmd: \"plan_response\"; id: number; response: PlanVerdict }\n | { cmd: \"checkpoint_response\"; id: number; response: CheckpointVerdict }\n | { cmd: \"revision_response\"; id: number; response: RevisionVerdict }\n | { cmd: \"session_list\" }\n | { cmd: \"session_delete\"; name: string }\n | { cmd: \"session_load\"; name: string }\n | { cmd: \"session_rename\"; name: string; title: string }\n | { cmd: \"session_import\"; source: ExternalSessionSource; path: string; name?: string }\n | { cmd: \"session_import_scan\" }\n | { cmd: \"session_import_bulk\"; sources: ExternalSessionSource[] }\n | { cmd: \"memory_read\"; path: string }\n | { cmd: \"new_chat\" }\n | { cmd: \"setup_save_key\"; key: string }\n | { cmd: \"settings_get\" }\n | {\n cmd: \"settings_save\";\n reasoningEffort?: import(\"../../config.js\").ReasoningEffort;\n editMode?: EditMode;\n budgetUsd?: number | null;\n baseUrl?: string;\n workspaceDir?: string;\n model?: string;\n editor?: string;\n webSearchEngine?: \"bing\" | \"searxng\" | \"metaso\" | \"tavily\" | \"perplexity\" | \"exa\";\n webSearchEndpoint?: string | null;\n metasoApiKey?: string | null;\n tavilyApiKey?: string | null;\n perplexityApiKey?: string | null;\n exaApiKey?: string | null;\n subagentModels?: Record<string, \"flash\" | \"pro\">;\n showSystemEvents?: boolean;\n }\n | { cmd: \"qq_status_get\" }\n | { cmd: \"qq_connect\" }\n | { cmd: \"qq_disconnect\" }\n | {\n cmd: \"qq_config_save\";\n appId?: string;\n appSecret?: string;\n sandbox: boolean;\n }\n | { cmd: \"mention_query\"; query: string; nonce: number }\n | { cmd: \"mention_preview\"; path: string; nonce: number }\n | { cmd: \"mention_picked\"; path: string }\n | { cmd: \"tab_open\"; workspaceDir?: string }\n | { cmd: \"tab_close\" }\n | { cmd: \"tab_activate\"; tabId: string }\n | { cmd: \"mcp_specs_get\" }\n | { cmd: \"mcp_specs_add\"; spec: string }\n | { cmd: \"mcp_specs_remove\"; spec: string }\n | { cmd: \"skills_get\" }\n | { cmd: \"skill_run\"; name: string; args?: string }\n | { cmd: \"jobs_list\" }\n | { cmd: \"jobs_stop\"; jobId: number }\n | { cmd: \"jobs_stop_all\" }\n | { cmd: \"compact_history\" }\n | { cmd: \"retry\" }\n | { cmd: \"btw\"; text: string }\n | { cmd: \"desktop_resync\" }\n);\n\ninterface NeedsSetupEvent {\n type: \"$needs_setup\";\n reason: \"no_api_key\";\n}\n\ninterface SettingsEvent {\n type: \"$settings\";\n reasoningEffort: import(\"../../config.js\").ReasoningEffort;\n editMode: EditMode;\n budgetUsd: number | null;\n baseUrl?: string;\n apiKeyPrefix?: string;\n workspaceDir: string;\n recentWorkspaces: string[];\n model: string;\n editor?: string;\n webSearchEngine?: \"bing\" | \"searxng\" | \"metaso\" | \"tavily\" | \"perplexity\" | \"exa\";\n webSearchEndpoint?: string;\n webSearchApiKeys?: {\n metaso?: string;\n tavily?: string;\n perplexity?: string;\n exa?: string;\n };\n subagentModels?: Record<string, \"flash\" | \"pro\">;\n showSystemEvents?: boolean;\n version: string;\n}\n\ninterface QQSettingsEvent {\n type: \"$qq_settings\";\n appId?: string;\n appSecret?: string;\n sandbox: boolean;\n enabled: boolean;\n configured: boolean;\n runtimeState: \"disconnected\" | \"connecting\" | \"connected\" | \"failed\";\n lastError?: string;\n appIdPreview?: string;\n access: string;\n}\n\ninterface BalanceEvent {\n type: \"$balance\";\n currency: string;\n total: number;\n isAvailable: boolean;\n}\n\ninterface PlanRequiredEvent {\n type: \"$plan_required\";\n id: number;\n plan: string;\n steps?: unknown[];\n summary?: string;\n}\n\ninterface SessionsEvent {\n type: \"$sessions\";\n items: {\n name: string;\n messageCount: number;\n mtime: string;\n summary?: string;\n workspaceStatus?: \"matched\" | \"legacy_missing_meta\";\n }[];\n}\n\ninterface SessionImportSourcesEvent {\n type: \"$session_import_sources\";\n apps: ReturnType<typeof discoverExternalSessionApps>;\n}\n\ninterface SessionImportResultEvent {\n type: \"$session_import_result\";\n imported: number;\n skipped: number;\n failed: number;\n}\n\ninterface MentionResultsEvent {\n type: \"$mention_results\";\n nonce: number;\n query: string;\n results: string[];\n}\n\ninterface MentionPreviewEvent {\n type: \"$mention_preview\";\n nonce: number;\n path: string;\n head: string;\n totalLines: number;\n}\n\ninterface TabOpenedEvent {\n type: \"$tab_opened\";\n workspaceDir: string;\n /** True when the frontend should focus this tab (user-opened, or the restored focused tab). */\n active?: boolean;\n}\n\ninterface TabClosedEvent {\n type: \"$tab_closed\";\n}\n\ntype LoadedSegment =\n | { kind: \"text\"; text: string }\n | { kind: \"reasoning\"; text: string }\n | {\n kind: \"tool\";\n callId: string;\n name: string;\n args: string;\n result?: string;\n ok?: boolean;\n };\n\ntype LoadedMessage =\n | { kind: \"user\"; text: string }\n | {\n kind: \"assistant\";\n turn: number;\n segments: LoadedSegment[];\n pending: false;\n };\n\ninterface SessionLoadedEvent {\n type: \"$session_loaded\";\n name: string;\n messages: LoadedMessage[];\n carryover: {\n totalCostUsd: number;\n cacheHitTokens: number;\n cacheMissTokens: number;\n totalCompletionTokens: number;\n };\n}\n\ninterface SessionEmptyEvent {\n type: \"$session_empty\";\n name: string;\n sizeBytes: number;\n}\n\ninterface ConfirmRequiredEvent {\n type: \"$confirm_required\";\n id: number;\n kind: \"run_command\" | \"run_background\";\n command: string;\n prompt?: import(\"@reasonix/core-utils\").ApprovalPrompt;\n}\n\ninterface PathAccessRequiredEvent {\n type: \"$path_access_required\";\n id: number;\n path: string;\n intent: \"read\" | \"write\";\n toolName: string;\n sandboxRoot: string;\n allowPrefix: string;\n prompt?: import(\"@reasonix/core-utils\").ApprovalPrompt;\n}\n\ninterface ChoiceRequiredEvent {\n type: \"$choice_required\";\n id: number;\n question: string;\n options: ChoiceOption[];\n allowCustom: boolean;\n}\n\ninterface PlanStepLite {\n id: string;\n title: string;\n action: string;\n risk?: \"low\" | \"med\" | \"high\";\n}\n\ninterface CheckpointRequiredEvent {\n type: \"$checkpoint_required\";\n id: number;\n stepId: string;\n title?: string;\n result: string;\n notes?: string;\n completed: number;\n total: number;\n}\n\ninterface RevisionRequiredEvent {\n type: \"$revision_required\";\n id: number;\n reason: string;\n remainingSteps: PlanStepLite[];\n summary?: string;\n}\n\ninterface StepCompletedEvent {\n type: \"$step_completed\";\n stepId: string;\n title?: string;\n result: string;\n notes?: string;\n}\n\ninterface PlanClearedEvent {\n type: \"$plan_cleared\";\n}\n\ntype McpSpecStatus = \"configured\" | \"handshake\" | \"connected\" | \"failed\" | \"disabled\";\n\ninterface McpSpecInfo {\n raw: string;\n name: string | null;\n transport: \"stdio\" | \"sse\" | \"streamable-http\";\n summary: string;\n parseError?: string;\n status: McpSpecStatus;\n statusReason?: string;\n toolCount?: number;\n}\n\ninterface McpSpecsEvent {\n type: \"$mcp_specs\";\n specs: McpSpecInfo[];\n bridged: boolean;\n}\n\ninterface CtxBreakdownEvent {\n type: \"$ctx_breakdown\";\n reservedTokens: number;\n /** Current log token count (real-time) — sent after /compact to refresh the meter. */\n logTokens?: number;\n}\n\ninterface MemoryEvent {\n type: \"$memory\";\n entries: MemoryEntryInfo[];\n}\n\ninterface MemoryDetailEvent {\n type: \"$memory_detail\";\n detail: MemoryEntryDetail;\n}\n\ninterface SkillInfo {\n name: string;\n description: string;\n scope: \"project\" | \"custom\" | \"global\" | \"builtin\";\n path: string;\n runAs: \"inline\" | \"subagent\";\n model?: string;\n}\n\ninterface SkillsEvent {\n type: \"$skills\";\n items: SkillInfo[];\n}\n\ninterface JobInfoPayload {\n id: number;\n tabId: string;\n sessionLabel: string;\n command: string;\n pid: number | null;\n running: boolean;\n exitCode: number | null;\n startedAt: number;\n outputTail: string;\n spawnError?: string;\n}\n\ninterface JobsEvent {\n type: \"$jobs\";\n items: JobInfoPayload[];\n}\n\nconst desktopQqRuntimeSnapshot: {\n runtimeState: \"disconnected\" | \"connecting\" | \"connected\" | \"failed\";\n lastError?: string;\n} = {\n runtimeState: \"disconnected\",\n};\n\ninterface RetryResultEvent {\n type: \"$retry_result\";\n text: string;\n}\n\ninterface BtwResultEvent {\n type: \"$btw_result\";\n question: string;\n answer: string;\n}\n\n/** Direct fd write — bypasses Node's stream layer (and its piped-output\n * block buffering) so every JSON line reaches Rust the moment it's\n * produced, not whenever the next 8 KB flushes. */\ntype EmittableEvent =\n | KernelEvent\n | { type: \"$ready\" }\n | { type: \"$error\"; message: string }\n | { type: \"$turn_complete\" }\n | ConfirmRequiredEvent\n | PathAccessRequiredEvent\n | ChoiceRequiredEvent\n | PlanRequiredEvent\n | CheckpointRequiredEvent\n | RevisionRequiredEvent\n | StepCompletedEvent\n | PlanClearedEvent\n | SessionsEvent\n | SessionImportSourcesEvent\n | SessionImportResultEvent\n | SessionLoadedEvent\n | SessionEmptyEvent\n | NeedsSetupEvent\n | SettingsEvent\n | QQSettingsEvent\n | BalanceEvent\n | MentionResultsEvent\n | MentionPreviewEvent\n | RetryResultEvent\n | BtwResultEvent\n | TabOpenedEvent\n | TabClosedEvent\n | McpSpecsEvent\n | SkillsEvent\n | CtxBreakdownEvent\n | MemoryEvent\n | MemoryDetailEvent\n | JobsEvent;\n\nconst STDOUT_BACKPRESSURE_WAIT = new Int32Array(new SharedArrayBuffer(4));\n\ntype SyncWriter = (fd: number, buffer: Buffer, offset: number, length: number) => number;\n\nconst SESSION_TITLE_MAX_CHARS = 200;\n\n/** Trim + cap a user-provided session title; empty string means \"clear summary\". Exported for tests. */\nexport function normalizeSessionTitle(raw: string): string {\n return raw.replace(/\\s+/g, \" \").trim().slice(0, SESSION_TITLE_MAX_CHARS);\n}\n\n/** Drain `buffer` to `fd` across partial writes; retry EAGAIN after a 5 ms park. Exported for tests. */\nexport function writeAllSync(\n fd: number,\n buffer: Buffer,\n opts: {\n write?: SyncWriter;\n wait?: () => void;\n } = {},\n): void {\n const write = opts.write ?? writeSync;\n const wait = opts.wait ?? (() => Atomics.wait(STDOUT_BACKPRESSURE_WAIT, 0, 0, 5));\n let offset = 0;\n while (offset < buffer.length) {\n let written: number;\n try {\n written = write(fd, buffer, offset, buffer.length - offset);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EAGAIN\") {\n wait();\n continue;\n }\n throw err;\n }\n if (written <= 0) throw new Error(\"stdout write returned 0 bytes\");\n offset += written;\n }\n}\n\nfunction emit(ev: EmittableEvent, tabId?: string): void {\n const payload = tabId ? { ...ev, tabId } : ev;\n writeAllSync(1, Buffer.from(`${JSON.stringify(payload)}\\n`, \"utf8\"));\n}\n\nfunction tailLines(s: string, n: number): string {\n if (!s) return \"\";\n const lines = s.split(/\\r?\\n/);\n return lines.slice(-n).join(\"\\n\");\n}\n\nconst LOADED_RECENT_MESSAGE_WINDOW = 200;\nconst LOADED_MIN_ELIDE_CHARS = 4096;\nconst LOADED_ELIDED_PREFIX = \"[elided — older than the last \";\n\nfunction elideLoadedField(value: string): string {\n if (value.length <= LOADED_MIN_ELIDE_CHARS) return value;\n if (value.startsWith(LOADED_ELIDED_PREFIX)) return value;\n return `${LOADED_ELIDED_PREFIX}${LOADED_RECENT_MESSAGE_WINDOW} messages; ${value.length.toLocaleString()} chars dropped to save memory. Full content is on disk in the session log.]`;\n}\n\nfunction elideLoadedMessages(messages: LoadedMessage[]): LoadedMessage[] {\n if (messages.length < LOADED_RECENT_MESSAGE_WINDOW) return messages;\n const cutoff = messages.length - LOADED_RECENT_MESSAGE_WINDOW;\n return messages.map((msg, i) => {\n if (i >= cutoff || msg.kind !== \"assistant\") return msg;\n return {\n ...msg,\n segments: msg.segments.map((segment) => {\n switch (segment.kind) {\n case \"reasoning\":\n case \"text\":\n return { ...segment, text: elideLoadedField(segment.text) };\n case \"tool\":\n return {\n ...segment,\n args: elideLoadedField(segment.args),\n ...(segment.result !== undefined ? { result: elideLoadedField(segment.result) } : {}),\n };\n default:\n return segment;\n }\n }),\n };\n });\n}\n\nexport function buildLoadedMessages(records: ChatMessage[]): LoadedMessage[] {\n const out: LoadedMessage[] = [];\n let turn = 0;\n let pendingAssistantIdx = -1;\n for (const rec of records) {\n if (rec.role === \"system\") continue;\n if (rec.role === \"user\") {\n out.push({ kind: \"user\", text: rec.content ?? \"\" });\n pendingAssistantIdx = -1;\n continue;\n }\n if (rec.role === \"assistant\") {\n turn++;\n const segments: LoadedSegment[] = [];\n if (rec.reasoning_content) segments.push({ kind: \"reasoning\", text: rec.reasoning_content });\n if (rec.content) segments.push({ kind: \"text\", text: rec.content });\n if (rec.tool_calls) {\n for (let i = 0; i < rec.tool_calls.length; i++) {\n const tc = rec.tool_calls[i];\n if (!tc) continue;\n segments.push({\n kind: \"tool\",\n callId: tc.id ?? `tc-r-${turn}-${i}`,\n name: tc.function?.name ?? \"\",\n args: tc.function?.arguments ?? \"\",\n });\n }\n }\n out.push({ kind: \"assistant\", turn, segments, pending: false });\n pendingAssistantIdx = out.length - 1;\n continue;\n }\n if (rec.role === \"tool\") {\n if (pendingAssistantIdx < 0) continue;\n const host = out[pendingAssistantIdx];\n if (host?.kind !== \"assistant\") continue;\n const callId = rec.tool_call_id;\n if (!callId) continue;\n const seg = host.segments.find((s) => s.kind === \"tool\" && s.callId === callId);\n if (seg && seg.kind === \"tool\") {\n seg.result = rec.content ?? \"\";\n seg.ok = !/error|failed/i.test(seg.result.slice(0, 200));\n }\n }\n }\n return elideLoadedMessages(out);\n}\n\nfunction maskApiKey(key: string | undefined): string | undefined {\n if (!key) return undefined;\n if (key.length <= 7) return `${key.slice(0, 2)}…`;\n return `${key.slice(0, 6)}…${key.slice(-3)}`;\n}\n\nfunction collectWebSearchApiKeyPrefixes(): {\n metaso?: string;\n tavily?: string;\n perplexity?: string;\n exa?: string;\n} {\n return {\n metaso: maskApiKey(loadMetasoApiKey()),\n tavily: maskApiKey(loadTavilyApiKey()),\n perplexity: maskApiKey(loadPerplexityApiKey()),\n exa: maskApiKey(loadExaApiKey()),\n };\n}\n\nfunction emitSettings(tab: Tab): void {\n const ep = loadEndpoint();\n const editMode = loadEditMode();\n if (tab.toolset) applyPlanMode(tab.toolset.tools, editMode);\n const recent = loadRecentWorkspaces().filter((p) => p !== tab.rootDir);\n emit(\n {\n type: \"$settings\",\n reasoningEffort: loadReasoningEffort(),\n editMode,\n budgetUsd: tab.runtime?.loop.budgetUsd ?? null,\n baseUrl: ep.baseUrl,\n apiKeyPrefix: ep.apiKey ? `${ep.apiKey.slice(0, 6)}…${ep.apiKey.slice(-3)}` : undefined,\n workspaceDir: tab.rootDir,\n recentWorkspaces: recent,\n model: tab.currentModel,\n editor: loadEditor(),\n webSearchEngine: readWebSearchEngine(),\n webSearchEndpoint: readConfig().webSearchEndpoint,\n webSearchApiKeys: collectWebSearchApiKeyPrefixes(),\n subagentModels: loadSubagentModels(),\n showSystemEvents: loadShowSystemEvents(),\n version: VERSION,\n },\n tab.id,\n );\n}\n\nfunction emitQQSettings(tab: Tab): void {\n const base = loadDesktopQQState();\n emit(\n {\n type: \"$qq_settings\",\n ...base,\n runtimeState: desktopQqRuntimeSnapshot.runtimeState,\n lastError: desktopQqRuntimeSnapshot.lastError,\n },\n tab.id,\n );\n}\n\nasync function emitBalance(tab: Tab): Promise<void> {\n if (!tab.runtime) return;\n const bal = await tab.runtime.loop.client.getBalance().catch(() => null);\n if (!bal) return;\n const primary = pickPrimaryBalance(bal.balance_infos);\n if (!primary) return;\n emit(\n {\n type: \"$balance\",\n currency: primary.currency,\n total: Number(primary.total_balance),\n isAvailable: bal.is_available,\n },\n tab.id,\n );\n}\n\nfunction emitSessions(tab: Tab): void {\n try {\n const items = listSessionsForWorkspace(tab.rootDir).map((s) => ({\n name: s.name,\n messageCount: s.messageCount,\n mtime: s.mtime.toISOString(),\n summary: s.meta.summary,\n workspaceStatus: s.workspaceStatus,\n }));\n emit({ type: \"$sessions\", items }, tab.id);\n } catch (err) {\n emit({ type: \"$error\", message: `session_list failed: ${(err as Error).message}` }, tab.id);\n }\n}\n\nfunction loadSessionIntoTab(\n tab: Tab,\n name: string,\n actions: {\n abortTurn: (tab: Tab) => void;\n cancelPendingGates: (tab: Tab) => void;\n persistOpenTabs: () => void;\n },\n): void {\n const records = loadSessionMessages(name);\n const backfilledWorkspace = patchSessionWorkspaceIfMissing(name, tab.rootDir);\n const meta = loadSessionMeta(name);\n // Only set switching flag when there's a live turn to abort —\n // otherwise the flag stays true and suppresses the first turn's events (#1217).\n if (tab.aborter) tab.switching = true;\n actions.abortTurn(tab);\n actions.cancelPendingGates(tab);\n tab.currentSession = name;\n actions.persistOpenTabs();\n if (tab.runtime) tab.runtime = buildRuntimeFor(tab);\n const loadedMessages = buildLoadedMessages(records);\n if (loadedMessages.length === 0) {\n let sizeBytes = 0;\n try {\n sizeBytes = statSync(sessionPath(name)).size;\n } catch {\n /* file may not exist */\n }\n process.stderr.write(\n `session_load: \"${name}\" returned 0 messages (file size=${sizeBytes}B) — empty or unreadable jsonl\\n`,\n );\n emit({ type: \"$session_empty\", name, sizeBytes }, tab.id);\n }\n emit(\n {\n type: \"$session_loaded\",\n name,\n messages: loadedMessages,\n carryover: {\n totalCostUsd: meta.totalCostUsd ?? 0,\n cacheHitTokens: meta.cacheHitTokens ?? 0,\n cacheMissTokens: meta.cacheMissTokens ?? 0,\n totalCompletionTokens: meta.totalCompletionTokens ?? 0,\n },\n },\n tab.id,\n );\n if (backfilledWorkspace) emitSessions(tab);\n}\n\nfunction summarizeMcpSpec(raw: string): McpSpecInfo {\n try {\n const parsed = parseMcpSpec(raw);\n if (parsed.transport === \"stdio\") {\n const argv = [parsed.command, ...parsed.args].join(\" \");\n return {\n raw,\n name: parsed.name,\n transport: \"stdio\",\n summary: `stdio · ${argv}`,\n status: \"configured\",\n };\n }\n return {\n raw,\n name: parsed.name,\n transport: parsed.transport,\n summary: `${parsed.transport} · ${parsed.url}`,\n status: \"configured\",\n };\n } catch (err) {\n return {\n raw,\n name: null,\n transport: \"stdio\",\n summary: raw,\n parseError: (err as Error).message,\n status: \"failed\",\n statusReason: (err as Error).message,\n };\n }\n}\n\nfunction emitMcpSpecs(tab: Tab): void {\n const cfg = readConfig();\n const specs = (cfg.mcp ?? []).map((raw) => {\n const base = summarizeMcpSpec(raw);\n const live = tab.mcpStatuses.get(raw);\n if (!live) return base;\n return { ...base, status: live.kind, statusReason: live.reason, toolCount: live.toolCount };\n });\n const bridged = specs.length > 0 && specs.every((s) => s.status === \"connected\");\n emit({ type: \"$mcp_specs\", specs, bridged }, tab.id);\n}\n\nfunction emitMemory(tab: Tab): void {\n try {\n const entries = collectMemoryEntriesForWorkspace(tab.rootDir);\n emit({ type: \"$memory\", entries }, tab.id);\n } catch (err) {\n emit({ type: \"$error\", message: `memory_get failed: ${(err as Error).message}` }, tab.id);\n }\n}\n\n// reserved = system prompt + tool specs, constant for the tab's lifetime once\n// the loop is built. The growing log portion is already covered by the\n// per-turn cache hit/miss numbers in `model.final`.\nfunction emitCtxBreakdown(tab: Tab): void {\n if (!tab.runtime) return;\n try {\n const sys = countTokensBounded(tab.runtime.loop.prefix.system);\n const tools = countTokensBounded(JSON.stringify(tab.runtime.loop.prefix.toolSpecs));\n const logTokens = tab.runtime.loop.getCurrentLogTokens();\n emit({ type: \"$ctx_breakdown\", reservedTokens: sys + tools, logTokens }, tab.id);\n } catch {\n // tokenizer warmup can throw on first call before the data file loads\n }\n}\n\nfunction emitSkills(tab: Tab): void {\n try {\n const store = new SkillStore({\n projectRoot: tab.rootDir,\n customSkillPaths: loadResolvedSkillPaths(tab.rootDir),\n subagentModels: loadSubagentModels(),\n });\n const items = store.list().map((s) => ({\n name: s.name,\n description: s.description,\n scope: s.scope,\n path: s.path,\n runAs: s.runAs,\n model: s.model,\n }));\n emit({ type: \"$skills\", items }, tab.id);\n } catch (err) {\n emit({ type: \"$error\", message: `skills_get failed: ${(err as Error).message}` }, tab.id);\n }\n}\n\ninterface RuntimeState {\n loop: CacheFirstLoop;\n eventizer: Eventizer;\n ctx: {\n model: string;\n prefixHash: string;\n reasoningEffort: import(\"../../config.js\").ReasoningEffort;\n };\n}\n\ntype SymbolEntry = { name: string; path: string; line: number; kind: string };\n\ninterface Tab {\n readonly id: string;\n rootDir: string;\n currentSession: string;\n currentModel: string;\n budgetUsd: number | undefined;\n /** null while the tab is bootstrapping — see `initTabToolset`. UI gates input on `$ready`, which only fires once this is set. */\n toolset: Awaited<ReturnType<typeof buildCodeToolset>> | null;\n /** Empty while bootstrapping; populated together with `toolset`. */\n system: string;\n runtime: RuntimeState | null;\n aborter: AbortController | null;\n fileIndex: FileWithStats[] | null;\n fileIndexBuilding: Promise<FileWithStats[]> | null;\n fileIndexBuiltAt: number;\n symbolIndex: SymbolEntry[] | null;\n symbolBuilding: Promise<SymbolEntry[]> | null;\n recentMentions: string[];\n /** Pause-gate ids waiting on this tab — abort uses these to free stranded plan_checkpoint / plan_revision / shell-confirm callers. */\n pendingGateIds: Set<number>;\n /** Step ids already marked complete in the in-flight plan — also tells UI when a plan is \"active\". */\n completedStepIds: Set<string>;\n /** Total steps in the in-flight plan (0 = no active plan / steps not provided). */\n planTotalSteps: number;\n mcpRuntime: McpRuntime | null;\n mcpStatuses: Map<string, { kind: McpSpecStatus; reason?: string; toolCount?: number }>;\n /** True while a session switch is in progress — prevents stale events from the old turn. */\n switching: boolean;\n}\n\nlet tabCounter = 0;\nfunction nextTabId(): string {\n tabCounter++;\n return `t${tabCounter}`;\n}\n\nfunction mintSessionFor(rootDir: string): string {\n const name = `desktop-${timestampSuffix()}-${tabCounter}`;\n try {\n patchSessionMeta(name, { workspace: rootDir });\n } catch {\n // session meta is for filtering only — failure shouldn't block chat\n }\n return name;\n}\n\nfunction buildRuntimeFor(tab: Tab): RuntimeState {\n if (!tab.toolset) throw new Error(\"buildRuntimeFor called before initTabToolset finished\");\n const toolset = tab.toolset;\n applyPlanMode(toolset.tools, loadEditMode());\n const ep = loadEndpoint();\n const client = new DeepSeekClient({ apiKey: ep.apiKey, baseUrl: ep.baseUrl });\n const prefix = new ImmutablePrefix({ system: tab.system, toolSpecs: toolset.tools.specs() });\n const reasoningEffort = loadReasoningEffort();\n const loop = new CacheFirstLoop({\n client,\n prefix,\n tools: toolset.tools,\n model: tab.currentModel,\n budgetUsd: tab.budgetUsd,\n session: tab.currentSession,\n reasoningEffort,\n });\n const eventizer = new Eventizer();\n const ctx = { model: tab.currentModel, prefixHash: prefix.fingerprint, reasoningEffort };\n return { loop, eventizer, ctx };\n}\n\nconst TS_EXPORT_RE =\n /^export\\s+(?:default\\s+)?(?:async\\s+)?(function|class|const|let|var|interface|type|enum)\\s+\\*?\\s*(\\w+)/;\n\n/** TTL on the in-memory file index — without this, files deleted / renamed since the last @ popup still show up as candidates. 10s balances \"fresh enough for typical edit-then-mention flows\" against \"don't re-scan 5000 files on every keystroke\". */\nconst FILE_INDEX_TTL_MS = 10_000;\n\nasync function getFileIndexFor(tab: Tab): Promise<FileWithStats[]> {\n const fresh = tab.fileIndex && Date.now() - tab.fileIndexBuiltAt < FILE_INDEX_TTL_MS;\n if (fresh) return tab.fileIndex as FileWithStats[];\n if (tab.fileIndexBuilding) return tab.fileIndexBuilding;\n tab.fileIndexBuilding = listFilesWithStatsAsync(tab.rootDir, { maxResults: 5000 })\n .then((res) => {\n tab.fileIndex = res;\n tab.fileIndexBuiltAt = Date.now();\n tab.fileIndexBuilding = null;\n return res;\n })\n .catch((err) => {\n tab.fileIndexBuilding = null;\n throw err;\n });\n return tab.fileIndexBuilding;\n}\n\nasync function getSymbolIndexFor(tab: Tab): Promise<SymbolEntry[]> {\n if (tab.symbolIndex) return tab.symbolIndex;\n if (tab.symbolBuilding) return tab.symbolBuilding;\n tab.symbolBuilding = (async () => {\n const files = await getFileIndexFor(tab);\n const sourceExts = /\\.(?:ts|tsx|js|jsx|mts|cts)$/;\n const candidates = files.filter((f) => sourceExts.test(f.path)).slice(0, 1500);\n const out: SymbolEntry[] = [];\n const PARALLEL = 16;\n for (let i = 0; i < candidates.length; i += PARALLEL) {\n const batch = candidates.slice(i, i + PARALLEL);\n await Promise.all(\n batch.map(async (entry) => {\n const abs = isAbsolute(entry.path) ? entry.path : join(tab.rootDir, entry.path);\n try {\n const text = await readFile(abs, \"utf8\");\n const lines = text.split(/\\r?\\n/);\n for (let li = 0; li < lines.length; li++) {\n const line = lines[li]!;\n if (!line.startsWith(\"export \")) continue;\n const m = TS_EXPORT_RE.exec(line);\n if (m) out.push({ kind: m[1]!, name: m[2]!, path: entry.path, line: li + 1 });\n }\n } catch {\n // unreadable / binary — skip\n }\n }),\n );\n }\n tab.symbolIndex = out;\n tab.symbolBuilding = null;\n return out;\n })().catch((err) => {\n tab.symbolBuilding = null;\n throw err;\n });\n return tab.symbolBuilding;\n}\n\nfunction rankSymbols(syms: readonly SymbolEntry[], q: string, limit: number): string[] {\n const needle = q.toLowerCase();\n const scored: { entry: SymbolEntry; score: number }[] = [];\n for (const s of syms) {\n const lower = s.name.toLowerCase();\n let score: number;\n if (lower === needle) score = 0;\n else if (lower.startsWith(needle)) score = 100;\n else if (lower.includes(needle)) score = 500 + lower.indexOf(needle);\n else continue;\n scored.push({ entry: s, score });\n }\n scored.sort((a, b) => a.score - b.score || a.entry.name.localeCompare(b.entry.name));\n return scored.slice(0, limit).map((s) => `${s.entry.path}:${s.entry.line}`);\n}\n\nfunction pushMentionRecent(tab: Tab, path: string): void {\n const MAX = 20;\n const idx = tab.recentMentions.indexOf(path);\n if (idx >= 0) tab.recentMentions.splice(idx, 1);\n tab.recentMentions.unshift(path);\n if (tab.recentMentions.length > MAX) tab.recentMentions.length = MAX;\n}\n\n/** The desktop sidecar is a long-running daemon — Tauri spawns this Node process once per app launch and pipes JSON over stdin/stdout. Without these handlers, any orphaned promise rejection (e.g. from an aborted turn whose cleanup races a session-switch — #1074) crashes the process with exit code 1, which the Tauri host surfaces as \"reasonix exited (code 1)\" and a full reconnect cycle. Log loudly so we can find the underlying bug, but don't take the daemon down. */\nexport function installDesktopCrashGuards(\n stderr: { write: (s: string) => unknown } = process.stderr,\n): void {\n process.on(\"unhandledRejection\", (reason) => {\n const err = reason instanceof Error ? reason : new Error(String(reason));\n stderr.write(`[desktop] unhandledRejection: ${err.stack ?? err.message}\\n`);\n });\n process.on(\"uncaughtException\", (err) => {\n stderr.write(`[desktop] uncaughtException: ${err.stack ?? err.message}\\n`);\n });\n}\n\nexport async function desktopCommand(opts: DesktopOptions): Promise<void> {\n loadDotenv();\n // Tauri spawns the bundled Node from the GUI process, which never runs the\n // user's shell init (`.bashrc` / `.zshrc` / profile). Probe the login shell\n // once so nvm / asdf / fnm / volta / mise PATH entries reach `run_command`\n // children too (#1252). No-op on Windows — system PATH already covers GUI apps.\n const augmented = augmentProcessPath();\n if (augmented.added.length > 0) {\n process.stderr.write(\n `[desktop] augmented PATH with ${augmented.added.length} login-shell entries\\n`,\n );\n }\n installDesktopCrashGuards();\n\n const tabs = new Map<string, Tab>();\n const tabContext = new AsyncLocalStorage<string>();\n // Frontend-reported focused tab — persisted so a restart reopens on it (#1244).\n let lastActiveTabId = \"\";\n\n function activeRunningTab(): Tab | undefined {\n const id = tabContext.getStore();\n return id ? tabs.get(id) : undefined;\n }\n\n let first: Tab;\n\n const qqRuntime = {\n channel: null as QQChannel | null,\n runtimeState: \"disconnected\" as \"disconnected\" | \"connecting\" | \"connected\" | \"failed\",\n lastError: undefined as string | undefined,\n routing: createQQTurnRoutingState(),\n };\n\n function currentQqSettings(): QQSettingsEvent {\n const base = loadDesktopQQState();\n return {\n type: \"$qq_settings\",\n ...base,\n runtimeState: qqRuntime.runtimeState,\n lastError: qqRuntime.lastError,\n };\n }\n\n function activeDesktopTab(): Tab | undefined {\n return (lastActiveTabId ? tabs.get(lastActiveTabId) : undefined) ?? first;\n }\n\n function broadcastQQSettings(): void {\n for (const tab of tabs.values()) emit(currentQqSettings(), tab.id);\n }\n\n function setQQRuntimeState(\n runtimeState: \"disconnected\" | \"connecting\" | \"connected\" | \"failed\",\n lastError?: string,\n ): void {\n qqRuntime.runtimeState = runtimeState;\n qqRuntime.lastError = lastError;\n desktopQqRuntimeSnapshot.runtimeState = runtimeState;\n desktopQqRuntimeSnapshot.lastError = lastError;\n broadcastQQSettings();\n }\n\n function sendQQInfo(message: string): void {\n const tab = activeDesktopTab();\n if (tab) {\n emit(\n {\n type: \"status\",\n id: Date.now(),\n ts: new Date().toISOString(),\n turn: 0,\n text: message,\n },\n tab.id,\n );\n }\n void qqRuntime.channel?.sendResponse(message).catch((err) => {\n const active = activeDesktopTab();\n if (active) {\n emit({ type: \"$error\", message: `qq send failed: ${(err as Error).message}` }, active.id);\n }\n });\n }\n\n function parseIndexedChoice(text: string): number {\n const rawIndex = text.match(/^(\\d+)/)?.[1];\n return rawIndex ? Number.parseInt(rawIndex, 10) - 1 : -1;\n }\n\n function parseRunPermissionChoice(text: string): \"run_once\" | \"always_allow\" | \"deny\" {\n const lower = text.toLowerCase();\n if (lower.includes(\"1\") || lower.includes(\"run\")) return \"run_once\";\n if (lower.includes(\"2\") || lower.includes(\"always\")) return \"always_allow\";\n return \"deny\";\n }\n\n function parsePlanChoice(text: string): \"approve\" | \"refine\" | \"cancel\" {\n const lower = text.toLowerCase();\n if (lower.includes(\"1\") || lower.includes(\"approve\")) return \"approve\";\n if (lower.includes(\"2\") || lower.includes(\"refine\")) return \"refine\";\n return \"cancel\";\n }\n\n function parseCheckpointChoice(text: string): \"continue\" | \"revise\" | \"stop\" {\n const lower = text.toLowerCase();\n if (lower.includes(\"1\") || lower.includes(\"continue\")) return \"continue\";\n if (lower.includes(\"2\") || lower.includes(\"revise\")) return \"revise\";\n return \"stop\";\n }\n\n function parseRevisionChoice(text: string): \"accept\" | \"reject\" | \"cancel\" {\n const lower = text.toLowerCase();\n if (lower.includes(\"1\") || lower.includes(\"accept\")) return \"accept\";\n if (lower.includes(\"2\") || lower.includes(\"reject\")) return \"reject\";\n return \"cancel\";\n }\n\n function stripFollowupPrefix(text: string): string {\n return text\n .replace(\n /^(?:\\d+\\s*|approve\\s*|refine\\s*|cancel\\s*|continue\\s*|revise\\s*|stop\\s*|accept\\s*|reject\\s*|run\\s*|always\\s*|deny\\s*)/iu,\n \"\",\n )\n .trim();\n }\n\n function handleQQPauseReply(tab: Tab, text: string): boolean {\n const pending = takeQQPendingInteraction(qqRuntime.routing, tab.id);\n if (!pending) return false;\n const followup = stripFollowupPrefix(text);\n const interaction = pending;\n const gateId = pending.gateId;\n\n switch (interaction.kind) {\n case \"run_command\":\n case \"run_background\":\n case \"path_access\":\n pauseGate.resolve(gateId, parseRunPermissionChoice(text));\n return true;\n case \"plan_proposed\": {\n const payload = (interaction.payload as { plan?: string }) ?? {};\n const choice = parsePlanChoice(text);\n if (choice === \"cancel\") {\n pauseGate.cancel(gateId);\n } else {\n pauseGate.resolve(gateId, {\n type: choice === \"approve\" ? \"approve\" : \"refine\",\n feedback: followup,\n override: {\n plan: payload.plan ?? \"\",\n mode: choice === \"approve\" ? \"approve\" : \"refine\",\n },\n });\n }\n return true;\n }\n case \"plan_checkpoint\": {\n const payload = (interaction.payload as { stepId?: string; title?: string }) ?? {};\n const choice = parseCheckpointChoice(text);\n if (choice === \"revise\") {\n pauseGate.resolve(gateId, {\n type: \"revise\",\n feedback: followup,\n checkpoint: { stepId: payload.stepId ?? \"\", title: payload.title },\n });\n } else {\n pauseGate.resolve(gateId, { type: choice });\n }\n return true;\n }\n case \"plan_revision\":\n pauseGate.resolve(gateId, parseRevisionChoice(text));\n return true;\n case \"choice\": {\n const payload =\n (interaction.payload as { options?: ChoiceOption[]; allowCustom?: boolean }) ?? {};\n const options = payload.options ?? [];\n const pickedIndex = parseIndexedChoice(text);\n if (pickedIndex >= 0 && pickedIndex < options.length) {\n const selected = options[pickedIndex];\n if (selected) pauseGate.resolve(gateId, { type: \"pick\", optionId: selected.id });\n return true;\n }\n for (const option of options) {\n if (text.toLowerCase().includes(option.title.toLowerCase())) {\n pauseGate.resolve(gateId, { type: \"pick\", optionId: option.id });\n return true;\n }\n }\n pauseGate.resolve(\n gateId,\n payload.allowCustom ? { type: \"text\", text } : { type: \"cancel\" },\n );\n return true;\n }\n default:\n return false;\n }\n }\n\n function handleQQPauseRequest(tab: Tab, kind: string, payload: Record<string, unknown>): void {\n if (!qqRuntime.channel || !shouldRouteQQForTab(qqRuntime.routing, tab.id)) return;\n let qqMessage = \"\";\n switch (kind) {\n case \"run_command\":\n case \"run_background\": {\n const p = payload as { command: string };\n qqMessage = `Need confirmation\\n\\nCommand: \\`${p.command}\\`\\n\\nReply with:\\n1. Run once\\n2. Always allow\\n3. Deny`;\n break;\n }\n case \"path_access\": {\n const p = payload as { path: string; intent: \"read\" | \"write\"; toolName: string };\n const intentText = p.intent === \"read\" ? \"Read\" : \"Write\";\n qqMessage = `Need file access confirmation\\n\\nAction: ${intentText}\\nPath: ${p.path}\\nTool: ${p.toolName}\\n\\nReply with:\\n1. Run once\\n2. Always allow\\n3. Deny`;\n break;\n }\n case \"plan_proposed\": {\n const p = payload as { plan: string };\n qqMessage = `Plan confirmation\\n\\n${p.plan}\\n\\nReply with:\\n1. Approve\\n2. Refine\\n3. Cancel`;\n break;\n }\n case \"plan_checkpoint\": {\n const p = payload as { title?: string; result: string };\n qqMessage = `Step complete (${tab.completedStepIds.size}/${tab.planTotalSteps})\\n\\n${\n p.title ? `Step: ${p.title}\\n` : \"\"\n }Result: ${p.result}\\n\\nReply with:\\n1. Continue\\n2. Revise\\n3. Stop`;\n break;\n }\n case \"plan_revision\": {\n const p = payload as { reason: string };\n qqMessage = `Plan revision proposed\\n\\n${p.reason}\\n\\nReply with:\\n1. Accept\\n2. Reject\\n3. Cancel`;\n break;\n }\n case \"choice\": {\n const p = payload as { question: string; options: ChoiceOption[]; allowCustom: boolean };\n const optionsList = p.options.map((opt, idx) => `${idx + 1}. ${opt.title}`).join(\"\\n\");\n qqMessage = `Please choose\\n\\n${p.question}\\n\\nOptions:\\n${optionsList}${\n p.allowCustom ? \"\\n\\n(You can also reply with custom text.)\" : \"\"\n }`;\n break;\n }\n }\n if (qqMessage) {\n void qqRuntime.channel.sendResponse(qqMessage).catch((err) => {\n emit({ type: \"$error\", message: `qq send failed: ${(err as Error).message}` }, tab.id);\n });\n }\n }\n\n async function startDesktopQQ(shouldPersistEnabled = true): Promise<void> {\n const current = loadQQConfig();\n if (!(current.appId && current.appSecret)) {\n throw new Error(\"QQ App ID and App Secret are required.\");\n }\n if (qqRuntime.channel) {\n qqRuntime.channel.refreshAccessConfig();\n setQQRuntimeState(\"connected\");\n return;\n }\n setQQRuntimeState(\"connecting\");\n const channel = new QQChannel({\n onSubmitMessage: (text) => {\n const tab = activeDesktopTab();\n if (!tab) return;\n const trimmed = text.trim();\n if (!trimmed) return;\n emit(\n {\n type: \"user.message\",\n id: Date.now(),\n ts: new Date().toISOString(),\n turn: 0,\n text: trimmed,\n },\n tab.id,\n );\n if (handleQQPauseReply(tab, trimmed)) return;\n if (tab.aborter) {\n void channel\n .sendResponse(\n \"Session is busy. Wait for the current turn or reply to the pending prompt.\",\n )\n .catch(() => undefined);\n return;\n }\n void runTurn(tab, trimmed, true);\n },\n onError: (message) => {\n const tab = activeDesktopTab();\n setQQRuntimeState(\"failed\", message);\n if (tab) emit({ type: \"$error\", message: `QQ: ${message}` }, tab.id);\n },\n });\n try {\n await channel.start();\n qqRuntime.channel = channel;\n if (shouldPersistEnabled) setDesktopQQEnabled(true);\n setQQRuntimeState(\"connected\");\n } catch (err) {\n await channel.stop().catch(() => undefined);\n qqRuntime.channel = null;\n if (shouldPersistEnabled) setDesktopQQEnabled(false);\n setQQRuntimeState(\"failed\", (err as Error).message);\n throw err;\n }\n }\n\n async function stopDesktopQQ(shouldDisable = true): Promise<void> {\n const channel = qqRuntime.channel;\n qqRuntime.channel = null;\n clearQQTurnRouting(qqRuntime.routing);\n if (channel) await channel.stop();\n if (shouldDisable) setDesktopQQEnabled(false);\n setQQRuntimeState(\"disconnected\");\n }\n\n /** Synchronous tab construction — no I/O. All cheap, disk-only events (`$settings`, `$sessions`, `$memory`, `$skills`, `$mcp_specs`) can fire against this immediately. The heavy bits (`buildCodeToolset`, MCP probes, runtime construction) happen in `initTabToolset` so the UI shell paints without waiting for them. */\n function createTabSkeleton(initialDir?: string): Tab {\n const dir = resolve(initialDir ?? opts.dir ?? loadWorkspaceDir() ?? process.cwd());\n pushRecentWorkspace(dir);\n const model = opts.model || loadModel() || DEFAULT_MODEL;\n const tab: Tab = {\n id: nextTabId(),\n rootDir: dir,\n currentSession: \"\",\n currentModel: model,\n budgetUsd: opts.budgetUsd,\n toolset: null,\n system: \"\",\n runtime: null,\n aborter: null,\n fileIndex: null,\n fileIndexBuilding: null,\n fileIndexBuiltAt: 0,\n symbolIndex: null,\n symbolBuilding: null,\n recentMentions: [],\n pendingGateIds: new Set<number>(),\n completedStepIds: new Set<string>(),\n planTotalSteps: 0,\n mcpRuntime: null,\n mcpStatuses: new Map(),\n switching: false,\n };\n tab.currentSession = mintSessionFor(dir);\n tabs.set(tab.id, tab);\n return tab;\n }\n\n /** Builds the toolset / system prompt / runtime / MCP bridge for a freshly-created skeleton. Reads `tab.currentModel` at call time so model changes during the wait are honored. */\n async function initTabToolset(tab: Tab): Promise<void> {\n const toolset = await buildCodeToolset({\n rootDir: tab.rootDir,\n onSkillInstalled: () => emitSkills(tab),\n onJobsChanged: () => emitJobs(),\n });\n tab.toolset = toolset;\n tab.system = codeSystemPrompt(tab.rootDir, {\n hasSemanticSearch: toolset.semantic.enabled,\n modelId: tab.currentModel,\n });\n if (loadApiKey()) {\n bridgeEndpointEnv();\n tab.runtime = buildRuntimeFor(tab);\n void bridgeTabMcp(tab);\n }\n }\n\n function bridgeTabMcp(tab: Tab): Promise<void> {\n if (!tab.runtime || !tab.toolset) return Promise.resolve();\n if (tab.mcpRuntime) {\n // Already constructed — reload so new/removed specs settle without restart.\n return tab.mcpRuntime\n .reloadFromConfig(tab.runtime.loop)\n .then(() => emitMcpSpecs(tab))\n .catch((err) => {\n emit({ type: \"$error\", message: `mcp reload failed: ${(err as Error).message}` }, tab.id);\n });\n }\n const requested = (readConfig().mcp ?? []).length;\n if (requested === 0) return Promise.resolve();\n const runtime = createMcpRuntime({\n getTools: () => {\n if (!tab.toolset) throw new Error(\"toolset gone\");\n return tab.toolset.tools;\n },\n getMcpPrefix: () => undefined,\n getRequestedCount: () => requested,\n getWorkspaceDir: () => tab.rootDir,\n progressSink: { current: null },\n });\n tab.mcpRuntime = runtime;\n runtime.setLifecycleSink((notice) => {\n if (notice.kind === \"slow\") return; // not surfaced in the desktop panel\n const cfg = readConfig().mcp ?? [];\n const target = cfg.find((raw) => {\n try {\n return parseMcpSpec(raw).name === notice.name;\n } catch {\n return false;\n }\n });\n if (!target) return;\n if (notice.kind === \"handshake\") {\n tab.mcpStatuses.set(target, { kind: \"handshake\" });\n } else if (notice.kind === \"connected\") {\n tab.mcpStatuses.set(target, { kind: \"connected\", toolCount: notice.tools });\n } else if (notice.kind === \"failed\") {\n tab.mcpStatuses.set(target, { kind: \"failed\", reason: notice.reason });\n } else if (notice.kind === \"disabled\") {\n tab.mcpStatuses.set(target, { kind: \"disabled\" });\n }\n emitMcpSpecs(tab);\n });\n return runtime\n .reloadFromConfig(tab.runtime.loop)\n .then(() => undefined)\n .catch((err) => {\n emit({ type: \"$error\", message: `mcp bridge failed: ${(err as Error).message}` }, tab.id);\n });\n }\n\n /** Snapshot of every open tab — workspace dir, loaded session and focus, in tab order. Persisted after open/close/switch so a restart restores the full tab set and each conversation (issues #933, #1244). */\n function persistOpenTabs(): void {\n try {\n saveDesktopOpenTabs(\n Array.from(tabs.values()).map((t) => ({\n dir: t.rootDir,\n session: t.currentSession || undefined,\n active: t.id === lastActiveTabId,\n })),\n );\n } catch {\n // best-effort — disk / perms shouldn't break tab management\n }\n }\n\n async function closeTab(tab: Tab): Promise<void> {\n abortTurn(tab);\n try {\n await tab.toolset?.jobs.shutdown();\n } catch {\n // shutdown errors aren't actionable here\n }\n if (tab.mcpRuntime) {\n try {\n await tab.mcpRuntime.closeAll();\n } catch {\n // MCP shutdown errors aren't actionable here either\n }\n }\n tabs.delete(tab.id);\n if (first && first.id === tab.id) {\n const next = tabs.values().next().value;\n if (next) first = next;\n }\n persistOpenTabs();\n emit({ type: \"$tab_closed\" }, tab.id);\n }\n\n async function runTurn(tab: Tab, text: string, fromQQ = false): Promise<void> {\n if (!tab.runtime) return;\n const rt = tab.runtime;\n tab.aborter = new AbortController();\n if (fromQQ) markQQTurnStarted(qqRuntime.routing, tab.id);\n let lastAssistantText = \"\";\n if (tab.currentSession) {\n const existing = loadSessionMeta(tab.currentSession).summary;\n if (!existing || !existing.trim()) {\n const summary = text.replace(/\\s+/g, \" \").trim().slice(0, 60);\n if (summary) {\n try {\n patchSessionMeta(tab.currentSession, { summary });\n } catch {\n // meta is for display only — failure shouldn't block the turn\n }\n }\n }\n }\n await tabContext.run(tab.id, async () => {\n try {\n for await (const ev of rt.loop.step(text)) {\n if (ev.role === \"assistant_final\" && ev.content) {\n lastAssistantText = ev.content;\n }\n for (const kev of rt.eventizer.consume(ev, rt.ctx)) emit(kev, tab.id);\n // Memory tools mutate disk state behind the loop's back — the UI\n // panel won't know until we re-emit. Without this the right-hand\n // panel only updates on tab reopen.\n if (ev.role === \"tool\" && (ev.toolName === \"remember\" || ev.toolName === \"forget\")) {\n emitMemory(tab);\n }\n if (tab.aborter?.signal.aborted) break;\n }\n } catch (err) {\n emit({ type: \"$error\", message: (err as Error).message }, tab.id);\n } finally {\n tab.aborter = null;\n // If a session switch happened while this turn was running,\n // suppress stale events to avoid UI state corruption (#1217).\n if (!tab.switching) {\n if (\n fromQQ &&\n lastAssistantText &&\n qqRuntime.channel &&\n shouldRouteQQForTab(qqRuntime.routing, tab.id)\n ) {\n await qqRuntime.channel.sendResponse(lastAssistantText).catch((err) => {\n emit(\n { type: \"$error\", message: `qq send failed: ${(err as Error).message}` },\n tab.id,\n );\n });\n }\n emit({ type: \"$turn_complete\" }, tab.id);\n if (tab.planTotalSteps > 0 && tab.completedStepIds.size >= tab.planTotalSteps) {\n tab.completedStepIds.clear();\n tab.planTotalSteps = 0;\n emit({ type: \"$plan_cleared\" }, tab.id);\n }\n emitSessions(tab);\n void emitBalance(tab);\n }\n if (fromQQ) markQQTurnFinished(qqRuntime.routing, tab.id);\n tab.switching = false;\n }\n });\n }\n\n async function switchWorkspace(tab: Tab, nextDir: string): Promise<void> {\n const target = resolve(nextDir);\n if (target === tab.rootDir) {\n emitSettings(tab);\n return;\n }\n if (!existsSync(target) || !statSync(target).isDirectory()) {\n emit({ type: \"$error\", message: `Workspace not found: ${target}` }, tab.id);\n emitSettings(tab);\n return;\n }\n abortTurn(tab);\n try {\n await tab.toolset?.jobs.shutdown();\n } catch {\n // shutdown errors aren't actionable here\n }\n tab.rootDir = target;\n saveWorkspaceDir(target);\n pushRecentWorkspace(target);\n tab.fileIndex = null;\n tab.fileIndexBuilding = null;\n tab.fileIndexBuiltAt = 0;\n tab.symbolIndex = null;\n tab.symbolBuilding = null;\n tab.recentMentions.length = 0;\n tab.currentSession = mintSessionFor(target);\n tab.toolset = await buildCodeToolset({\n rootDir: target,\n onSkillInstalled: () => emitSkills(tab),\n onJobsChanged: () => emitJobs(),\n });\n tab.system = codeSystemPrompt(target, {\n hasSemanticSearch: tab.toolset.semantic.enabled,\n modelId: tab.currentModel,\n });\n if (tab.runtime) tab.runtime = buildRuntimeFor(tab);\n emitSessions(tab);\n emitSettings(tab);\n emitSkills(tab);\n persistOpenTabs();\n }\n\n function forgetGate(id: number): Tab | undefined {\n for (const t of tabs.values()) {\n if (t.pendingGateIds.delete(id)) return t;\n }\n return undefined;\n }\n\n function abortTurn(tab: Tab, opts: { discardCurrentTurn?: boolean } = {}): void {\n tab.aborter?.abort();\n tab.runtime?.loop.abort(opts.discardCurrentTurn ? { discardCurrentTurn: true } : undefined);\n }\n\n function tabSessionLabel(tab: Tab): string {\n if (tab.currentSession) {\n try {\n const summary = loadSessionMeta(tab.currentSession).summary?.trim();\n if (summary) return summary;\n } catch {\n // session file unreadable — fall through to workspace basename\n }\n }\n return tab.rootDir.split(/[\\\\/]/).filter(Boolean).pop() ?? tab.rootDir;\n }\n\n function emitJobs(): void {\n const items: JobInfoPayload[] = [];\n for (const t of tabs.values()) {\n const reg = t.toolset?.jobs;\n if (!reg) continue;\n const label = tabSessionLabel(t);\n for (const j of reg.list()) {\n items.push({\n id: j.id,\n tabId: t.id,\n sessionLabel: label,\n command: j.command,\n pid: j.pid,\n running: j.running,\n exitCode: j.exitCode,\n startedAt: j.startedAt,\n outputTail: tailLines(j.output, 8),\n spawnError: j.spawnError,\n });\n }\n }\n items.sort((a, b) => {\n if (a.running !== b.running) return a.running ? -1 : 1;\n return b.startedAt - a.startedAt;\n });\n emit({ type: \"$jobs\", items });\n }\n\n async function stopJob(jobId: number): Promise<boolean> {\n for (const t of tabs.values()) {\n const reg = t.toolset?.jobs;\n if (!reg) continue;\n const hit = reg.list().find((j) => j.id === jobId);\n if (!hit) continue;\n await reg.stop(jobId);\n return true;\n }\n return false;\n }\n\n async function stopAllJobs(): Promise<void> {\n const ops: Promise<unknown>[] = [];\n for (const t of tabs.values()) {\n const reg = t.toolset?.jobs;\n if (!reg) continue;\n for (const j of reg.list()) {\n if (j.running) ops.push(reg.stop(j.id));\n }\n }\n await Promise.allSettled(ops);\n }\n\n function cancelPendingGates(tab: Tab): void {\n const hadActivePlan = tab.planTotalSteps > 0 || tab.completedStepIds.size > 0;\n const ids = [...tab.pendingGateIds];\n tab.pendingGateIds.clear();\n for (const id of ids) pauseGate.cancel(id);\n if (hadActivePlan) {\n tab.completedStepIds.clear();\n tab.planTotalSteps = 0;\n emit({ type: \"$plan_cleared\" }, tab.id);\n }\n }\n\n // `first` is the fallback tab for legacy tabId-less RPC messages. We\n // assign it lazily below so saved-tabs restore (issue #933) can choose\n // the boot dir before construction, and rotate `first` to the next\n // surviving tab when its source closes.\n let shuttingDown = false;\n async function gracefulShutdown(): Promise<void> {\n if (shuttingDown) return;\n shuttingDown = true;\n await stopDesktopQQ(false).catch(() => undefined);\n await Promise.allSettled(\n [...tabs.values()].map((t) => t.toolset?.jobs.shutdown(1500) ?? Promise.resolve()),\n );\n process.exit(0);\n }\n process.on(\"SIGTERM\", () => {\n void gracefulShutdown();\n });\n process.on(\"SIGINT\", () => {\n void gracefulShutdown();\n });\n\n pauseGate.on((req) => {\n const tab = activeRunningTab();\n const tabId = tab?.id;\n if (tab) tab.pendingGateIds.add(req.id);\n // Shared auto-resolve policy (e.g. plan_checkpoint in auto/yolo) — must\n // still run BEFORE we emit any UI event, otherwise the surface flickers\n // a card that we'd immediately tear down.\n const auto = autoResolveVerdict(req, loadEditMode());\n if (auto !== null) {\n // plan_checkpoint specifically needs the step-completed signal to flow\n // through so the rail progress ticks. Emit it before resolving.\n if (req.kind === \"plan_checkpoint\") {\n const payload = req.payload as {\n stepId: string;\n title?: string;\n result: string;\n notes?: string;\n };\n if (tab) tab.completedStepIds.add(payload.stepId);\n emit(\n {\n type: \"$step_completed\",\n stepId: payload.stepId,\n title: payload.title,\n result: payload.result,\n notes: payload.notes,\n },\n tabId,\n );\n }\n if (tab) tab.pendingGateIds.delete(req.id);\n pauseGate.resolve(req.id, auto);\n return;\n }\n if (req.kind === \"run_command\" || req.kind === \"run_background\") {\n const payload = req.payload as {\n command?: string;\n cwd?: string;\n timeoutSec?: number;\n waitSec?: number;\n };\n if (tab) setQQPendingInteraction(qqRuntime.routing, tab.id, req.id, req.kind, payload);\n emit(\n {\n type: \"$confirm_required\",\n id: req.id,\n kind: req.kind,\n command: payload.command ?? \"\",\n prompt: toApprovalPrompt({\n id: req.id,\n kind: req.kind,\n payload,\n }),\n },\n tabId,\n );\n if (tab) handleQQPauseRequest(tab, req.kind, payload as Record<string, unknown>);\n return;\n }\n if (req.kind === \"path_access\") {\n const payload = req.payload as {\n path: string;\n intent: \"read\" | \"write\";\n toolName: string;\n sandboxRoot: string;\n allowPrefix: string;\n };\n if (tab) setQQPendingInteraction(qqRuntime.routing, tab.id, req.id, req.kind, payload);\n emit(\n {\n type: \"$path_access_required\",\n id: req.id,\n path: payload.path,\n intent: payload.intent,\n toolName: payload.toolName,\n sandboxRoot: payload.sandboxRoot,\n allowPrefix: payload.allowPrefix,\n prompt: toApprovalPrompt({\n id: req.id,\n kind: req.kind,\n payload,\n }),\n },\n tabId,\n );\n if (tab) handleQQPauseRequest(tab, req.kind, payload as Record<string, unknown>);\n return;\n }\n if (req.kind === \"choice\") {\n const payload = req.payload as {\n question: string;\n options: ChoiceOption[];\n allowCustom: boolean;\n };\n if (tab) setQQPendingInteraction(qqRuntime.routing, tab.id, req.id, req.kind, payload);\n emit(\n {\n type: \"$choice_required\",\n id: req.id,\n question: payload.question,\n options: payload.options,\n allowCustom: payload.allowCustom,\n },\n tabId,\n );\n if (tab) handleQQPauseRequest(tab, req.kind, payload as Record<string, unknown>);\n return;\n }\n if (req.kind === \"plan_proposed\") {\n const payload = req.payload as { plan: string; steps?: PlanStepLite[]; summary?: string };\n if (tab) {\n tab.completedStepIds.clear();\n tab.planTotalSteps = payload.steps?.length ?? 0;\n setQQPendingInteraction(qqRuntime.routing, tab.id, req.id, req.kind, payload);\n }\n emit(\n {\n type: \"$plan_required\",\n id: req.id,\n plan: payload.plan,\n steps: payload.steps,\n summary: payload.summary,\n },\n tabId,\n );\n if (tab) handleQQPauseRequest(tab, req.kind, payload as Record<string, unknown>);\n return;\n }\n if (req.kind === \"plan_checkpoint\") {\n const payload = req.payload as {\n stepId: string;\n title?: string;\n result: string;\n notes?: string;\n };\n if (tab) {\n tab.completedStepIds.add(payload.stepId);\n setQQPendingInteraction(qqRuntime.routing, tab.id, req.id, req.kind, payload);\n }\n emit(\n {\n type: \"$step_completed\",\n stepId: payload.stepId,\n title: payload.title,\n result: payload.result,\n notes: payload.notes,\n },\n tabId,\n );\n emit(\n {\n type: \"$checkpoint_required\",\n id: req.id,\n stepId: payload.stepId,\n title: payload.title,\n result: payload.result,\n notes: payload.notes,\n completed: tab?.completedStepIds.size ?? 0,\n total: tab?.planTotalSteps ?? 0,\n },\n tabId,\n );\n if (tab) handleQQPauseRequest(tab, req.kind, payload as Record<string, unknown>);\n return;\n }\n if (req.kind === \"plan_revision\") {\n const payload = req.payload as {\n reason: string;\n remainingSteps: PlanStepLite[];\n summary?: string;\n };\n if (tab) setQQPendingInteraction(qqRuntime.routing, tab.id, req.id, req.kind, payload);\n emit(\n {\n type: \"$revision_required\",\n id: req.id,\n reason: payload.reason,\n remainingSteps: payload.remainingSteps,\n summary: payload.summary,\n },\n tabId,\n );\n if (tab) handleQQPauseRequest(tab, req.kind, payload as Record<string, unknown>);\n return;\n }\n // Unknown PauseKind — `never` makes a new kind without a handler a compile\n // error; the runtime cancel is the last-mile defense so the agent loop\n // doesn't hang waiting on a request no one will resolve.\n const exhaustive: never = req.kind;\n process.stderr.write(\n `[desktop] no handler for pause kind \"${String(exhaustive)}\" — auto-cancelling gate id=${req.id}\\n`,\n );\n if (tab) tab.pendingGateIds.delete(req.id);\n pauseGate.cancel(req.id);\n });\n\n // Fast-path: emit disk-only events immediately so the UI shell renders\n // before the toolset finishes building. Heavy work (semantic bootstrap,\n // MCP probes, runtime construction) runs in initTabToolset which fires\n // `$ready` when it completes — until then `state.ready` keeps the\n // composer disabled, so users can't send a message before the runtime\n // exists. emitBalance was already fire-and-forget.\n function bootstrapTab(\n initialDir?: string,\n restore?: { session?: string; active?: boolean },\n ): Tab {\n const tab = createTabSkeleton(initialDir);\n // Reopen the conversation the tab had, if its jsonl is still readable.\n let restoredMessages: LoadedMessage[] | undefined;\n if (restore?.session) {\n try {\n if (existsSync(sessionPath(restore.session))) {\n const msgs = buildLoadedMessages(loadSessionMessages(restore.session));\n if (msgs.length > 0) {\n tab.currentSession = restore.session;\n restoredMessages = msgs;\n }\n }\n } catch {\n // unreadable jsonl — fall back to the freshly minted session\n }\n }\n emit({ type: \"$tab_opened\", workspaceDir: tab.rootDir, active: restore?.active }, tab.id);\n emitSessions(tab);\n emitSettings(tab);\n emitMcpSpecs(tab);\n emitSkills(tab);\n emitMemory(tab);\n emitQQSettings(tab);\n if (restoredMessages) {\n const meta = loadSessionMeta(tab.currentSession);\n emit(\n {\n type: \"$session_loaded\",\n name: tab.currentSession,\n messages: restoredMessages,\n carryover: {\n totalCostUsd: meta.totalCostUsd ?? 0,\n cacheHitTokens: meta.cacheHitTokens ?? 0,\n cacheMissTokens: meta.cacheMissTokens ?? 0,\n totalCompletionTokens: meta.totalCompletionTokens ?? 0,\n },\n },\n tab.id,\n );\n }\n if (!loadApiKey()) emit({ type: \"$needs_setup\", reason: \"no_api_key\" }, tab.id);\n void emitBalance(tab);\n void initTabToolset(tab)\n .then(() => {\n if (loadApiKey()) emit({ type: \"$ready\" }, tab.id);\n emitCtxBreakdown(tab);\n })\n .catch((err) => {\n emit({ type: \"$error\", message: `init failed: ${(err as Error).message}` }, tab.id);\n });\n return tab;\n }\n\n // Restore the full tab set from the previous session — workspace dir,\n // loaded session and focused tab (issues #933, #1244). Missing dirs\n // are silently skipped — a deleted workspace shouldn't break boot.\n const savedTabs = loadDesktopOpenTabs().filter((t) => {\n try {\n return existsSync(t.dir) && statSync(t.dir).isDirectory();\n } catch {\n return false;\n }\n });\n // When launched with --dir, find the matching saved tab so the user's\n // previous session is restored automatically.\n const startupDir = opts.dir;\n const startupTab = startupDir\n ? savedTabs.find((t) => resolve(t.dir) === resolve(startupDir))\n : savedTabs[0];\n first = bootstrapTab(opts.dir ?? savedTabs[0]?.dir, startupTab);\n const restored: Tab[] = [first];\n for (const t of savedTabs.slice(1)) restored.push(bootstrapTab(t.dir, t));\n // Mirror the persisted focus so the next persist round-trips it.\n const activeIdx = savedTabs.findIndex((t) => t.active);\n lastActiveTabId = ((activeIdx >= 0 ? restored[activeIdx] : first) ?? first).id;\n persistOpenTabs();\n const qqConfig = loadQQConfig();\n if (qqConfig.enabled && qqConfig.appId && qqConfig.appSecret) {\n void startDesktopQQ(false).catch(() => undefined);\n } else {\n broadcastQQSettings();\n }\n\n const rl = createInterface({ input: stdin });\n rl.on(\"line\", (line) => {\n const trimmed = line.trim();\n if (!trimmed) return;\n let msg: InMessage;\n try {\n msg = JSON.parse(trimmed) as InMessage;\n } catch {\n emit({ type: \"$error\", message: `bad json on stdin: ${trimmed.slice(0, 80)}` });\n return;\n }\n\n if (msg.cmd === \"tab_open\") {\n try {\n // A user-opened tab takes focus.\n const opened = bootstrapTab(msg.workspaceDir, { active: true });\n lastActiveTabId = opened.id;\n persistOpenTabs();\n } catch (err) {\n emit({ type: \"$error\", message: `tab_open failed: ${(err as Error).message}` });\n }\n return;\n }\n if (msg.cmd === \"tab_activate\") {\n if (tabs.has(msg.tabId)) {\n lastActiveTabId = msg.tabId;\n persistOpenTabs();\n }\n return;\n }\n if (msg.cmd === \"confirm_response\") {\n forgetGate(msg.id);\n pauseGate.resolve(msg.id, msg.response);\n return;\n }\n if (msg.cmd === \"choice_response\") {\n forgetGate(msg.id);\n pauseGate.resolve(msg.id, msg.response);\n return;\n }\n if (msg.cmd === \"plan_response\") {\n const tab = forgetGate(msg.id);\n if (tab && msg.response.type === \"cancel\") {\n tab.completedStepIds.clear();\n tab.planTotalSteps = 0;\n emit({ type: \"$plan_cleared\" }, tab.id);\n }\n pauseGate.resolve(msg.id, msg.response);\n return;\n }\n if (msg.cmd === \"checkpoint_response\") {\n const tab = forgetGate(msg.id);\n if (tab && msg.response.type === \"stop\") {\n tab.completedStepIds.clear();\n tab.planTotalSteps = 0;\n emit({ type: \"$plan_cleared\" }, tab.id);\n }\n pauseGate.resolve(msg.id, msg.response);\n return;\n }\n if (msg.cmd === \"revision_response\") {\n forgetGate(msg.id);\n pauseGate.resolve(msg.id, msg.response);\n return;\n }\n if (msg.cmd === \"setup_save_key\") {\n const key = msg.key.trim();\n if (!isPlausibleKey(key)) {\n emit({\n type: \"$error\",\n message: \"Key looks too short — paste the full token (16+ chars, no spaces).\",\n });\n return;\n }\n try {\n saveApiKey(key);\n bridgeEndpointEnv();\n for (const tab of tabs.values()) {\n // Skeleton tabs still mid-bootstrap pick up the new key inside\n // initTabToolset's tail when buildCodeToolset settles — don't\n // try to construct a runtime against a null toolset here.\n if (!tab.toolset) {\n emitSettings(tab);\n void emitBalance(tab);\n continue;\n }\n tab.runtime = buildRuntimeFor(tab);\n emit({ type: \"$ready\" }, tab.id);\n emitSettings(tab);\n void emitBalance(tab);\n }\n } catch (err) {\n emit({ type: \"$error\", message: `saveApiKey failed: ${(err as Error).message}` });\n }\n return;\n }\n\n if (msg.cmd === \"desktop_resync\") {\n // WebView reloads (DevTools F5, host-side respawn) leave the Node child\n // alive but the React app starts blank. Re-fire the bootstrap events\n // so it can rehydrate without restarting the agent.\n const hasKey = !!loadApiKey();\n for (const t of tabs.values()) {\n emit(\n { type: \"$tab_opened\", workspaceDir: t.rootDir, active: t.id === lastActiveTabId },\n t.id,\n );\n emitSessions(t);\n emitSettings(t);\n emitMcpSpecs(t);\n emitSkills(t);\n emitMemory(t);\n emitQQSettings(t);\n if (!hasKey) emit({ type: \"$needs_setup\", reason: \"no_api_key\" }, t.id);\n else if (t.toolset) emit({ type: \"$ready\" }, t.id);\n void emitBalance(t);\n // Re-emit session_loaded so the resumed session's messages and\n // usage stats (cost, tokens, cache%) are restored on the frontend.\n if (t.currentSession) {\n try {\n const msgs = buildLoadedMessages(loadSessionMessages(t.currentSession));\n const meta = loadSessionMeta(t.currentSession);\n emit(\n {\n type: \"$session_loaded\",\n name: t.currentSession,\n messages: msgs,\n carryover: {\n totalCostUsd: meta.totalCostUsd ?? 0,\n cacheHitTokens: meta.cacheHitTokens ?? 0,\n cacheMissTokens: meta.cacheMissTokens ?? 0,\n totalCompletionTokens: meta.totalCompletionTokens ?? 0,\n },\n },\n t.id,\n );\n } catch {\n // unreadable jsonl — skip re-emit\n }\n }\n }\n return;\n }\n if (msg.cmd === \"jobs_list\") {\n emitJobs();\n return;\n }\n if (msg.cmd === \"jobs_stop\") {\n void stopJob(msg.jobId).finally(() => emitJobs());\n return;\n }\n if (msg.cmd === \"jobs_stop_all\") {\n void stopAllJobs().finally(() => emitJobs());\n return;\n }\n\n const tab = msg.tabId ? tabs.get(msg.tabId) : first;\n if (!tab) {\n // No tabId on the emit ⇒ the renderer's per-tab router drops it\n // silently. Surface to stderr instead so it's at least visible\n // when the desktop is launched from a terminal.\n process.stderr.write(\n `rpc dispatch: unknown tabId=${msg.tabId} for cmd=${msg.cmd} — dropping\\n`,\n );\n return;\n }\n\n if (msg.cmd === \"abort\") {\n abortTurn(tab, { discardCurrentTurn: true });\n cancelPendingGates(tab);\n return;\n }\n if (msg.cmd === \"tab_close\") {\n void closeTab(tab);\n return;\n }\n if (msg.cmd === \"mcp_specs_get\") {\n emitMcpSpecs(tab);\n return;\n }\n if (msg.cmd === \"mcp_specs_add\") {\n const spec = msg.spec.trim();\n if (!spec) {\n emit({ type: \"$error\", message: \"mcp_specs_add: spec is empty\" }, tab.id);\n return;\n }\n try {\n parseMcpSpec(spec);\n } catch (err) {\n emit({ type: \"$error\", message: `mcp_specs_add: ${(err as Error).message}` }, tab.id);\n return;\n }\n try {\n const cfg = readConfig();\n const list = cfg.mcp ?? [];\n if (!list.includes(spec)) {\n cfg.mcp = [...list, spec];\n writeConfig(cfg);\n }\n emitMcpSpecs(tab);\n void bridgeTabMcp(tab);\n } catch (err) {\n emit({ type: \"$error\", message: `mcp_specs_add: ${(err as Error).message}` }, tab.id);\n }\n return;\n }\n if (msg.cmd === \"mcp_specs_remove\") {\n try {\n const cfg = readConfig();\n const list = cfg.mcp ?? [];\n if (list.includes(msg.spec)) {\n cfg.mcp = list.filter((s) => s !== msg.spec);\n writeConfig(cfg);\n }\n tab.mcpStatuses.delete(msg.spec);\n emitMcpSpecs(tab);\n void bridgeTabMcp(tab);\n } catch (err) {\n emit({ type: \"$error\", message: `mcp_specs_remove: ${(err as Error).message}` }, tab.id);\n }\n return;\n }\n if (msg.cmd === \"skills_get\") {\n emitSkills(tab);\n return;\n }\n if (msg.cmd === \"skill_run\") {\n if (!tab.runtime) {\n emit(\n { type: \"$error\", message: \"Not configured yet — paste your DeepSeek API key first.\" },\n tab.id,\n );\n return;\n }\n try {\n const store = new SkillStore({\n projectRoot: tab.rootDir,\n customSkillPaths: loadResolvedSkillPaths(tab.rootDir),\n });\n const found = store.read(msg.name);\n if (!found) {\n emit({ type: \"$error\", message: `skill not found: ${msg.name}` }, tab.id);\n return;\n }\n const extra = msg.args?.trim() ?? \"\";\n const header = `# Skill: ${found.name}${found.description ? `\\n> ${found.description}` : \"\"}`;\n const argsLine = extra ? `\\n\\nArguments: ${extra}` : \"\";\n const payload = `${header}\\n\\n${found.body}${argsLine}`;\n void runTurn(tab, payload);\n } catch (err) {\n emit({ type: \"$error\", message: `skill_run: ${(err as Error).message}` }, tab.id);\n }\n return;\n }\n if (msg.cmd === \"session_list\") {\n emitSessions(tab);\n return;\n }\n if (msg.cmd === \"session_delete\") {\n deleteSession(msg.name);\n emitSessions(tab);\n return;\n }\n if (msg.cmd === \"session_rename\") {\n try {\n const trimmed = normalizeSessionTitle(msg.title);\n patchSessionMeta(msg.name, { summary: trimmed || undefined });\n emitSessions(tab);\n } catch (err) {\n emit(\n { type: \"$error\", message: `session_rename failed: ${(err as Error).message}` },\n tab.id,\n );\n }\n return;\n }\n if (msg.cmd === \"session_import\") {\n try {\n const result = importExternalSession({\n source: msg.source,\n path: msg.path,\n name: msg.name,\n workspace: tab.rootDir,\n });\n emitSessions(tab);\n loadSessionIntoTab(tab, result.name, {\n abortTurn,\n cancelPendingGates,\n persistOpenTabs,\n });\n } catch (err) {\n emit(\n { type: \"$error\", message: `session_import failed: ${(err as Error).message}` },\n tab.id,\n );\n }\n return;\n }\n if (msg.cmd === \"session_import_scan\") {\n try {\n emit({ type: \"$session_import_sources\", apps: discoverExternalSessionApps() }, tab.id);\n } catch (err) {\n emit(\n { type: \"$error\", message: `session_import_scan failed: ${(err as Error).message}` },\n tab.id,\n );\n }\n return;\n }\n if (msg.cmd === \"session_import_bulk\") {\n try {\n const result = importExternalSessions({\n sources: msg.sources,\n workspace: tab.rootDir,\n });\n emitSessions(tab);\n emit(\n {\n type: \"$session_import_result\",\n imported: result.imported,\n skipped: result.skipped,\n failed: result.failed,\n },\n tab.id,\n );\n if (result.latestName) {\n loadSessionIntoTab(tab, result.latestName, {\n abortTurn,\n cancelPendingGates,\n persistOpenTabs,\n });\n }\n } catch (err) {\n emit(\n { type: \"$error\", message: `session_import_bulk failed: ${(err as Error).message}` },\n tab.id,\n );\n }\n return;\n }\n if (msg.cmd === \"session_load\") {\n try {\n loadSessionIntoTab(tab, msg.name, {\n abortTurn,\n cancelPendingGates,\n persistOpenTabs,\n });\n } catch (err) {\n process.stderr.write(`session_load: \"${msg.name}\" threw — ${(err as Error).message}\\n`);\n emit({ type: \"$error\", message: `session_load failed: ${(err as Error).message}` }, tab.id);\n }\n return;\n }\n if (msg.cmd === \"memory_read\") {\n try {\n const detail = readMemoryEntryDetail({ path: msg.path }, tab.rootDir);\n emit({ type: \"$memory_detail\", detail }, tab.id);\n } catch (err) {\n emit({ type: \"$error\", message: `memory_read failed: ${(err as Error).message}` }, tab.id);\n }\n return;\n }\n if (msg.cmd === \"new_chat\") {\n // Only set switching flag when there's a live turn to abort —\n // otherwise the flag stays true and suppresses the first turn's events (#1217).\n if (tab.aborter) tab.switching = true;\n abortTurn(tab);\n cancelPendingGates(tab);\n tab.currentSession = mintSessionFor(tab.rootDir);\n persistOpenTabs();\n if (tab.runtime) tab.runtime = buildRuntimeFor(tab);\n emitSessions(tab);\n return;\n }\n if (msg.cmd === \"settings_get\") {\n emitSettings(tab);\n return;\n }\n if (msg.cmd === \"qq_status_get\") {\n emitQQSettings(tab);\n return;\n }\n if (msg.cmd === \"settings_save\") {\n try {\n if (msg.reasoningEffort !== undefined && isReasoningEffort(msg.reasoningEffort)) {\n saveReasoningEffort(msg.reasoningEffort);\n tab.runtime?.loop.configure({ reasoningEffort: msg.reasoningEffort });\n }\n if (msg.editMode !== undefined) {\n saveEditMode(msg.editMode);\n if (tab.toolset) applyPlanMode(tab.toolset.tools, msg.editMode);\n }\n if (msg.budgetUsd !== undefined) {\n tab.budgetUsd = msg.budgetUsd ?? undefined;\n tab.runtime?.loop.setBudget(msg.budgetUsd);\n }\n if (msg.baseUrl !== undefined) saveBaseUrl(msg.baseUrl);\n if (msg.workspaceDir !== undefined) {\n void switchWorkspace(tab, msg.workspaceDir);\n return;\n }\n if (msg.editor !== undefined) saveEditor(msg.editor);\n if (msg.showSystemEvents !== undefined) saveShowSystemEvents(msg.showSystemEvents);\n if (\n msg.webSearchEngine !== undefined ||\n msg.webSearchEndpoint !== undefined ||\n msg.metasoApiKey !== undefined ||\n msg.tavilyApiKey !== undefined ||\n msg.perplexityApiKey !== undefined ||\n msg.exaApiKey !== undefined\n ) {\n const cfg = readConfig();\n if (msg.webSearchEngine !== undefined) cfg.webSearchEngine = msg.webSearchEngine;\n if (msg.webSearchEndpoint !== undefined) {\n cfg.webSearchEndpoint = msg.webSearchEndpoint?.trim() || undefined;\n }\n if (msg.metasoApiKey !== undefined) {\n cfg.metasoApiKey = msg.metasoApiKey?.trim() || undefined;\n }\n if (msg.tavilyApiKey !== undefined) {\n cfg.tavilyApiKey = msg.tavilyApiKey?.trim() || undefined;\n }\n if (msg.perplexityApiKey !== undefined) {\n cfg.perplexityApiKey = msg.perplexityApiKey?.trim() || undefined;\n }\n if (msg.exaApiKey !== undefined) {\n cfg.exaApiKey = msg.exaApiKey?.trim() || undefined;\n }\n writeConfig(cfg);\n }\n if (msg.subagentModels !== undefined) {\n saveSubagentModels(msg.subagentModels);\n emitSkills(tab);\n }\n if (msg.model !== undefined) {\n const next = msg.model.trim();\n if (next) {\n tab.currentModel = next;\n saveModel(next);\n if (tab.toolset) {\n tab.system = codeSystemPrompt(tab.rootDir, {\n hasSemanticSearch: tab.toolset.semantic.enabled,\n modelId: tab.currentModel,\n });\n if (tab.runtime) tab.runtime = buildRuntimeFor(tab);\n }\n }\n }\n emitSettings(tab);\n } catch (err) {\n emit(\n { type: \"$error\", message: `settings_save failed: ${(err as Error).message}` },\n tab.id,\n );\n }\n return;\n }\n if (msg.cmd === \"qq_config_save\") {\n try {\n saveDesktopQQSettings(\n {\n appId: msg.appId,\n appSecret: msg.appSecret,\n sandbox: msg.sandbox,\n },\n undefined,\n );\n emitQQSettings(tab);\n } catch (err) {\n emit(\n { type: \"$error\", message: `qq_config_save failed: ${(err as Error).message}` },\n tab.id,\n );\n }\n return;\n }\n if (msg.cmd === \"qq_connect\") {\n try {\n const current = loadQQConfig();\n emit(\n {\n type: \"status\",\n id: Date.now(),\n ts: new Date().toISOString(),\n turn: 0,\n text: `QQ connecting (${current.sandbox ? \"sandbox\" : \"production\"})`,\n },\n tab.id,\n );\n void startDesktopQQ(true).then(\n () => {\n emit(\n {\n type: \"status\",\n id: Date.now(),\n ts: new Date().toISOString(),\n turn: 0,\n text: `QQ connected (${current.sandbox ? \"sandbox\" : \"production\"})`,\n },\n tab.id,\n );\n emitQQSettings(tab);\n },\n (err) => {\n emit(\n { type: \"$error\", message: `qq_connect failed: ${(err as Error).message}` },\n tab.id,\n );\n emitQQSettings(tab);\n },\n );\n } catch (err) {\n emit({ type: \"$error\", message: `qq_connect failed: ${(err as Error).message}` }, tab.id);\n emitQQSettings(tab);\n }\n return;\n }\n if (msg.cmd === \"qq_disconnect\") {\n try {\n void stopDesktopQQ(true).then(\n () => {\n emit(\n {\n type: \"status\",\n id: Date.now(),\n ts: new Date().toISOString(),\n turn: 0,\n text: \"QQ disabled\",\n },\n tab.id,\n );\n emitQQSettings(tab);\n },\n (err) => {\n emit(\n { type: \"$error\", message: `qq_disconnect failed: ${(err as Error).message}` },\n tab.id,\n );\n },\n );\n } catch (err) {\n emit(\n { type: \"$error\", message: `qq_disconnect failed: ${(err as Error).message}` },\n tab.id,\n );\n }\n return;\n }\n if (msg.cmd === \"mention_query\") {\n const nonce = msg.nonce;\n const query = msg.query;\n const parsed = parseAtQuery(query);\n // Empty query → list workspace root's top-level entries (tree\n // style). Without this, bare `@` floods with all 5000 files; the\n // TUI's @+Tab pattern already shows the tree top.\n const treeWalk = parsed.trailingSlash || query.length === 0;\n if (treeWalk) {\n void listDirectory(tab.rootDir, parsed.dir)\n .then((entries) => {\n const results = entries.map((e) => (e.isDir ? `${e.path}/` : e.path));\n emit({ type: \"$mention_results\", nonce, query, results }, tab.id);\n })\n .catch((err) => {\n emit(\n { type: \"$error\", message: `mention_query (dir) failed: ${(err as Error).message}` },\n tab.id,\n );\n emit({ type: \"$mention_results\", nonce, query, results: [] }, tab.id);\n });\n return;\n }\n const wantSymbols = query.length >= 2 && !query.includes(\"/\");\n void (async () => {\n try {\n const files = await getFileIndexFor(tab);\n const fileResults = rankPickerCandidates(files, query, {\n limit: wantSymbols ? 19 : 25,\n recentlyUsed: tab.recentMentions,\n });\n let symResults: string[] = [];\n if (wantSymbols) {\n const syms = await getSymbolIndexFor(tab);\n symResults = rankSymbols(syms, query, 6);\n }\n emit(\n { type: \"$mention_results\", nonce, query, results: [...symResults, ...fileResults] },\n tab.id,\n );\n } catch (err) {\n emit(\n { type: \"$error\", message: `mention_query failed: ${(err as Error).message}` },\n tab.id,\n );\n emit({ type: \"$mention_results\", nonce, query, results: [] }, tab.id);\n }\n })();\n return;\n }\n if (msg.cmd === \"mention_picked\") {\n pushMentionRecent(tab, msg.path);\n return;\n }\n if (msg.cmd === \"mention_preview\") {\n const nonce = msg.nonce;\n const rel = msg.path;\n const abs = isAbsolute(rel) ? rel : join(tab.rootDir, rel);\n const safeAbs = resolve(abs);\n const safeRoot = resolve(tab.rootDir);\n if (!safeAbs.startsWith(safeRoot)) {\n emit({ type: \"$mention_preview\", nonce, path: rel, head: \"\", totalLines: 0 }, tab.id);\n return;\n }\n void readFile(safeAbs, \"utf8\")\n .then((text) => {\n const lines = text.split(/\\r?\\n/);\n if (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n const head = lines.slice(0, 12).join(\"\\n\");\n emit(\n { type: \"$mention_preview\", nonce, path: rel, head, totalLines: lines.length },\n tab.id,\n );\n })\n .catch(() => {\n emit({ type: \"$mention_preview\", nonce, path: rel, head: \"\", totalLines: 0 }, tab.id);\n });\n return;\n }\n if (msg.cmd === \"compact_history\") {\n if (!tab.runtime) return;\n void tab.runtime.loop\n .compactHistory()\n .then(() => emitCtxBreakdown(tab))\n .catch((err: Error) => {\n emit({ type: \"$error\", message: `/compact failed: ${err.message}` }, tab.id);\n });\n return;\n }\n if (msg.cmd === \"retry\") {\n if (!tab.runtime) return;\n const prev = tab.runtime.loop.retryLastUser();\n if (prev) {\n emit({ type: \"$retry_result\", text: prev }, tab.id);\n }\n return;\n }\n if (msg.cmd === \"btw\") {\n if (!tab.runtime) return;\n const question = msg.text.trim();\n if (!question) return;\n void (async () => {\n try {\n const reply = await tab.runtime!.loop.client.chat({\n model: tab.currentModel,\n messages: [\n {\n role: \"system\",\n content:\n \"You are answering a side question that is unrelated to the current coding conversation. Answer concisely (1-3 sentences) in plain prose. Do not call tools, do not ask clarifying questions, and do not reference any prior turns.\",\n },\n { role: \"user\", content: question },\n ],\n });\n const answer =\n (typeof reply.content === \"string\" ? reply.content.trim() : \"\") || \"(no answer)\";\n emit({ type: \"$btw_result\", question, answer }, tab.id);\n } catch (err) {\n emit({ type: \"$error\", message: `/btw failed: ${(err as Error).message}` }, tab.id);\n }\n })();\n return;\n }\n if (msg.cmd === \"user_input\") {\n if (!tab.runtime) {\n emit(\n { type: \"$error\", message: \"Not configured yet — paste your DeepSeek API key first.\" },\n tab.id,\n );\n return;\n }\n void runTurn(tab, msg.text);\n }\n });\n\n await new Promise<void>((resolve) => {\n rl.on(\"close\", () => {\n void gracefulShutdown();\n resolve();\n });\n });\n}\n","/** GUI launches inherit OS-level env, not the user's interactive-shell env (#1252).\n * Probe `$SHELL -ilc` once at startup so nvm/asdf/fnm/volta/mise injected PATH entries survive. */\n\nimport { spawnSync } from \"node:child_process\";\n\nlet cached: { value: string | null } | undefined;\n\n/** Returns the user's interactive-shell PATH on macOS/Linux, null on Windows or on error. Cached. */\nexport function resolveLoginShellPath(opts: { timeoutMs?: number } = {}): string | null {\n if (cached !== undefined) return cached.value;\n cached = { value: null };\n if (process.platform === \"win32\") return null;\n\n const shell = process.env.SHELL || \"/bin/bash\";\n // -i forces zsh/bash to source rc files; -l also sources profile. The literal\n // `printf '__REASONIX_PATH__=%s\\\\n'` framing protects us from rc files that\n // print banners / completion notices on every interactive shell.\n const marker = \"__REASONIX_PATH__=\";\n try {\n const result = spawnSync(shell, [\"-ilc\", `printf '${marker}%s\\\\n' \"$PATH\"`], {\n encoding: \"utf8\",\n timeout: opts.timeoutMs ?? 2000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n if (result.status !== 0 && result.signal === null) return null;\n const stdout = result.stdout ?? \"\";\n const idx = stdout.lastIndexOf(marker);\n if (idx < 0) return null;\n const tail = stdout.slice(idx + marker.length);\n const newline = tail.indexOf(\"\\n\");\n const path = (newline >= 0 ? tail.slice(0, newline) : tail).trim();\n if (!path || !path.includes(\"/\")) return null;\n cached.value = path;\n return path;\n } catch {\n return null;\n }\n}\n\n/** Prepend missing login-shell PATH entries onto `process.env.PATH`. Idempotent. */\nexport function augmentProcessPath(): { added: string[] } {\n const loginPath = resolveLoginShellPath();\n if (!loginPath) return { added: [] };\n const current = process.env.PATH ?? \"\";\n const seen = new Set(\n current\n .split(\":\")\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const additions: string[] = [];\n for (const entry of loginPath.split(\":\")) {\n const t = entry.trim();\n if (!t || seen.has(t)) continue;\n seen.add(t);\n additions.push(t);\n }\n if (additions.length === 0) return { added: [] };\n process.env.PATH = additions.concat(current ? [current] : []).join(\":\");\n return { added: additions };\n}\n\n/** Test-only — clear the resolved-PATH cache so a fresh `resolveLoginShellPath()` re-probes. */\nexport function resetLoginShellPathCache(): void {\n cached = undefined;\n}\n","import { type LoadedQQConfig, type QQBotConfig, loadQQConfig, saveQQConfig } from \"../config.js\";\nimport { describeQQAccess } from \"../qq/access.js\";\n\nexport interface DesktopQQSettingsState extends Omit<LoadedQQConfig, \"sandbox\" | \"enabled\"> {\n sandbox: boolean;\n enabled: boolean;\n configured: boolean;\n runtimeState: \"disconnected\" | \"connecting\" | \"connected\" | \"failed\";\n lastError?: string;\n appIdPreview?: string;\n access: string;\n}\n\nexport interface DesktopQQSettingsPatch {\n appId?: string;\n appSecret?: string;\n sandbox: boolean;\n}\n\nfunction trimOptional(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction toPreview(appId: string | undefined): string | undefined {\n if (!appId) return undefined;\n return appId.length > 6 ? `${appId.slice(0, 6)}...` : appId;\n}\n\nfunction toAccess(config: QQBotConfig | LoadedQQConfig): string {\n return describeQQAccess({\n ownerOpenId: config.ownerOpenId,\n allowlist: config.allowlist,\n });\n}\n\nexport function loadDesktopQQState(path?: string): DesktopQQSettingsState {\n const config = loadQQConfig(path);\n const configured = Boolean(config.appId && config.appSecret);\n return {\n ...config,\n sandbox: config.sandbox ?? false,\n enabled: config.enabled === true,\n configured,\n runtimeState: \"disconnected\",\n appIdPreview: toPreview(config.appId),\n access: toAccess(config),\n };\n}\n\nexport function saveDesktopQQSettings(\n patch: DesktopQQSettingsPatch,\n path?: string,\n): DesktopQQSettingsState {\n const existing = loadQQConfig(path);\n saveQQConfig(\n {\n ...existing,\n appId: trimOptional(patch.appId),\n appSecret: trimOptional(patch.appSecret),\n sandbox: patch.sandbox,\n },\n path,\n );\n return loadDesktopQQState(path);\n}\n\nexport function setDesktopQQEnabled(enabled: boolean, path?: string): DesktopQQSettingsState {\n const existing = loadQQConfig(path);\n if (enabled && !(existing.appId && existing.appSecret)) {\n throw new Error(\"QQ App ID and App Secret are required.\");\n }\n saveQQConfig({ ...existing, enabled }, path);\n return loadDesktopQQState(path);\n}\n","export type QQPendingInteraction = {\n gateId: number;\n kind: string;\n payload: unknown;\n};\n\nexport type QQTurnRoutingState = {\n replyTabs: Set<string>;\n pendingByTab: Map<string, QQPendingInteraction>;\n};\n\nexport function createQQTurnRoutingState(): QQTurnRoutingState {\n return {\n replyTabs: new Set<string>(),\n pendingByTab: new Map<string, QQPendingInteraction>(),\n };\n}\n\nexport function markQQTurnStarted(state: QQTurnRoutingState, tabId: string): void {\n state.replyTabs.add(tabId);\n}\n\nexport function markQQTurnFinished(state: QQTurnRoutingState, tabId: string): void {\n state.replyTabs.delete(tabId);\n state.pendingByTab.delete(tabId);\n}\n\nexport function shouldRouteQQForTab(state: QQTurnRoutingState, tabId: string): boolean {\n return state.replyTabs.has(tabId);\n}\n\nexport function setQQPendingInteraction(\n state: QQTurnRoutingState,\n tabId: string,\n gateId: number,\n kind: string,\n payload: unknown,\n): void {\n if (!shouldRouteQQForTab(state, tabId)) return;\n state.pendingByTab.set(tabId, { gateId, kind, payload });\n}\n\nexport function takeQQPendingInteraction(\n state: QQTurnRoutingState,\n tabId: string,\n): QQPendingInteraction | null {\n const hit = state.pendingByTab.get(tabId);\n if (!hit) return null;\n state.pendingByTab.delete(tabId);\n return hit;\n}\n\nexport function clearQQTurnRouting(state: QQTurnRoutingState): void {\n state.replyTabs.clear();\n state.pendingByTab.clear();\n}\n","import { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, extname, join } from \"node:path\";\nimport {\n detectGitBranch,\n loadSessionMeta,\n patchSessionMeta,\n rewriteSession,\n sessionPath,\n sessionsDir,\n} from \"./memory/session.js\";\nimport type { ChatMessage, ToolCall } from \"./types.js\";\n\nexport type ExternalSessionSource = \"claude\" | \"codex\";\n\nexport interface ImportedSession {\n messages: ChatMessage[];\n workspace?: string;\n nameHint?: string;\n summary?: string;\n}\n\nexport interface ImportExternalSessionOptions {\n source: ExternalSessionSource;\n path: string;\n name?: string;\n workspace?: string;\n summary?: string;\n force?: boolean;\n}\n\nexport interface ImportExternalSessionResult {\n source: ExternalSessionSource;\n path: string;\n name: string;\n messageCount: number;\n workspace?: string;\n summary?: string;\n branch?: string;\n}\n\nexport interface ExternalSessionApp {\n source: ExternalSessionSource;\n label: string;\n root: string;\n available: boolean;\n sessionCount: number;\n latestMtime?: string;\n}\n\nexport interface ImportExternalSessionsResult {\n imported: number;\n skipped: number;\n failed: number;\n latestName?: string;\n}\n\ninterface ExternalSessionFile {\n source: ExternalSessionSource;\n path: string;\n mtimeMs: number;\n}\n\ninterface ClaudeRecord {\n type?: unknown;\n isMeta?: unknown;\n cwd?: unknown;\n project?: unknown;\n message?: {\n role?: unknown;\n content?: unknown;\n };\n}\n\ninterface CodexRecord {\n type?: unknown;\n payload?: {\n type?: unknown;\n role?: unknown;\n cwd?: unknown;\n message?: unknown;\n content?: unknown;\n };\n}\n\nexport function parseExternalSessionFile(\n source: ExternalSessionSource,\n path: string,\n): ImportedSession {\n if (!existsSync(path)) {\n throw new Error(`source file not found: ${path}`);\n }\n return source === \"claude\" ? parseClaudeSessionFile(path) : parseCodexSessionFile(path);\n}\n\nexport function buildImportedSessionName(\n source: ExternalSessionSource,\n path: string,\n imported: ImportedSession,\n): string {\n const stem = basename(path, extname(path));\n const hint = oneLine(imported.nameHint || imported.summary || stem, 48);\n return `${source}-${hint || stem || \"session\"}`;\n}\n\nexport function importExternalSession(\n opts: ImportExternalSessionOptions,\n): ImportExternalSessionResult {\n const imported = parseExternalSessionFile(opts.source, opts.path);\n if (imported.messages.length === 0) {\n throw new Error(`no importable chat messages found in ${opts.path}`);\n }\n\n const name = opts.name?.trim() || buildImportedSessionName(opts.source, opts.path, imported);\n const outputPath = sessionPath(name);\n if (existsSync(outputPath) && !opts.force) {\n throw new Error(`target session already exists: ${name}`);\n }\n\n rewriteSession(name, imported.messages);\n\n const workspace = opts.workspace?.trim() || imported.workspace;\n const summary = opts.summary?.trim() || imported.summary;\n const branch = workspace ? detectGitBranch(workspace) : undefined;\n patchSessionMeta(name, {\n workspace,\n summary,\n branch,\n importedSource: opts.source,\n importedPath: opts.path,\n });\n\n return {\n source: opts.source,\n path: opts.path,\n name,\n messageCount: imported.messages.length,\n workspace,\n summary,\n branch,\n };\n}\n\nexport function discoverExternalSessionApps(): ExternalSessionApp[] {\n return ([\"claude\", \"codex\"] as const).map((source) => {\n const root = defaultSessionRoot(source);\n const files = scanExternalSessionFiles(source);\n const latest = files[0];\n return {\n source,\n label: source === \"claude\" ? \"Claude Code\" : \"Codex\",\n root,\n available: files.length > 0,\n sessionCount: files.length,\n latestMtime: latest ? new Date(latest.mtimeMs).toISOString() : undefined,\n };\n });\n}\n\nexport function importExternalSessions(opts: {\n sources: ExternalSessionSource[];\n workspace?: string;\n}): ImportExternalSessionsResult {\n let imported = 0;\n let skipped = 0;\n let failed = 0;\n let latestName: string | undefined;\n\n const existing = importedPathKeys();\n for (const source of opts.sources) {\n const files = scanExternalSessionFiles(source);\n for (const file of files) {\n const key = importKey(source, file.path);\n if (existing.has(key)) {\n skipped++;\n continue;\n }\n try {\n const result = importExternalSession({\n source,\n path: file.path,\n workspace: opts.workspace,\n });\n existing.add(key);\n imported++;\n latestName ||= result.name;\n } catch {\n failed++;\n }\n }\n }\n\n return { imported, skipped, failed, latestName };\n}\n\nfunction defaultSessionRoot(source: ExternalSessionSource): string {\n return source === \"claude\"\n ? join(homedir(), \".claude\", \"projects\")\n : join(homedir(), \".codex\", \"sessions\");\n}\n\nfunction scanExternalSessionFiles(source: ExternalSessionSource): ExternalSessionFile[] {\n const root = defaultSessionRoot(source);\n const out: ExternalSessionFile[] = [];\n collectJsonl(root, source, out);\n out.sort((a, b) => b.mtimeMs - a.mtimeMs);\n return out;\n}\n\nfunction collectJsonl(\n dir: string,\n source: ExternalSessionSource,\n out: ExternalSessionFile[],\n): void {\n if (!existsSync(dir)) return;\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const entry of entries) {\n const path = join(dir, entry);\n let stat: ReturnType<typeof statSync>;\n try {\n stat = statSync(path);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n collectJsonl(path, source, out);\n } else if (stat.isFile() && entry.endsWith(\".jsonl\")) {\n out.push({ source, path, mtimeMs: stat.mtimeMs });\n }\n }\n}\n\nfunction importedPathKeys(): Set<string> {\n const out = new Set<string>();\n const dir = sessionsDir();\n if (!existsSync(dir)) return out;\n let files: string[];\n try {\n files = readdirSync(dir);\n } catch {\n return out;\n }\n for (const file of files) {\n if (!file.endsWith(\".jsonl\") || file.endsWith(\".events.jsonl\")) continue;\n const name = file.replace(/\\.jsonl$/, \"\");\n const meta = loadSessionMeta(name);\n if (meta.importedSource && meta.importedPath) {\n out.add(importKey(meta.importedSource, meta.importedPath));\n }\n }\n return out;\n}\n\nfunction importKey(source: ExternalSessionSource, path: string): string {\n return `${source}:${path}`;\n}\n\nfunction parseClaudeSessionFile(path: string): ImportedSession {\n const records = readJsonl(path) as ClaudeRecord[];\n const messages: ChatMessage[] = [];\n const toolNames = new Map<string, string>();\n let workspace: string | undefined;\n let firstUserText: string | undefined;\n\n for (const record of records) {\n if (!workspace) workspace = firstString(record.cwd) || firstString(record.project);\n if (record.isMeta === true) continue;\n if (!record.message || typeof record.message !== \"object\") continue;\n const role = normalizeRole(record.message.role);\n if (!role) continue;\n\n if (role === \"assistant\") {\n const assistant = normalizeClaudeAssistant(record.message.content);\n for (const call of assistant.toolCalls) {\n if (call.id && call.function?.name) toolNames.set(call.id, call.function.name);\n }\n if (assistant.content || assistant.toolCalls.length > 0) {\n messages.push({\n role: \"assistant\",\n content: assistant.content || null,\n tool_calls: assistant.toolCalls.length > 0 ? assistant.toolCalls : undefined,\n reasoning_content: assistant.reasoning || undefined,\n });\n }\n continue;\n }\n\n const user = normalizeClaudeUser(record.message.content, toolNames);\n if (user.content) {\n messages.push({ role: \"user\", content: user.content });\n if (!firstUserText) firstUserText = user.content;\n }\n messages.push(...user.toolMessages);\n }\n\n return {\n messages,\n workspace,\n nameHint: firstUserText,\n summary: summarize(firstUserText),\n };\n}\n\nfunction parseCodexSessionFile(path: string): ImportedSession {\n const records = readJsonl(path) as CodexRecord[];\n const messages: ChatMessage[] = [];\n const fallback: ChatMessage[] = [];\n let workspace: string | undefined;\n let firstUserText: string | undefined;\n\n for (const record of records) {\n if (record.type === \"session_meta\" || record.type === \"turn_context\") {\n workspace ||= firstString(record.payload?.cwd);\n }\n\n if (record.type === \"response_item\" && record.payload?.type === \"message\") {\n const role = normalizeRole(record.payload.role);\n if (!role) continue;\n const content = normalizeCodexMessageContent(role, record.payload.content);\n if (!content) continue;\n messages.push({ role, content });\n if (role === \"user\" && !firstUserText) firstUserText = content;\n continue;\n }\n\n if (record.type === \"event_msg\") {\n const eventType = firstString(record.payload?.type);\n const content = firstString(record.payload?.message);\n if (!content) continue;\n if (eventType === \"user_message\") {\n fallback.push({ role: \"user\", content });\n if (!firstUserText) firstUserText = content;\n } else if (eventType === \"agent_message\") {\n fallback.push({ role: \"assistant\", content });\n }\n }\n }\n\n const importedMessages = messages.length > 0 ? messages : dedupeAdjacentMessages(fallback);\n return {\n messages: importedMessages,\n workspace,\n nameHint: firstUserText,\n summary: summarize(firstUserText),\n };\n}\n\nfunction normalizeClaudeAssistant(content: unknown): {\n content: string;\n toolCalls: ToolCall[];\n reasoning?: string;\n} {\n if (typeof content === \"string\") {\n return { content: content.trim(), toolCalls: [] };\n }\n if (!Array.isArray(content)) {\n return { content: \"\", toolCalls: [] };\n }\n\n const textParts: string[] = [];\n const toolCalls: ToolCall[] = [];\n const reasoningParts: string[] = [];\n\n for (const item of content) {\n if (!item || typeof item !== \"object\") continue;\n const type = firstString((item as Record<string, unknown>).type);\n if (type === \"text\") {\n const text = firstString((item as Record<string, unknown>).text);\n if (text) textParts.push(text);\n continue;\n }\n if (type === \"thinking\") {\n const text = firstString((item as Record<string, unknown>).thinking);\n if (text) reasoningParts.push(text);\n continue;\n }\n if (type === \"tool_use\") {\n const name = firstString((item as Record<string, unknown>).name);\n if (!name) continue;\n toolCalls.push({\n id: firstString((item as Record<string, unknown>).id),\n type: \"function\",\n function: {\n name,\n arguments: safeJson((item as Record<string, unknown>).input ?? {}),\n },\n });\n }\n }\n\n return {\n content: joinParts(textParts),\n toolCalls,\n reasoning: joinParts(reasoningParts) || undefined,\n };\n}\n\nfunction normalizeClaudeUser(\n content: unknown,\n toolNames: ReadonlyMap<string, string>,\n): { content: string; toolMessages: ChatMessage[] } {\n if (typeof content === \"string\") {\n return { content: content.trim(), toolMessages: [] };\n }\n if (!Array.isArray(content)) {\n return { content: \"\", toolMessages: [] };\n }\n\n const userText: string[] = [];\n const toolMessages: ChatMessage[] = [];\n\n for (const item of content) {\n if (!item || typeof item !== \"object\") continue;\n const type = firstString((item as Record<string, unknown>).type);\n if (type === \"text\") {\n const text = firstString((item as Record<string, unknown>).text);\n if (text) userText.push(text);\n continue;\n }\n if (type === \"image\") {\n userText.push(\"[image omitted]\");\n continue;\n }\n if (type === \"tool_result\") {\n const callId = firstString((item as Record<string, unknown>).tool_use_id);\n toolMessages.push({\n role: \"tool\",\n content: normalizeArbitraryContent((item as Record<string, unknown>).content),\n tool_call_id: callId,\n name: callId ? toolNames.get(callId) : undefined,\n });\n }\n }\n\n return { content: joinParts(userText), toolMessages };\n}\n\nfunction normalizeCodexMessageContent(role: \"user\" | \"assistant\", content: unknown): string {\n if (typeof content === \"string\") return content.trim();\n if (!Array.isArray(content)) return \"\";\n const textParts: string[] = [];\n for (const item of content) {\n if (!item || typeof item !== \"object\") continue;\n const type = firstString((item as Record<string, unknown>).type);\n if (type === \"input_text\" || type === \"output_text\" || type === \"text\") {\n const text = firstString((item as Record<string, unknown>).text);\n if (!text) continue;\n if (role === \"user\" && looksLikeCodexBootstrapBlock(text)) continue;\n textParts.push(text);\n }\n }\n return joinParts(textParts);\n}\n\nfunction looksLikeCodexBootstrapBlock(text: string): boolean {\n const trimmed = text.trimStart();\n return (\n trimmed.startsWith(\"# AGENTS.md instructions for \") ||\n trimmed.startsWith(\"<environment_context>\")\n );\n}\n\nfunction dedupeAdjacentMessages(messages: ChatMessage[]): ChatMessage[] {\n const out: ChatMessage[] = [];\n for (const msg of messages) {\n const prev = out[out.length - 1];\n if (prev && prev.role === msg.role && prev.content === msg.content) continue;\n out.push(msg);\n }\n return out;\n}\n\nfunction normalizeArbitraryContent(value: unknown): string {\n if (typeof value === \"string\") return value;\n if (Array.isArray(value)) {\n const textParts = value\n .map((item) => {\n if (typeof item === \"string\") return item;\n if (item && typeof item === \"object\") {\n return firstString((item as Record<string, unknown>).text);\n }\n return \"\";\n })\n .filter(Boolean) as string[];\n if (textParts.length > 0) return joinParts(textParts);\n }\n return safeJson(value);\n}\n\nfunction readJsonl(path: string): unknown[] {\n const raw = readFileSync(path, \"utf8\");\n return raw\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .flatMap((line) => {\n try {\n return [JSON.parse(line)];\n } catch {\n return [];\n }\n });\n}\n\nfunction normalizeRole(value: unknown): \"user\" | \"assistant\" | undefined {\n return value === \"user\" || value === \"assistant\" ? value : undefined;\n}\n\nfunction firstString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0 ? value : undefined;\n}\n\nfunction safeJson(value: unknown): string {\n try {\n return JSON.stringify(value ?? null);\n } catch {\n return JSON.stringify(String(value));\n }\n}\n\nfunction joinParts(parts: string[]): string {\n return parts\n .map((part) => part.trim())\n .filter(Boolean)\n .join(\"\\n\\n\");\n}\n\nfunction summarize(text: string | undefined): string | undefined {\n const flat = oneLine(text || \"\", 120);\n return flat || undefined;\n}\n\nfunction oneLine(text: string, max: number): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n return flat.length > max ? `${flat.slice(0, max)}...` : flat;\n}\n"],"mappings":"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","names":["existsSync","statSync","join","statSync","join","existsSync","opts","tab","trimmed","resolve"]}
@@ -1,165 +0,0 @@
1
- #!/usr/bin/env node
2
- import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
- import {
4
- RecordView
5
- } from "./chunk-I3NE5S63.js";
6
- import {
7
- diffTranscripts,
8
- findNextDivergence,
9
- findPrevDivergence,
10
- renderMarkdown,
11
- renderSummaryTable
12
- } from "./chunk-MW64SQUE.js";
13
- import {
14
- readTranscript
15
- } from "./chunk-D6WRFR6V.js";
16
- import {
17
- Br,
18
- L,
19
- W,
20
- Wo,
21
- fc,
22
- require_react,
23
- vv
24
- } from "./chunk-3OXD5CBM.js";
25
- import "./chunk-GFJJEW3Z.js";
26
- import "./chunk-25T6CVUP.js";
27
- import "./chunk-6QBUXA73.js";
28
- import {
29
- t
30
- } from "./chunk-CLHMV6OL.js";
31
- import "./chunk-AOYUW3HR.js";
32
- import {
33
- __toESM
34
- } from "./chunk-TUK7OWJA.js";
35
-
36
- // src/cli/commands/diff.ts
37
- import { writeFileSync } from "fs";
38
- import { basename } from "path";
39
- var import_react2 = __toESM(require_react(), 1);
40
-
41
- // src/cli/ui/DiffApp.tsx
42
- var import_react = __toESM(require_react(), 1);
43
- function DiffApp({ report }) {
44
- const { exit } = fc();
45
- const maxIdx = Math.max(0, report.pairs.length - 1);
46
- const initialIdx = report.firstDivergenceTurn ? report.pairs.findIndex((p) => p.turn === report.firstDivergenceTurn) : 0;
47
- const [idx, setIdx] = (0, import_react.useState)(Math.max(0, initialIdx));
48
- Br((input, key) => {
49
- if (input === "q" || key.ctrl && input === "c") {
50
- exit();
51
- return;
52
- }
53
- if (input === "j" || key.downArrow || input === " " || key.return) {
54
- setIdx((i) => Math.min(maxIdx, i + 1));
55
- } else if (input === "k" || key.upArrow) {
56
- setIdx((i) => Math.max(0, i - 1));
57
- } else if (input === "g") {
58
- setIdx(0);
59
- } else if (input === "G") {
60
- setIdx(maxIdx);
61
- } else if (input === "n") {
62
- const next = findNextDivergence(report.pairs, idx);
63
- if (next !== -1) setIdx(next);
64
- } else if (input === "N" || input === "p") {
65
- const prev = findPrevDivergence(report.pairs, idx);
66
- if (prev !== -1) setIdx(prev);
67
- }
68
- });
69
- const pair = report.pairs[idx];
70
- return /* @__PURE__ */ import_react.default.createElement(W, { flexDirection: "column" }, /* @__PURE__ */ import_react.default.createElement(DiffHeader, { report }), /* @__PURE__ */ import_react.default.createElement(W, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ import_react.default.createElement(L, { color: "cyan", bold: true }, t("diffApp.turnLabel", {
71
- turn: pair?.turn ?? "?",
72
- current: idx + 1,
73
- total: report.pairs.length
74
- })), /* @__PURE__ */ import_react.default.createElement(L, null, pair ? /* @__PURE__ */ import_react.default.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ import_react.default.createElement(W, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ import_react.default.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ import_react.default.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ import_react.default.createElement(W, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ import_react.default.createElement(L, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ import_react.default.createElement(L, null, pair.divergenceNote)) : null, /* @__PURE__ */ import_react.default.createElement(W, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "j"), "/", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "\\u2193"), " next \\u00b7 ", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "k"), "/", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "\\u2191"), " prev \\u00b7 ", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "n"), " next-diverge \\u00b7", " ", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "N"), "/", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "p"), " prev-diverge \\u00b7 ", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "g"), "/", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "G"), " first/last \\u00b7 ", /* @__PURE__ */ import_react.default.createElement(L, { bold: true }, "q"), " quit")));
75
- }
76
- function DiffHeader({ report }) {
77
- const a = report.a;
78
- const b = report.b;
79
- const cacheDelta = b.stats.cacheHitRatio - a.stats.cacheHitRatio;
80
- const costDelta = a.stats.totalCostUsd > 0 ? (b.stats.totalCostUsd - a.stats.totalCostUsd) / a.stats.totalCostUsd * 100 : 0;
81
- const aStable = a.stats.prefixHashes.length <= 1;
82
- const bStable = b.stats.prefixHashes.length <= 1;
83
- let prefixLine = null;
84
- if (aStable !== bStable) {
85
- const stableLabel = aStable ? report.a.label : report.b.label;
86
- const churnLabel = aStable ? report.b.label : report.a.label;
87
- const churnCount = aStable ? b.stats.prefixHashes.length : a.stats.prefixHashes.length;
88
- prefixLine = `${stableLabel} stayed byte-stable; ${churnLabel} churned ${churnCount} distinct prefixes.`;
89
- } else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
90
- prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
91
- }
92
- return /* @__PURE__ */ import_react.default.createElement(W, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ import_react.default.createElement(W, { justifyContent: "space-between" }, /* @__PURE__ */ import_react.default.createElement(L, null, /* @__PURE__ */ import_react.default.createElement(L, { color: "cyan", bold: true }, t("diffApp.title")), /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, " \\u00b7 A="), /* @__PURE__ */ import_react.default.createElement(L, { color: "blue" }, a.label), /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, " vs B="), /* @__PURE__ */ import_react.default.createElement(L, { color: "magenta" }, b.label)), /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, t("diffApp.turnsAligned", { count: report.pairs.length }))), /* @__PURE__ */ import_react.default.createElement(W, { marginTop: 1, gap: 3 }, /* @__PURE__ */ import_react.default.createElement(L, null, /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, "cache "), /* @__PURE__ */ import_react.default.createElement(L, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, " \u2192 "), /* @__PURE__ */ import_react.default.createElement(L, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ import_react.default.createElement(L, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ import_react.default.createElement(L, null, /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, "cost "), /* @__PURE__ */ import_react.default.createElement(L, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, " \u2192 "), /* @__PURE__ */ import_react.default.createElement(L, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ import_react.default.createElement(L, { color: costDelta <= 0 ? "green" : "red", bold: true }, " ", costDelta >= 0 ? "+" : "", costDelta.toFixed(1), "%")), /* @__PURE__ */ import_react.default.createElement(L, null, /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true }, "model calls "), /* @__PURE__ */ import_react.default.createElement(L, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ import_react.default.createElement(W, { marginTop: 1 }, /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true, italic: true }, prefixLine)) : null);
93
- }
94
- function Pane({
95
- label,
96
- headerColor,
97
- records
98
- }) {
99
- return /* @__PURE__ */ import_react.default.createElement(
100
- W,
101
- {
102
- flexDirection: "column",
103
- flexGrow: 1,
104
- paddingX: 1,
105
- borderStyle: "single",
106
- borderColor: headerColor
107
- },
108
- /* @__PURE__ */ import_react.default.createElement(L, { color: headerColor, bold: true }, label),
109
- records.length === 0 ? /* @__PURE__ */ import_react.default.createElement(W, { marginTop: 1 }, /* @__PURE__ */ import_react.default.createElement(L, { dimColor: true, italic: true }, t("diffApp.paneEmpty"))) : /* @__PURE__ */ import_react.default.createElement(vv, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ import_react.default.createElement(RecordView, { key, rec, compact: true }))
110
- );
111
- }
112
- function KindBadge({ kind }) {
113
- if (kind === "match") {
114
- return /* @__PURE__ */ import_react.default.createElement(L, { color: "green" }, t("diffApp.kindMatch"));
115
- }
116
- if (kind === "diverge") {
117
- return /* @__PURE__ */ import_react.default.createElement(L, { color: "yellow" }, t("diffApp.kindDiverge"));
118
- }
119
- if (kind === "only_in_a") {
120
- return /* @__PURE__ */ import_react.default.createElement(L, { color: "blue" }, t("diffApp.kindOnlyInA"));
121
- }
122
- return /* @__PURE__ */ import_react.default.createElement(L, { color: "magenta" }, t("diffApp.kindOnlyInB"));
123
- }
124
- function paneRecords(pair, side) {
125
- if (!pair) return [];
126
- const tools = side === "a" ? pair.aTools : pair.bTools;
127
- const assistant = side === "a" ? pair.aAssistant : pair.bAssistant;
128
- const out = [...tools];
129
- if (assistant) out.push(assistant);
130
- return out;
131
- }
132
-
133
- // src/cli/commands/diff.ts
134
- async function diffCommand(opts) {
135
- const aParsed = readTranscript(opts.a);
136
- const bParsed = readTranscript(opts.b);
137
- const report = diffTranscripts(
138
- { label: opts.labelA ?? basename(opts.a), parsed: aParsed },
139
- { label: opts.labelB ?? basename(opts.b), parsed: bParsed }
140
- );
141
- const wantMarkdown = !!opts.mdPath;
142
- const wantPrint = opts.print || !process.stdout.isTTY;
143
- const wantTui = opts.tui || !wantPrint && !wantMarkdown;
144
- if (wantMarkdown) {
145
- console.log(renderSummaryTable(report));
146
- const md = renderMarkdown(report);
147
- writeFileSync(opts.mdPath, md, "utf8");
148
- console.log(`
149
- markdown report written to ${opts.mdPath}`);
150
- return;
151
- }
152
- if (wantTui) {
153
- const { waitUntilExit } = Wo(import_react2.default.createElement(DiffApp, { report }), {
154
- exitOnCtrlC: true,
155
- patchConsole: false
156
- });
157
- await waitUntilExit();
158
- return;
159
- }
160
- console.log(renderSummaryTable(report));
161
- }
162
- export {
163
- diffCommand
164
- };
165
- //# sourceMappingURL=diff-2JHMQAHI.js.map