tide-commander 1.172.1 → 1.174.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 (110) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/assets/{BossLogsModal-QsbzN4Kf.js → BossLogsModal-CsjhF9hQ.js} +1 -1
  3. package/dist/assets/{BossSpawnModal-DhwhZLhl.js → BossSpawnModal-DRgrZpYr.js} +1 -1
  4. package/dist/assets/{ControlsModal-aMgyNfN1.js → ControlsModal-zYwhMaaL.js} +1 -1
  5. package/dist/assets/{DockerLogsModal-BrpJ3mdr.js → DockerLogsModal-D7bewBqJ.js} +1 -1
  6. package/dist/assets/{EmbeddedEditor-KJESczMw.js → EmbeddedEditor-IxYwI5JV.js} +1 -1
  7. package/dist/assets/{GmailOAuthSetup-Bqll-wNA.js → GmailOAuthSetup-CfOuUZnu.js} +1 -1
  8. package/dist/assets/{GoogleOAuthSetup-D1-QMZ0M.js → GoogleOAuthSetup-Cw1tGSti.js} +1 -1
  9. package/dist/assets/{IframeModal-DTgAWYpT.js → IframeModal-Bi8MNGZY.js} +1 -1
  10. package/dist/assets/{IntegrationsPanel-DLOLI_B7.js → IntegrationsPanel-01iVXM-l.js} +2 -2
  11. package/dist/assets/{LogViewerModal-Drfk0Oeq.js → LogViewerModal-BXhxgz7Z.js} +1 -1
  12. package/dist/assets/{MonitoringModal-DFxN1iq7.js → MonitoringModal-Gf0AkCEl.js} +1 -1
  13. package/dist/assets/{PM2LogsModal-vr3C3Iwx.js → PM2LogsModal-BfoL_mEK.js} +1 -1
  14. package/dist/assets/{RestoreArchivedAreaModal-PfH31tum.js → RestoreArchivedAreaModal-Ctss__a9.js} +1 -1
  15. package/dist/assets/{Scene2DCanvas-DNZIgKRt.js → Scene2DCanvas-BuCW0Zaw.js} +1 -1
  16. package/dist/assets/{SceneManager-CfQzjU0Q.js → SceneManager-BFnKKU1I.js} +1 -1
  17. package/dist/assets/{SkillsPanel-CXgN7qvm.js → SkillsPanel-D7kJE7eT.js} +1 -1
  18. package/dist/assets/{SlackMultiInstanceSetup-CVXwTOcN.js → SlackMultiInstanceSetup-Hp7r3YK0.js} +1 -1
  19. package/dist/assets/{SpawnModal-CKSWGTkb.js → SpawnModal-Dq9P-FdI.js} +1 -1
  20. package/dist/assets/{StatisticsModal-BXQ4U5CD.js → StatisticsModal-BQOkmrmY.js} +1 -1
  21. package/dist/assets/{SubordinateAssignmentModal-CISUQILg.js → SubordinateAssignmentModal-D2-IpRLn.js} +1 -1
  22. package/dist/assets/{TriggerManagerPanel-DFyESe24.js → TriggerManagerPanel-BCZhLuoZ.js} +1 -1
  23. package/dist/assets/{WorkflowEditorPanel-CjtpyLPe.js → WorkflowEditorPanel-BEjublaK.js} +1 -1
  24. package/dist/assets/{abnfDiagram-VRR7QNED-CMoocadP.js → abnfDiagram-VRR7QNED-jjWEEISc.js} +1 -1
  25. package/dist/assets/{arc-Dl9yOoLr.js → arc-xqT5-bwQ.js} +1 -1
  26. package/dist/assets/{architectureDiagram-ZJ3FMSHR-CAYHzwiE.js → architectureDiagram-ZJ3FMSHR-BXEbOurL.js} +1 -1
  27. package/dist/assets/{area-logos-eA9M1wr9.js → area-logos-BH-HM2a-.js} +1 -1
  28. package/dist/assets/{blockDiagram-677ZJIJ3-BiHqoF5c.js → blockDiagram-677ZJIJ3-D-0HVLDv.js} +1 -1
  29. package/dist/assets/{c4Diagram-LMCZKHZV-Dl8sifqe.js → c4Diagram-LMCZKHZV-BK39PXfT.js} +1 -1
  30. package/dist/assets/channel-BgBFpxsT.js +1 -0
  31. package/dist/assets/{chunk-2Q5K7J3B-BTlBkCAr.js → chunk-2Q5K7J3B-CuW4NYbO.js} +1 -1
  32. package/dist/assets/{chunk-32BRIVSS-CNdTOM-g.js → chunk-32BRIVSS-eJLo7W-b.js} +1 -1
  33. package/dist/assets/{chunk-5VM5RSS4-CWNk7gDz.js → chunk-5VM5RSS4-E2Yaai0b.js} +1 -1
  34. package/dist/assets/{chunk-EX3LRPZG-YFeqF_nh.js → chunk-EX3LRPZG-9uAbQnMb.js} +1 -1
  35. package/dist/assets/{chunk-JWPE2WC7-DQHe11j4.js → chunk-JWPE2WC7-kKtXyMkv.js} +1 -1
  36. package/dist/assets/{chunk-MOJQB5TN-xfSSbB52.js → chunk-MOJQB5TN-DPN5ReJ7.js} +1 -1
  37. package/dist/assets/{chunk-RYQCIY6F--sw5O4hb.js → chunk-RYQCIY6F-d3yFo4Hu.js} +1 -1
  38. package/dist/assets/{chunk-V7JOEXUC-DCISYHxl.js → chunk-V7JOEXUC--3A8oVa7.js} +1 -1
  39. package/dist/assets/{chunk-VR4S4FIN-BT-BEUKi.js → chunk-VR4S4FIN-KpHuZy9_.js} +1 -1
  40. package/dist/assets/{chunk-XXDRQBXY-BC5LBfBr.js → chunk-XXDRQBXY-hpU30gZQ.js} +1 -1
  41. package/dist/assets/classDiagram-OUVF2IWQ-CXHgnAgF.js +1 -0
  42. package/dist/assets/classDiagram-v2-EOCWNBFH-CXHgnAgF.js +1 -0
  43. package/dist/assets/{cose-bilkent-JH36ORCC-CAA9BVJw.js → cose-bilkent-JH36ORCC-DOhYmYxe.js} +1 -1
  44. package/dist/assets/{cynefin-VYW2F7L2-B1EXJM3W.js → cynefin-VYW2F7L2-UDH0NYTi.js} +1 -1
  45. package/dist/assets/{cynefinDiagram-TSTJHNR4-CVPdO2-X.js → cynefinDiagram-TSTJHNR4-DnGUiXaD.js} +1 -1
  46. package/dist/assets/{dagre-VKFMJZFB-7DQFHpL-.js → dagre-VKFMJZFB-BQ6C_GWY.js} +1 -1
  47. package/dist/assets/{diagram-FQU43EPY-BjtiDNN3.js → diagram-FQU43EPY-CREz1035.js} +1 -1
  48. package/dist/assets/{diagram-G47NLZAW-DRPq9aYV.js → diagram-G47NLZAW-9Jr7GbsE.js} +1 -1
  49. package/dist/assets/{diagram-NH7WQ7WH-CKO9hg5d.js → diagram-NH7WQ7WH-DtN5x74X.js} +1 -1
  50. package/dist/assets/{diagram-OA4YK3LP-Ra81Kti3.js → diagram-OA4YK3LP-UuOi8FAP.js} +1 -1
  51. package/dist/assets/{diagram-WEI45ONY-CITyCdct.js → diagram-WEI45ONY-CWiUGHfM.js} +1 -1
  52. package/dist/assets/{ebnfDiagram-CCIWWBDH-uCGvhl6i.js → ebnfDiagram-CCIWWBDH-3eMfQx1G.js} +1 -1
  53. package/dist/assets/{erDiagram-Q63AITRT-CMhsDfB6.js → erDiagram-Q63AITRT-DYzSgp8n.js} +1 -1
  54. package/dist/assets/{flowDiagram-23GEKE2U-Czoe88ky.js → flowDiagram-23GEKE2U-DBLDGx8O.js} +1 -1
  55. package/dist/assets/{ganttDiagram-NO4QXBWP-BGW0lkZn.js → ganttDiagram-NO4QXBWP-Dv7Uyp2U.js} +1 -1
  56. package/dist/assets/{gitGraphDiagram-IHSO6WYX-BGL5LvXP.js → gitGraphDiagram-IHSO6WYX-leeHrOrC.js} +1 -1
  57. package/dist/assets/index-Bnk8mX62.js +2 -0
  58. package/dist/assets/{index-CzZ7zgVI.js → index-BrN1fSea.js} +1 -1
  59. package/dist/assets/{index-Dc06TGsb.js → index-CFiAyn9P.js} +3 -3
  60. package/dist/assets/{index-BKPwvgsm.js → index-Cpf2LUXa.js} +1 -1
  61. package/dist/assets/{index-BH5YVgOj.js → index-CtGcfchE.js} +1 -1
  62. package/dist/assets/{index-DndPvIH3.js → index-DY2LUL1D.js} +1 -1
  63. package/dist/assets/{index-Dpe8XNlP.js → index-fP8UTiVP.js} +2 -2
  64. package/dist/assets/index-jlRDILHc.js +1 -0
  65. package/dist/assets/{index-OOltFoDp.js → index-lHF2zw41.js} +1 -1
  66. package/dist/assets/{infoDiagram-FWYZ7A6U-BNL1Wsoh.js → infoDiagram-FWYZ7A6U-B23FL64X.js} +1 -1
  67. package/dist/assets/{ishikawaDiagram-FXEZZL3T-CpH1l4dh.js → ishikawaDiagram-FXEZZL3T-BPsjNXWV.js} +1 -1
  68. package/dist/assets/{journeyDiagram-5HDEW3XC-ElYAdw-X.js → journeyDiagram-5HDEW3XC-3jqJYemY.js} +1 -1
  69. package/dist/assets/{kanban-definition-HUTT4EX6-4JmbIjZ5.js → kanban-definition-HUTT4EX6-rHfIfWqi.js} +1 -1
  70. package/dist/assets/{linear-t_5G5KTB.js → linear-CvofFTBe.js} +1 -1
  71. package/dist/assets/main-CZA5Uyu6.css +1 -0
  72. package/dist/assets/main-ts-uUN3p.js +299 -0
  73. package/dist/assets/{mermaid.core-_Iqk-m82.js → mermaid.core-BuuQCwr7.js} +4 -4
  74. package/dist/assets/{mindmap-definition-LN4V7U3C-DAVAqGxu.js → mindmap-definition-LN4V7U3C-CdMbsouS.js} +1 -1
  75. package/dist/assets/{pegDiagram-2B236MQR-C_hkJRiS.js → pegDiagram-2B236MQR-Cl7drnf-.js} +1 -1
  76. package/dist/assets/{pieDiagram-ENE6RG2P-DW4eT-Bf.js → pieDiagram-ENE6RG2P-CrfvJw6b.js} +1 -1
  77. package/dist/assets/{quadrantDiagram-ABIIQ3AL-MHlY4RX3.js → quadrantDiagram-ABIIQ3AL-D6Z7VqX6.js} +1 -1
  78. package/dist/assets/{railroadDiagram-RFXS5EU6-UOYYtczg.js → railroadDiagram-RFXS5EU6-DBhqTpwY.js} +1 -1
  79. package/dist/assets/{requirementDiagram-TGXJPOKE-CoUb4-QX.js → requirementDiagram-TGXJPOKE-DjYygiNl.js} +1 -1
  80. package/dist/assets/{sankeyDiagram-HTMAVEWB-CAo4GEMz.js → sankeyDiagram-HTMAVEWB-Cb8su5H6.js} +1 -1
  81. package/dist/assets/{sequenceDiagram-DBY2YBRQ-DV-7J7Gm.js → sequenceDiagram-DBY2YBRQ-DH326uFa.js} +1 -1
  82. package/dist/assets/{sizeCapture-X5ZJPWSS-DrrCOhEN.js → sizeCapture-X5ZJPWSS-BA-8zei3.js} +1 -1
  83. package/dist/assets/{stateDiagram-2N3HPSRC-BpsPHUha.js → stateDiagram-2N3HPSRC-DM412fD5.js} +1 -1
  84. package/dist/assets/stateDiagram-v2-6OUMAXLB-BZJwjeVk.js +1 -0
  85. package/dist/assets/{swimlanes-5IMT3BWC-BwyLQeZ3.js → swimlanes-5IMT3BWC-BouPQ02z.js} +2 -2
  86. package/dist/assets/swimlanesDiagram-G3AALYLV-BRQaNmpd.js +8 -0
  87. package/dist/assets/{timeline-definition-FHXFAJF6-CclEvbuB.js → timeline-definition-FHXFAJF6-CHbeQn6a.js} +1 -1
  88. package/dist/assets/{vennDiagram-L72KCM5P-CiL_wzh1.js → vennDiagram-L72KCM5P-HSzYjTi7.js} +1 -1
  89. package/dist/assets/{wardleyDiagram-EHGQE667-DnOymUXX.js → wardleyDiagram-EHGQE667-DvrdmzxK.js} +1 -1
  90. package/dist/assets/{web-CMuYbvNC.js → web-BvtZvOK9.js} +1 -1
  91. package/dist/assets/{web-6aER7lOr.js → web-DT7q-yw_.js} +1 -1
  92. package/dist/assets/{web-DuP_2pSe.js → web-DwD7eqxR.js} +1 -1
  93. package/dist/assets/{xychartDiagram-FW5EYKEG-C9no0HxB.js → xychartDiagram-FW5EYKEG-DgSgkHvg.js} +1 -1
  94. package/dist/build-info.json +1 -1
  95. package/dist/index.html +2 -2
  96. package/dist/src/packages/server/claude/backend.js +75 -11
  97. package/dist/src/packages/server/routes/custom-sounds.js +170 -0
  98. package/dist/src/packages/server/routes/index.js +2 -0
  99. package/dist/src/packages/server/services/runtime-events.js +29 -1
  100. package/dist/src/packages/server/websocket/handlers/command-handler.js +13 -0
  101. package/package.json +1 -1
  102. package/dist/assets/channel-Do0ikKxE.js +0 -1
  103. package/dist/assets/classDiagram-OUVF2IWQ-uk12XVRi.js +0 -1
  104. package/dist/assets/classDiagram-v2-EOCWNBFH-uk12XVRi.js +0 -1
  105. package/dist/assets/index-BA7Q2Sle.js +0 -2
  106. package/dist/assets/index-BfYC8cZK.js +0 -1
  107. package/dist/assets/main-h6n299s0.css +0 -1
  108. package/dist/assets/main-vnfQDZqc.js +0 -299
  109. package/dist/assets/stateDiagram-v2-6OUMAXLB-BXrc6Zwm.js +0 -1
  110. package/dist/assets/swimlanesDiagram-G3AALYLV-DT5BZIav.js +0 -8
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Custom Notification Sound Routes
3
+ * Upload, serve and remove user-supplied audio for each notification event.
4
+ * Stored server-side (not in the browser) so the same sounds apply on every
5
+ * device that connects to this commander.
6
+ *
7
+ * Storage: ~/.local/share/tide-commander/custom-sounds/
8
+ */
9
+ import { Router } from 'express';
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import * as os from 'os';
13
+ import { createLogger } from '../utils/logger.js';
14
+ const log = createLogger('CustomSounds');
15
+ const router = Router();
16
+ /** Events that can carry a custom sound — mirrors the client's SoundKind. */
17
+ const SOUND_EVENTS = ['question', 'notification', 'completion'];
18
+ const ALLOWED_AUDIO_TYPES = {
19
+ 'audio/mpeg': '.mp3',
20
+ 'audio/mp3': '.mp3',
21
+ 'audio/wav': '.wav',
22
+ 'audio/x-wav': '.wav',
23
+ 'audio/wave': '.wav',
24
+ 'audio/ogg': '.ogg',
25
+ 'audio/webm': '.webm',
26
+ 'audio/aac': '.aac',
27
+ 'audio/mp4': '.m4a',
28
+ };
29
+ const MIME_BY_EXT = {
30
+ '.mp3': 'audio/mpeg',
31
+ '.wav': 'audio/wav',
32
+ '.ogg': 'audio/ogg',
33
+ '.webm': 'audio/webm',
34
+ '.aac': 'audio/aac',
35
+ '.m4a': 'audio/mp4',
36
+ };
37
+ /** Notification cues are short; 5MB is generous and keeps playback instant. */
38
+ const MAX_SOUND_SIZE = 5 * 1024 * 1024;
39
+ const SOUNDS_DIR = path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local', 'share'), 'tide-commander', 'custom-sounds');
40
+ function ensureSoundsDir() {
41
+ if (!fs.existsSync(SOUNDS_DIR)) {
42
+ fs.mkdirSync(SOUNDS_DIR, { recursive: true });
43
+ }
44
+ }
45
+ function isSoundEvent(value) {
46
+ return SOUND_EVENTS.includes(value);
47
+ }
48
+ /** The stored file for an event, if any (extension varies by upload). */
49
+ function findSoundFile(event) {
50
+ ensureSoundsDir();
51
+ for (const ext of Object.keys(MIME_BY_EXT)) {
52
+ const filename = `${event}${ext}`;
53
+ if (fs.existsSync(path.join(SOUNDS_DIR, filename)))
54
+ return filename;
55
+ }
56
+ return null;
57
+ }
58
+ function removeSoundFiles(event) {
59
+ for (const ext of Object.keys(MIME_BY_EXT)) {
60
+ const filePath = path.join(SOUNDS_DIR, `${event}${ext}`);
61
+ if (fs.existsSync(filePath)) {
62
+ try {
63
+ fs.unlinkSync(filePath);
64
+ }
65
+ catch { /* best effort */ }
66
+ }
67
+ }
68
+ }
69
+ // GET /api/custom-sounds - which events have a custom sound
70
+ router.get('/', (_req, res) => {
71
+ const sounds = {};
72
+ for (const event of SOUND_EVENTS) {
73
+ const filename = findSoundFile(event);
74
+ // Cache-bust on change so a re-upload is picked up immediately.
75
+ sounds[event] = filename
76
+ ? `/api/custom-sounds/file/${filename}?v=${fs.statSync(path.join(SOUNDS_DIR, filename)).mtimeMs}`
77
+ : null;
78
+ }
79
+ res.json({ sounds });
80
+ });
81
+ // GET /api/custom-sounds/file/:filename - serve an uploaded sound
82
+ router.get('/file/:filename', (req, res) => {
83
+ try {
84
+ ensureSoundsDir();
85
+ const filename = path.basename(String(req.params.filename)); // sanitize
86
+ const filePath = path.join(SOUNDS_DIR, filename);
87
+ if (!fs.existsSync(filePath)) {
88
+ res.status(404).json({ error: 'Sound not found' });
89
+ return;
90
+ }
91
+ const ext = path.extname(filename).toLowerCase();
92
+ res.setHeader('Content-Type', MIME_BY_EXT[ext] || 'application/octet-stream');
93
+ res.setHeader('Cache-Control', 'public, max-age=31536000');
94
+ fs.createReadStream(filePath).pipe(res);
95
+ }
96
+ catch (err) {
97
+ log.error('Failed to serve custom sound:', err);
98
+ res.status(500).json({ error: err.message });
99
+ }
100
+ });
101
+ // POST /api/custom-sounds/:event - upload a sound (raw audio body)
102
+ router.post('/:event', (req, res) => {
103
+ try {
104
+ ensureSoundsDir();
105
+ const event = String(req.params.event);
106
+ if (!isSoundEvent(event)) {
107
+ res.status(400).json({ error: `Unknown event: ${event}. Allowed: ${SOUND_EVENTS.join(', ')}` });
108
+ return;
109
+ }
110
+ const contentType = (req.headers['content-type'] || '').split(';')[0].trim();
111
+ const ext = ALLOWED_AUDIO_TYPES[contentType];
112
+ if (!ext) {
113
+ res.status(400).json({
114
+ error: `Invalid audio type: ${contentType || 'none'}. Allowed: ${Object.keys(ALLOWED_AUDIO_TYPES).join(', ')}`,
115
+ });
116
+ return;
117
+ }
118
+ const chunks = [];
119
+ let totalSize = 0;
120
+ req.on('data', (chunk) => {
121
+ totalSize += chunk.length;
122
+ if (totalSize > MAX_SOUND_SIZE) {
123
+ res.status(413).json({ error: `Sound too large. Max size: ${MAX_SOUND_SIZE / 1024 / 1024}MB` });
124
+ req.destroy();
125
+ return;
126
+ }
127
+ chunks.push(chunk);
128
+ });
129
+ req.on('end', () => {
130
+ if (res.headersSent)
131
+ return; // already rejected as too large
132
+ const buffer = Buffer.concat(chunks);
133
+ if (buffer.length === 0) {
134
+ res.status(400).json({ error: 'Empty upload' });
135
+ return;
136
+ }
137
+ // One sound per event: drop any previous file (possibly a different ext).
138
+ removeSoundFiles(event);
139
+ const filename = `${event}${ext}`;
140
+ fs.writeFileSync(path.join(SOUNDS_DIR, filename), buffer);
141
+ log.log(`Uploaded custom sound for "${event}": ${filename} (${buffer.length} bytes)`);
142
+ res.json({
143
+ success: true,
144
+ event,
145
+ url: `/api/custom-sounds/file/${filename}?v=${Date.now()}`,
146
+ size: buffer.length,
147
+ });
148
+ });
149
+ req.on('error', (err) => {
150
+ log.error('Custom sound upload error:', err);
151
+ if (!res.headersSent)
152
+ res.status(500).json({ error: 'Upload failed' });
153
+ });
154
+ }
155
+ catch (err) {
156
+ log.error('Failed to upload custom sound:', err);
157
+ res.status(500).json({ error: err.message });
158
+ }
159
+ });
160
+ // DELETE /api/custom-sounds/:event - revert to the built-in synthesized cue
161
+ router.delete('/:event', (req, res) => {
162
+ const event = String(req.params.event);
163
+ if (!isSoundEvent(event)) {
164
+ res.status(400).json({ error: `Unknown event: ${event}` });
165
+ return;
166
+ }
167
+ removeSoundFiles(event);
168
+ res.json({ success: true, event });
169
+ });
170
+ export default router;
@@ -20,6 +20,7 @@ import sttRouter from './stt.js';
20
20
  import voiceAssistantRouter from './voice-assistant.js';
21
21
  import areasRouter from './areas.js';
22
22
  import customClassIconsRouter from './custom-class-icons.js';
23
+ import customSoundsRouter from './custom-sounds.js';
23
24
  import workspacesRouter from './workspaces.js';
24
25
  import perfRouter from './perf.js';
25
26
  import triggerRouter, { setBroadcast as setTriggerBroadcast } from './trigger-routes.js';
@@ -53,6 +54,7 @@ router.use('/stt', sttRouter);
53
54
  router.use('/voice-assistant', voiceAssistantRouter);
54
55
  router.use('/areas', areasRouter);
55
56
  router.use('/custom-class-icons', customClassIconsRouter);
57
+ router.use('/custom-sounds', customSoundsRouter);
56
58
  router.use('/workspaces', workspacesRouter);
57
59
  router.use('/perf', perfRouter);
58
60
  router.use('/triggers', triggerRouter);
@@ -47,6 +47,22 @@ function getDefaultContextWindow(provider) {
47
47
  return DEFAULT_GROK_CONTEXT_WINDOW;
48
48
  return DEFAULT_CLAUDE_CONTEXT_WINDOW;
49
49
  }
50
+ /** Context window tiers Claude models ship with, smallest first. */
51
+ const CLAUDE_CONTEXT_WINDOW_TIERS = [200_000, 1_000_000];
52
+ /**
53
+ * Widen a stale Claude context limit to fit an observed prompt size.
54
+ *
55
+ * A Claude usage_snapshot is the token count of a *single* request
56
+ * (cacheRead + cacheCreation + input of one assistant message), so it can
57
+ * never be a cumulative session total. If it exceeds the limit we have on
58
+ * file, the limit is what's wrong — typically because the window was learned
59
+ * from a turn where an auxiliary model was billed alongside the main one.
60
+ * Returns null when the value is beyond anything Claude offers, so the caller
61
+ * can fall back to discarding it.
62
+ */
63
+ function widenClaudeContextLimit(observedTokens) {
64
+ return CLAUDE_CONTEXT_WINDOW_TIERS.find((tier) => observedTokens <= tier) ?? null;
65
+ }
50
66
  function updateCodexRollingContextEstimate(agentId, turnGrowth) {
51
67
  const history = codexContextGrowthHistory.get(agentId) || [];
52
68
  history.push(Math.max(0, Math.round(turnGrowth)));
@@ -252,7 +268,19 @@ export function createRuntimeEventHandlers(deps) {
252
268
  if (snapshotContextUsed > 0) {
253
269
  // Grok signals also carry the authoritative window size.
254
270
  const modelWindow = event.modelUsage?.contextWindow;
255
- const effectiveLimit = Math.max(1, modelWindow || agent.contextLimit || getDefaultContextWindow(agent.provider));
271
+ let effectiveLimit = Math.max(1, modelWindow || agent.contextLimit || getDefaultContextWindow(agent.provider));
272
+ // Claude snapshots are per-request, never cumulative, so one that
273
+ // overflows the tracked window means the *window* is stale (it is
274
+ // only learned at end of turn). Widen it instead of discarding a
275
+ // good reading — the old behaviour also zeroed contextUsed, which
276
+ // is what made the meter collapse to 0k mid-conversation.
277
+ if (isClaudeProvider && snapshotContextUsed > effectiveLimit) {
278
+ const widened = widenClaudeContextLimit(snapshotContextUsed);
279
+ if (widened) {
280
+ log.log(`[usage_snapshot] ${agentId}: snapshot ${snapshotContextUsed} exceeds tracked limit ${effectiveLimit}; widening to ${widened}`);
281
+ effectiveLimit = widened;
282
+ }
283
+ }
256
284
  // Guard against cumulative session totals: if the sum exceeds the
257
285
  // context window, it can't represent per-request context fill.
258
286
  // Grok signals can report used slightly over window during compaction —
@@ -283,6 +283,19 @@ export async function handleSendCommand(ctx, payload, buildBossMessage) {
283
283
  return;
284
284
  }
285
285
  const trimmedCmd = command.trim();
286
+ // Commands handled entirely here never reach the runner, so they'd never get
287
+ // the usual `command_started` broadcast and the user's own command would
288
+ // vanish from the chat. Echo it first so every slash command the user types
289
+ // appears in history through the same path as an ordinary message.
290
+ const isInterceptedCommand = trimmedCmd === '/context'
291
+ || trimmedCmd === '/cost'
292
+ || trimmedCmd === '/clear';
293
+ if (isInterceptedCommand) {
294
+ ctx.broadcast({
295
+ type: 'command_started',
296
+ payload: { agentId, command: trimmedCmd },
297
+ });
298
+ }
286
299
  // Intercept /context and /cost for ALL agents (boss or regular) BEFORE routing.
287
300
  // The CLI /context slash command does NOT work via stdin in --print mode
288
301
  // (it gets treated as a user message). We generate stats from tracked data instead.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tide-commander",
3
- "version": "1.172.1",
3
+ "version": "1.174.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-_Iqk-m82.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-DCISYHxl.js";import{_ as i}from"./mermaid.core-_Iqk-m82.js";import"./chunk-5VM5RSS4-CWNk7gDz.js";import"./chunk-XXDRQBXY-BC5LBfBr.js";import"./chunk-VR4S4FIN-BT-BEUKi.js";import"./chunk-32BRIVSS-CNdTOM-g.js";import"./main-vnfQDZqc.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-DCISYHxl.js";import{_ as i}from"./mermaid.core-_Iqk-m82.js";import"./chunk-5VM5RSS4-CWNk7gDz.js";import"./chunk-XXDRQBXY-BC5LBfBr.js";import"./chunk-VR4S4FIN-BT-BEUKi.js";import"./chunk-32BRIVSS-CNdTOM-g.js";import"./main-vnfQDZqc.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,2 +0,0 @@
1
- import{r as s,aP as Sa,aQ as aa,K as ma,aR as pa,j as e,aS as fa,aT as Ea,u as Jt,aU as Ma,aV as Ia,aW as Ta,aX as La,aY as Pa,an as $a,ae as Da,av as ha,m as Gt,S as y,w as Vt,aZ as Zt,a_ as na,a$ as Mt,b0 as _e,b1 as Ra,s as g,_ as ga,f as xa,b2 as za,b3 as sa,b4 as ia,I as d,b5 as Oa,ay as Ba,b6 as Fa,n as ba,b7 as _a,b8 as wa,b9 as va,ba as Wa,bb as Ha,bc as Ua,ad as Ga,bd as Va,be as Xa,bf as qa,aB as Ya,aC as Ka,aD as Za,bg as Ja,bh as Qa,bi as la,X as en,R as tn,E as ra,bj as an,bk as nn,bl as sn,bm as ln,bn as rn,bo as on,bp as cn,bq as dn,br as un,bs as mn,x as pn,bt as fn,bu as hn,bv as gn,bw as xn,bx as it,by as bn,bz as _n,bA as wn,bB as vn,bC as gt,bD as jn,bE as Cn,bF as kn,bG as Nn,p as yn,q as oa,o as An}from"./main-vnfQDZqc.js";import{g as Sn}from"./area-logos-eA9M1wr9.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-3OKhI9bz.js";function En(c){const r=s.useRef(c);r.current=c,s.useEffect(()=>{if(!Sa())return;let p=null,b=!1;return aa.addListener("backButton",()=>{r.current()==="exit"&&aa.exitApp()}).then(N=>{b?N.remove():p=N}),()=>{b=!0,p&&(p.remove(),p=null)}},[])}async function Mn(c){const r=ma(),p=await fetch(`${pa()}/api/agents/${c}/terminal`,{method:"POST",headers:{Authorization:`Bearer ${r}`}});if(!p.ok){const b=await p.json().catch(()=>({}));throw new Error((b==null?void 0:b.error)||`Failed to start terminal (${p.status})`)}return p.json()}async function In(c){const r=ma();await fetch(`${pa()}/api/agents/${c}/terminal`,{method:"DELETE",headers:{Authorization:`Bearer ${r}`}})}const xt=new Map;function Tn({agentId:c}){const[r,p]=s.useState(null),[b,N]=s.useState(null);return s.useEffect(()=>{let I=!1;const E=xt.get(c);return E&&(clearTimeout(E),xt.delete(c)),p(null),N(null),Mn(c).then(A=>{I||p(A.url)}).catch(A=>{I||N(A instanceof Error?A.message:"Failed to start terminal")}),()=>{I=!0;const A=xt.get(c);A&&clearTimeout(A),xt.set(c,setTimeout(()=>{xt.delete(c),In(c)},2500))}},[c]),b?e.jsx("div",{className:"flat-classic-terminal flat-classic-terminal--message",children:e.jsx("span",{children:b})}):r?e.jsx("div",{className:"flat-classic-terminal",children:e.jsx(fa,{terminalUrl:r,visible:!0})}):e.jsx("div",{className:"flat-classic-terminal flat-classic-terminal--message",children:e.jsx("span",{children:"Attaching to interactive session…"})})}const Xt=new Map,Ln=6e4;function ca(c){return Number.isFinite(c)?Math.abs(c)>=1e3?c.toLocaleString(void 0,{maximumFractionDigits:0}):c.toLocaleString(void 0,{maximumFractionDigits:2}):String(c)}function Pn(c,r){var N,I,E;const p=[];if(!c.rateLimits)return p;if(c.provider==="claude"){const A=c,K=[{key:"fiveHour",label:r("terminal:usage.currentSession"),window:A.rateLimits.fiveHour},{key:"sevenDay",label:r("terminal:usage.currentWeekAll"),window:A.rateLimits.sevenDay},{key:"sevenDayOpus",label:r("terminal:usage.currentWeekOpus"),window:A.rateLimits.sevenDayOpus},{key:"sevenDayFable",label:r("terminal:usage.currentWeekFable"),window:A.rateLimits.sevenDayFable}];for(const v of K)(v.window||v.key==="sevenDayFable")&&p.push(v);return p}const b=c;return(N=b.rateLimits)!=null&&N.weekly&&p.push({key:"weekly",label:r("terminal:usage.weeklyLimit"),window:b.rateLimits.weekly}),(I=b.rateLimits)!=null&&I.monthly&&p.push({key:"monthly",label:r("terminal:usage.monthlyLimit"),window:b.rateLimits.monthly}),(E=b.rateLimits)!=null&&E.onDemand&&p.push({key:"onDemand",label:r("terminal:usage.onDemandLimit"),window:b.rateLimits.onDemand}),p}function $n({agentId:c,contextSummary:r}){const{t:p}=Jt(["terminal","common"]),[b,N]=s.useState(()=>{var D;return((D=Xt.get(c))==null?void 0:D.snapshot)??null}),[I,E]=s.useState(!1),[A,K]=s.useState(null),v=s.useRef(0);s.useEffect(()=>{const D=Xt.get(c);if(D&&Date.now()-D.fetchedAt<Ln){N(D.snapshot);return}const re=++v.current;E(!0),K(null),Ma(c).then(T=>{re===v.current&&(Xt.set(c,{snapshot:T,fetchedAt:Date.now()}),N(T),E(!1))}).catch(T=>{re===v.current&&(K(T.message||"Failed to load plan limits"),E(!1))})},[c]);const H=b?Pn(b,p):[];return e.jsxs("div",{className:"plan-limits-tooltip",children:[r&&e.jsx("div",{className:"plan-limits-tooltip__context",children:r}),e.jsx("div",{className:"plan-limits-tooltip__title",children:p("terminal:usage.limits")}),I&&!b&&e.jsxs("div",{className:"plan-limits-tooltip__muted",children:[p("common:status.loading"),"…"]}),!I&&A&&!b&&e.jsx("div",{className:"plan-limits-tooltip__muted",children:p("terminal:usage.limitsError",{message:A})}),H.length>0?e.jsx("div",{className:"plan-limits-tooltip__gauges",children:H.map(({key:D,label:re,window:T})=>{const Ee=T?Math.max(0,Math.min(100,T.utilization)):0,oe=Ta(Ee),ce=T!=null&&typeof T.used=="number"&&typeof T.limit=="number"&&Number.isFinite(T.used)&&Number.isFinite(T.limit);return e.jsxs("div",{className:"plan-limits-tooltip__gauge",children:[e.jsxs("div",{className:"plan-limits-tooltip__gauge-head",children:[e.jsx("span",{className:"plan-limits-tooltip__gauge-label",children:re}),e.jsx("span",{className:"plan-limits-tooltip__gauge-percent",style:{color:oe},children:p("terminal:usage.percentUsed",{percent:Math.round(Ee)})})]}),e.jsx("div",{className:"plan-limits-tooltip__bar",children:e.jsx("div",{className:"plan-limits-tooltip__bar-fill",style:{width:`${Ee}%`,background:oe}})}),e.jsxs("div",{className:"plan-limits-tooltip__reset",children:[T&&p("terminal:usage.resets",{time:Ia(T.resetsAt)}),ce&&e.jsx("span",{style:{marginLeft:8},children:p("terminal:usage.creditsUsed",{used:ca(T.used),limit:ca(T.limit)})})]})]},D)})}):b&&!I&&e.jsx("div",{className:"plan-limits-tooltip__muted",children:b.rateLimitsError?p("terminal:usage.limitsError",{message:b.rateLimitsError}):b.cliHint})]})}function Dn({agentId:c,disabled:r,contextSummary:p,children:b}){return e.jsx(Ea,{position:"top",maxWidth:320,disabled:r,className:"plan-limits-tooltip-wrapper",triggerStyle:{display:"inline-flex",alignItems:"center"},content:e.jsx($n,{agentId:c,contextSummary:p}),children:b})}const Rn=s.memo(function({className:r=""}){const{t:p}=Jt(["common"]),[b,N]=La(),I=s.useRef(null),[E,A]=s.useState(null);s.useLayoutEffect(()=>{const v=I.current;if(!v)return;const H=v.querySelector(".view-mode-toggle__btn--active");H&&A({left:H.offsetLeft,width:H.offsetWidth})},[b]);const K=s.useCallback(v=>{if(v!==b){if(typeof window<"u"&&window.dispatchEvent(new CustomEvent("tide:viewmode-switch-pressed",{detail:{mode:v}})),v==="3d"){requestAnimationFrame(()=>N(v));return}N(v)}},[b,N]);return e.jsxs("div",{className:`view-mode-toggle ${r}`,ref:I,children:[E&&e.jsx("div",{className:"view-mode-toggle__indicator",style:{left:E.left,width:E.width}}),Pa.map(v=>e.jsxs("button",{className:`view-mode-toggle__btn ${b===v?"view-mode-toggle__btn--active":""}`,onClick:()=>K(v),title:p(`common:viewMode.descriptions.${v}`),children:[e.jsxs("span",{className:"view-mode-toggle__icon",children:[v==="2d"&&e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}),e.jsx("line",{x1:"3",y1:"12",x2:"21",y2:"12"}),e.jsx("line",{x1:"12",y1:"3",x2:"12",y2:"21"})]}),v==="3d"&&e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("path",{d:"M12 2L2 7l10 5 10-5-10-5z"}),e.jsx("path",{d:"M2 17l10 5 10-5"}),e.jsx("path",{d:"M2 12l10 5 10-5"})]}),v==="flat"&&e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("rect",{x:"3",y:"3",width:"8",height:"8",rx:"1"}),e.jsx("rect",{x:"13",y:"3",width:"8",height:"8",rx:"1"}),e.jsx("rect",{x:"3",y:"13",width:"8",height:"8",rx:"1"}),e.jsx("rect",{x:"13",y:"13",width:"8",height:"8",rx:"1"})]}),v==="dashboard"&&e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("rect",{x:"3",y:"3",width:"7",height:"9",rx:"1"}),e.jsx("rect",{x:"14",y:"3",width:"7",height:"5",rx:"1"}),e.jsx("rect",{x:"14",y:"12",width:"7",height:"9",rx:"1"}),e.jsx("rect",{x:"3",y:"16",width:"7",height:"5",rx:"1"})]})]}),e.jsx("span",{className:"view-mode-toggle__label",children:p(`common:viewMode.labels.${v}`)})]},v))]})}),It=3,Tt=280,da=320,qt=240,ua=64,zn=["simple","chat","advanced"],On={simple:"Simple",chat:"Chat",advanced:"Advanced"},Bn={simple:"○",chat:"◐",advanced:"◉"},Fn={simple:"Simple view — clean messages only",chat:"Chat view — assistant replies (no tool calls)",advanced:"Advanced view — everything including tools"},Yt="flat-clear-context",ja="tide:flat-embedded-panels";function Ca(){try{const c=localStorage.getItem(ja),r=c?JSON.parse(c):{};return r&&typeof r=="object"?r:{}}catch{return{}}}function Kt(c,r){try{const p=Ca();r?p[c]=r:delete p[c],localStorage.setItem(ja,JSON.stringify(p))}catch{}}function Wn(c){const r=c.split("/").filter(Boolean);return r.length===0?c:r.slice(-2).join("/")}function Hn(c){if(c.provider==="codex"){const I=c.codexModel||"gpt-5.6-luna",E=yn[I];return{model:(E==null?void 0:E.label)||I}}if(c.provider==="opencode")return{model:c.opencodeModel||"opencode"};if(c.provider==="grok"){const I=c.grokModel||"grok-4.5",E=c.effort,A=E?oa[E]:void 0;return{model:I,effort:A==null?void 0:A.label}}const r=c.model||"sonnet",p=An[r],b=c.effort,N=b?oa[b]:void 0;return{model:(p==null?void 0:p.label)||r,effort:N==null?void 0:N.label}}function Un(c,r){if(r.type==="rectangle"&&r.width&&r.height){const p=r.width/2,b=r.height/2;return c.x>=r.center.x-p&&c.x<=r.center.x+p&&c.z>=r.center.z-b&&c.z<=r.center.z+b}if(r.type==="circle"&&r.radius){const p=c.x-r.center.x,b=c.z-r.center.z;return p*p+b*b<=r.radius*r.radius}return!1}const Gn=tn.memo(function({agentId:r,terminalViewMode:p,onTerminalViewModeChange:b,inspectorOpen:N,onToggleInspector:I,onShowTaskBoard:E,onImageClick:A,onFileClick:K,onBashClick:v,onViewMarkdown:H,onRequestClearSubordinates:D,keyboard:re,canNavigateBack:T,canNavigateForward:Ee,onNavigateBack:oe,onNavigateForward:ce,agentInfoOpen:Oe,onToggleAgentInfo:bt,onHeaderContextMenu:we,onBuildingContextMenu:ve}){var Nt,yt;const u=ra(r),R=xa(),Me=an(),Ie=s.useRef(null),Ze=s.useRef(null),{displayedAgentId:Te,fadingOut:Lt}=nn(r),_t=ra(Te),Je=!!Me.interactiveMode&&((u==null?void 0:u.provider)??"claude")==="claude"&&!!(u!=null&&u.sessionId),[de,Qe]=s.useState(!1),[Be,ue]=s.useState(!1),$=s.useCallback(()=>ue(!1),[]);ha("flat-chat-actions",Be,$),s.useEffect(()=>{const a=()=>ue(o=>!o);return window.addEventListener("tide:toggle-chat-actions",a),()=>window.removeEventListener("tide:toggle-chat-actions",a)},[]),s.useEffect(()=>{Qe(!1),ue(!1)},[r]),s.useEffect(()=>{!Je&&de&&Qe(!1)},[Je,de]),s.useEffect(()=>{const a=Ze.current;if(!a)return;const o=m=>{m.button===3?(m.preventDefault(),m.stopPropagation(),oe()):m.button===4&&(m.preventDefault(),m.stopPropagation(),ce())},i=m=>{(m.button===3||m.button===4)&&m.preventDefault()};return a.addEventListener("mouseup",o),a.addEventListener("mousedown",i),()=>{a.removeEventListener("mouseup",o),a.removeEventListener("mousedown",i)}},[oe,ce]),s.useEffect(()=>{const a=Ze.current;if(!a)return;let o=0,i=0,m=0;const X=250,Q=600,L=80,st=1.5,ae=ne=>{let U=ne instanceof HTMLElement?ne:null;for(;U&&U!==a;){const At=window.getComputedStyle(U).overflowX;if((At==="auto"||At==="scroll")&&U.scrollWidth>U.clientWidth)return!0;U=U.parentElement}return!1},Ye=ne=>{const U=Date.now();if(U<m){ne.preventDefault();return}if(Math.abs(ne.deltaX)<=Math.abs(ne.deltaY)*st){o=0;return}if(ae(ne.target)){o=0;return}U-i>X&&(o=0),i=U,o+=ne.deltaX,o<=-L?(o=0,m=U+Q,ne.preventDefault(),oe()):o>=L&&(o=0,m=U+Q,ne.preventDefault(),ce())};return a.addEventListener("wheel",Ye,{passive:!1}),()=>a.removeEventListener("wheel",Ye)},[oe,ce]);const me=ga(),lt=s.useMemo(()=>{if(!u)return null;const a=new Set,o=[];for(const i of me.values())i.archived||i.directories.length===0||i.assignedAgentIds.includes(r)&&(a.add(i.id),o.push(i));for(const i of me.values())i.archived||i.directories.length===0||a.has(i.id)||Un({x:u.position.x,z:u.position.z},i)&&(a.add(i.id),o.push(i));return o.length===0?null:o.flatMap(i=>i.directories.filter(m=>m&&m.trim().length>0).map(m=>({areaId:i.id,areaName:i.name,dir:m})))},[u,r,me]),{branches:wt,fetchRemote:Fe,fetchingDirs:Le}=sn(lt),pe=s.useMemo(()=>{var i;const a=g.getAreaForAgent(r);if(!a)return[];const o=[];for(const m of R.values())m.type==="terminal"&&g.isPositionInArea(m.position,a)&&o.push({id:m.id,name:m.name,hasUrl:!!((i=m.terminalStatus)!=null&&i.url)});return o},[r,R]),je=s.useMemo(()=>{var i;const a=g.getAreaForAgent(r);if(!a)return[];const o=[];for(const m of R.values())m.type==="server"&&((i=m.pm2)!=null&&i.enabled)&&g.isPositionInArea(m.position,a)&&o.push({id:m.id,name:m.name});return o},[r,R]),Z=s.useMemo(()=>{const a=g.getAreaForAgent(r);if(!a)return[];const o=[];for(const i of R.values())i.type==="database"&&i.database&&g.isPositionInArea(i.position,a)&&o.push({id:i.id,name:i.name});return o},[r,R]),We=ln(),se=s.useMemo(()=>{const a=g.getAreaForAgent(r);if(!a)return[];const o=[];for(const i of R.values())if(i.type==="tests"&&g.isPositionInArea(i.position,a)){const m=!!i.folderPath&&We.some(X=>rn(X,i.folderPath));o.push({id:i.id,name:i.name,working:m})}return o},[r,R,We]),ie=s.useMemo(()=>{const a=g.getAreaForAgent(r);if(!a)return[];const o=[];for(const i of R.values())i.type==="http"&&g.isPositionInArea(i.position,a)&&o.push({id:i.id,name:i.name});return o},[r,R]),[,Pt]=s.useReducer(a=>a+1,0),Ce=((Nt=Ie.current)==null?void 0:Nt.search.searchMode)??!1,rt=s.useCallback(()=>{var a;(a=Ie.current)==null||a.search.toggleSearch(),Pt()},[]),Pe=on(),$e=Pe.isPending(Yt),[j,te]=s.useState(null),J=j?R.get(j.buildingId):null,[He,De]=s.useState(""),[Ue,$t]=s.useState(()=>cn()),z=s.useMemo(()=>{var a;return((a=g.getAreaForAgent(r))==null?void 0:a.id)??null},[r,R]),Ge=s.useCallback((a,o)=>{De(""),te(i=>{const m=(i==null?void 0:i.buildingId)===o?null:{type:a,buildingId:o};return z&&Kt(z,m),m})},[z]),ke=s.useCallback(()=>{De(""),te(null),z&&Kt(z,null)},[z]);s.useEffect(()=>{if((j==null?void 0:j.type)!=="pm2-logs")return;const a=j.buildingId;return g.startLogStreaming(a,200),()=>g.stopLogStreaming(a)},[j]);const{height:Dt,onResizeStart:Rt}=dn(),{sidePanelWidth:zt,handleSidePanelResizeStart:ot}=un(),[w,vt]=s.useState(()=>Zt(y.GIT_PANEL_OPEN,!1)),[Re,fe]=s.useState(()=>Zt(y.BUILDINGS_PANEL_OPEN,!1)),[O,Ve]=s.useState(!1),ct=s.useCallback(()=>{Ve(a=>{const o=!a;return o&&mn.setEnabled(!0),o})},[]),Ot=s.useCallback(()=>Ve(!1),[]),jt=s.useCallback(()=>{vt(a=>{const o=!a;return _e(y.GIT_PANEL_OPEN,o),o})},[]),Ct=s.useCallback(()=>{fe(a=>{const o=!a;return _e(y.BUILDINGS_PANEL_OPEN,o),o})},[]),Bt=s.useCallback(()=>{vt(!1),_e(y.GIT_PANEL_OPEN,!1)},[]),dt=s.useCallback(()=>{fe(!1),_e(y.BUILDINGS_PANEL_OPEN,!1)},[]),Xe=pn(),he=s.useMemo(()=>({terminal:pe,"pm2-logs":je,database:Z,tests:se,http:ie}),[pe,je,Z,se,ie]);s.useEffect(()=>{if(!j)return;he[j.type].some(o=>o.id===j.buildingId)||(De(""),te(null))},[j,he]);const Ne=s.useRef(void 0);s.useEffect(()=>{var o;if(Ne.current===z)return;Ne.current=z;const a=z?Ca()[z]:void 0;De(""),a&&((o=he[a.type])!=null&&o.some(i=>i.id===a.buildingId))?te(a):te(null)},[z,he]),s.useEffect(()=>{const a=o=>{var X;const i=o.detail;if(!(i!=null&&i.buildingId)||!(i!=null&&i.type)||!((X=he[i.type])!=null&&X.some(Q=>Q.id===i.buildingId)))return;i.handled=!0,De("");const m={type:i.type,buildingId:i.buildingId};te(m),z&&Kt(z,m)};return window.addEventListener("tide:dock-building-flat",a),()=>window.removeEventListener("tide:dock-building-flat",a)},[he,z]);const[qe,B]=s.useState(!1),ge=s.useRef(null);if(s.useEffect(()=>{if(!qe)return;const a=o=>{ge.current&&!ge.current.contains(o.target)&&B(!1)};return document.addEventListener("mousedown",a),()=>document.removeEventListener("mousedown",a)},[qe]),!u)return e.jsx("div",{className:"flat-chat flat-chat--empty",children:e.jsxs("div",{className:"flat-chat__placeholder",children:[e.jsx("span",{className:"flat-chat__placeholder-icon",children:"💬"}),e.jsx("span",{className:"flat-chat__placeholder-text",children:"Select an agent to start chatting"})]})});const ye=u.contextStats,ut=!!ye,et=ye?ye.totalTokens:u.contextUsed||0,mt=ye?ye.contextWindow:u.contextLimit||(u.provider==="grok"?5e5:2e5),Ft=ye?ye.usedPercent:Math.round(et/mt*100),ze=Math.max(0,Math.min(100,Ft)),kt=Math.round(ze*10)/10,xe=Math.round((100-ze)*10)/10,tt=ze>=80?"#ff4a4a":ze>=60?"#ff9e4a":ze>=40?"#ffd700":"#4aff9e",at=(et/1e3).toFixed(1),pt=(mt/1e3).toFixed(1),be=u.cwd,ft=be?Wn(be):null,Ae=((yt=u.subordinateIds)==null?void 0:yt.length)||0,nt=Ae>0;return e.jsxs("div",{ref:Ze,className:`flat-terminal-wrapper ${w||Re||O?"flat-terminal-wrapper--with-side-panel":""} ${Lt?"pane-fading-out":""}`,style:{"--guake-side-panel-width":`min(${zt}px, 70%)`},children:[e.jsxs("div",{className:"flat-terminal-wrapper__header",children:[e.jsxs("button",{type:"button",className:`flat-terminal-wrapper__header-main ${Oe?"flat-terminal-wrapper__header-main--active":""}`,onClick:bt,onContextMenu:a=>{a.preventDefault(),a.stopPropagation(),we({x:a.clientX,y:a.clientY})},title:Oe?"Hide agent info":"Show agent info","aria-pressed":Oe,children:[e.jsx("span",{className:`flat-terminal-wrapper__header-avatar${u.status==="working"?" is-working":""}`,children:e.jsx(ba,{agent:u,size:28})}),e.jsxs("span",{className:"flat-terminal-wrapper__header-info",children:[e.jsx("span",{className:"flat-terminal-wrapper__header-name",children:u.name}),e.jsx("span",{className:"flat-terminal-wrapper__header-status",style:{color:va(u.status)},title:u.status==="error"&&u.lastError?u.lastError:void 0,children:u.status})]}),u.taskLabel&&e.jsxs("span",{className:"flat-terminal-wrapper__header-task",title:u.taskLabel,children:["📋 ",u.taskLabel]}),e.jsxs("span",{className:"flat-terminal-wrapper__header-model",children:[e.jsx("img",{src:wa(u.provider,"/"),alt:u.provider,className:"flat-terminal-wrapper__header-provider-icon",title:_a(u.provider)}),(()=>{const{model:a,effort:o}=Hn(u);return e.jsxs("span",{className:"flat-terminal-wrapper__header-model-chip",title:o?`Model: ${a} · Effort: ${o}`:`Model: ${a}`,children:[e.jsx("span",{className:"flat-terminal-wrapper__header-model-name",children:a}),o&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"flat-terminal-wrapper__header-model-sep","aria-hidden":"true",children:"·"}),e.jsx("span",{className:"flat-terminal-wrapper__header-model-effort",children:o})]})]})})()]})]}),e.jsxs("div",{className:"flat-terminal-wrapper__header-meta",children:[e.jsxs("div",{className:"flat-terminal-wrapper__view-mode",role:"group","aria-label":"Message view mode",children:[zn.map(a=>e.jsxs("button",{type:"button",className:`flat-terminal-wrapper__view-mode-btn ${!de&&p===a?"flat-terminal-wrapper__view-mode-btn--active":""}`,onClick:()=>{Qe(!1),b(a)},title:Fn[a],"aria-pressed":!de&&p===a,children:[e.jsx("span",{className:"flat-terminal-wrapper__view-mode-icon","aria-hidden":"true",children:Bn[a]}),e.jsx("span",{className:"flat-terminal-wrapper__view-mode-label",children:On[a]})]},a)),Je&&e.jsxs("button",{type:"button",className:`flat-terminal-wrapper__view-mode-btn ${de?"flat-terminal-wrapper__view-mode-btn--active":""}`,onClick:()=>Qe(a=>!a),title:"Classic TUI — attach to the live interactive claude session in a terminal","aria-pressed":de,children:[e.jsx("span",{className:"flat-terminal-wrapper__view-mode-icon","aria-hidden":"true",children:e.jsx(d,{name:"terminal",size:13})}),e.jsx("span",{className:"flat-terminal-wrapper__view-mode-label",children:"Classic TUI"})]})]}),e.jsxs("div",{className:"flat-terminal-wrapper__actions",role:"group","aria-label":"Terminal actions",children:[e.jsx("button",{type:"button",className:"flat-terminal-wrapper__action-btn",onClick:oe,disabled:!T,title:"Back to previous agent","aria-label":"Back to previous agent",children:e.jsx(d,{name:"arrow-left",size:14})}),e.jsx("button",{type:"button",className:"flat-terminal-wrapper__action-btn",onClick:ce,disabled:!Ee,title:"Forward to next agent","aria-label":"Forward to next agent",children:e.jsx(d,{name:"arrow-right",size:14})}),e.jsx("button",{type:"button",className:`flat-terminal-wrapper__action-btn ${Ce?"flat-terminal-wrapper__action-btn--active":""}`,onClick:rt,title:Ce?"Close search":"Search messages","aria-pressed":Ce,children:e.jsx(d,{name:Ce?"cross":"search",size:14})}),e.jsx("button",{type:"button",className:`flat-terminal-wrapper__action-btn flat-terminal-wrapper__action-btn--danger ${$e?"flat-terminal-wrapper__action-btn--confirm":""}`,onClick:()=>Pe.handleClick(Yt,()=>{var a;g.clearContext(r),(a=Ie.current)==null||a.historyLoader.clearHistory()}),title:$e?"Click again to confirm clear context":"Clear context",children:e.jsx(d,{name:$e?"question":"clear",size:14})}),e.jsx("button",{type:"button",className:`flat-terminal-wrapper__action-btn ${w?"flat-terminal-wrapper__action-btn--active":""}`,onClick:jt,title:w?"Hide git panel":"Show git changes","aria-pressed":w,children:e.jsx(d,{name:"git-branch",size:14})}),e.jsx("button",{type:"button",className:`flat-terminal-wrapper__action-btn ${Re?"flat-terminal-wrapper__action-btn--active":""}`,onClick:Ct,title:Re?"Hide buildings panel":"Show area buildings","aria-pressed":Re,children:e.jsx(d,{name:"buildings",size:14})}),e.jsxs("div",{className:"flat-terminal-wrapper__more",ref:ge,children:[e.jsx("button",{type:"button",className:`flat-terminal-wrapper__action-btn ${qe?"flat-terminal-wrapper__action-btn--active":""}`,onClick:()=>B(a=>!a),title:"More actions","aria-expanded":qe,children:"⋮"}),qe&&e.jsxs("div",{className:"flat-terminal-wrapper__more-menu",role:"menu",children:[e.jsxs("button",{type:"button",role:"menuitem",className:`flat-terminal-wrapper__more-item ${O?"flat-terminal-wrapper__more-item--active":""}`,onClick:()=>{ct(),B(!1)},title:O?"Hide Debug Panel":"Show Debug Panel",children:[e.jsx(d,{name:"bug",size:14}),e.jsx("span",{children:O?"Hide Debug Panel":"Show Debug Panel"})]}),e.jsx("div",{className:"flat-terminal-wrapper__more-divider"}),e.jsxs("button",{type:"button",role:"menuitem",className:"flat-terminal-wrapper__more-item",onClick:()=>{g.collapseContext(r),B(!1)},disabled:u.status!=="idle",title:u.status!=="idle"?"Agent must be idle to collapse context":"Collapse context",children:[e.jsx(d,{name:"package",size:14}),e.jsx("span",{children:"Collapse context"})]}),nt&&e.jsxs("button",{type:"button",role:"menuitem",className:"flat-terminal-wrapper__more-item flat-terminal-wrapper__more-item--danger",onClick:()=>{D(r,Ae),B(!1)},children:[e.jsx(d,{name:"crown",size:14}),e.jsxs("span",{children:["Clear ",Ae," subordinate",Ae===1?"":"s"]})]}),e.jsx("div",{className:"flat-terminal-wrapper__more-divider"}),e.jsxs("button",{type:"button",role:"menuitem",className:"flat-terminal-wrapper__more-item flat-terminal-wrapper__more-item--danger",onClick:()=>{g.killAgent(r),B(!1)},children:[e.jsx(d,{name:"cross",size:14}),e.jsx("span",{children:"Remove agent"})]})]})]})]}),e.jsxs("button",{type:"button",className:`flat-terminal-wrapper__inspector-toggle ${N?"flat-terminal-wrapper__inspector-toggle--active":""}`,onClick:I,title:N?"Hide inspector panel":"Show inspector panel","aria-label":N?"Hide inspector panel":"Show inspector panel","aria-pressed":N,children:[e.jsx("span",{className:"flat-terminal-wrapper__inspector-icon","aria-hidden":"true",children:e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"1.5",y:"2.5",width:"13",height:"11",rx:"1.5"}),e.jsx("line",{x1:"10",y1:"2.5",x2:"10",y2:"13.5"})]})}),e.jsx("span",{className:"flat-terminal-wrapper__inspector-label",children:"Inspector"})]}),e.jsx("button",{type:"button",className:"flat-terminal-wrapper__close",onClick:()=>g.deselectAll(),title:"Close chat","aria-label":"Close chat",children:e.jsx(d,{name:"cross",size:14})})]})]}),Be&&e.jsxs("div",{className:"flat-chat-actions-sheet-root",role:"presentation",children:[e.jsx("div",{className:"flat-chat-actions-sheet__backdrop",onClick:$}),e.jsxs("div",{className:"flat-chat-actions-sheet",role:"menu","aria-label":"Chat actions",children:[e.jsx("div",{className:"flat-chat-actions-sheet__grabber","aria-hidden":"true"}),e.jsxs("div",{className:"flat-chat-actions-sheet__title-row",children:[e.jsx("span",{className:"flat-chat-actions-sheet__title",children:u.name}),e.jsx("button",{type:"button",className:"flat-chat-actions-sheet__done",onClick:$,children:"Done"})]}),e.jsxs("div",{className:"flat-chat-actions-sheet__grid",children:[e.jsxs("button",{type:"button",role:"menuitem",className:`flat-chat-actions-sheet__item ${Ce?"is-active":""}`,onClick:()=>{rt(),$()},children:[e.jsx(d,{name:Ce?"cross":"search",size:20}),e.jsx("span",{children:Ce?"Close search":"Search"})]}),e.jsxs("button",{type:"button",role:"menuitem",className:`flat-chat-actions-sheet__item ${w?"is-active":""}`,onClick:()=>{jt(),$()},children:[e.jsx(d,{name:"git-branch",size:20}),e.jsx("span",{children:"Git changes"})]}),e.jsxs("button",{type:"button",role:"menuitem",className:`flat-chat-actions-sheet__item ${Re?"is-active":""}`,onClick:()=>{Ct(),$()},children:[e.jsx(d,{name:"buildings",size:20}),e.jsx("span",{children:"Buildings"})]}),e.jsxs("button",{type:"button",role:"menuitem",className:`flat-chat-actions-sheet__item ${O?"is-active":""}`,onClick:()=>{ct(),$()},children:[e.jsx(d,{name:"bug",size:20}),e.jsx("span",{children:"Debug"})]})]}),e.jsxs("div",{className:"flat-chat-actions-sheet__list",children:[e.jsxs("button",{type:"button",role:"menuitem",className:`flat-chat-actions-sheet__row flat-chat-actions-sheet__row--danger ${$e?"is-armed":""}`,onClick:()=>Pe.handleClick(Yt,()=>{var a;g.clearContext(r),(a=Ie.current)==null||a.historyLoader.clearHistory(),$()}),children:[e.jsx(d,{name:$e?"question":"clear",size:18}),e.jsx("span",{children:$e?"Tap again to confirm clear":"Clear context"})]}),e.jsxs("button",{type:"button",role:"menuitem",className:"flat-chat-actions-sheet__row",disabled:u.status!=="idle",onClick:()=>{g.collapseContext(r),$()},children:[e.jsx(d,{name:"package",size:18}),e.jsx("span",{children:"Collapse context"})]}),nt&&e.jsxs("button",{type:"button",role:"menuitem",className:"flat-chat-actions-sheet__row flat-chat-actions-sheet__row--danger",onClick:()=>{D(r,Ae),$()},children:[e.jsx(d,{name:"crown",size:18}),e.jsxs("span",{children:["Clear ",Ae," subordinate",Ae===1?"":"s"]})]}),e.jsxs("button",{type:"button",role:"menuitem",className:"flat-chat-actions-sheet__row flat-chat-actions-sheet__row--danger",onClick:()=>{g.killAgent(r),$()},children:[e.jsx(d,{name:"cross",size:18}),e.jsx("span",{children:"Remove agent"})]})]})]})]}),e.jsx(fn,{agent:u,onClick:E}),de&&Je?e.jsx(Tn,{agentId:r}):Te&&_t?e.jsx(hn,{ref:Ie,agentId:Te,agent:_t,viewMode:p,isOpen:!0,onImageClick:A,onFileClick:K,onBashClick:v,onViewMarkdown:H,keyboard:re,hasModalOpen:!1},Te):null,j&&J&&(()=>{var X,Q;const a=j.type,o={terminal:"terminal","pm2-logs":"scroll",database:"hard-drives",tests:"flask",http:"globe"},i=a==="terminal"&&!((X=J.terminalStatus)!=null&&X.url),m=!i;return e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"guake-bottom-terminal-resize",onMouseDown:Rt,role:"separator","aria-orientation":"horizontal","aria-label":"Resize embedded panel"}),e.jsxs("div",{className:"flat-bottom-panel",role:"region","aria-label":`${J.name} panel`,style:{height:Dt},children:[e.jsxs("div",{className:"flat-bottom-panel__header",children:[e.jsxs("span",{className:"flat-bottom-panel__title",children:[e.jsx(d,{name:o[a],size:12}),e.jsx("span",{children:J.name}),i&&e.jsx("span",{className:"flat-bottom-panel__muted",children:"(starting...)"})]}),e.jsxs("span",{className:"flat-bottom-panel__header-actions",children:[a==="pm2-logs"&&e.jsxs(e.Fragment,{children:[e.jsx("input",{type:"text",className:"guake-bottom-terminal-filter",value:He,onChange:L=>De(L.target.value),placeholder:"Filter logs","aria-label":`Filter logs for ${J.name}`,spellCheck:!1}),e.jsx("select",{className:"guake-bottom-terminal-retention",value:Ue===null?"unlimited":String(Ue),onChange:L=>{const st=L.target.value==="unlimited"?null:Number(L.target.value);$t(st),xn(st)},"aria-label":`Max log retention for ${J.name}`,children:gn.map(L=>e.jsx("option",{value:L===null?"unlimited":String(L),children:L===null?"Unlimited":`${L.toLocaleString()} lines`},L===null?"unlimited":L))}),e.jsx("button",{type:"button",className:"flat-bottom-panel__close",onClick:()=>g.clearStreamingLogs(j.buildingId),title:"Clear logs",children:e.jsx(d,{name:"trash",size:12})}),e.jsx("button",{type:"button",className:"flat-bottom-panel__close",onClick:()=>g.sendBuildingCommand(j.buildingId,"restart"),title:"Restart",children:e.jsx(d,{name:"restart",size:12})})]}),m&&e.jsx("button",{type:"button",className:"flat-bottom-panel__close",onClick:()=>{ke(),it(j.buildingId)},title:"Maximize — open as modal","aria-label":"Open as modal",children:e.jsx(d,{name:"fullscreen",size:12})}),e.jsx("button",{type:"button",className:"flat-bottom-panel__close",onClick:ke,title:"Close panel","aria-label":"Close panel",children:e.jsx(d,{name:"cross",size:12})})]})]}),e.jsx("div",{className:"flat-bottom-panel__body",children:a==="terminal"?(Q=J.terminalStatus)!=null&&Q.url?e.jsx(fa,{terminalUrl:J.terminalStatus.url,visible:!0}):e.jsx("div",{className:"flat-bottom-panel__placeholder",children:"Starting terminal..."}):a==="pm2-logs"?e.jsx(bn,{buildingId:j.buildingId,filterText:He,maxRetention:Ue}):a==="database"?e.jsx(_n,{building:J}):a==="tests"?e.jsx("div",{className:"tests-panel-host",children:e.jsx(wn,{building:J,autoFocusSearch:!1})}):e.jsx("div",{className:"http-requests-panel-host",children:e.jsx(vn,{building:J,autoFocusSearch:!1})})})]})]})})(),e.jsxs("div",{className:"flat-terminal-wrapper__statusbar",role:"contentinfo",children:[u.isDetached&&e.jsxs("span",{className:"flat-terminal-wrapper__detached",title:"Reattaching session...",children:[e.jsx(d,{name:"refresh",size:12}),e.jsx("span",{children:"Reattaching"})]}),be&&ft&&e.jsxs("span",{className:"flat-terminal-wrapper__cwd",title:`Open in file explorer: ${be}`,"aria-label":`Open ${be} in file explorer`,role:"button",tabIndex:0,onClick:()=>g.openFileExplorer(be),onKeyDown:a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),g.openFileExplorer(be))},children:[e.jsx("span",{className:"flat-terminal-wrapper__cwd-icon",children:e.jsx(d,{name:"folder",size:12})}),e.jsx("span",{className:"flat-terminal-wrapper__cwd-text",children:ft})]}),lt&&lt.map(({areaId:a,areaName:o,dir:i})=>{const m=wt.get(i),X=Le.has(i),Q=i.split("/").filter(Boolean).pop()||i;return e.jsxs("span",{className:"flat-terminal-wrapper__area-dir",title:`${o}: ${i}${m?` (${m.branch}${m.ahead?` ↑${m.ahead}`:""}${m.behind?` ↓${m.behind}`:""})`:""}`,onClick:()=>g.openFileExplorerForAreaFolder(a,i),children:[e.jsx(d,{name:"folder-open",size:12}),e.jsx("span",{className:"flat-terminal-wrapper__area-dir-name",children:Q}),m&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"flat-terminal-wrapper__area-dir-branch",children:[e.jsx(d,{name:"git-branch",size:10})," ",m.branch]}),m.ahead>0&&e.jsxs("span",{className:"flat-terminal-wrapper__branch-ahead",title:`${m.ahead} ahead`,children:[e.jsx(d,{name:"arrow-up",size:9}),m.ahead]}),m.behind>0&&e.jsxs("span",{className:"flat-terminal-wrapper__branch-behind",title:`${m.behind} behind`,children:[e.jsx(d,{name:"arrow-down",size:9}),m.behind]}),e.jsx("span",{className:`flat-terminal-wrapper__area-fetch ${X?"flat-terminal-wrapper__area-fetch--fetching":""}`,title:"Git fetch",onClick:L=>{L.stopPropagation(),Fe(i)},children:e.jsx(d,{name:X?"hourglass":"download",size:12})})]})]},`${a}:${i}`)}),e.jsx(Dn,{agentId:r,disabled:((u==null?void 0:u.provider)??"claude")!=="claude"&&((u==null?void 0:u.provider)??"claude")!=="grok",contextSummary:ut?`Context: ${at}k / ${pt}k tokens (${kt}% used)`:void 0,children:e.jsxs("span",{className:"flat-terminal-wrapper__context",tabIndex:0,role:"button",onClick:()=>g.setContextModalAgentId(r),onKeyDown:a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),g.setContextModalAgentId(r))},title:((u==null?void 0:u.provider)??"claude")!=="claude"&&((u==null?void 0:u.provider)??"claude")!=="grok"?ut?`Context usage: ${at}k / ${pt}k tokens (${kt}% used). Click to view stats.`:"Click to fetch context stats":void 0,children:[e.jsx("span",{className:"flat-terminal-wrapper__context-icon",children:e.jsx(d,{name:"dashboard",size:12})}),e.jsx("span",{className:"flat-terminal-wrapper__context-label",children:"Ctx:"}),e.jsx("span",{className:"flat-terminal-wrapper__context-bar",children:e.jsx("span",{className:"flat-terminal-wrapper__context-bar-fill",style:{width:`${ze}%`,backgroundColor:tt}})}),e.jsxs("span",{className:"flat-terminal-wrapper__context-tokens",style:{color:tt},children:[at,"k/",pt,"k"]}),e.jsxs("span",{className:"flat-terminal-wrapper__context-free",children:["(",xe,"% free)"]}),!ut&&e.jsx("span",{className:"flat-terminal-wrapper__context-warning",title:"No context stats yet",children:e.jsx(d,{name:"warn",size:12})})]})}),e.jsx("div",{className:"flat-terminal-wrapper__statusbar-spacer","aria-hidden":"true"}),pe.length>0&&e.jsx("span",{className:"flat-terminal-wrapper__buildings",role:"group","aria-label":"Area terminals",children:pe.map(a=>{const o=(j==null?void 0:j.buildingId)===a.id;return e.jsx("button",{type:"button",className:`flat-terminal-wrapper__building-btn ${o?"flat-terminal-wrapper__building-btn--active":""} ${a.hasUrl?"":"flat-terminal-wrapper__building-btn--offline"}`,title:`${o?"Hide":"Show"} terminal: ${a.name}${a.hasUrl?"":" (starting...)"}`,onClick:()=>{if(o){ke();return}if(a.hasUrl&&gt(a.id)==="modal"){it(a.id);return}a.hasUrl||g.sendBuildingCommand(a.id,"start"),Ge("terminal",a.id)},onContextMenu:i=>{i.preventDefault(),i.stopPropagation(),ve(a.id,{x:i.clientX,y:i.clientY})},children:e.jsx(d,{name:"terminal",size:14})},a.id)})}),je.length>0&&e.jsx("span",{className:"flat-terminal-wrapper__buildings",role:"group","aria-label":"Area PM2 logs",children:je.map(a=>{const o=(j==null?void 0:j.buildingId)===a.id;return e.jsx("button",{type:"button",className:`flat-terminal-wrapper__building-btn ${o?"flat-terminal-wrapper__building-btn--active":""}`,title:`${o?"Hide":"Show"} logs: ${a.name}`,onClick:()=>{o?ke():gt(a.id)==="modal"?it(a.id):Ge("pm2-logs",a.id)},onContextMenu:i=>{i.preventDefault(),i.stopPropagation(),ve(a.id,{x:i.clientX,y:i.clientY})},children:e.jsx(d,{name:"scroll",size:14})},a.id)})}),Z.length>0&&e.jsx("span",{className:"flat-terminal-wrapper__buildings",role:"group","aria-label":"Area databases",children:Z.map(a=>{const o=(j==null?void 0:j.buildingId)===a.id;return e.jsx("button",{type:"button",className:`flat-terminal-wrapper__building-btn ${o?"flat-terminal-wrapper__building-btn--active":""}`,title:`${o?"Hide":"Show"} database: ${a.name}`,onClick:()=>{o?ke():gt(a.id)==="modal"?it(a.id):Ge("database",a.id)},onContextMenu:i=>{i.preventDefault(),i.stopPropagation(),ve(a.id,{x:i.clientX,y:i.clientY})},children:e.jsx(d,{name:"hard-drives",size:14})},a.id)})}),se.length>0&&e.jsx("span",{className:"flat-terminal-wrapper__buildings",role:"group","aria-label":"Area tests",children:se.map(a=>{const o=(j==null?void 0:j.buildingId)===a.id;return e.jsx("button",{type:"button",className:`flat-terminal-wrapper__building-btn ${o?"flat-terminal-wrapper__building-btn--active":""} ${a.working?"flat-terminal-wrapper__building-btn--tests-working":""}`,title:a.working?`Running tests: ${a.name}`:`${o?"Hide":"Show"} tests: ${a.name}`,onClick:()=>{o?ke():gt(a.id)==="modal"?it(a.id):Ge("tests",a.id)},onContextMenu:i=>{i.preventDefault(),i.stopPropagation(),ve(a.id,{x:i.clientX,y:i.clientY})},children:e.jsx(d,{name:"flask",size:14})},a.id)})}),ie.length>0&&e.jsx("span",{className:"flat-terminal-wrapper__buildings",role:"group","aria-label":"Area HTTP requests",children:ie.map(a=>{const o=(j==null?void 0:j.buildingId)===a.id;return e.jsx("button",{type:"button",className:`flat-terminal-wrapper__building-btn ${o?"flat-terminal-wrapper__building-btn--active":""}`,title:`${o?"Hide":"Show"} HTTP requests: ${a.name}`,onClick:()=>{o?ke():gt(a.id)==="modal"?it(a.id):Ge("http",a.id)},onContextMenu:i=>{i.preventDefault(),i.stopPropagation(),ve(a.id,{x:i.clientX,y:i.clientY})},children:e.jsx(d,{name:"globe",size:14})},a.id)})}),e.jsx("div",{className:"flat-terminal-wrapper__theme",children:e.jsx(jn,{})})]}),w&&e.jsx(Cn,{agentId:r,agents:Xe,onClose:Bt,branchInfoMap:wt,fetchRemote:Fe,fetchingDirs:Le,onResizeStart:a=>ot(a,"right")}),Re&&e.jsx(kn,{agentId:r,onClose:dt}),O&&e.jsx(Nn,{agentId:r,onClose:Ot})]})}),Vn={groups:[],gridCols:1,gridRows:1,positions:new Map};function Zn({onAgentClick:c,onBuildingClick:r,onBuildingDoubleClick:p,onBuildingPopup:b,onAreaContextMenu:N,onOpenSpawnModal:I,onOpenBossSpawnModal:E,onOpenAreaModal:A}){const{t:K}=Jt(["common"]),v=$a(),H=Da(),[D,re]=s.useState(null),[T,Ee]=s.useState(null),[oe,ce]=s.useState(null);ha("flatview-image-modal",D!==null,()=>re(null));const[Oe,bt]=s.useState(null),[we,ve]=s.useState(null),[u,R]=s.useState(null),[Me,Ie]=s.useState(null),[Ze,Te]=s.useState(!1),Lt=s.useCallback(()=>{Te(t=>!t)},[]),_t=s.useCallback(()=>{Te(!1)},[]),[Je,de]=s.useState(()=>{const t=Gt(y.VIEW_MODE);return t==="simple"||t==="chat"||t==="advanced"?t:"simple"}),Qe=s.useCallback(t=>{de(t),Vt(y.VIEW_MODE,t)},[]);s.useEffect(()=>{const t=n=>{if(n.key!==y.VIEW_MODE)return;const l=n.newValue;(l==="simple"||l==="chat"||l==="advanced")&&de(l)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[]);const[Be,ue]=s.useState(()=>Zt(y.FLAT_INSPECTOR_OPEN,!1)),[$,me]=s.useState(!1),lt=s.useCallback(()=>me(t=>!t),[]),wt=s.useCallback(()=>me(!1),[]);s.useEffect(()=>{window.dispatchEvent(new CustomEvent("tide-flat-agents-drawer-state",{detail:{open:$}}))},[$]),s.useEffect(()=>{window.dispatchEvent(new CustomEvent("tide-flat-inspector-state",{detail:{open:Be}}))},[Be]),s.useEffect(()=>{const t=()=>me(k=>!k),n=()=>{ue(k=>{const M=!k;return _e(y.FLAT_INSPECTOR_OPEN,M),M})},l=()=>{me(!1),ue(!1),_e(y.FLAT_INSPECTOR_OPEN,!1)},x=()=>me(!1),_=()=>{ue(!1),_e(y.FLAT_INSPECTOR_OPEN,!1)};return window.addEventListener("tide-toggle-flat-agents-drawer",t),window.addEventListener("tide-toggle-flat-inspector",n),window.addEventListener("tide-close-flat-side-views",l),window.addEventListener("tide-close-flat-agents-drawer-only",x),window.addEventListener("tide-close-flat-inspector-only",_),()=>{window.removeEventListener("tide-toggle-flat-agents-drawer",t),window.removeEventListener("tide-toggle-flat-inspector",n),window.removeEventListener("tide-close-flat-side-views",l),window.removeEventListener("tide-close-flat-agents-drawer-only",x),window.removeEventListener("tide-close-flat-inspector-only",_)}},[]);const Fe=s.useRef(null),Le=s.useRef(null),[pe,je]=s.useState(()=>{const t=na(y.FLAT_MIDDLE_WIDTH,0);return t>=Tt?t:null}),[Z,We]=s.useState(()=>{const t=na(y.FLAT_INSPECTOR_WIDTH,0);return t>=qt?t:null}),se=s.useCallback(t=>{if(typeof window>"u")return t;const n=Z!==null?It+Z:0,l=window.innerWidth-ua-It-da-n;return Math.max(Tt,Math.min(Math.max(l,Tt),t))},[Z]),ie=s.useCallback(t=>{var _;if(typeof window>"u")return t;const n=(_=Fe.current)==null?void 0:_.querySelector(".flat-middle"),l=(n==null?void 0:n.getBoundingClientRect().width)??Tt,x=window.innerWidth-ua-l-It-da-It;return Math.max(qt,Math.min(Math.max(x,qt),t))},[]);s.useEffect(()=>{if(pe===null&&Z===null)return;const t=()=>{je(n=>{if(n===null)return n;const l=se(n);return l===n?n:l}),We(n=>{if(n===null)return n;const l=ie(n);return l===n?n:l})};return window.addEventListener("resize",t),()=>window.removeEventListener("resize",t)},[pe,Z,se,ie]);const Pt=s.useCallback(t=>{var l;if(t.button!==0)return;const n=(l=Fe.current)==null?void 0:l.querySelector(".flat-middle");n&&(t.currentTarget.setPointerCapture(t.pointerId),Le.current={kind:"middle",startX:t.clientX,startWidth:n.getBoundingClientRect().width,pointerId:t.pointerId},document.body.classList.add("flat-splitter-dragging"))},[]),Ce=s.useCallback(t=>{var l;if(t.button!==0)return;const n=(l=Fe.current)==null?void 0:l.querySelector(".flat-inspector");n&&(t.currentTarget.setPointerCapture(t.pointerId),Le.current={kind:"inspector",startX:t.clientX,startWidth:n.getBoundingClientRect().width,pointerId:t.pointerId},document.body.classList.add("flat-splitter-dragging"))},[]),rt=s.useCallback(t=>{const n=Le.current;if(!n||t.pointerId!==n.pointerId)return;const l=t.clientX-n.startX;n.kind==="middle"?je(se(n.startWidth+l)):We(ie(n.startWidth-l))},[se,ie]),Pe=s.useCallback(t=>{const n=Le.current;if(!n||t.pointerId!==n.pointerId)return;try{t.currentTarget.releasePointerCapture(t.pointerId)}catch{}if(Le.current=null,document.body.classList.remove("flat-splitter-dragging"),!(Math.abs(t.clientX-n.startX)>2))return;const x=t.clientX-n.startX;if(n.kind==="middle"){const _=se(n.startWidth+x);je(_),Mt(y.FLAT_MIDDLE_WIDTH,_)}else{const _=ie(n.startWidth-x);We(_),Mt(y.FLAT_INSPECTOR_WIDTH,_)}},[se,ie]),$e=s.useCallback(()=>{je(null),Mt(y.FLAT_MIDDLE_WIDTH,0)},[]),j=s.useCallback(()=>{We(null),Mt(y.FLAT_INSPECTOR_WIDTH,0)},[]),[te,J]=s.useState(()=>Gt(y.FLAT_INSPECTOR_VIEW)==="tracking"?"tracking":"agent"),He=s.useCallback(t=>{J(t),Vt(y.FLAT_INSPECTOR_VIEW,t)},[]),De=s.useCallback(()=>{ue(t=>{const n=!t;return _e(y.FLAT_INSPECTOR_OPEN,n),n})},[]),Ue=s.useCallback(()=>{ue(!1),_e(y.FLAT_INSPECTOR_OPEN,!1)},[]),$t=s.useCallback(()=>{He("tracking"),ue(!0),_e(y.FLAT_INSPECTOR_OPEN,!0)},[He]),z=Ra(),Ge=s.useCallback((t,n)=>{re({url:t,name:n})},[]),ke=s.useCallback((t,n)=>{Ee({command:t,output:n,isLive:!1})},[]),Dt=s.useCallback((t,n)=>{var _;const l=H.size>0?Array.from(H)[0]:null,x=l?(_=g.getState().agents.get(l))==null?void 0:_.cwd:void 0;g.setFileViewerPath(t,n,x)},[H]),Rt=s.useCallback(t=>{ce(t)},[]),zt=s.useCallback((t,n)=>{bt({agentId:t,count:n})},[]),ot=s.useCallback(t=>{p?p(t):r(t)},[r,p]),w=s.useMemo(()=>H.size>0?Array.from(H)[0]:null,[H]),vt=s.useCallback(t=>{w&&ve({agentId:w,position:t})},[w]),Re=s.useCallback((t,n)=>{R({buildingId:t,position:n})},[]);s.useEffect(()=>{Te(!1)},[w]);const fe=s.useRef([]),O=s.useRef(-1),Ve=s.useRef(!1),ct=s.useRef(Gt(y.LAST_OPENED_AGENT,"")||null),[Ot,jt]=s.useState(!1),[Ct,Bt]=s.useState(!1),dt=s.useRef(!1),Xe=s.useRef(null),he=s.useRef(!1),Ne=s.useMemo(()=>new Set(v.map(t=>t.id)),[v]),qe=s.useMemo(()=>{const t=new Map(v.map(l=>[l.id,l])),n=new Map;for(const l of v)if((l.isBoss||l.class==="boss")&&l.subordinateIds&&l.subordinateIds.length>0){const x=l.subordinateIds.map(_=>t.get(_)).filter(_=>_!==void 0);x.length>0&&n.set(l.id,x)}return n},[v]),B=s.useCallback(()=>{const t=fe.current,n=O.current;jt(n>0),Bt(n>=0&&n<t.length-1)},[]),ge=s.useCallback(t=>{const n=fe.current;if(n.length===0)return;let l=O.current+t;for(;l>=0&&l<n.length;){const x=n[l];if(Ne.has(x)){Ve.current=!0,O.current=l,B(),g.selectAgent(x);return}l+=t}},[Ne,B]),ye=s.useCallback(()=>ge(-1),[ge]),ut=s.useCallback(()=>ge(1),[ge]);En(s.useCallback(()=>{const t=fe.current,n=O.current;return t.length>0&&n>0?(ge(-1),"handled"):"exit"},[ge]));const et=s.useCallback((t,n)=>{if(typeof window>"u")return;const l=window.history.state,_={...typeof l=="object"&&l!==null?l:{},__flatAgentNav:{agentId:t}};n==="replace"?window.history.replaceState(_,"",window.location.href):window.history.pushState(_,"",window.location.href)},[]);s.useEffect(()=>{if(!w){dt.current=!1,Xe.current=null;return}if(!dt.current){et(w,"replace"),dt.current=!0,Xe.current=w;return}if(he.current){he.current=!1,Xe.current=w;return}Xe.current!==w&&(et(w,"push"),Xe.current=w)},[w,et]),s.useEffect(()=>{const t=n=>{var k,M;const l=(M=(k=n.state)==null?void 0:k.__flatAgentNav)==null?void 0:M.agentId;if(!l||typeof l!="string"||!Ne.has(l)||l===w)return;he.current=!0,Ve.current=!0;const x=fe.current,_=x.lastIndexOf(l);_>=0?O.current=_:(x.push(l),O.current=x.length-1),B(),g.selectAgent(l)};return window.addEventListener("popstate",t),()=>window.removeEventListener("popstate",t)},[Ne,w,B]),s.useEffect(()=>{if(!w){fe.current=[],O.current=-1,B();return}if(ct.current=w,Vt(y.LAST_OPENED_AGENT,w),Ve.current){Ve.current=!1,B();return}const t=fe.current,n=O.current;if(n>=0&&t[n]===w){B();return}const l=n<t.length-1?t.slice(0,n+1):t.slice();l.push(w),l.length>100&&l.shift(),fe.current=l,O.current=l.length-1,B()},[w,B]);const mt=s.useCallback(t=>{c(t),me(!1)},[c]),Ft=w??"",ze=s.useCallback(()=>{},[]),kt=s.useCallback(t=>{mt(t)},[mt]),xe=Be,[tt,at]=s.useState(xe),[pt,be]=s.useState(xe);s.useEffect(()=>{if(xe){at(!0);return}be(!1);const t=setTimeout(()=>at(!1),240);return()=>clearTimeout(t)},[xe]),s.useEffect(()=>{if(!tt||!xe)return;let t=0;const n=requestAnimationFrame(()=>{t=requestAnimationFrame(()=>be(!0))});return()=>{cancelAnimationFrame(n),cancelAnimationFrame(t)}},[tt,xe]);const ft=s.useRef(null);s.useEffect(()=>{if(w)return;const t=n=>{if(n.key!==" "&&n.key!=="Backspace")return;const l=n.target;if(l.tagName==="INPUT"||l.tagName==="TEXTAREA"||l.isContentEditable)return;const x=ct.current;!x||!Ne.has(x)||(n.preventDefault(),g.selectAgent(x))};return document.addEventListener("keydown",t),()=>document.removeEventListener("keydown",t)},[w,Ne]);const[Ae,nt]=s.useState(new Set),Nt=s.useCallback(t=>{nt(n=>{const l=new Set(n);return l.has(t)?l.delete(t):l.add(t),l})},[]),yt=s.useCallback(t=>{nt(new Set(t))},[]),[a,o]=s.useState(()=>typeof window<"u"&&window.matchMedia("(max-width: 768px)").matches);s.useEffect(()=>{if(typeof window>"u")return;const t=window.matchMedia("(max-width: 768px)"),n=l=>o(l.matches);return t.addEventListener("change",n),()=>t.removeEventListener("change",n)},[]);const[i,m]=s.useState(null),X=s.useCallback(t=>{m(n=>n===t?null:t)},[]),Q=ga(),L=xa(),[st]=za(),ae=s.useMemo(()=>{if(w)return Vn;const t=new Map,n=[];for(const h of v){const C=g.getAreaForAgent(h.id);if(!sa((C==null?void 0:C.id)??null))continue;if(!C||C.archived){n.push(h);continue}const P=t.get(C.id);P?P.push(h):t.set(C.id,[h])}const l=new Map,x=[];for(const h of L.values()){let C=!1;for(const P of Q.values())if(!P.archived&&ia(P.id)&&g.isPositionInArea(h.position,P)){const le=l.get(P.id);le?le.push(h):l.set(P.id,[h]),C=!0;break}!C&&sa(null)&&x.push(h)}const _=[];for(const[,h]of Q){if(h.archived||!ia(h.id))continue;const C=t.get(h.id),P=l.get(h.id)??[];(C&&C.length>0||P.length>0)&&_.push({area:h,agents:C??[],buildings:P})}(n.length>0||x.length>0)&&_.push({area:{id:"__unassigned__",name:"Unassigned",color:"#6272a4",center:{x:0,z:0},type:"circle",radius:0,directories:[],archived:!1,assignedAgentIds:[],zIndex:0},agents:n,buildings:x});const k=_.filter(h=>h.area.id!=="__unassigned__"),M=_.filter(h=>h.area.id==="__unassigned__");let G=1,F=1;const f=new Map;if(k.length>1){let h=1/0,C=-1/0,P=1/0,le=-1/0;for(const q of k)h=Math.min(h,q.area.center.x),C=Math.max(C,q.area.center.x),P=Math.min(P,q.area.center.z),le=Math.max(le,q.area.center.z);const Se=C-h||1,St=le-P||1;if(k.length<=4){G=k.length,F=1;const q=[...k].sort((Y,Wt)=>Y.area.center.x-Wt.area.center.x);for(let Y=0;Y<q.length;Y++)f.set(q[Y].area.id,{row:1,col:Y+1})}else{const q=[...k].sort((S,W)=>S.area.center.x-W.area.center.x),Y=[];for(let S=1;S<q.length;S++)Y.push(q[S].area.center.x-q[S-1].area.center.x);const Wt=Y.reduce((S,W)=>S+W,0)/Y.length||1;let Qt=1;for(const S of Y)S>Wt*1.3&&Qt++;G=Math.max(2,Math.min(Qt,k.length));const Ht=[...k].sort((S,W)=>S.area.center.z-W.area.center.z),Et=[];for(let S=1;S<Ht.length;S++)Et.push(Ht[S].area.center.z-Ht[S-1].area.center.z);const ka=Et.reduce((S,W)=>S+W,0)/Et.length||1;let ea=1;for(const S of Et)S>ka*1.3&&ea++;F=Math.max(2,Math.min(ea,k.length)),G=Math.max(G,Math.ceil(k.length/F)),F=Math.max(F,Math.ceil(k.length/G));const Na=Se/G,ya=St/F,Ut=new Set;for(const S of k){let W=Math.min(G-1,Math.max(0,Math.floor((S.area.center.x-h)/Na))),Ke=Math.min(F-1,Math.max(0,Math.floor((S.area.center.z-P)/ya))),ht=`${Ke},${W}`,ta=0;const Aa=F*G;for(;Ut.has(ht)&&ta<Aa;)W++,W>=G&&(W=0,Ke=(Ke+1)%F),ht=`${Ke},${W}`,ta++;Ut.has(ht)&&(Ke=F,W=0,ht=`${Ke},${W}`,F++),Ut.add(ht),f.set(S.area.id,{row:Ke+1,col:W+1})}}}const ee=h=>{h.sort((C,P)=>{var Se,St,q,Y;const le=(((Se=C.position)==null?void 0:Se.z)??0)-(((St=P.position)==null?void 0:St.z)??0);return le!==0?le:(((q=C.position)==null?void 0:q.x)??0)-(((Y=P.position)==null?void 0:Y.x)??0)})};for(const h of k)ee(h.agents);for(const h of M)ee(h.agents);const V=[...k,...M].sort((h,C)=>h.area.name.localeCompare(C.area.name,void 0,{sensitivity:"base",numeric:!0})||h.area.id.localeCompare(C.area.id));return f.clear(),V.forEach((h,C)=>{f.set(h.area.id,{row:Math.floor(C/G)+1,col:C%G+1})}),F=Math.max(1,Math.ceil(V.length/G)),{groups:V,gridCols:G,gridRows:F,positions:f}},[v,Q,L,st,w]),Ye=s.useMemo(()=>{let t=0,n=0;for(const l of ae.groups)t+=l.agents.length,n+=l.agents.filter(x=>x.status==="working").length;return{areaCount:ae.groups.length,agentCount:t,workingCount:n}},[ae]),ne=s.useMemo(()=>{if(!we)return[];const t=v.find(n=>n.id===we.agentId);return t?[{id:"edit-agent",label:"Edit Agent",icon:e.jsx(d,{name:"edit",size:14}),onClick:()=>{window.dispatchEvent(new CustomEvent("tide:open-agent-edit",{detail:{agentId:t.id}}))}},{id:"open-chat",label:"Open Chat",icon:e.jsx(d,{name:"chat",size:14}),onClick:()=>c(t.id)},{id:"clone-agent",label:"Clone Agent",icon:e.jsx(d,{name:"clipboard",size:14}),onClick:()=>g.cloneAgent(t.id)},{id:"fork-agent",label:"Fork Agent (with history)",icon:e.jsx(d,{name:"git-branch",size:14}),onClick:()=>g.forkAgent(t.id)},{id:"delete-agent",label:"Delete Agent",icon:e.jsx(d,{name:"trash",size:14}),danger:!0,onClick:()=>{Ie({agentId:t.id,name:t.name})}}]:[]},[we,v,c]),U=s.useMemo(()=>{var k;if(!u)return[];const t=L.get(u.buildingId);if(!t)return[];const n=[],l=t.type==="server"||t.type==="docker"||t.type==="terminal",x=t.status==="running",_=t.type==="boss";if(n.push({id:"open",label:t.type==="database"?"Open Database":t.type==="folder"?"Open Folder":t.type==="tests"?"Open Tests":t.type==="http"?"Open Requests":t.type==="boss"?"View Boss Logs":t.type==="terminal"?"Open Terminal":t.type==="server"&&((k=t.pm2)!=null&&k.enabled)?"View PM2 Logs":"Open",icon:e.jsx(d,{name:t.type==="database"?"database":t.type==="folder"?"folder":t.type==="tests"?"flask":t.type==="http"?"globe":t.type==="terminal"?"terminal":"eye",size:14}),onClick:()=>ot(t.id)}),l&&(x||n.push({id:"start",label:"Start",icon:e.jsx(d,{name:"play",size:14}),onClick:()=>g.sendBuildingCommand(t.id,"start")}),x&&(n.push({id:"restart",label:"Restart",icon:e.jsx(d,{name:"refresh",size:14}),onClick:()=>g.sendBuildingCommand(t.id,"restart")}),n.push({id:"stop",label:"Stop",icon:e.jsx(d,{name:"stop",size:14}),onClick:()=>g.sendBuildingCommand(t.id,"stop")}))),_&&t.subordinateBuildingIds&&t.subordinateBuildingIds.length>0&&(n.push({id:"start-all",label:"Start All Subordinates",icon:e.jsx(d,{name:"launch",size:14}),onClick:()=>{for(const M of t.subordinateBuildingIds)g.sendBuildingCommand(M,"start")}}),n.push({id:"stop-all",label:"Stop All Subordinates",icon:e.jsx(d,{name:"pause",size:14}),onClick:()=>{for(const M of t.subordinateBuildingIds)g.sendBuildingCommand(M,"stop")}}),n.push({id:"restart-all",label:"Restart All Subordinates",icon:e.jsx(d,{name:"restart",size:14}),onClick:()=>{for(const M of t.subordinateBuildingIds)g.sendBuildingCommand(M,"restart")}})),l&&n.push({id:"health-check",label:"Health Check",icon:e.jsx(d,{name:"health",size:14}),onClick:()=>g.sendBuildingCommand(t.id,"healthCheck")}),n.push({id:"divider-edit",label:"",divider:!0,onClick:()=>{}}),n.push({id:"edit",label:"Edit Building",icon:e.jsx(d,{name:"edit",size:14}),onClick:()=>{window.dispatchEvent(new CustomEvent("tide:building-edit",{detail:{buildingId:t.id}}))}}),n.push({id:"clone",label:"Clone Building",icon:e.jsx(d,{name:"copy",size:14}),onClick:()=>{g.createBuilding({name:`${t.name} (Copy)`,type:t.type,style:t.style,color:t.color,scale:t.scale,position:{x:t.position.x+2,z:t.position.z+2},cwd:t.cwd,folderPath:t.folderPath,commands:t.commands,pm2:t.pm2,docker:t.docker,database:t.database,terminal:t.terminal,urls:t.urls,subordinateBuildingIds:t.subordinateBuildingIds})}}),t.urls&&t.urls.length>0)for(const M of t.urls)n.push({id:`url-${M.label}`,label:M.label,icon:e.jsx(d,{name:"link",size:14}),onClick:()=>window.open(M.url,"_blank","noopener,noreferrer")});return n.push({id:"divider-danger",label:"",divider:!0,onClick:()=>{}}),n.push({id:"delete",label:"Delete Building",icon:e.jsx(d,{name:"trash",size:14}),danger:!0,onClick:()=>g.deleteBuilding(t.id)}),n},[u,L,ot]),At=s.useCallback(t=>{nt(new Set([t])),requestAnimationFrame(()=>{const n=ft.current;if(!n)return;const l=n.querySelector(`[data-area-id="${t}"]`);if(!l)return;const x=n.getBoundingClientRect(),k=l.getBoundingClientRect().top-x.top+n.scrollTop-8;n.scrollTo({top:Math.max(0,k),behavior:"smooth"})})},[]);return e.jsxs("div",{ref:Fe,className:`flat-view ${xe?"flat-view--with-inspector":""} ${w?"flat-view--has-chat":""} ${$?"flat-view--mobile-sidebar-open":""}`,style:(()=>{if(pe===null&&Z===null)return;const t={};return pe!==null&&(t["--flat-middle-width"]=`${pe}px`),Z!==null&&(t["--flat-inspector-width"]=`${Z}px`),t})(),children:[$&&e.jsx("div",{className:"flat-mobile-sidebar-backdrop",onClick:wt,"aria-hidden":"true"}),e.jsxs("div",{className:"flat-middle",children:[e.jsx("div",{className:"flat-middle__header",children:e.jsxs("div",{className:"flat-middle__actions",children:[e.jsx("button",{className:"flat-cta-btn flat-cta-btn--agent",onClick:I,title:"Create new agent",children:"+ Agent"}),e.jsx("button",{className:"flat-cta-btn flat-cta-btn--boss",onClick:E,title:"Create new boss agent",children:"+ Boss"}),e.jsx("button",{className:"flat-cta-btn flat-cta-btn--area",onClick:A,title:"Create new area",children:"+ Area"})]})}),e.jsx("div",{className:"flat-middle__content",children:e.jsx(Oa,{activeAgentId:Ft,onClose:ze,onSelectAgent:kt,expandedAreas:Ae,onToggleArea:Nt,onSetExpandedAreas:yt,agentListRef:ft})})]}),e.jsx("div",{className:"flat-splitter flat-splitter--middle",role:"separator","aria-orientation":"vertical","aria-label":"Resize agents panel",title:"Drag to resize · Double-click to reset",onPointerDown:Pt,onPointerMove:rt,onPointerUp:Pe,onPointerCancel:Pe,onDoubleClick:$e}),e.jsxs("div",{className:"flat-right",children:[e.jsxs("button",{type:"button",className:"flat-mobile-sidebar-toggle","aria-label":$?"Close agents sidebar":"Open agents sidebar","aria-expanded":$,onClick:lt,children:[e.jsx(d,{name:"list",size:18}),e.jsx("span",{className:"flat-mobile-sidebar-toggle__label",children:"Agents"})]}),w?e.jsx(Gn,{agentId:w,terminalViewMode:Je,onTerminalViewModeChange:Qe,inspectorOpen:Be,onToggleInspector:De,onShowTaskBoard:$t,onImageClick:Ge,onFileClick:Dt,onBashClick:ke,onViewMarkdown:Rt,onRequestClearSubordinates:zt,keyboard:z,canNavigateBack:Ot,canNavigateForward:Ct,onNavigateBack:ye,onNavigateForward:ut,agentInfoOpen:Ze,onToggleAgentInfo:Lt,onHeaderContextMenu:vt,onBuildingContextMenu:Re}):e.jsx("div",{className:"flat-chat flat-chat--empty",children:e.jsxs("div",{className:"flat-map",children:[e.jsxs("div",{className:"flat-map__header",children:[e.jsx("span",{className:"flat-map__title",children:"🗺️ Areas"}),e.jsx("span",{className:"flat-map__hint",children:"Click an area to focus it, or an agent to chat"}),e.jsxs("span",{className:"flat-map__stats",children:[e.jsxs("span",{children:[Ye.areaCount," areas"]}),e.jsxs("span",{children:[Ye.agentCount," agents"]}),Ye.workingCount>0&&e.jsxs("span",{className:"flat-map__stats-working",children:[e.jsx("span",{className:"flat-map__stats-dot","aria-hidden":"true"}),Ye.workingCount," working"]})]}),e.jsx(Rn,{className:"flat-map__view-mode"})]}),e.jsx("div",{className:"flat-map__grid",style:{gridTemplateColumns:a?"repeat(2, minmax(0, 1fr))":`repeat(${ae.gridCols}, 1fr)`},children:ae.groups.length===0?e.jsx("div",{className:"flat-map__empty",children:e.jsx("span",{children:"No areas or agents yet"})}):(a?[...ae.groups].sort((n,l)=>{const x=ae.positions.get(n.area.id),_=ae.positions.get(l.area.id);return!x&&!_?0:x?_?x.row-_.row||x.col-_.col:-1:1}):ae.groups).map(n=>{var F;const l=n.area.id,x=ae.positions.get(l),_=n.agents.filter(f=>f.status==="working").length,k=_>0,M=a&&i!==l,G=a&&!M;return e.jsxs("div",{className:`flat-map-area-card${k?" flat-map-area-card--working":""}${M?" flat-map-area-card--collapsed":""}${G?" flat-map-area-card--expanded":""}`,style:{"--area-color":n.area.color,gridRow:a||x==null?void 0:x.row,gridColumn:a||x==null?void 0:x.col},onContextMenu:f=>{N&&(f.preventDefault(),f.stopPropagation(),N(l,{x:f.clientX,y:f.clientY}))},children:[e.jsxs("button",{type:"button",className:"flat-map-area-card__header",onClick:()=>a?X(l):At(l),title:a?M?`Expand ${n.area.name}`:`Collapse ${n.area.name}`:`Focus ${n.area.name} in left panel`,"aria-expanded":a?!M:void 0,children:[e.jsx("span",{className:"flat-map-area-card__color",style:{background:n.area.color}}),((F=n.area.logo)==null?void 0:F.filename)&&e.jsx("img",{className:"flat-map-area-card__logo",src:Sn(n.area.logo.filename),alt:"","aria-hidden":"true",onError:f=>{f.currentTarget.style.display="none"}}),e.jsx("span",{className:"flat-map-area-card__name",children:n.area.name}),e.jsxs("span",{className:"flat-map-area-card__count",title:`${n.agents.length} agent${n.agents.length===1?"":"s"}`,"aria-label":`${n.agents.length} agent${n.agents.length===1?"":"s"}`,children:[e.jsx(d,{name:"users",size:10}),n.agents.length]}),k&&e.jsxs("span",{className:"flat-map-area-card__working",title:`${_} working agent${_===1?"":"s"}`,"aria-label":`${_} working agent${_===1?"":"s"}`,children:[e.jsxs("span",{className:"flat-map-area-card__working-bars","aria-hidden":"true",children:[e.jsx("i",{}),e.jsx("i",{}),e.jsx("i",{})]}),e.jsx("span",{className:"flat-map-area-card__working-count",children:_})]}),a&&e.jsx(d,{name:M?"caret-down":"caret-up",size:11,className:"flat-map-area-card__caret"})]}),e.jsx("div",{className:"flat-map-area-card__agents",children:n.agents.map(f=>{const ee=f.isBoss||f.class==="boss",V=ee?qe.get(f.id):void 0,h=Ba(f),C=h.usedPercent>=80?"#ff4a4a":h.usedPercent>=60?"#ff9e4a":h.usedPercent>=40?"#ffd700":"#4aff9e",P=`Context: ${(h.totalTokens/1e3).toFixed(1)}k / ${(h.contextWindow/1e3).toFixed(1)}k (${h.usedPercent}% used, ${h.freePercent}% free)`,le=f.latestTodos&&f.latestTodos.length>0||V&&V.length>0;return e.jsx(Fa,{todos:f.latestTodos,subordinates:V,position:"top",children:e.jsxs("button",{type:"button",className:`flat-map-agent-chip ${f.status}`,onClick:()=>c(f.id),onContextMenu:Se=>{Se.preventDefault(),Se.stopPropagation(),ve({agentId:f.id,position:{x:Se.clientX,y:Se.clientY}})},title:le?void 0:`${ee?"Boss · ":""}Open chat with ${f.name}
2
- ${P}`,children:[e.jsx(ba,{agent:f,size:16}),ee&&e.jsx("span",{className:"flat-map-agent-chip__crown","aria-hidden":"true",children:e.jsx(d,{name:"crown",size:11,color:"#ffd700",weight:"fill"})}),e.jsx("span",{className:"flat-map-agent-chip__name",children:f.name}),e.jsx("img",{src:wa(f.provider,"/"),alt:f.provider,className:"flat-map-agent-chip__provider-icon",title:_a(f.provider)}),e.jsx("span",{className:"flat-map-agent-chip__dot",style:{backgroundColor:va(f.status)}}),f.latestTodos&&f.latestTodos.length>0&&e.jsx(Wa,{todos:f.latestTodos,maxDots:6}),ee&&V&&V.length>0&&e.jsx(Ha,{subordinates:V,maxDots:6}),e.jsx("span",{className:"flat-map-agent-chip__context-bar","aria-hidden":"true",children:e.jsx("span",{className:"flat-map-agent-chip__context-bar-fill",style:{width:`${h.usedPercent}%`,backgroundColor:C}})})]})},f.id)})}),n.area.directories.length>0&&e.jsx("div",{className:"flat-map-area-card__folders",role:"group","aria-label":`${n.area.name} folders`,children:n.area.directories.map(f=>{const ee=f.split("/").filter(Boolean).pop()||f;return e.jsxs("button",{type:"button",className:"flat-map-folder-chip",onClick:V=>{V.stopPropagation(),g.openFileExplorerForAreaFolder(l,f)},title:`Open in file explorer: ${f}`,children:[e.jsx(d,{name:"folder-open",size:12}),e.jsx("span",{className:"flat-map-folder-chip__name",children:ee})]},f)})}),n.buildings.length>0&&e.jsx("div",{className:"flat-map-area-card__buildings",children:n.buildings.map(f=>{var V;const ee=(V=Ua[f.type])==null?void 0:V.color;return e.jsxs("button",{type:"button",className:`flat-map-building-chip flat-map-building-chip--${f.status}`,style:ee?{"--building-type-color":ee}:void 0,onClick:h=>{if(b){const C=h.currentTarget.getBoundingClientRect();b(f.id,{x:C.right,y:C.top+C.height/2})}else ot(f.id)},onContextMenu:h=>{h.preventDefault(),h.stopPropagation(),R({buildingId:f.id,position:{x:h.clientX,y:h.clientY}})},title:`${f.name} · ${f.type} · ${f.status}`,children:[e.jsx(d,{name:Ga(f.type),size:12,color:ee}),e.jsx("span",{className:"flat-map-building-chip__name",children:f.name}),e.jsx("span",{className:"flat-map-building-chip__dot",style:{backgroundColor:Va(f.status)}})]},f.id)})})]},l)})})]})})]}),xe&&e.jsx("div",{className:"flat-splitter flat-splitter--inspector",role:"separator","aria-orientation":"vertical","aria-label":"Resize inspector panel",title:"Drag to resize · Double-click to reset",onPointerDown:Ce,onPointerMove:rt,onPointerUp:Pe,onPointerCancel:Pe,onDoubleClick:j}),tt&&e.jsxs("aside",{className:`flat-inspector ${pt?"flat-inspector--open":"flat-inspector--closing"}`,"aria-label":"Inspector panel",children:[e.jsxs("div",{className:"flat-inspector__header",children:[e.jsxs("div",{className:"flat-inspector__tabs",role:"tablist","aria-label":"Inspector view",children:[e.jsx("button",{type:"button",role:"tab","aria-selected":te==="agent",className:`flat-inspector__tab ${te==="agent"?"flat-inspector__tab--active":""}`,onClick:()=>He("agent"),children:"Agent"}),e.jsx("button",{type:"button",role:"tab","aria-selected":te==="tracking",className:`flat-inspector__tab ${te==="tracking"?"flat-inspector__tab--active":""}`,onClick:()=>He("tracking"),children:"Tracking"})]}),e.jsx("button",{type:"button",className:"flat-inspector__close",onClick:Ue,title:"Close inspector","aria-label":"Close inspector",children:"✕"})]}),e.jsx("div",{className:"flat-inspector__body",children:te==="tracking"?e.jsx(Xa,{activeAgentId:w??"",onSelectAgent:t=>{c(t),window.innerWidth<=768&&Ue()}}):(()=>{if(!w)return e.jsx("div",{className:"flat-inspector__empty",children:e.jsx("span",{children:"Select an agent to inspect"})});const t=v.find(n=>n.id===w);return t?e.jsx(qa,{agent:t,onFocusAgent:n=>{c(n),window.innerWidth<=768&&Ue()},onKillAgent:n=>g.killAgent(n)}):e.jsx("div",{className:"flat-inspector__empty",children:e.jsx("span",{children:"Agent not found"})})})()})]}),D&&e.jsx(Ya,{url:D.url,name:D.name,onClose:()=>re(null)}),T&&e.jsx(Ka,{state:T,onClose:()=>Ee(null)}),e.jsx(Za,{agent:w?v.find(t=>t.id===w)??null:null,content:oe,onClose:()=>ce(null)}),Oe&&e.jsx(Ja,{action:"clear-subordinates",selectedAgentId:Oe.agentId,subordinateCount:Oe.count,onClose:()=>bt(null),onClearHistory:()=>{}}),e.jsx(Qa,{agent:w?v.find(t=>t.id===w)??null:null,isOpen:Ze&&!!w,onClose:_t}),e.jsx(la,{isOpen:we!==null,position:(we==null?void 0:we.position)??{x:0,y:0},worldPosition:{x:0,z:0},actions:ne,onClose:()=>ve(null)}),e.jsx(la,{isOpen:u!==null,position:(u==null?void 0:u.position)??{x:0,y:0},worldPosition:{x:0,z:0},actions:U,onClose:()=>R(null)}),e.jsx(en,{isOpen:Me!==null,title:K("common:confirm.removeAgentTitle"),message:K("common:confirm.removeAgentMessage",{name:(Me==null?void 0:Me.name)??""}),confirmLabel:K("common:buttons.remove"),cancelLabel:K("common:buttons.cancel"),variant:"danger",onConfirm:()=>{Me&&g.removeAgentFromServer(Me.agentId)},onClose:()=>Ie(null)})]})}export{Zn as FlatView};