tide-commander 1.169.0 → 1.171.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 (138) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/assets/{BossLogsModal-lFeLoDYQ.js → BossLogsModal-B9vWbBNr.js} +1 -1
  3. package/dist/assets/{BossSpawnModal-Hd6BE1_1.js → BossSpawnModal-CFSomgOD.js} +1 -1
  4. package/dist/assets/{ControlsModal-BogPdPgP.js → ControlsModal-CcRz85tD.js} +1 -1
  5. package/dist/assets/{DockerLogsModal-CO0bptY3.js → DockerLogsModal-DFdfNEUF.js} +1 -1
  6. package/dist/assets/{EmbeddedEditor-VhhJKJWu.js → EmbeddedEditor-Cukk30o6.js} +18 -18
  7. package/dist/assets/{GmailOAuthSetup-D4XqI8K4.js → GmailOAuthSetup-CXdwc7yi.js} +1 -1
  8. package/dist/assets/{GoogleOAuthSetup-D4Q7Zkf1.js → GoogleOAuthSetup-DrYleYt6.js} +1 -1
  9. package/dist/assets/{IframeModal-u9KddMkk.js → IframeModal-CI6RMCgD.js} +1 -1
  10. package/dist/assets/{IntegrationsPanel-Bjj_cALx.js → IntegrationsPanel-COn4wJBS.js} +2 -2
  11. package/dist/assets/{LogViewerModal-CYpewZ36.js → LogViewerModal-DCS9o7LT.js} +1 -1
  12. package/dist/assets/{MonitoringModal-DsRCjUvY.js → MonitoringModal-thfKDr-c.js} +1 -1
  13. package/dist/assets/{PM2LogsModal-CoD0U27e.js → PM2LogsModal-zV7WAdsd.js} +1 -1
  14. package/dist/assets/{RestoreArchivedAreaModal-DyYrh0Dn.js → RestoreArchivedAreaModal-BB0nzljs.js} +1 -1
  15. package/dist/assets/{Scene2DCanvas-LSpu3CMy.js → Scene2DCanvas-DBBaUgWI.js} +1 -1
  16. package/dist/assets/{SceneManager-CoSgXbt6.js → SceneManager-DGwUwHG4.js} +1 -1
  17. package/dist/assets/{SkillsPanel-DCOYtvqY.js → SkillsPanel-B8Oqd8MA.js} +1 -1
  18. package/dist/assets/{SlackMultiInstanceSetup-DzwD7mdT.js → SlackMultiInstanceSetup-B7ApyiDc.js} +1 -1
  19. package/dist/assets/{SpawnModal-CYKMGe4A.js → SpawnModal-DAGdavGj.js} +1 -1
  20. package/dist/assets/{StatisticsModal-Rsk3RBJ-.js → StatisticsModal-DPasxY5d.js} +1 -1
  21. package/dist/assets/{SubordinateAssignmentModal-D_fpOQfa.js → SubordinateAssignmentModal-lDYen20X.js} +1 -1
  22. package/dist/assets/{TriggerManagerPanel-dO5Q66AM.js → TriggerManagerPanel-BeQfU75h.js} +1 -1
  23. package/dist/assets/{WorkflowEditorPanel-ChFVP91n.js → WorkflowEditorPanel-BHAml2sK.js} +1 -1
  24. package/dist/assets/{abnfDiagram-VRR7QNED-Bd736gc1.js → abnfDiagram-VRR7QNED-CKRbGbPs.js} +1 -1
  25. package/dist/assets/{arc-CicRk3Wa.js → arc-D2zNUdvM.js} +1 -1
  26. package/dist/assets/{architectureDiagram-ZJ3FMSHR-uk1YbOOV.js → architectureDiagram-ZJ3FMSHR-Bv7ShjpG.js} +1 -1
  27. package/dist/assets/{area-logos-CtetiK8U.js → area-logos-Tkw0BxmP.js} +1 -1
  28. package/dist/assets/{blockDiagram-677ZJIJ3-CPr5yp_O.js → blockDiagram-677ZJIJ3-DToi6Gg_.js} +1 -1
  29. package/dist/assets/{c4Diagram-LMCZKHZV-Cwhulsrr.js → c4Diagram-LMCZKHZV-B27vS_z6.js} +1 -1
  30. package/dist/assets/channel-CthULdSA.js +1 -0
  31. package/dist/assets/{chunk-2Q5K7J3B-DntPK0R4.js → chunk-2Q5K7J3B-DtUOfC37.js} +1 -1
  32. package/dist/assets/{chunk-32BRIVSS-DPGnMNRt.js → chunk-32BRIVSS-BJ_WREuq.js} +1 -1
  33. package/dist/assets/{chunk-5VM5RSS4-HqD1WKnr.js → chunk-5VM5RSS4-BGp6ep7q.js} +1 -1
  34. package/dist/assets/{chunk-EX3LRPZG-CnQzt-nk.js → chunk-EX3LRPZG-Bo-8A4Wf.js} +1 -1
  35. package/dist/assets/{chunk-JWPE2WC7-96_obCN5.js → chunk-JWPE2WC7-B5stP4bm.js} +1 -1
  36. package/dist/assets/{chunk-MOJQB5TN-CNhoYGDI.js → chunk-MOJQB5TN-dKTY7Lj6.js} +1 -1
  37. package/dist/assets/{chunk-RYQCIY6F-B66k9-Zp.js → chunk-RYQCIY6F-DMva3WON.js} +1 -1
  38. package/dist/assets/{chunk-V7JOEXUC-CDq9VX4u.js → chunk-V7JOEXUC-Bj74vJ9Y.js} +1 -1
  39. package/dist/assets/{chunk-VR4S4FIN-BoUv9bdH.js → chunk-VR4S4FIN-bWcxnfsP.js} +1 -1
  40. package/dist/assets/{chunk-XXDRQBXY-Bilx42me.js → chunk-XXDRQBXY-BiEmebgj.js} +1 -1
  41. package/dist/assets/classDiagram-OUVF2IWQ-BAuqHPhA.js +1 -0
  42. package/dist/assets/classDiagram-v2-EOCWNBFH-BAuqHPhA.js +1 -0
  43. package/dist/assets/{cose-bilkent-JH36ORCC-BLO85xX-.js → cose-bilkent-JH36ORCC-CXxRJxnB.js} +1 -1
  44. package/dist/assets/{cynefin-VYW2F7L2-WYLw8wuA.js → cynefin-VYW2F7L2-Dm0Nd1JY.js} +1 -1
  45. package/dist/assets/{cynefinDiagram-TSTJHNR4-LAbqztaC.js → cynefinDiagram-TSTJHNR4-DDb1Kwcy.js} +1 -1
  46. package/dist/assets/{dagre-VKFMJZFB-CpnUxGz2.js → dagre-VKFMJZFB-GpvMjmNf.js} +1 -1
  47. package/dist/assets/{diagram-FQU43EPY-D4XAWe06.js → diagram-FQU43EPY-11fs9Ufj.js} +1 -1
  48. package/dist/assets/{diagram-G47NLZAW-CLgptSnw.js → diagram-G47NLZAW-BsvFEFjq.js} +1 -1
  49. package/dist/assets/{diagram-NH7WQ7WH-ClRPCJJG.js → diagram-NH7WQ7WH-wwkU2oMd.js} +1 -1
  50. package/dist/assets/{diagram-OA4YK3LP-DAwXS8R3.js → diagram-OA4YK3LP-XNr7VZph.js} +1 -1
  51. package/dist/assets/{diagram-WEI45ONY-B-um2qgR.js → diagram-WEI45ONY-BlsopXOY.js} +1 -1
  52. package/dist/assets/{ebnfDiagram-CCIWWBDH-BuluWV6z.js → ebnfDiagram-CCIWWBDH-BKywI0Nz.js} +1 -1
  53. package/dist/assets/{erDiagram-Q63AITRT-iViEXIuX.js → erDiagram-Q63AITRT-C7-QLp5I.js} +1 -1
  54. package/dist/assets/{flowDiagram-23GEKE2U-BB1xkRK-.js → flowDiagram-23GEKE2U-Cl03LtDW.js} +1 -1
  55. package/dist/assets/{ganttDiagram-NO4QXBWP-Y056vaku.js → ganttDiagram-NO4QXBWP-D9MviXdG.js} +1 -1
  56. package/dist/assets/{gitGraphDiagram-IHSO6WYX-RVnA3-Oq.js → gitGraphDiagram-IHSO6WYX-DJK3sEDX.js} +1 -1
  57. package/dist/assets/{index-BGc24jpF.js → index-BFpl32n6.js} +2 -2
  58. package/dist/assets/{index-BMDcamyw.js → index-BQyCpuhe.js} +1 -1
  59. package/dist/assets/{index-DIxINv38.js → index-BgDEVN-P.js} +1 -1
  60. package/dist/assets/{index-BukJVnzE.js → index-Bm0btvjf.js} +1 -1
  61. package/dist/assets/{index-B_8jWBCl.js → index-BmW2I_FC.js} +2 -2
  62. package/dist/assets/{index-Dy4xURwo.js → index-BrYZ4x3u.js} +1 -1
  63. package/dist/assets/{index-B6QXj8_t.js → index-C3fJJwvY.js} +1 -1
  64. package/dist/assets/{index-GNffDlPO.js → index-CXN8rJHS.js} +3 -3
  65. package/dist/assets/{index-BsZHZI4z.js → index-DwCFZW5i.js} +1 -1
  66. package/dist/assets/{infoDiagram-FWYZ7A6U-B5GbrTtK.js → infoDiagram-FWYZ7A6U-Cks_TYBJ.js} +1 -1
  67. package/dist/assets/{ishikawaDiagram-FXEZZL3T-BAiw7b0j.js → ishikawaDiagram-FXEZZL3T-Bm7aexa9.js} +1 -1
  68. package/dist/assets/{journeyDiagram-5HDEW3XC-CKR52gw7.js → journeyDiagram-5HDEW3XC-DifsbtCm.js} +1 -1
  69. package/dist/assets/{kanban-definition-HUTT4EX6-CWrhHM6G.js → kanban-definition-HUTT4EX6-Bo8SttS7.js} +1 -1
  70. package/dist/assets/{linear-CAZvZbxC.js → linear-B6QdBMun.js} +1 -1
  71. package/dist/assets/main-DF7C8hzR.js +299 -0
  72. package/dist/assets/main-h6n299s0.css +1 -0
  73. package/dist/assets/{mermaid.core-8841kka_.js → mermaid.core-CEMk16Os.js} +4 -4
  74. package/dist/assets/{mindmap-definition-LN4V7U3C-CFOf-bER.js → mindmap-definition-LN4V7U3C-vk790me8.js} +1 -1
  75. package/dist/assets/{pegDiagram-2B236MQR-tiGmjXoe.js → pegDiagram-2B236MQR-BJACQXAW.js} +1 -1
  76. package/dist/assets/{pieDiagram-ENE6RG2P-ByoCrcjG.js → pieDiagram-ENE6RG2P-Uk-NBCqZ.js} +1 -1
  77. package/dist/assets/{quadrantDiagram-ABIIQ3AL-D3njdqNJ.js → quadrantDiagram-ABIIQ3AL-BDQbYz5s.js} +1 -1
  78. package/dist/assets/{railroadDiagram-RFXS5EU6-Co1Qyv4I.js → railroadDiagram-RFXS5EU6-C5G6xypa.js} +1 -1
  79. package/dist/assets/{requirementDiagram-TGXJPOKE-Bcc-ZmtM.js → requirementDiagram-TGXJPOKE-ReBLA33O.js} +1 -1
  80. package/dist/assets/{sankeyDiagram-HTMAVEWB-NGc5ZbW2.js → sankeyDiagram-HTMAVEWB-CopjNXJ8.js} +1 -1
  81. package/dist/assets/{sequenceDiagram-DBY2YBRQ-DMK9vu1q.js → sequenceDiagram-DBY2YBRQ-5T9JzLdC.js} +1 -1
  82. package/dist/assets/{sizeCapture-X5ZJPWSS-fw74589N.js → sizeCapture-X5ZJPWSS-CeJnznzr.js} +1 -1
  83. package/dist/assets/{stateDiagram-2N3HPSRC-Ct1CF4lH.js → stateDiagram-2N3HPSRC-D9xhIzw5.js} +1 -1
  84. package/dist/assets/stateDiagram-v2-6OUMAXLB-BzOILtxT.js +1 -0
  85. package/dist/assets/{swimlanes-5IMT3BWC-BTA4j6h_.js → swimlanes-5IMT3BWC-CJeo_EeU.js} +2 -2
  86. package/dist/assets/swimlanesDiagram-G3AALYLV-oysql1_F.js +8 -0
  87. package/dist/assets/{timeline-definition-FHXFAJF6-Cdsu0GVG.js → timeline-definition-FHXFAJF6-C-LnQuak.js} +1 -1
  88. package/dist/assets/{vennDiagram-L72KCM5P-DpcwNBEA.js → vennDiagram-L72KCM5P-B6m0bHRx.js} +1 -1
  89. package/dist/assets/{wardleyDiagram-EHGQE667-B24yQ2jy.js → wardleyDiagram-EHGQE667-BNH4Dn0X.js} +1 -1
  90. package/dist/assets/{web-wlEp31pO.js → web-0EupeQR8.js} +1 -1
  91. package/dist/assets/{web-Da6xoNEp.js → web-DP98dDU1.js} +1 -1
  92. package/dist/assets/{web-DObpRERU.js → web-DSzkgcIW.js} +1 -1
  93. package/dist/assets/{xychartDiagram-FW5EYKEG-um8cUnVI.js → xychartDiagram-FW5EYKEG-Bf571fyY.js} +1 -1
  94. package/dist/build-info.json +1 -1
  95. package/dist/index.html +2 -2
  96. package/dist/locales/de/config.json +3 -1
  97. package/dist/locales/de/terminal.json +1 -0
  98. package/dist/locales/de/tools.json +10 -1
  99. package/dist/locales/en/common.json +3 -1
  100. package/dist/locales/en/config.json +2 -0
  101. package/dist/locales/en/terminal.json +1 -0
  102. package/dist/locales/en/tools.json +10 -1
  103. package/dist/locales/es/config.json +2 -0
  104. package/dist/locales/es/terminal.json +1 -0
  105. package/dist/locales/es/tools.json +10 -1
  106. package/dist/locales/fr/config.json +3 -1
  107. package/dist/locales/fr/terminal.json +1 -0
  108. package/dist/locales/fr/tools.json +10 -1
  109. package/dist/locales/hi/config.json +3 -1
  110. package/dist/locales/hi/terminal.json +1 -0
  111. package/dist/locales/hi/tools.json +10 -1
  112. package/dist/locales/it/config.json +3 -1
  113. package/dist/locales/it/terminal.json +1 -0
  114. package/dist/locales/it/tools.json +10 -1
  115. package/dist/locales/ja/config.json +3 -1
  116. package/dist/locales/ja/terminal.json +1 -0
  117. package/dist/locales/ja/tools.json +10 -1
  118. package/dist/locales/pt/config.json +3 -1
  119. package/dist/locales/pt/terminal.json +1 -0
  120. package/dist/locales/pt/tools.json +10 -1
  121. package/dist/locales/ru/config.json +3 -1
  122. package/dist/locales/ru/terminal.json +1 -0
  123. package/dist/locales/ru/tools.json +10 -1
  124. package/dist/locales/zh-CN/config.json +3 -1
  125. package/dist/locales/zh-CN/terminal.json +1 -0
  126. package/dist/locales/zh-CN/tools.json +10 -1
  127. package/dist/src/packages/server/opencode/server/opencode-server-event-adapter.js +21 -0
  128. package/dist/src/packages/server/opencode/server/opencode-server-process.js +52 -8
  129. package/dist/src/packages/server/opencode/server/opencode-server-runner.js +28 -0
  130. package/dist/src/packages/server/routes/files.js +25 -3
  131. package/package.json +1 -1
  132. package/dist/assets/channel-5_glBCpe.js +0 -1
  133. package/dist/assets/classDiagram-OUVF2IWQ-BvvPWiAV.js +0 -1
  134. package/dist/assets/classDiagram-v2-EOCWNBFH-BvvPWiAV.js +0 -1
  135. package/dist/assets/main-BgmmrYDn.js +0 -298
  136. package/dist/assets/main-Dhz40TGa.css +0 -1
  137. package/dist/assets/stateDiagram-v2-6OUMAXLB-CUuNeVFf.js +0 -1
  138. package/dist/assets/swimlanesDiagram-G3AALYLV-FjJqxVNN.js +0 -8
@@ -38,7 +38,9 @@
38
38
  "notifications": "Notifiche",
39
39
  "soundEffects": "Effetti sonori",
40
40
  "streamTextLive": "Streaming parola per parola",
41
- "streamTextLiveTitle": "Mostra testo/pensiero di Claude e Grok mentre vengono generati. Disattiva per vedere solo le risposte complete."
41
+ "streamTextLiveTitle": "Mostra testo/pensiero di Claude e Grok mentre vengono generati. Disattiva per vedere solo le risposte complete.",
42
+ "toolHoverPreview": "Anteprima con Ctrl",
43
+ "toolHoverPreviewTitle": "Tieni premuto Ctrl passando sopra una riga di strumento o un percorso file nel terminale per vedere il file, il diff, l'immagine o l'output del comando. Il pannello è scorrevole."
42
44
  },
43
45
  "agentNames": {
44
46
  "customConfigured": "{{count}} nomi personalizzati configurati",
@@ -901,6 +901,7 @@
901
901
  "fileNotFound": "File non trovato",
902
902
  "loading": "Caricamento diff...",
903
903
  "showDiff": "Mostra diff",
904
+ "showRendered": "Mostra renderizzato",
904
905
  "modifiedOnly": "Solo modificati",
905
906
  "copied": "Copiato",
906
907
  "errorCopy": "Errore",
@@ -44,7 +44,8 @@
44
44
  "attemptCompletion": "AttemptCompletion",
45
45
  "listFiles": "ListFiles",
46
46
  "searchFiles": "SearchFiles",
47
- "executeCommand": "ExecuteCommand"
47
+ "executeCommand": "ExecuteCommand",
48
+ "viewImage": "Vedi immagine"
48
49
  },
49
50
  "showOutputsInline": "Mostra tutti gli output bash in linea",
50
51
  "hideOutputsInline": "Nascondi gli output bash in linea"
@@ -273,5 +274,13 @@
273
274
  "response": {
274
275
  "noContent": "Nessun contenuto di risposta disponibile.",
275
276
  "rawMarkdown": "Markdown grezzo"
277
+ },
278
+ "preview": {
279
+ "loading": "Caricamento anteprima…",
280
+ "emptyFile": "(file vuoto)",
281
+ "noDiff": "(nessun diff disponibile)",
282
+ "diffTruncated": "diff troncato…",
283
+ "moreLines": "+{{count}} righe in più",
284
+ "skippedLines": "… {{count}} righe omesse …"
276
285
  }
277
286
  }
@@ -38,7 +38,9 @@
38
38
  "notifications": "通知",
39
39
  "soundEffects": "効果音",
40
40
  "streamTextLive": "単語ごとのストリーミング",
41
- "streamTextLiveTitle": "Claude と Grok のテキスト/思考をストリーミング表示します。オフにすると完成した返答のみ表示します。"
41
+ "streamTextLiveTitle": "Claude と Grok のテキスト/思考をストリーミング表示します。オフにすると完成した返答のみ表示します。",
42
+ "toolHoverPreview": "Ctrl+ホバーのプレビュー",
43
+ "toolHoverPreviewTitle": "Ctrl を押しながらターミナルのツール行やファイルパスにカーソルを合わせると、ファイル・差分・画像・コマンド出力をプレビューできます。パネルはスクロールできます。"
42
44
  },
43
45
  "agentNames": {
44
46
  "customConfigured": "{{count}}個のカスタム名が設定済み",
@@ -901,6 +901,7 @@
901
901
  "fileNotFound": "ファイルが見つかりません",
902
902
  "loading": "差分を読み込み中...",
903
903
  "showDiff": "差分を表示",
904
+ "showRendered": "レンダリング表示",
904
905
  "modifiedOnly": "変更のみ",
905
906
  "copied": "コピー済み",
906
907
  "errorCopy": "エラー",
@@ -44,7 +44,8 @@
44
44
  "attemptCompletion": "AttemptCompletion",
45
45
  "listFiles": "ListFiles",
46
46
  "searchFiles": "SearchFiles",
47
- "executeCommand": "ExecuteCommand"
47
+ "executeCommand": "ExecuteCommand",
48
+ "viewImage": "画像を表示"
48
49
  },
49
50
  "showOutputsInline": "すべてのBash出力をインライン表示",
50
51
  "hideOutputsInline": "インラインBash出力を非表示"
@@ -273,5 +274,13 @@
273
274
  "response": {
274
275
  "noContent": "レスポンス内容がありません。",
275
276
  "rawMarkdown": "生Markdown"
277
+ },
278
+ "preview": {
279
+ "loading": "プレビューを読み込み中…",
280
+ "emptyFile": "(空のファイル)",
281
+ "noDiff": "(差分なし)",
282
+ "diffTruncated": "差分を省略…",
283
+ "moreLines": "他 {{count}} 行",
284
+ "skippedLines": "… {{count}} 行を省略 …"
276
285
  }
277
286
  }
@@ -38,7 +38,9 @@
38
38
  "notifications": "Notificacoes",
39
39
  "soundEffects": "Efeitos Sonoros",
40
40
  "streamTextLive": "Streaming palavra a palavra",
41
- "streamTextLiveTitle": "Mostrar texto/pensamento do Claude e Grok à medida que são gerados. Desative para ver apenas respostas completas."
41
+ "streamTextLiveTitle": "Mostrar texto/pensamento do Claude e Grok à medida que são gerados. Desative para ver apenas respostas completas.",
42
+ "toolHoverPreview": "Pré-visualização com Ctrl",
43
+ "toolHoverPreviewTitle": "Segure Ctrl ao passar o cursor sobre uma linha de ferramenta ou caminho de arquivo no terminal para ver o arquivo, o diff, a imagem ou a saída do comando. O painel pode ser rolado."
42
44
  },
43
45
  "agentNames": {
44
46
  "customConfigured": "{{count}} nomes personalizados configurados",
@@ -901,6 +901,7 @@
901
901
  "fileNotFound": "Arquivo nao encontrado",
902
902
  "loading": "Carregando diff...",
903
903
  "showDiff": "Mostrar Diff",
904
+ "showRendered": "Mostrar renderizado",
904
905
  "modifiedOnly": "Somente Modificados",
905
906
  "copied": "Copiado",
906
907
  "errorCopy": "Erro",
@@ -44,7 +44,8 @@
44
44
  "attemptCompletion": "AttemptCompletion",
45
45
  "listFiles": "ListFiles",
46
46
  "searchFiles": "SearchFiles",
47
- "executeCommand": "ExecuteCommand"
47
+ "executeCommand": "ExecuteCommand",
48
+ "viewImage": "Ver imagem"
48
49
  },
49
50
  "showOutputsInline": "Mostrar todas as saídas do bash em linha",
50
51
  "hideOutputsInline": "Ocultar as saídas do bash em linha"
@@ -273,5 +274,13 @@
273
274
  "response": {
274
275
  "noContent": "Nenhum conteudo de resposta disponivel.",
275
276
  "rawMarkdown": "Markdown Bruto"
277
+ },
278
+ "preview": {
279
+ "loading": "Carregando pré-visualização…",
280
+ "emptyFile": "(arquivo vazio)",
281
+ "noDiff": "(nenhum diff disponível)",
282
+ "diffTruncated": "diff truncado…",
283
+ "moreLines": "+{{count}} linhas a mais",
284
+ "skippedLines": "… {{count}} linhas omitidas …"
276
285
  }
277
286
  }
@@ -38,7 +38,9 @@
38
38
  "notifications": "Уведомления",
39
39
  "soundEffects": "Звуковые эффекты",
40
40
  "streamTextLive": "Потоковая передача по словам",
41
- "streamTextLiveTitle": "Показывать текст/мысли Claude и Grok по мере генерации. Отключите, чтобы видеть только готовые ответы."
41
+ "streamTextLiveTitle": "Показывать текст/мысли Claude и Grok по мере генерации. Отключите, чтобы видеть только готовые ответы.",
42
+ "toolHoverPreview": "Предпросмотр по Ctrl",
43
+ "toolHoverPreviewTitle": "Удерживайте Ctrl при наведении на строку инструмента или путь к файлу в терминале, чтобы увидеть файл, diff, изображение или вывод команды. Панель можно прокручивать."
42
44
  },
43
45
  "agentNames": {
44
46
  "customConfigured": "{{count}} пользовательских имён настроено",
@@ -901,6 +901,7 @@
901
901
  "fileNotFound": "Файл не найден",
902
902
  "loading": "Загрузка diff...",
903
903
  "showDiff": "Показать Diff",
904
+ "showRendered": "Показать рендер",
904
905
  "modifiedOnly": "Только изменённые",
905
906
  "copied": "Скопировано",
906
907
  "errorCopy": "Ошибка",
@@ -44,7 +44,8 @@
44
44
  "attemptCompletion": "AttemptCompletion",
45
45
  "listFiles": "ListFiles",
46
46
  "searchFiles": "SearchFiles",
47
- "executeCommand": "ExecuteCommand"
47
+ "executeCommand": "ExecuteCommand",
48
+ "viewImage": "Просмотр изображения"
48
49
  },
49
50
  "showOutputsInline": "Показывать все выводы bash в строке",
50
51
  "hideOutputsInline": "Скрыть встроенные выводы bash"
@@ -273,5 +274,13 @@
273
274
  "response": {
274
275
  "noContent": "Содержимое ответа недоступно.",
275
276
  "rawMarkdown": "Исходный Markdown"
277
+ },
278
+ "preview": {
279
+ "loading": "Загрузка предпросмотра…",
280
+ "emptyFile": "(пустой файл)",
281
+ "noDiff": "(нет доступных изменений)",
282
+ "diffTruncated": "diff усечён…",
283
+ "moreLines": "+{{count}} строк ещё",
284
+ "skippedLines": "… пропущено строк: {{count}} …"
276
285
  }
277
286
  }
@@ -38,7 +38,9 @@
38
38
  "notifications": "通知",
39
39
  "soundEffects": "音效",
40
40
  "streamTextLive": "逐字流式输出",
41
- "streamTextLiveTitle": "实时显示 Claude 和 Grok 的文本/思考。关闭后仅显示完整回复。"
41
+ "streamTextLiveTitle": "实时显示 Claude 和 Grok 的文本/思考。关闭后仅显示完整回复。",
42
+ "toolHoverPreview": "Ctrl 悬停预览",
43
+ "toolHoverPreviewTitle": "在终端中按住 Ctrl 并将鼠标悬停在工具行或文件路径上,即可预览文件、差异、图片或命令输出。面板可滚动。"
42
44
  },
43
45
  "agentNames": {
44
46
  "customConfigured": "已配置 {{count}} 个自定义名称",
@@ -901,6 +901,7 @@
901
901
  "fileNotFound": "文件未找到",
902
902
  "loading": "加载差异中...",
903
903
  "showDiff": "显示差异",
904
+ "showRendered": "显示渲染",
904
905
  "modifiedOnly": "仅修改内容",
905
906
  "copied": "已复制",
906
907
  "errorCopy": "错误",
@@ -44,7 +44,8 @@
44
44
  "attemptCompletion": "尝试完成",
45
45
  "listFiles": "列出文件",
46
46
  "searchFiles": "搜索文件",
47
- "executeCommand": "执行命令"
47
+ "executeCommand": "执行命令",
48
+ "viewImage": "查看图片"
48
49
  },
49
50
  "showOutputsInline": "内联显示所有 Bash 输出",
50
51
  "hideOutputsInline": "隐藏内联 Bash 输出"
@@ -273,5 +274,13 @@
273
274
  "response": {
274
275
  "noContent": "没有可用的响应内容。",
275
276
  "rawMarkdown": "原始 Markdown"
277
+ },
278
+ "preview": {
279
+ "loading": "正在加载预览…",
280
+ "emptyFile": "(空文件)",
281
+ "noDiff": "(无可用差异)",
282
+ "diffTruncated": "差异已截断…",
283
+ "moreLines": "还有 {{count}} 行",
284
+ "skippedLines": "… 已跳过 {{count}} 行 …"
276
285
  }
277
286
  }
@@ -37,11 +37,23 @@ export class OpencodeServerEventAdapter {
37
37
  partType = new Map();
38
38
  lastTokens;
39
39
  lastCost;
40
+ /** True once actual CONTENT flowed (message.part.* events) since the last
41
+ * finalized turn. A `session.idle` with no content behind it is a stale
42
+ * duplicate: aborting a turn double-fires idle, and the second one lands
43
+ * AFTER the next turn already started, which used to finalize that new turn
44
+ * prematurely (agent flipped idle while the model was still generating).
45
+ * Only part events arm this — the abort fallout replays a `message.updated`
46
+ * (metadata of the aborted message) BETWEEN the two idles, so metadata must
47
+ * not count as activity (captured live: error → idle#1 → message.updated →
48
+ * idle#2). */
49
+ sawActivity = false;
40
50
  handle(event) {
41
51
  const type = event.type;
42
52
  if (!type)
43
53
  return [];
44
54
  const props = event.properties || {};
55
+ if (type === 'message.part.delta' || type === 'message.part.updated')
56
+ this.sawActivity = true;
45
57
  switch (type) {
46
58
  case 'message.part.delta': {
47
59
  // OpenCode streams a part for the USER message too (the prompt itself);
@@ -91,6 +103,8 @@ export class OpencodeServerEventAdapter {
91
103
  return [];
92
104
  }
93
105
  case 'session.idle':
106
+ if (!this.sawActivity)
107
+ return [];
94
108
  return this.finalizeTurn();
95
109
  case 'session.error': {
96
110
  const err = props.error;
@@ -127,6 +141,12 @@ export class OpencodeServerEventAdapter {
127
141
  }
128
142
  return events;
129
143
  }
144
+ /** Finalize unconditionally — for the runner's POST-resolution fallback,
145
+ * which fires when a turn ended server-side but its session.idle never
146
+ * arrived (so the activity gate must not apply). */
147
+ forceFinalize() {
148
+ return this.finalizeTurn();
149
+ }
130
150
  finalizeTurn() {
131
151
  // Feed a synthetic step_finish so the parser finalizes any open streaming
132
152
  // rows and emits usage_snapshot + step_complete (with resultText from the
@@ -152,6 +172,7 @@ export class OpencodeServerEventAdapter {
152
172
  this.toolDone.clear();
153
173
  this.lastTokens = undefined;
154
174
  this.lastCost = undefined;
175
+ this.sawActivity = false;
155
176
  return events;
156
177
  }
157
178
  }
@@ -2,12 +2,18 @@
2
2
  * OpencodeServerProcess
3
3
  *
4
4
  * Manages a DETACHED, restart-surviving `opencode serve` HTTP server and speaks
5
- * its API: one SSE stream (`GET /event`) carries every session's events
5
+ * its API: one SSE stream (`GET /global/event`) carries every session's events
6
6
  * (word-by-word `message.part.delta`), and prompts/sessions/aborts go over plain
7
7
  * HTTP. One server multiplexes every OpenCode agent — each agent owns a
8
8
  * `sessionID`, and every event carries `properties.sessionID` so the runner can
9
9
  * fan them back out.
10
10
  *
11
+ * The stream MUST be `/global/event`: the plain `/event` endpoint is
12
+ * PROJECT-SCOPED (resolved from the request's directory, defaulting to the
13
+ * daemon's cwd), so a subscription there silently drops every event from
14
+ * sessions living in any other working directory — those agents then get no
15
+ * deltas and no `session.idle`, wedging them in 'working' forever.
16
+ *
11
17
  * Why detached + HTTP/SSE (vs `opencode run` per turn): `opencode run --format
12
18
  * json` emits one full assistant message (no token deltas), and a child process
13
19
  * dies with the commander. A detached server bound to a localhost port survives
@@ -31,6 +37,9 @@ export class OpencodeServerProcess {
31
37
  stopped = false;
32
38
  connected = false;
33
39
  reconnectedToExisting = false;
40
+ /** Set once `/global/event` came back non-200 (older opencode) — stick to the
41
+ * legacy project-scoped `/event` stream from then on. */
42
+ legacyEventStream = false;
34
43
  constructor(opts) {
35
44
  this.opts = opts;
36
45
  }
@@ -97,11 +106,22 @@ export class OpencodeServerProcess {
97
106
  }
98
107
  throw new Error('opencode server /api/health never became healthy');
99
108
  }
100
- /** Open the single global SSE stream and parse `data:` frames. */
109
+ /** Open the single all-projects SSE stream (`/global/event`) and parse
110
+ * `data:` frames. Falls back to the legacy project-scoped `/event` on
111
+ * daemons too old to serve the global stream. */
101
112
  openSse() {
102
113
  if (this.stopped)
103
114
  return;
104
- const req = http.get(`${this.baseUrl}/event`, { headers: { Accept: 'text/event-stream' } }, (res) => {
115
+ const path = this.legacyEventStream ? '/event' : '/global/event';
116
+ const req = http.get(`${this.baseUrl}${path}`, { headers: { Accept: 'text/event-stream' } }, (res) => {
117
+ if (res.statusCode !== 200 && !this.legacyEventStream) {
118
+ log.warn(`GET /global/event → HTTP ${res.statusCode}; falling back to legacy project-scoped /event`);
119
+ this.legacyEventStream = true;
120
+ this.sseReq = null; // guard: the destroyed request's error/end must not trigger a reconnect
121
+ req.destroy();
122
+ this.openSse();
123
+ return;
124
+ }
105
125
  res.setEncoding('utf8');
106
126
  let buffer = '';
107
127
  res.on('data', (chunk) => {
@@ -114,10 +134,15 @@ export class OpencodeServerProcess {
114
134
  this.handleFrame(frame);
115
135
  }
116
136
  });
117
- res.on('end', () => this.handleSseClosed());
137
+ res.on('end', () => {
138
+ if (this.sseReq === req)
139
+ this.handleSseClosed();
140
+ });
118
141
  });
119
142
  this.sseReq = req;
120
143
  req.on('error', (err) => {
144
+ if (this.sseReq !== req)
145
+ return;
121
146
  log.warn(`SSE connection error: ${err.message}`);
122
147
  this.handleSseClosed();
123
148
  });
@@ -140,7 +165,7 @@ export class OpencodeServerProcess {
140
165
  catch {
141
166
  return;
142
167
  }
143
- this.opts.onEvent(evt);
168
+ this.opts.onEvent(unwrapGlobalSseEvent(evt));
144
169
  }
145
170
  handleSseClosed() {
146
171
  this.sseReq = null;
@@ -273,10 +298,10 @@ export class OpencodeServerProcess {
273
298
  async activeSessionIds() {
274
299
  try {
275
300
  const resp = await this.httpJson('GET', '/api/session/active');
276
- const list = (resp?.data ?? resp);
301
+ const raw = resp?.data ?? resp;
277
302
  const ids = new Set();
278
- if (Array.isArray(list)) {
279
- for (const item of list) {
303
+ if (Array.isArray(raw)) {
304
+ for (const item of raw) {
280
305
  if (typeof item === 'string')
281
306
  ids.add(item);
282
307
  else if (item?.id)
@@ -285,6 +310,13 @@ export class OpencodeServerProcess {
285
310
  ids.add(item.sessionID);
286
311
  }
287
312
  }
313
+ else if (raw && typeof raw === 'object') {
314
+ // 1.18.x returns a map keyed by sessionID: {"ses_…": {…}}
315
+ for (const key of Object.keys(raw)) {
316
+ if (key.startsWith('ses'))
317
+ ids.add(key);
318
+ }
319
+ }
288
320
  return ids;
289
321
  }
290
322
  catch {
@@ -316,6 +348,18 @@ export class OpencodeServerProcess {
316
348
  clearDaemonInfo();
317
349
  }
318
350
  }
351
+ /**
352
+ * `/global/event` wraps every bus event as `{directory, project, payload: {id,
353
+ * type, properties}}`, while the legacy `/event` stream delivers the inner
354
+ * shape directly. Unwrap the envelope so downstream routing sees ONE shape.
355
+ */
356
+ export function unwrapGlobalSseEvent(evt) {
357
+ const payload = evt.payload;
358
+ if (payload && typeof payload === 'object' && typeof payload.type === 'string') {
359
+ return payload;
360
+ }
361
+ return evt;
362
+ }
319
363
  function isPidAlive(pid) {
320
364
  if (!pid || pid < 1)
321
365
  return false;
@@ -26,6 +26,9 @@ import { createLogger } from '../../utils/logger.js';
26
26
  import { withAgentContext } from '../../utils/log-context.js';
27
27
  const log = createLogger('OpencodeServerRunner');
28
28
  const RECOVER_DELAY_MS = 1500;
29
+ /** How long after the turn's message POST resolves (= turn ended server-side)
30
+ * to wait for the real `session.idle` before force-finalizing the turn. */
31
+ const POST_IDLE_GRACE_MS = 3000;
29
32
  export class OpencodeServerRunner {
30
33
  callbacks;
31
34
  backend = new OpencodeBackend();
@@ -98,6 +101,7 @@ export class OpencodeServerRunner {
98
101
  lastActivityTime: Date.now(),
99
102
  lastRequest: p.lastRequest,
100
103
  queue: [],
104
+ turnSeq: 0,
101
105
  };
102
106
  this.agents.set(p.agentId, state);
103
107
  this.sessionToAgent.set(p.sessionId, p.agentId);
@@ -169,6 +173,12 @@ export class OpencodeServerRunner {
169
173
  }
170
174
  }
171
175
  }
176
+ // A step_complete for a turn that's already finalized (the POST-resolution
177
+ // fallback raced the real session.idle, or the server double-fired idle)
178
+ // must be dropped whole — re-emitting would render a spurious
179
+ // "(Empty response)" row and double-fire onComplete/drainQueue.
180
+ if (event.type === 'step_complete' && state.turnState !== 'processing')
181
+ return;
172
182
  this.pipeline.emitStandardEvent(agentId, event);
173
183
  if (event.type === 'step_complete') {
174
184
  state.turnState = 'waiting_for_input';
@@ -228,6 +238,7 @@ export class OpencodeServerRunner {
228
238
  lastActivityTime: Date.now(),
229
239
  lastRequest: request,
230
240
  queue: [],
241
+ turnSeq: 0,
231
242
  };
232
243
  this.agents.set(agentId, state);
233
244
  this.sessionToAgent.set(sessionId, agentId);
@@ -266,8 +277,25 @@ export class OpencodeServerRunner {
266
277
  const promptText = buildOpencodePrompt(config);
267
278
  state.turnState = 'processing';
268
279
  state.lastActivityTime = Date.now();
280
+ state.turnSeq += 1;
281
+ const seq = state.turnSeq;
269
282
  try {
270
283
  await proc.sendPrompt(state.sessionId, promptText, this.modelRef(state.lastRequest.model));
284
+ // opencode holds the message POST open for the ENTIRE turn, so resolving
285
+ // means the turn already ended server-side. `session.idle` over SSE is
286
+ // the normal finalizer — but if it doesn't land shortly after (missed
287
+ // frame, broken/mis-scoped stream), force-finalize so one lost event can
288
+ // never wedge the agent in 'working' with its queue backing up forever.
289
+ setTimeout(() => {
290
+ if (this.agents.get(agentId) !== state)
291
+ return;
292
+ if (state.turnSeq !== seq || state.turnState !== 'processing')
293
+ return;
294
+ log.warn(`Turn POST resolved but no session.idle after ${POST_IDLE_GRACE_MS}ms for ${agentId.slice(0, 8)}; force-finalizing turn`);
295
+ for (const event of state.adapter.forceFinalize()) {
296
+ this.applyEvent(agentId, state, event);
297
+ }
298
+ }, POST_IDLE_GRACE_MS);
271
299
  }
272
300
  catch (err) {
273
301
  const msg = err instanceof Error ? err.message : String(err);
@@ -549,17 +549,39 @@ router.get('/read', async (req, res) => {
549
549
  const content = fs.readFileSync(filePath, 'utf-8');
550
550
  const extension = path.extname(filePath).toLowerCase();
551
551
  const filename = path.basename(filePath);
552
- res.json({
552
+ const base = {
553
553
  path: filePath,
554
554
  filename,
555
555
  extension,
556
- content,
557
556
  size: stats.size,
558
557
  modified: stats.mtime,
559
558
  strategy: resolution.strategy,
560
559
  areaId: resolution.areaId,
561
560
  areaName: resolution.areaName,
562
- });
561
+ };
562
+ // Preview mode (Ctrl+hover tooltip in the terminal): return only the
563
+ // requested line window. Reading the file is cheap; shipping a 1MB body
564
+ // over the wire on every hover is not.
565
+ const previewLines = Number(req.query.previewLines);
566
+ if (Number.isFinite(previewLines) && previewLines > 0) {
567
+ const allLines = content.split('\n');
568
+ const rawOffset = Number(req.query.previewOffset);
569
+ const startLine = Number.isFinite(rawOffset) && rawOffset >= 1
570
+ ? Math.min(Math.floor(rawOffset), Math.max(allLines.length, 1))
571
+ : 1;
572
+ const slice = allLines.slice(startLine - 1, startLine - 1 + Math.floor(previewLines));
573
+ res.json({
574
+ ...base,
575
+ content: slice.join('\n'),
576
+ preview: {
577
+ startLine,
578
+ totalLines: allLines.length,
579
+ truncated: startLine - 1 + slice.length < allLines.length,
580
+ },
581
+ });
582
+ return;
583
+ }
584
+ res.json({ ...base, content });
563
585
  }
564
586
  catch (err) {
565
587
  log.error(' Failed to read file:', err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tide-commander",
3
- "version": "1.169.0",
3
+ "version": "1.171.0",
4
4
  "description": "Visual multi-agent orchestrator and manager for Claude Code with 3D/2D interface",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1 +0,0 @@
1
- import{U as a,C as n}from"./mermaid.core-8841kka_.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-V7JOEXUC-CDq9VX4u.js";import{_ as i}from"./mermaid.core-8841kka_.js";import"./chunk-5VM5RSS4-HqD1WKnr.js";import"./chunk-XXDRQBXY-Bilx42me.js";import"./chunk-VR4S4FIN-BoUv9bdH.js";import"./chunk-32BRIVSS-DPGnMNRt.js";import"./main-BgmmrYDn.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-3OKhI9bz.js";var b={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{b as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-V7JOEXUC-CDq9VX4u.js";import{_ as i}from"./mermaid.core-8841kka_.js";import"./chunk-5VM5RSS4-HqD1WKnr.js";import"./chunk-XXDRQBXY-Bilx42me.js";import"./chunk-VR4S4FIN-BoUv9bdH.js";import"./chunk-32BRIVSS-DPGnMNRt.js";import"./main-BgmmrYDn.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-3OKhI9bz.js";var b={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{b as diagram};