tide-commander 1.41.0 → 1.43.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 (47) hide show
  1. package/dist/assets/{BossLogsModal-gE17BBT9.js → BossLogsModal-CnIyv0O7.js} +1 -1
  2. package/dist/assets/{BossSpawnModal-SPvzti1i.js → BossSpawnModal-C5JHnXoV.js} +1 -1
  3. package/dist/assets/{ControlsModal-A489_yUU.js → ControlsModal-DJ6kwJQg.js} +1 -1
  4. package/dist/assets/{DockerLogsModal-Bexhv2Eo.js → DockerLogsModal-wLLPPw3N.js} +1 -1
  5. package/dist/assets/{EmbeddedEditor-BdrKX9Ef.js → EmbeddedEditor-BZUBqqzE.js} +1 -1
  6. package/dist/assets/{GmailOAuthSetup-BRDLCsnz.js → GmailOAuthSetup-DU-rYgPc.js} +1 -1
  7. package/dist/assets/{GoogleOAuthSetup-8tWGRN1a.js → GoogleOAuthSetup-DUG794k5.js} +1 -1
  8. package/dist/assets/{IframeModal-AIthNZLG.js → IframeModal-BEaeYao1.js} +1 -1
  9. package/dist/assets/{IntegrationsPanel-D4rlShHL.js → IntegrationsPanel-CrT3G7gD.js} +2 -2
  10. package/dist/assets/{LogViewerModal-CWASeq5k.js → LogViewerModal-pmKvg2_3.js} +1 -1
  11. package/dist/assets/{MonitoringModal-GCxQ22tf.js → MonitoringModal-BopLTYX0.js} +1 -1
  12. package/dist/assets/{PM2LogsModal-BFJ1_6O0.js → PM2LogsModal-akdCsnNY.js} +1 -1
  13. package/dist/assets/{RestoreArchivedAreaModal-BtuMbJVE.js → RestoreArchivedAreaModal-BAe0BLNN.js} +1 -1
  14. package/dist/assets/{SaveSnapshotModal-BUn9mntc.js → SaveSnapshotModal-CCK5ncy-.js} +1 -1
  15. package/dist/assets/{Scene2DCanvas-CToncCYk.js → Scene2DCanvas-CTrNCLiT.js} +1 -1
  16. package/dist/assets/{SceneManager-BivL9Mu6.js → SceneManager-WQvF4y8-.js} +1 -1
  17. package/dist/assets/{SkillsPanel-IE07LIWC.js → SkillsPanel-BpY-jIMP.js} +1 -1
  18. package/dist/assets/{SnapshotManager-Cs7fZ_aA.js → SnapshotManager-DlJQAEC-.js} +1 -1
  19. package/dist/assets/SpawnModal-Ci_uvH1F.js +1 -0
  20. package/dist/assets/{SubordinateAssignmentModal-DdANoM7g.js → SubordinateAssignmentModal-kFDllrhg.js} +1 -1
  21. package/dist/assets/{SupervisorPanel-CE7sMgHN.js → SupervisorPanel-CPyoCa6i.js} +1 -1
  22. package/dist/assets/{TriggerManagerPanel-Cyb1Sf8s.js → TriggerManagerPanel-B7qEVCh4.js} +1 -1
  23. package/dist/assets/{WorkflowEditorPanel-BM9nnUIT.js → WorkflowEditorPanel-D8FwpAyj.js} +1 -1
  24. package/dist/assets/{index-CvetF6vL.js → index-BWCjlz0C.js} +3 -3
  25. package/dist/assets/{index-DESPWRkl.js → index-Bu3B9Eke.js} +2 -2
  26. package/dist/assets/{index-DahUmubU.js → index-C5IJ99Dq.js} +1 -1
  27. package/dist/assets/{index-Ez0uF12M.js → index-CRD8TN18.js} +1 -1
  28. package/dist/assets/{index-bXLSkGdM.js → index-CjH90tsj.js} +1 -1
  29. package/dist/assets/{index-DlFukYeW.js → index-DkhEv4qN.js} +1 -1
  30. package/dist/assets/{index-B_0CIcus.js → index-M90uUgxL.js} +1 -1
  31. package/dist/assets/{index-dnQQyjiL.js → index-OOJWJ_4Z.js} +1 -1
  32. package/dist/assets/{main-CVYa_fKP.css → main-Chjl2UXl.css} +1 -1
  33. package/dist/assets/main-DB67UbmQ.js +153 -0
  34. package/dist/assets/{web-CwCZTch8.js → web-D4vvRMYa.js} +1 -1
  35. package/dist/assets/{web-DGZ9VJ1o.js → web-DRj84zWD.js} +1 -1
  36. package/dist/index.html +2 -2
  37. package/dist/src/packages/server/data/builtin-skills/agent-tracking.js +48 -0
  38. package/dist/src/packages/server/data/builtin-skills/boss-instructions.js +75 -129
  39. package/dist/src/packages/server/data/builtin-skills/index.js +2 -0
  40. package/dist/src/packages/server/routes/agents.js +21 -0
  41. package/dist/src/packages/server/services/agent-service.js +26 -11
  42. package/dist/src/packages/server/services/boss-message-service.js +1 -1
  43. package/dist/src/packages/server/services/skill-service.js +4 -1
  44. package/dist/src/packages/server/websocket/handlers/agent-handler.js +3 -0
  45. package/package.json +1 -1
  46. package/dist/assets/SpawnModal-DbfTe3y2.js +0 -1
  47. package/dist/assets/main-BL6u5aPD.js +0 -153
@@ -1 +1 @@
1
- import{bx as s}from"./main-BL6u5aPD.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class f extends s{constructor(){super(...arguments),this.pending=[],this.deliveredNotifications=[],this.hasNotificationSupport=()=>{if(!("Notification"in window)||!Notification.requestPermission)return!1;if(Notification.permission!=="granted")try{new Notification("")}catch(i){if(i instanceof Error&&i.name==="TypeError")return!1}return!0}}async getDeliveredNotifications(){const i=[];for(const t of this.deliveredNotifications){const e={title:t.title,id:parseInt(t.tag),body:t.body};i.push(e)}return{notifications:i}}async removeDeliveredNotifications(i){for(const t of i.notifications){const e=this.deliveredNotifications.find(n=>n.tag===String(t.id));e==null||e.close(),this.deliveredNotifications=this.deliveredNotifications.filter(()=>!e)}}async removeAllDeliveredNotifications(){for(const i of this.deliveredNotifications)i.close();this.deliveredNotifications=[]}async createChannel(){throw this.unimplemented("Not implemented on web.")}async deleteChannel(){throw this.unimplemented("Not implemented on web.")}async listChannels(){throw this.unimplemented("Not implemented on web.")}async schedule(i){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");for(const t of i.notifications)this.sendNotification(t);return{notifications:i.notifications.map(t=>({id:t.id}))}}async getPending(){return{notifications:this.pending}}async registerActionTypes(){throw this.unimplemented("Not implemented on web.")}async cancel(i){this.pending=this.pending.filter(t=>!i.notifications.find(e=>e.id===t.id))}async areEnabled(){const{display:i}=await this.checkPermissions();return{value:i==="granted"}}async changeExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async checkExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async requestPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(await Notification.requestPermission())}}async checkPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(Notification.permission)}}transformNotificationPermission(i){switch(i){case"granted":return"granted";case"denied":return"denied";default:return"prompt"}}sendPending(){var i;const t=[],e=new Date().getTime();for(const n of this.pending)!((i=n.schedule)===null||i===void 0)&&i.at&&n.schedule.at.getTime()<=e&&(this.buildNotification(n),t.push(n));this.pending=this.pending.filter(n=>!t.find(o=>o===n))}sendNotification(i){var t;if(!((t=i.schedule)===null||t===void 0)&&t.at){const e=i.schedule.at.getTime()-new Date().getTime();this.pending.push(i),setTimeout(()=>{this.sendPending()},e);return}this.buildNotification(i)}buildNotification(i){const t=new Notification(i.title,{body:i.body,tag:String(i.id)});return t.addEventListener("click",this.onClick.bind(this,i),!1),t.addEventListener("show",this.onShow.bind(this,i),!1),t.addEventListener("close",()=>{this.deliveredNotifications=this.deliveredNotifications.filter(()=>!this)},!1),this.deliveredNotifications.push(t),t}onClick(i){const t={actionId:"tap",notification:i};this.notifyListeners("localNotificationActionPerformed",t)}onShow(i){this.notifyListeners("localNotificationReceived",i)}}export{f as LocalNotificationsWeb};
1
+ import{bx as s}from"./main-DB67UbmQ.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class f extends s{constructor(){super(...arguments),this.pending=[],this.deliveredNotifications=[],this.hasNotificationSupport=()=>{if(!("Notification"in window)||!Notification.requestPermission)return!1;if(Notification.permission!=="granted")try{new Notification("")}catch(i){if(i instanceof Error&&i.name==="TypeError")return!1}return!0}}async getDeliveredNotifications(){const i=[];for(const t of this.deliveredNotifications){const e={title:t.title,id:parseInt(t.tag),body:t.body};i.push(e)}return{notifications:i}}async removeDeliveredNotifications(i){for(const t of i.notifications){const e=this.deliveredNotifications.find(n=>n.tag===String(t.id));e==null||e.close(),this.deliveredNotifications=this.deliveredNotifications.filter(()=>!e)}}async removeAllDeliveredNotifications(){for(const i of this.deliveredNotifications)i.close();this.deliveredNotifications=[]}async createChannel(){throw this.unimplemented("Not implemented on web.")}async deleteChannel(){throw this.unimplemented("Not implemented on web.")}async listChannels(){throw this.unimplemented("Not implemented on web.")}async schedule(i){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");for(const t of i.notifications)this.sendNotification(t);return{notifications:i.notifications.map(t=>({id:t.id}))}}async getPending(){return{notifications:this.pending}}async registerActionTypes(){throw this.unimplemented("Not implemented on web.")}async cancel(i){this.pending=this.pending.filter(t=>!i.notifications.find(e=>e.id===t.id))}async areEnabled(){const{display:i}=await this.checkPermissions();return{value:i==="granted"}}async changeExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async checkExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async requestPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(await Notification.requestPermission())}}async checkPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(Notification.permission)}}transformNotificationPermission(i){switch(i){case"granted":return"granted";case"denied":return"denied";default:return"prompt"}}sendPending(){var i;const t=[],e=new Date().getTime();for(const n of this.pending)!((i=n.schedule)===null||i===void 0)&&i.at&&n.schedule.at.getTime()<=e&&(this.buildNotification(n),t.push(n));this.pending=this.pending.filter(n=>!t.find(o=>o===n))}sendNotification(i){var t;if(!((t=i.schedule)===null||t===void 0)&&t.at){const e=i.schedule.at.getTime()-new Date().getTime();this.pending.push(i),setTimeout(()=>{this.sendPending()},e);return}this.buildNotification(i)}buildNotification(i){const t=new Notification(i.title,{body:i.body,tag:String(i.id)});return t.addEventListener("click",this.onClick.bind(this,i),!1),t.addEventListener("show",this.onShow.bind(this,i),!1),t.addEventListener("close",()=>{this.deliveredNotifications=this.deliveredNotifications.filter(()=>!this)},!1),this.deliveredNotifications.push(t),t}onClick(i){const t={actionId:"tap",notification:i};this.notifyListeners("localNotificationActionPerformed",t)}onShow(i){this.notifyListeners("localNotificationReceived",i)}}export{f as LocalNotificationsWeb};
@@ -1 +1 @@
1
- import{bx as a}from"./main-BL6u5aPD.js";import{ImpactStyle as i,NotificationType as r}from"./index-DESPWRkl.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class u extends a{constructor(){super(...arguments),this.selectionStarted=!1}async impact(t){const e=this.patternForImpact(t==null?void 0:t.style);this.vibrateWithPattern(e)}async notification(t){const e=this.patternForNotification(t==null?void 0:t.type);this.vibrateWithPattern(e)}async vibrate(t){const e=(t==null?void 0:t.duration)||300;this.vibrateWithPattern([e])}async selectionStart(){this.selectionStarted=!0}async selectionChanged(){this.selectionStarted&&this.vibrateWithPattern([70])}async selectionEnd(){this.selectionStarted=!1}patternForImpact(t=i.Heavy){return t===i.Medium?[43]:t===i.Light?[20]:[61]}patternForNotification(t=r.Success){return t===r.Warning?[30,40,30,50,60]:t===r.Error?[27,45,50]:[35,65,21]}vibrateWithPattern(t){if(navigator.vibrate)navigator.vibrate(t);else throw this.unavailable("Browser does not support the vibrate API")}}export{u as HapticsWeb};
1
+ import{bx as a}from"./main-DB67UbmQ.js";import{ImpactStyle as i,NotificationType as r}from"./index-Bu3B9Eke.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class u extends a{constructor(){super(...arguments),this.selectionStarted=!1}async impact(t){const e=this.patternForImpact(t==null?void 0:t.style);this.vibrateWithPattern(e)}async notification(t){const e=this.patternForNotification(t==null?void 0:t.type);this.vibrateWithPattern(e)}async vibrate(t){const e=(t==null?void 0:t.duration)||300;this.vibrateWithPattern([e])}async selectionStart(){this.selectionStarted=!0}async selectionChanged(){this.selectionStarted&&this.vibrateWithPattern([70])}async selectionEnd(){this.selectionStarted=!1}patternForImpact(t=i.Heavy){return t===i.Medium?[43]:t===i.Light?[20]:[61]}patternForNotification(t=r.Success){return t===r.Warning?[30,40,30,50,60]:t===r.Error?[27,45,50]:[35,65,21]}vibrateWithPattern(t){if(navigator.vibrate)navigator.vibrate(t);else throw this.unavailable("Browser does not support the vibrate API")}}export{u as HapticsWeb};
package/dist/index.html CHANGED
@@ -22,11 +22,11 @@
22
22
  <link rel="icon" type="image/png" sizes="16x16" href="/assets/icons/favicon-16x16.png" />
23
23
  <link rel="apple-touch-icon" sizes="180x180" href="/assets/icons/apple-touch-icon.png" />
24
24
  <title>Tide Commander</title>
25
- <script type="module" crossorigin src="/assets/main-BL6u5aPD.js"></script>
25
+ <script type="module" crossorigin src="/assets/main-DB67UbmQ.js"></script>
26
26
  <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
27
27
  <link rel="modulepreload" crossorigin href="/assets/vendor-react--Eh9ivFN.js">
28
28
  <link rel="modulepreload" crossorigin href="/assets/vendor-three-Chj50gSY.js">
29
- <link rel="stylesheet" crossorigin href="/assets/main-CVYa_fKP.css">
29
+ <link rel="stylesheet" crossorigin href="/assets/main-Chjl2UXl.css">
30
30
  </head>
31
31
  <body>
32
32
  <div id="app"></div>
@@ -0,0 +1,48 @@
1
+ export const agentTracking = {
2
+ slug: 'agent-tracking',
3
+ name: 'Agent Tracking',
4
+ description: 'Let agents keep tracking status updated through work completion',
5
+ allowedTools: ['Bash(curl:*)'],
6
+ assignedAgentClasses: ['*'],
7
+ content: `# Agent Tracking Status (MANDATORY)
8
+
9
+ **IMPORTANT: You MUST update your tracking status after EVERY single task completion. This is not optional.**
10
+
11
+ ## Trigger Conditions (Act Immediately)
12
+ 1. **After ANY user request is finished** - No matter how small (even a simple greeting, a one-line answer, or a trivial task), you MUST set a final tracking status
13
+ 2. **When you get blocked** - Cannot proceed for any reason
14
+ 3. **When your situation changes** - Update immediately so the board stays accurate
15
+
16
+ ## Command
17
+ \`\`\`bash
18
+ curl -s -X PATCH -H "X-Auth-Token: abcd" http://localhost:5174/api/agents/YOUR_AGENT_ID -H "Content-Type: application/json" -d '{"trackingStatus":"STATUS","trackingStatusDetail":"SHORT_DESCRIPTION"}'
19
+ \`\`\`
20
+
21
+ ## Available Statuses
22
+ - \`working\` — This is set automatically when you start working. Do not set this manually unless explicitly told to do so.
23
+ - \`need-review\` — Use when you finished work that needs the user to review (code changes, plans, findings)
24
+ - \`blocked\` — Use when you cannot proceed (waiting on another agent, need user input, hit an error you cannot resolve)
25
+ - \`can-clear-context\` — Use when your task is fully complete and your context can be safely cleared
26
+ - \`waiting-subordinates\` — Use when you (as a boss agent) have delegated tasks and are waiting for subordinates to complete their work
27
+
28
+ ## Rules
29
+ - Replace YOUR_AGENT_ID with your actual agent ID from the system prompt
30
+ - Replace STATUS with one of the status values above
31
+ - Keep trackingStatusDetail under 80 characters
32
+ - Do NOT use exclamation marks in the detail string
33
+ - The system automatically sets \`working\` while you are actively working
34
+ - After finishing work, you MUST set a final status such as \`need-review\` or \`can-clear-context\`
35
+ - When your situation changes, update the tracking status immediately so the board stays accurate
36
+ - When blocked, include WHO or WHAT you are blocked on in the detail
37
+ - When setting need-review, briefly describe what needs review in the detail
38
+ - When setting can-clear-context, briefly describe what is safe to clear
39
+ - Boss agents: after delegating tasks to subordinates, set \`waiting-subordinates\` with a detail describing what you are waiting for
40
+
41
+ ## CRITICAL: Notification Must Be Your ABSOLUTE LAST Action
42
+ - The tracking status curl command must be the VERY LAST thing you do - your final tool call
43
+ - Present ALL findings, summaries, and explanations to the user BEFORE sending the tracking status update
44
+ - Do NOT output any text, commentary, or follow-up messages after updating the tracking status
45
+ - Think of the tracking status update as your "exit" command - nothing comes after it
46
+ - **Correct order**: Do work -> present results to user -> update tracking status (end)
47
+ - **Wrong order**: Do work -> update tracking status -> present results (NEVER do this)`,
48
+ };
@@ -7,28 +7,33 @@ export const bossInstructions = {
7
7
  content: `# BOSS AGENT INSTRUCTIONS
8
8
 
9
9
  **CRITICAL - YOU MUST FOLLOW THESE:**
10
- You are a Boss Agent manager. Your #1 job is **DELEGATING work to your subordinates**. Default to delegation for everything.
10
+ You are a Boss Agent manager. Your #1 job is **DELEGATING work to your subordinates**. You are a DISPATCHER, not a worker. Delegate EVERYTHING.
11
11
 
12
- ## DELEGATION FIRSTBY DEFAULT
12
+ ## DELEGATION ALWAYSNO EXCEPTIONS
13
13
 
14
- **Your default action for ANY request is to delegate it to a subordinate.** This includes:
15
- - Coding tasks (features, bugs, refactoring)
14
+ **DELEGATE EVERY SINGLE REQUEST. PERIOD.** This includes:
15
+ - Coding tasks (features, bugs, refactoring) — even tiny ones
16
16
  - Research, exploration, and codebase analysis
17
17
  - Simple messages ("tell X to say hi", "ask Y about Z")
18
18
  - Testing and verification
19
19
  - Documentation tasks
20
20
  - Investigation and debugging
21
+ - One-line fixes, typos, small changes — YES, DELEGATE THESE TOO
22
+ - File reads, searches, grep commands — delegate, don't do it yourself
23
+ - "Quick" tasks — there is no such thing as quick for you, DELEGATE
21
24
 
22
- ### When to do work yourself (the exception, not the rule):
23
- If you **already have the context** needed to complete a small task quickly, just do it. Examples:
24
- - You just received a task report and can see a trivial fix (a typo, a one-line change)
25
- - The information is already in your conversation and you can answer/act without exploring
26
- - A quick \\\`curl\\\` call, a fast \\\`ls\\\`, or checking agent status via the TC API
27
- - Making delegation decisions (choosing which agent gets which task)
25
+ **YOU DO NOT WRITE CODE. YOU DO NOT READ CODE. YOU DO NOT EXPLORE CODE.**
26
+ You dispatch. You coordinate. You delegate. That is ALL you do.
28
27
 
29
- **The test:** Can you do this in under 1-2 tool calls with info you already have? Do it yourself. Otherwise, delegate.
28
+ ### The ONLY things you do yourself:
29
+ - \\\`curl\\\` calls to the Tide Commander API (checking agent status, delegating)
30
+ - Deciding WHICH agent gets WHICH task
31
+ - Summarizing reports from subordinates back to the user
32
+ - Answering questions using information agents already reported to you
30
33
 
31
- **If you need to explore, read multiple files, search code, or investigate something you don't already understand that is delegation territory.** Don't spend 5+ tool calls researching when a scout can do it.
34
+ **If it involves touching the codebase in ANY way — reading, writing, searching, exploringDELEGATE IT.**
35
+
36
+ **NEVER use Claude Code subagents (Agent tool) for research.** That is what your subordinates are for. You have a team — USE THEM.
32
37
 
33
38
  ## PLANNING (ONLY WHEN REQUESTED)
34
39
 
@@ -54,109 +59,77 @@ If you **already have the context** needed to complete a small task quickly, jus
54
59
  2. **WAIT FOR USER APPROVAL** - Ask: "Does this plan look good? Should I proceed with delegation?"
55
60
  3. **DELEGATE AFTER APPROVAL** - Once confirmed, delegate tasks in parallel
56
61
 
57
- ## ASK ONLY CRITICAL QUESTIONS
58
-
59
- **Don't over-ask.** Most decisions you can make yourself. Only ask when:
60
- - The request is truly ambiguous and could mean completely different things
61
- - You're about to do something destructive or irreversible
62
- - The user explicitly asked for your input
62
+ ## ZERO QUESTIONS POLICY
63
63
 
64
- **DON'T ask about:**
65
- - Implementation details (just pick a reasonable approach)
66
- - Which agent to use (that's YOUR job)
67
- - Scope details you can infer from context
68
- - "Where should this live?" / "What's the workflow?" (figure it out or delegate exploration first)
64
+ **DO NOT ASK QUESTIONS. DELEGATE IMMEDIATELY.**
69
65
 
70
- **Example - TOO MANY QUESTIONS (BAD):**
71
- > "What project is this for? What do you mean by X? Where should this live? What's the workflow? Should it be per-tenant?"
66
+ The ONLY time you ask a question is if you literally cannot determine which agent to send a task to because the request is completely unintelligible. Otherwise:
67
+ - Ambiguous request? Delegate to the most relevant agent. THEY will figure it out or ask.
68
+ - Don't know where code lives? → Delegate. The agent will find it.
69
+ - Multiple interpretations? → Pick the most likely one and delegate.
70
+ - Need more context? → Delegate a scout to gather it.
72
71
 
73
- **Example - DECISIVE (GOOD):**
74
- > "I'll delegate this to [agent] to implement. They'll figure out the details in the codebase."
72
+ **NEVER ask about:**
73
+ - Implementation details delegate and let the agent decide
74
+ - Which approach to take — delegate and trust your agent
75
+ - Scope or requirements — delegate with your best interpretation
76
+ - "Did you mean X or Y?" — pick one and delegate
75
77
 
76
- **When truly unclear**, ask ONE focused question, not a list of 5.
78
+ **Your speed is your value.** The moment you receive a request, you should be writing a delegation block. Not thinking. Not asking. DELEGATING.
77
79
 
78
80
  ---
79
81
 
80
- ## CORE RULE: BE DECISIVE DELEGATE BY DEFAULT, ACT WHEN HANDY
81
-
82
- **YOU ARE PRIMARILY A MANAGER.** Your main value is routing tasks to the right agent efficiently.
82
+ ## CORE RULE: YOU ARE A DISPATCHER, NOT A WORKER
83
83
 
84
- **Your workflow for most requests:**
85
- 1. **DECIDE** which agent is best (spend seconds, not minutes)
86
- 2. **DELEGATE immediately** with clear instructions
87
- 3. **EXPLAIN** in 1-2 sentences max
84
+ **Your workflow for EVERY request (no exceptions):**
85
+ 1. **READ** the request (1 second)
86
+ 2. **PICK** the best available agent (1 second)
87
+ 3. **DELEGATE** with clear instructions (write the delegation block)
88
+ 4. **DONE** — move on
88
89
 
89
- **But if you already have the context**, just act. Don't delegate a 30-second task that you can handle right now with information already in your conversation.
90
+ **You do NOT:**
91
+ - Read files
92
+ - Search code
93
+ - Write code
94
+ - Debug anything
95
+ - Explore the codebase
96
+ - Launch Claude Code subagents for research
97
+ - Do "quick" fixes yourself
98
+ - Make "small" changes yourself
90
99
 
91
- **Signs you should DELEGATE (not do it yourself):**
92
- - You'd need to explore/search code you haven't seen yet
93
- - You'd need 3+ tool calls to gather context before acting
94
- - The task involves substantial code writing, debugging, or testing
95
- - You're launching Claude Code subagents just to research before delegating
96
-
97
- **Signs you can DO IT YOURSELF:**
98
- - You already know the answer from a recent task report or conversation context
99
- - It's a trivial change you can make in 1-2 tool calls
100
- - It's a quick API call or status check
100
+ **There is no task too small to delegate.** A one-line fix? Delegate. A typo? Delegate. Renaming a variable? Delegate. Your agents are faster at these tasks than you because they have direct codebase access and context.
101
101
 
102
102
  **ALWAYS DO THIS:**
103
103
  - Make reasonable assumptions based on context
104
- - If something needs exploration, delegate to an agent who can figure it out
105
- - If something is unclear, the assigned agent will ask or figure it out
106
- - Be confident - you're the boss
107
- - Trust your subordinates to handle substantial work
108
-
109
- ## INVESTIGATION AND RESEARCH — PREFER DELEGATION
110
-
111
- **For substantial research (exploring codebases, understanding architecture, reading multiple files), delegate to your subordinates:**
112
- - **Scouts** are specifically designed for exploration and research
113
- - **Any idle agent** can explore, search, read code, and report back
114
-
115
- **BAD (boss doing heavy research itself):**
116
- > [Boss launches multiple Claude Code subagents to explore codebase]
117
- > [Boss reads 10 files and searches code to understand architecture]
118
- > [Boss spends many tool calls investigating before finally delegating]
119
-
120
- **GOOD (boss delegates research):**
121
- > [Boss delegates exploration to Scout] -> "Explore the auth module and report back what you find"
122
- > [Scout reports back] -> [Boss uses findings to delegate implementation or acts on simple follow-ups]
123
-
124
- ### When you need information to make a decision:
125
- 1. **Quick checks you already have context for** -> do it yourself (a single file read, a curl call, an ls)
126
- 2. **Substantial exploration** (multiple files, searching patterns, understanding architecture) -> delegate to a scout or idle agent
127
- 3. **Context before a work plan** -> delegate research phase first, then plan after reports come back
128
-
129
- ### Claude Code subagents (Agent tool)
130
- Use Claude Code subagents for **quick, focused lookups** (e.g., "which file contains class X?", "what does function Y do?"). For broader investigation, delegate to your TC team — they build persistent context that helps with follow-up work.
104
+ - Delegate immediately without overthinking
105
+ - Trust your subordinates completely they are competent
106
+ - Be confident and decisive — you are the boss
107
+ - If multiple things need doing, delegate them ALL at once
131
108
 
132
109
  ---
133
110
 
134
- ## DECISION CRITERIA (in priority order):
111
+ ## AGENT SELECTION (spend 2 seconds max):
135
112
 
136
- 1. **Idle agents first** - Strongly prefer idle agents. Do not pick a working agent just because they touched nearby code if a capable idle agent is available
137
- 2. **Specialization match** - debugger for bugs, builder for features, scout for exploration
138
- 3. **Recent context** - Treat recent related work as a tiebreaker, not a reason to interrupt an active agent
139
- 4. **Low context usage** - Prefer agents with <50% context; avoid >80%
140
- 5. **Fullstack versatility** - Fullstack/custom agents can handle most tasks
113
+ 1. **Idle agents first** always prefer idle agents over working ones
114
+ 2. **Specialization** debugger for bugs, builder for features, scout for exploration
115
+ 3. **Low context** prefer agents with room to work (<50% context)
116
+ 4. **Any capable agent** don't overthink it, any agent can handle most tasks
141
117
 
142
- ### Idle-vs-active assignment rule
143
- - If an idle agent can reasonably handle the task, assign the idle agent
144
- - A working agent's nearby context is usually not enough reason to interrupt them
145
- - Provide the needed repo paths, summaries, constraints, and handoff notes in the delegation so another capable idle agent can pick it up quickly
146
- - Only choose an already-working agent over an idle capable agent when the continuity benefit is clearly substantial and worth the interruption
118
+ **Do NOT waste time deliberating.** Pick the first reasonable match and delegate. Wrong agent? The agent will figure it out or you can redirect later. Speed > perfection.
147
119
 
148
120
  ---
149
121
 
150
122
  ## YOUR CAPABILITIES:
151
123
 
152
- ### 1. TASK DELEGATION (most common)
153
- For any task → **delegate immediately**. This includes:
154
- - Coding tasks (features, bugs, refactoring)
124
+ ### 1. TASK DELEGATION (your ONLY real job)
125
+ For ANY task → **delegate immediately**. Everything. Always. No exceptions:
126
+ - Coding tasks (features, bugs, refactoring) — even one-liners
155
127
  - Simple requests ("tell X to do Y", "ask X about Z")
156
128
  - Messages and communications between agents
157
129
  - Research, testing, documentation
130
+ - File reads, searches, explorations — ALL of it
158
131
 
159
- No lengthy analysis needed - just delegate.
132
+ **Speed is everything.** The moment you get a request, output a delegation block. Do not think. Do not analyze. Do not research. DELEGATE.
160
133
 
161
134
  ### 2. GET DETAILED AGENT INFORMATION
162
135
 
@@ -379,11 +352,10 @@ User: "Analyze the frontend, create a parallelizable plan, and assign tasks"
379
352
 
380
353
  ## DELEGATION RESPONSE FORMAT:
381
354
 
382
- **Keep responses CONCISE.** No lengthy explanations needed.
355
+ **Keep responses ULTRA-SHORT.** Delegate in under 3 sentences. No analysis, no preamble, no "let me think about this."
383
356
 
384
357
  ### Format:
385
358
  **[Agent Name]** → [Brief task description]
386
- **Reason:** [One sentence reason]
387
359
 
388
360
  \\\`\\\`\\\`delegation
389
361
  [{"selectedAgentId": "<EXACT Agent ID>", "selectedAgentName": "<Name>", "taskCommand": "<Detailed task for agent>", "reasoning": "<brief>", "confidence": "high|medium|low"}]
@@ -404,50 +376,24 @@ User: "Analyze the frontend, create a parallelizable plan, and assign tasks"
404
376
 
405
377
  ---
406
378
 
407
- ## SINGLE vs MULTI-AGENT DELEGATION:
408
-
409
- **DEFAULT TO SINGLE AGENT for simple tasks.** One capable agent with full context beats multiple agents with fragmented knowledge.
410
-
411
- ### When to use SINGLE agent:
412
- - Tasks are sequential phases of the same work
413
- - One step needs context from a previous step
414
- - A single competent agent can handle the full scope
415
-
416
- ### When MULTI-agent delegation is appropriate:
417
- - Tasks are truly independent (no shared context needed)
418
- - Tasks require different specializations AND can run in parallel
419
- - User explicitly asks to split work across agents
420
- - Executing a work plan with parallel phases
421
-
422
- ### DON'T split tasks when:
423
- - The tasks share context
424
- - One agent would need to re-discover what another learned
425
- - The tasks are phases of one larger task
426
-
427
- ---
428
-
429
- ## PARALLELIZATION CAUTION
379
+ ## MAXIMIZE PARALLEL DELEGATION
430
380
 
431
- **Only parallelize when you are 100% certain:**
432
- 1. Tasks are truly independent with NO shared context or dependencies
433
- 2. Each task has ALL required information/context to complete independently
434
- 3. One task's output won't be needed as input for another task
435
- 4. Both agents can work simultaneously without blocking each other
436
- 5. You've verified both agents have the capabilities needed
381
+ **DEFAULT TO MULTI-AGENT PARALLEL DELEGATION.** If you have idle agents and work that can be split, split it and delegate in parallel. Keep your whole team busy.
437
382
 
438
- **If unsure, use SEQUENTIAL delegation instead.** It's better to have one agent complete work, then pass context to the next agent, than to have two agents working in parallel and later discovering they needed each other's results.
383
+ ### Parallelize aggressively:
384
+ - Different files or modules? → **Parallel**
385
+ - Frontend + backend work? → **Parallel** (different agents)
386
+ - Multiple bugs or features? → **Parallel** (one per agent)
387
+ - Research + implementation you can start without research? → **Parallel**
388
+ - Testing + documentation? → **Parallel**
439
389
 
440
- **Default to SINGLE AGENT** for most work. Parallelization should be rare and intentional, not the default.
390
+ ### Only go sequential when:
391
+ - Task B literally cannot start until Task A produces output it needs
392
+ - Two tasks modify the exact same file in conflicting ways
441
393
 
442
- **Example - DON'T PARALLELIZE (BAD):**
443
- - Task A: "Refactor the auth module"
444
- - Task B: "Update the login form to match new auth API"
445
- → Task B depends on Task A being done first. Sequential only.
394
+ **When in doubt, PARALLELIZE.** Agents are smart enough to handle partial context. It is always better to have 3 agents working simultaneously than 1 agent doing 3 tasks sequentially while 2 sit idle.
446
395
 
447
- **Example - DO PARALLELIZE (GOOD):**
448
- - Task A: "Add button styling to _buttons.scss"
449
- - Task B: "Add input styling to _inputs.scss"
450
- → Independent files, no dependencies. Can parallelize.
396
+ **KEEP YOUR TEAM UTILIZED.** If you have 4 idle agents and get a request, find a way to involve multiple agents. Break the task down. Send scouts to research while builders prepare. Don't leave agents sitting idle when there is work to do.
451
397
 
452
398
  ---
453
399
 
@@ -15,6 +15,7 @@ import { pm2Logs } from './pm2-logs.js';
15
15
  import { createBuilding } from './create-building.js';
16
16
  import { releasePipeline } from './release-pipeline.js';
17
17
  import { taskLabel } from './task-label.js';
18
+ import { agentTracking } from './agent-tracking.js';
18
19
  import { reportTaskToBoss } from './report-task-to-boss.js';
19
20
  import { bossInstructions } from './boss-instructions.js';
20
21
  import { workflowDesigner } from './workflow-designer.js';
@@ -34,6 +35,7 @@ export const BUILTIN_SKILLS = [
34
35
  createBuilding,
35
36
  releasePipeline,
36
37
  taskLabel,
38
+ agentTracking,
37
39
  reportTaskToBoss,
38
40
  bossInstructions,
39
41
  workflowDesigner,
@@ -494,6 +494,21 @@ router.post('/', async (req, res) => {
494
494
  res.status(500).json({ error: err.message });
495
495
  }
496
496
  });
497
+ // GET /api/agents/tracking-statuses - List all non-null tracking statuses
498
+ // NOTE: This must be defined BEFORE /:id routes to prevent being interpreted as an ID
499
+ router.get('/tracking-statuses', (_req, res) => {
500
+ const trackingStatuses = agentService
501
+ .getAllAgents()
502
+ .filter(agent => agent.trackingStatus != null)
503
+ .map(agent => ({
504
+ agentId: agent.id,
505
+ agentName: agent.name,
506
+ trackingStatus: agent.trackingStatus,
507
+ trackingStatusDetail: agent.trackingStatusDetail,
508
+ trackingStatusTimestamp: agent.trackingStatusTimestamp,
509
+ }));
510
+ res.json(trackingStatuses);
511
+ });
497
512
  // GET /api/agents/:id - Get single agent
498
513
  router.get('/:id', (req, res) => {
499
514
  const agent = agentService.getAgent(req.params.id);
@@ -511,6 +526,12 @@ router.patch('/:id', (req, res) => {
511
526
  if (sessionId !== undefined) {
512
527
  log.warn(`API attempted to modify sessionId for agent ${req.params.id} - blocked`);
513
528
  }
529
+ if ('trackingStatus' in safeUpdates) {
530
+ safeUpdates.trackingStatusTimestamp = safeUpdates.trackingStatus == null ? undefined : Date.now();
531
+ if (safeUpdates.trackingStatus == null && !('trackingStatusDetail' in safeUpdates)) {
532
+ safeUpdates.trackingStatusDetail = undefined;
533
+ }
534
+ }
514
535
  const updated = agentService.updateAgent(req.params.id, safeUpdates);
515
536
  if (!updated) {
516
537
  res.status(404).json({ error: 'Agent not found' });
@@ -396,47 +396,62 @@ export function updateAgent(id, updates, updateActivity = true) {
396
396
  const agent = agents.get(id);
397
397
  if (!agent)
398
398
  return null;
399
+ const normalizedUpdates = { ...updates };
399
400
  const sessionIdBefore = agent.sessionId;
400
- const hasSessionIdInUpdates = 'sessionId' in updates;
401
+ const hasSessionIdInUpdates = 'sessionId' in normalizedUpdates;
401
402
  // Track pending property updates for notification on next command
402
403
  // (these are changes that affect behavior but don't require restart)
403
404
  const pending = pendingPropertyUpdates.get(id) || {};
404
- if (updates.class !== undefined && updates.class !== agent.class) {
405
+ if (normalizedUpdates.class !== undefined && normalizedUpdates.class !== agent.class) {
405
406
  pending.classChanged = true;
406
407
  pending.oldClass = agent.class;
407
- log.log(`Agent ${agent.name}: Class change pending (${agent.class} -> ${updates.class})`);
408
+ log.log(`Agent ${agent.name}: Class change pending (${agent.class} -> ${normalizedUpdates.class})`);
408
409
  }
409
- if (updates.permissionMode !== undefined && updates.permissionMode !== agent.permissionMode) {
410
+ if (normalizedUpdates.permissionMode !== undefined && normalizedUpdates.permissionMode !== agent.permissionMode) {
410
411
  pending.permissionModeChanged = true;
411
412
  pending.oldPermissionMode = agent.permissionMode;
412
- log.log(`Agent ${agent.name}: Permission mode change pending (${agent.permissionMode} -> ${updates.permissionMode})`);
413
+ log.log(`Agent ${agent.name}: Permission mode change pending (${agent.permissionMode} -> ${normalizedUpdates.permissionMode})`);
413
414
  }
414
- if (updates.useChrome !== undefined && updates.useChrome !== agent.useChrome) {
415
+ if (normalizedUpdates.useChrome !== undefined && normalizedUpdates.useChrome !== agent.useChrome) {
415
416
  pending.useChromeChanged = true;
416
417
  pending.oldUseChrome = agent.useChrome;
417
- log.log(`Agent ${agent.name}: Chrome mode change pending (${agent.useChrome} -> ${updates.useChrome})`);
418
+ log.log(`Agent ${agent.name}: Chrome mode change pending (${agent.useChrome} -> ${normalizedUpdates.useChrome})`);
418
419
  }
419
420
  // Note: Model changes are handled via hot restart (stop + resume with new model)
420
421
  // in agent-handler.ts, not via pending updates
421
422
  if (Object.keys(pending).length > 0) {
422
423
  pendingPropertyUpdates.set(id, pending);
423
424
  }
425
+ const nextStatus = normalizedUpdates.status ?? agent.status;
426
+ const hasExplicitTrackingStatus = Object.prototype.hasOwnProperty.call(normalizedUpdates, 'trackingStatus');
427
+ const explicitTrackingStatus = normalizedUpdates.trackingStatus;
428
+ const shouldPreserveExplicitTrackingStatus = explicitTrackingStatus !== undefined
429
+ && explicitTrackingStatus !== null
430
+ && explicitTrackingStatus !== 'working';
431
+ const enteredWorkingState = agent.status !== 'working' && nextStatus === 'working';
432
+ if (enteredWorkingState && !shouldPreserveExplicitTrackingStatus) {
433
+ normalizedUpdates.trackingStatus = 'working';
434
+ normalizedUpdates.trackingStatusDetail = undefined;
435
+ if (!hasExplicitTrackingStatus || explicitTrackingStatus === null || explicitTrackingStatus === 'working') {
436
+ normalizedUpdates.trackingStatusTimestamp = Date.now();
437
+ }
438
+ }
424
439
  // Only update lastActivity for real activity (not position changes, etc.)
425
440
  if (updateActivity) {
426
- Object.assign(agent, updates, { lastActivity: Date.now() });
441
+ Object.assign(agent, normalizedUpdates, { lastActivity: Date.now() });
427
442
  }
428
443
  else {
429
- Object.assign(agent, updates);
444
+ Object.assign(agent, normalizedUpdates);
430
445
  }
431
446
  agents.set(id, agent);
432
447
  debouncedPersistAgents();
433
448
  // Reconcile area assignment when position changes
434
- if (updates.position) {
449
+ if (normalizedUpdates.position) {
435
450
  reconcileAgentAreaAssignment(id, { x: agent.position.x, z: agent.position.z });
436
451
  }
437
452
  // Debug logging for sessionId changes
438
453
  if (sessionIdBefore !== agent.sessionId) {
439
- log.warn(`🔑 [SESSION CHANGE] Agent ${agent.name} (${id}): sessionId changed from "${sessionIdBefore}" to "${agent.sessionId}". Updates had sessionId: ${hasSessionIdInUpdates}, updates keys: ${Object.keys(updates).join(', ')}`);
454
+ log.warn(`🔑 [SESSION CHANGE] Agent ${agent.name} (${id}): sessionId changed from "${sessionIdBefore}" to "${agent.sessionId}". Updates had sessionId: ${hasSessionIdInUpdates}, updates keys: ${Object.keys(normalizedUpdates).join(', ')}`);
440
455
  }
441
456
  emit('updated', agent);
442
457
  return agent;
@@ -12,7 +12,7 @@ import { buildBossContext } from './subordinate-context-service.js';
12
12
  export function buildBossSystemPrompt(bossName, bossId) {
13
13
  const agent = agentService.getAgent(bossId);
14
14
  const customInstructions = agent?.customInstructions;
15
- let prompt = `You are "${bossName}", a Boss Agent manager with ID \`${bossId}\`. Your default is to delegate tasks to your subordinates. Do small tasks yourself only when you already have the context to finish quickly (1-2 tool calls). For anything requiring exploration or substantial work, delegate to your team.
15
+ let prompt = `You are "${bossName}", a Boss Agent dispatcher with ID \`${bossId}\`. You NEVER do work yourself. You delegate EVERYTHING to your subordinates no exceptions. You do not read code, write code, search code, or explore the codebase. You are a pure dispatcher: receive request, pick agent(s), delegate immediately, done. Keep your entire team busy by parallelizing aggressively.
16
16
 
17
17
  Your agent ID for notifications: ${bossId}`;
18
18
  // Append agent-specific custom instructions
@@ -45,7 +45,10 @@ export function initSkills() {
45
45
  const restoredSkill = {
46
46
  ...builtinSkill,
47
47
  assignedAgentIds: storedVersion.assignedAgentIds,
48
- assignedAgentClasses: storedVersion.assignedAgentClasses,
48
+ assignedAgentClasses: Array.from(new Set([
49
+ ...builtinSkill.assignedAgentClasses,
50
+ ...storedVersion.assignedAgentClasses,
51
+ ])),
49
52
  enabled: storedVersion.enabled, // Also restore enabled state
50
53
  };
51
54
  skills.set(builtinId, restoredSkill);
@@ -156,6 +156,9 @@ export async function handleClearContext(ctx, payload) {
156
156
  status: 'idle',
157
157
  currentTask: undefined,
158
158
  taskLabel: undefined,
159
+ trackingStatus: undefined,
160
+ trackingStatusDetail: undefined,
161
+ trackingStatusTimestamp: undefined,
159
162
  currentTool: undefined,
160
163
  lastAssignedTask: undefined,
161
164
  lastAssignedTaskTime: undefined,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tide-commander",
3
- "version": "1.41.0",
3
+ "version": "1.43.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 Xe,H as Ve,L as Ze,M as Qe,N as es,O as ss,r as t,P as ns,S as ke,U as te,A as ye,w as le,V as as,s as B,h as ts,j as s,W as ls,X as x,Y as os,Z as oe,_ as G,$ as K,a0 as ie,a1 as is}from"./main-BL6u5aPD.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";function Ae(c,j){const S=j.filter(b=>!c.has(b));return S.length===0?`${j[Math.floor(Math.random()*j.length)]}-${Date.now()%1e3}`:S[Math.floor(Math.random()*S.length)]}function ms({isOpen:c,onClose:j,onSpawnStart:S,onSpawnEnd:b,spawnPosition:De,spawnAreaId:v}){const{t:n}=Xe(["terminal","common"]),C=Ve(),$=Ze(),p=Qe(),ce=es(),H=ce.length>0?ce:ss,[m,N]=t.useState(""),[M,P]=t.useState(()=>ns(ke.LAST_CWD)),[i,Y]=t.useState("scout"),[re,D]=t.useState(!1),[Ee,T]=t.useState(!1),[de,J]=t.useState(!1),[pe,me]=t.useState(""),[k,X]=t.useState([]),[y,F]=t.useState(null),[Le,ue]=t.useState(!1),[E,he]=t.useState(""),[u,_e]=t.useState(""),[R,Ie]=t.useState(!0),[U,$e]=t.useState("bypass"),[o,V]=t.useState("claude"),[g,L]=t.useState({fullAuto:!0,sandbox:"workspace-write",approvalMode:"on-request",search:!1}),[we,Z]=t.useState(new Set),[Q,xe]=t.useState("opus"),[ee,fe]=t.useState("high"),[se,Pe]=t.useState("gpt-5.3-codex"),[ne,Te]=t.useState("minimax/MiniMax-M1-80k"),[je,Fe]=t.useState(""),[A,Re]=t.useState(""),q=t.useRef(null),ge=t.useRef(!1),_=t.useCallback(()=>{window.__spawnModalAreaContext=null},[]),h=t.useMemo(()=>$.filter(e=>e.enabled),[$]),Ue=["full-notifications","streaming-exec","task-label","report-task-to-boss"];t.useEffect(()=>{if(c&&!ge.current&&h.length>0){const a=h.filter(l=>Ue.includes(l.slug)).map(l=>l.id);a.length>0&&Z(new Set(a))}ge.current=c},[c,h]);const ve=t.useMemo(()=>{if(!A.trim())return h;const e=A.toLowerCase();return h.filter(a=>a.name.toLowerCase().includes(e)||a.description.toLowerCase().includes(e)||a.slug.toLowerCase().includes(e))},[h,A]),qe=t.useCallback(e=>{Z(a=>{const l=new Set(a);return l.has(e)?l.delete(e):l.add(e),l})},[]);t.useMemo(()=>h.filter(e=>e.assignedAgentClasses.includes(i)),[h,i]);const ze=t.useMemo(()=>{var a;const e=p.find(l=>l.id===i);return(a=e==null?void 0:e.defaultSkillIds)!=null&&a.length?$.filter(l=>e.defaultSkillIds.includes(l.id)):[]},[p,i,$]),Ne=t.useMemo(()=>{if(!E.trim())return k;const e=E.toLowerCase();return k.filter(a=>a.sessionId.toLowerCase().includes(e)||a.projectPath.toLowerCase().includes(e)||a.firstMessage&&a.firstMessage.toLowerCase().includes(e))},[k,E]),z=t.useMemo(()=>{if(!u.trim())return p;const e=u.toLowerCase();return p.filter(a=>a.name.toLowerCase().includes(e)||a.description.toLowerCase().includes(e)||a.id.toLowerCase().includes(e))},[p,u]),W=t.useMemo(()=>{if(!u.trim())return te;const e=u.toLowerCase();return te.filter(a=>{const l=ye[a.id];return a.name.toLowerCase().includes(e)||a.id.toLowerCase().includes(e)||l.description.toLowerCase().includes(e)})},[u]);t.useEffect(()=>{if(!c||!u.trim())return;const e=[...z.map(a=>a.id),...W.map(a=>a.id)];e.length===1&&e[0]!==i&&Y(e[0])},[c,u,z,W,i]);const r=t.useMemo(()=>p.find(e=>e.id===i),[p,i]),We=t.useMemo(()=>{if(r!=null&&r.model)return r.model},[r]),Oe=t.useMemo(()=>{if(r!=null&&r.customModelPath)return le(`/api/custom-models/${r.id}`)},[r]),Be=r==null?void 0:r.modelScale,Ge=t.useMemo(()=>r?"scout":i,[i,r]),O=t.useCallback(async e=>{ue(!0);try{const a=e?le(`/api/agents/claude-sessions?cwd=${encodeURIComponent(e)}`):le("/api/agents/claude-sessions"),d=await(await as(a)).json();X(d.sessions||[])}catch(a){console.error("Failed to fetch sessions:",a),X([])}finally{ue(!1)}},[]);t.useEffect(()=>{c?O(M||void 0):(X([]),F(null),he(""))},[c,O]),t.useEffect(()=>{if(!c)return;const e=setTimeout(()=>{O(M||void 0),F(null)},300);return()=>clearTimeout(e)},[M,c,O]),t.useEffect(()=>{if(!c||!v)return;const e=B.getState().areas.get(v);if(e!=null&&e.directories&&e.directories.length>0){P(e.directories[0]);return}const a=Array.from(C.values()).filter(f=>{var I;return((I=B.getAreaForAgent(f.id))==null?void 0:I.id)===v&&f.cwd});if(a.length===0)return;const l=new Map;for(const f of a)l.set(f.cwd,(l.get(f.cwd)||0)+1);let d="",w=0;for(const[f,I]of l)I>w&&(d=f,w=I);d&&P(d)},[c,v,C]),t.useEffect(()=>{if(c){const e=new Set(Array.from(C.values()).map(w=>w.name)),a=Ae(e,H),l=p.find(w=>w.id===i),d=l?`${l.name} ${a}`:a;N(d),q.current&&(q.current.focus(),q.current.select())}},[c,C,H]),t.useEffect(()=>{if(!c)return;new Set(Array.from(C.values()).map(a=>a.name));const e=p.find(a=>a.id===i);if(e){const a=p.find(l=>m.startsWith(l.name+" "));if(a){const l=m.substring(a.name.length+1);N(`${e.name} ${l}`)}else N(`${e.name} ${m}`)}else{const a=p.find(l=>m.startsWith(l.name+" "));if(a){const l=m.substring(a.name.length+1);N(l)}}},[i]),t.useEffect(()=>{i==="boss"&&xe("opus")},[i]);const Ke=()=>{var d;console.log("[SpawnModal] handleSpawn called"),T(!1);const e=y&&((d=k.find(w=>w.sessionId===y))==null?void 0:d.projectPath)||M;if(console.log("[SpawnModal] Effective CWD:",e),console.log("[SpawnModal] Agent name:",m),console.log("[SpawnModal] Agent class:",i),console.log("[SpawnModal] Permission mode:",U),console.log("[SpawnModal] Provider:",o),console.log("[SpawnModal] Use Chrome:",R),console.log("[SpawnModal] Session ID:",y||"none"),!e.trim()){console.error("[SpawnModal] Empty CWD, showing error"),T(!0);return}if(!m.trim()){console.log("[SpawnModal] Empty name, regenerating");const w=new Set(Array.from(C.values()).map(f=>f.name));N(Ae(w,H));return}is(ke.LAST_CWD,e),D(!0),S();const a=Array.from(we),l=je.trim()||void 0;console.log("[SpawnModal] Calling store.spawnAgent with:",{name:m.trim(),class:i,cwd:e.trim(),sessionId:y||void 0,useChrome:o==="claude"?R:!1,permissionMode:U,provider:o,codexConfig:o==="codex"?g:void 0,codexModel:o==="codex"?se:void 0,opencodeModel:o==="opencode"?ne:void 0,initialSkillIds:a,model:o==="claude"?Q:void 0,customInstructions:l?`${l.length} chars`:void 0,spawnAreaId:v||void 0}),window.__spawnModalAreaContext=v?{areaId:v}:null,B.spawnAgent(m.trim(),i,e.trim(),De||void 0,y||void 0,o==="claude"?R:!1,U,a,o,o==="codex"?g:void 0,o==="codex"?se:void 0,o==="claude"?Q:void 0,l,o==="claude"?ee:void 0,o==="opencode"?ne:void 0)},Se=()=>{console.log("[SpawnModal] Agent creation successful"),D(!1),N(""),Z(new Set),_(),b(),j()},be=()=>{console.error("[SpawnModal] Agent creation failed"),D(!1),T(!0),_(),b()},Ce=e=>{console.log("[SpawnModal] Directory not found:",e),D(!1),me(e),J(!0),b()},Me=()=>{J(!1),D(!0),S(),B.createDirectoryAndSpawn(pe,m.trim(),i)},ae=()=>{J(!1),me(""),_()};t.useEffect(()=>(window.__spawnModalSuccess=Se,window.__spawnModalError=be,window.__spawnModalDirNotFound=Ce,()=>{_(),delete window.__spawnModalSuccess,delete window.__spawnModalError,delete window.__spawnModalDirNotFound}),[m,i,Se,be,Ce,_]);const{handleMouseDown:He,handleClick:Ye}=ts(j),Je=e=>{e.key==="Escape"&&j()};return!c&&!de?null:de?s.jsx("div",{className:"modal-overlay visible",onClick:ae,onKeyDown:e=>{e.key==="Escape"&&ae(),e.key==="Enter"&&Me()},children:s.jsxs("div",{className:"modal confirm-modal",onClick:e=>e.stopPropagation(),children:[s.jsx("div",{className:"modal-header",children:n("terminal:spawn.directoryNotFound")}),s.jsxs("div",{className:"modal-body confirm-modal-body",children:[s.jsx("p",{children:n("terminal:spawn.directoryNotExist")}),s.jsx("code",{className:"confirm-modal-path",children:pe}),s.jsx("p",{children:n("terminal:spawn.wouldYouCreate")})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:ae,children:n("common:buttons.cancel")}),s.jsx("button",{className:"btn btn-primary",onClick:Me,autoFocus:!0,children:n("terminal:spawn.createDirectory")})]})]})}):s.jsx("div",{className:`modal-overlay ${c?"visible":""}`,onMouseDown:He,onClick:Ye,onKeyDown:Je,children:s.jsxs("div",{className:"modal spawn-modal",children:[s.jsx("div",{className:"modal-header",children:n("terminal:spawn.deployTitle")}),s.jsxs("div",{className:"modal-body spawn-modal-body",children:[s.jsxs("div",{className:"spawn-top-section",children:[s.jsx("div",{className:"spawn-preview-compact",children:s.jsx(ls,{agentClass:Ge,modelFile:We,customModelUrl:Oe,modelScale:Be,width:100,height:120})}),s.jsxs("div",{className:"spawn-class-section",children:[s.jsx("div",{className:"spawn-class-label",children:n("terminal:spawn.agentClass")}),p.length+te.length>6&&s.jsx("input",{type:"text",className:"spawn-input class-search-input",placeholder:n("terminal:spawn.filterClasses"),value:u,onChange:e=>_e(e.target.value)}),s.jsxs("div",{className:"class-selector-inline",children:[z.map(e=>s.jsxs("button",{className:`class-chip ${i===e.id?"selected":""}`,onClick:()=>Y(e.id),title:e.description,children:[s.jsx("span",{className:"class-chip-icon",children:e.icon}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id)),W.map(e=>{const a=ye[e.id];return s.jsxs("button",{className:`class-chip ${i===e.id?"selected":""}`,onClick:()=>Y(e.id),title:a.description,children:[s.jsx("span",{className:"class-chip-icon",children:a.icon}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id)}),u&&z.length===0&&W.length===0&&s.jsx("div",{className:"class-search-empty",children:n("terminal:spawn.noClassesMatch",{query:u})})]})]})]}),s.jsxs("div",{className:"spawn-form-section",children:[s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.name")}),s.jsx("input",{ref:q,type:"text",className:"spawn-input",placeholder:n("terminal:spawn.agentNamePlaceholder"),value:m,onChange:e=>N(e.target.value)})]}),s.jsxs("div",{className:"spawn-field spawn-field-wide",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.workingDir"),s.jsx(x,{text:n("terminal:spawn.helpWorkingDir"),title:n("terminal:spawn.workingDir"),position:"top",size:"sm"})]}),s.jsx(os,{value:M,onChange:e=>{P(e),T(!1)},placeholder:n("terminal:spawn.workingDirPlaceholder"),className:`spawn-input ${Ee?"error":""}`,directoriesOnly:!0})]})]}),s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.selectRuntime"),s.jsx(x,{text:n("terminal:spawn.helpRuntime"),title:n("terminal:spawn.runtimeTitle"),position:"top",size:"sm"})]}),s.jsxs("div",{className:"spawn-select-row",children:[s.jsxs("button",{className:`spawn-select-btn ${o==="claude"?"selected":""}`,onClick:()=>V("claude"),title:n("terminal:spawn.useClaudeCli"),children:[s.jsx("img",{src:"/assets/claude.ico",alt:"Claude",className:"spawn-provider-icon"}),s.jsx("span",{children:"Claude"})]}),s.jsxs("button",{className:`spawn-select-btn ${o==="codex"?"selected":""}`,onClick:()=>V("codex"),title:n("terminal:spawn.useCodexCli"),children:[s.jsx("img",{src:"/assets/codex.ico",alt:"Codex",className:"spawn-provider-icon"}),s.jsx("span",{children:"Codex"})]}),s.jsxs("button",{className:`spawn-select-btn spawn-select-btn--opencode ${o==="opencode"?"selected":""}`,onClick:()=>V("opencode"),title:"Use OpenCode CLI (multi-provider)",children:[s.jsx("span",{children:"🟢"}),s.jsx("span",{children:"OpenCode"})]})]})]}),s.jsxs("div",{className:"spawn-field",children:[s.jsxs("label",{className:"spawn-label",children:[n("common:labels.permissions"),s.jsx(x,{text:n("terminal:spawn.helpPermission"),title:n("terminal:spawn.permissionMode"),position:"top",size:"sm"})]}),s.jsx("div",{className:"spawn-select-row",children:Object.keys(oe).map(e=>s.jsxs("button",{className:`spawn-select-btn ${U===e?"selected":""}`,onClick:()=>$e(e),title:oe[e].description,children:[s.jsx("span",{children:e==="bypass"?"⚡":"🔐"}),s.jsx("span",{children:oe[e].label})]},e))})]})]}),s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsxs("label",{className:"spawn-label",children:[n("common:labels.model"),s.jsx(x,{text:n("terminal:spawn.helpModel"),title:n("terminal:spawn.modelTitle"),position:"top",size:"sm"})]}),o==="claude"?s.jsx("div",{className:"spawn-select-row",children:Object.keys(G).map(e=>s.jsxs("button",{className:`spawn-select-btn ${Q===e?"selected":""}`,onClick:()=>xe(e),title:G[e].description,children:[s.jsx("span",{children:G[e].icon}),s.jsx("span",{children:G[e].label})]},e))}):o==="codex"?s.jsx("div",{className:"spawn-select-row spawn-select-row--codex-models",children:Object.keys(K).map(e=>s.jsxs("button",{className:`spawn-select-btn ${se===e?"selected":""}`,onClick:()=>Pe(e),title:K[e].description,children:[s.jsx("span",{children:K[e].icon}),s.jsx("span",{children:K[e].label})]},e))}):o==="opencode"?s.jsx("input",{type:"text",className:"spawn-input",value:ne,onChange:e=>Te(e.target.value),placeholder:"provider/model (e.g., minimax/MiniMax-M1-80k)"}):s.jsx("div",{className:"spawn-inline-hint",children:n("terminal:spawn.chooseCodexModel")})]}),o==="claude"&&s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:"Effort"}),s.jsxs("div",{className:"spawn-select-row spawn-select-row--effort",children:[s.jsx("button",{className:`spawn-select-btn spawn-select-btn--compact ${ee===void 0?"selected":""}`,onClick:()=>fe(void 0),title:"Use default effort level",children:s.jsx("span",{children:"Default"})}),Object.keys(ie).map(e=>s.jsx("button",{className:`spawn-select-btn spawn-select-btn--compact ${ee===e?"selected":""}`,onClick:()=>fe(e),title:ie[e].description,children:s.jsx("span",{children:ie[e].label})},e))]})]}),s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("terminal:spawn.browser")}),s.jsx("div",{className:"spawn-form-row spawn-options-row",children:s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:R,onChange:e=>Ie(e.target.checked),disabled:o!=="claude"}),s.jsxs("span",{children:["🌐 ",n("terminal:spawn.chromeBrowser")]}),s.jsx(x,{text:n(o==="claude"?"terminal:spawn.helpChrome":"terminal:spawn.helpChromeDisabled"),title:n("terminal:spawn.chromeBrowser"),position:"top",size:"sm"})]})})]})]}),o==="codex"&&s.jsxs("div",{className:"codex-config-section",children:[s.jsx("div",{className:"codex-config-title",children:n("terminal:spawn.codex.configuration")}),s.jsxs("div",{className:"codex-config-options",children:[s.jsxs("div",{className:"codex-option-group",children:[s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:g.fullAuto!==!1,onChange:e=>L(a=>({...a,fullAuto:e.target.checked}))}),s.jsx("span",{children:n("terminal:spawn.codex.fullAuto")}),s.jsx(x,{text:n("terminal:spawn.helpFullAuto"),title:n("terminal:spawn.fullAutoTitle"),position:"top",size:"sm"})]}),s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:!!g.search,onChange:e=>L(a=>({...a,search:e.target.checked}))}),s.jsx("span",{children:n("terminal:spawn.codex.search")}),s.jsx(x,{text:n("terminal:spawn.helpSearch"),title:n("terminal:spawn.searchTitle"),position:"top",size:"sm"})]})]}),g.fullAuto===!1&&s.jsxs("div",{className:"codex-option-group",children:[s.jsx("div",{className:"codex-option-header",children:n("terminal:spawn.codex.restrictions")}),s.jsxs("select",{className:"spawn-input codex-select",value:g.sandbox||"workspace-write",onChange:e=>L(a=>({...a,sandbox:e.target.value})),children:[s.jsxs("option",{value:"read-only",children:["📖 ",n("terminal:spawn.codex.sandboxReadOnly")]}),s.jsxs("option",{value:"workspace-write",children:["✏️ ",n("terminal:spawn.codex.sandboxWorkspaceWrite")]}),s.jsxs("option",{value:"danger-full-access",children:["⚡ ",n("terminal:spawn.codex.sandboxDangerFullAccess")]})]}),s.jsxs("select",{className:"spawn-input codex-select",value:g.approvalMode||"on-request",onChange:e=>L(a=>({...a,approvalMode:e.target.value})),children:[s.jsxs("option",{value:"untrusted",children:["🔒 ",n("terminal:spawn.codex.approvalsUntrusted")]}),s.jsxs("option",{value:"on-failure",children:["⚠️ ",n("terminal:spawn.codex.approvalsOnFailure")]}),s.jsxs("option",{value:"on-request",children:["🤔 ",n("terminal:spawn.codex.approvalsOnRequest")]}),s.jsxs("option",{value:"never",children:["✅ ",n("terminal:spawn.codex.approvalsNever")]})]})]}),s.jsxs("div",{className:"codex-option-group",children:[s.jsx("div",{className:"codex-option-header",children:n("terminal:spawn.codex.profile")}),s.jsx("input",{type:"text",className:"spawn-input codex-profile-input",placeholder:n("terminal:spawn.codex.profilePlaceholder"),value:g.profile||"",onChange:e=>L(a=>({...a,profile:e.target.value||void 0}))})]})]})]}),h.length>0&&s.jsxs("div",{className:"spawn-skills-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.skills")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]}),s.jsx(x,{text:n("terminal:spawn.helpSkills"),title:n("terminal:spawn.skillsTitle"),position:"top",size:"sm"})]}),h.length>6&&s.jsx("input",{type:"text",className:"spawn-input skill-search-input",placeholder:n("terminal:spawn.filterSkills"),value:A,onChange:e=>Re(e.target.value)}),s.jsxs("div",{className:"spawn-skills-inline",children:[ve.map(e=>{const a=we.has(e.id);return ze.some(d=>d.id===e.id)?null:s.jsxs("button",{className:`spawn-skill-chip ${a?"selected":""}`,onClick:()=>qe(e.id),title:e.description,children:[a&&s.jsx("span",{className:"spawn-skill-check",children:"✓"}),s.jsx("span",{children:e.name}),e.builtin&&s.jsx("span",{className:"spawn-skill-builtin",children:"TC"})]},e.id)}),A&&ve.length===0&&s.jsx("div",{className:"skill-search-empty",children:n("terminal:spawn.noSkillsMatch",{query:A})})]})]}),s.jsxs("div",{className:"spawn-custom-instructions-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.customInstructions")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]}),s.jsx(x,{text:n("terminal:spawn.helpCustomInstructions"),title:n("terminal:spawn.customInstructions"),position:"top",size:"sm"})]}),s.jsx("textarea",{className:"spawn-input spawn-textarea",placeholder:n("terminal:spawn.customInstructionsPlaceholder"),value:je,onChange:e=>Fe(e.target.value),rows:3})]}),s.jsxs("div",{className:"spawn-sessions-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.linkSession")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]}),s.jsx(x,{text:n("terminal:spawn.helpLinkSession"),title:n("terminal:spawn.linkSessionTitle"),position:"top",size:"sm"})]}),k.length>0&&s.jsx("input",{type:"text",className:"spawn-input session-search-input",placeholder:n("terminal:spawn.searchSessions"),value:E,onChange:e=>he(e.target.value)}),s.jsx("div",{className:"sessions-list",children:Le?s.jsx("div",{className:"sessions-loading",children:n("terminal:spawn.loadingSessions")}):k.length===0?s.jsx("div",{className:"sessions-empty",children:n("terminal:spawn.noSessions")}):Ne.length===0?s.jsx("div",{className:"sessions-empty",children:n("terminal:spawn.noSessionsMatch",{query:E})}):Ne.map(e=>{const a=y===e.sessionId,l=Date.now()-new Date(e.lastModified).getTime(),d=l<6e4?n("common:time.justNow"):l<36e5?n("common:time.minutesAgo",{count:Math.floor(l/6e4)}):l<864e5?n("common:time.hoursAgo",{count:Math.floor(l/36e5)}):n("common:time.daysAgo",{count:Math.floor(l/864e5)});return s.jsxs("div",{className:`session-item ${a?"selected":""}`,onClick:()=>{a?F(null):(F(e.sessionId),P(e.projectPath))},children:[s.jsxs("div",{className:"session-item-header",children:[s.jsx("span",{className:"session-item-path",children:e.projectPath}),s.jsx("span",{className:"session-item-age",children:d})]}),s.jsx("div",{className:"session-item-preview",children:e.firstMessage||n("terminal:spawn.messagesCount",{count:e.messageCount})})]},e.sessionId)})})]})]})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:j,children:n("common:buttons.cancel")}),s.jsx("button",{className:"btn btn-primary",onClick:Ke,disabled:re,children:n(re?"common:buttons.deploying":"common:buttons2.deploy")})]})]})})}export{ms as SpawnModal};