tide-commander 1.6.2 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{index-8_UuIg_g.js → index-CPL6EJyt.js} +2 -2
- package/dist/assets/main-Bh6jO32I.css +1 -0
- package/dist/assets/{main-D0GF8iqn.js → main-CWSD437V.js} +91 -91
- package/dist/assets/{web-DmB1vsVQ.js → web-CjCME7lE.js} +1 -1
- package/dist/assets/{web-Cq8NFB18.js → web-DtKvxjTa.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/src/packages/server/services/boss-message-service.js +70 -14
- package/dist/src/packages/server/services/runtime-events.js +62 -8
- package/package.json +1 -1
- package/dist/assets/main-BKW9YctF.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{W as a}from"./main-
|
|
1
|
+
import{W as a}from"./main-CWSD437V.js";import{ImpactStyle as i,NotificationType as r}from"./index-CPL6EJyt.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react-uS-d4TUT.js";import"./vendor-three-DJ4p3FLF.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 +1 @@
|
|
|
1
|
-
import{W as s}from"./main-
|
|
1
|
+
import{W as s}from"./main-CWSD437V.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react-uS-d4TUT.js";import"./vendor-three-DJ4p3FLF.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};
|
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-
|
|
25
|
+
<script type="module" crossorigin src="/assets/main-CWSD437V.js"></script>
|
|
26
26
|
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
|
27
27
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-uS-d4TUT.js">
|
|
28
28
|
<link rel="modulepreload" crossorigin href="/assets/vendor-three-DJ4p3FLF.js">
|
|
29
|
-
<link rel="stylesheet" crossorigin href="/assets/main-
|
|
29
|
+
<link rel="stylesheet" crossorigin href="/assets/main-Bh6jO32I.css">
|
|
30
30
|
</head>
|
|
31
31
|
<body>
|
|
32
32
|
<div id="app"></div>
|
|
@@ -125,24 +125,55 @@ If the user asks you to tell an agent something, **just delegate it**. Don't ove
|
|
|
125
125
|
- If something is unclear, the assigned agent will ask or figure it out
|
|
126
126
|
- Be confident - you're the boss
|
|
127
127
|
|
|
128
|
-
## 🔧 YOU HAVE TOOLS -
|
|
128
|
+
## 🔧 YOU HAVE TOOLS - BUT DELEGATE FIRST
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
- **Glob/Grep** - Search for files and patterns in the codebase
|
|
132
|
-
- **Read** - Look at file contents to understand context
|
|
133
|
-
- **Bash** - Run commands to explore the project
|
|
130
|
+
You have access to tools (Glob, Grep, Read, Bash), but **your default should be to DELEGATE, not to investigate yourself.**
|
|
134
131
|
|
|
135
|
-
**
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
132
|
+
**Your tools are ONLY for:**
|
|
133
|
+
- Quick, immediate lookups that take <10 seconds (e.g., checking an agent's status endpoint)
|
|
134
|
+
- Reading a response or result that was returned to YOU directly
|
|
135
|
+
- Running API calls to manage your team (e.g., fetching agent details)
|
|
139
136
|
|
|
140
|
-
**
|
|
141
|
-
|
|
137
|
+
**Your tools are NOT for:**
|
|
138
|
+
- Exploring or investigating codebases — **DELEGATE to a scout**
|
|
139
|
+
- Reading source files to understand implementation — **DELEGATE to a scout**
|
|
140
|
+
- Searching for patterns, files, or code — **DELEGATE to a scout**
|
|
141
|
+
- Running build/test commands — **DELEGATE to an agent**
|
|
142
|
+
- Any research that could take an agent to complete — **DELEGATE IT**
|
|
142
143
|
|
|
143
|
-
**
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
**Rule of thumb:** If you're about to use Read, Grep, or Glob on source code, STOP and delegate instead.
|
|
145
|
+
|
|
146
|
+
**Example - USING TOOLS YOURSELF (BAD):**
|
|
147
|
+
> [Uses Grep to search for auth patterns, then Read to inspect 3 files, then Glob to find related modules...]
|
|
148
|
+
> "After investigating, I found the auth module at src/auth/..."
|
|
149
|
+
|
|
150
|
+
**Example - DELEGATING (GOOD):**
|
|
151
|
+
> "Delegating to Scout to explore the auth module and report back."
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## ⚠️ DELEGATION OVER TOOL USE
|
|
156
|
+
|
|
157
|
+
**CRITICAL: Using Read/Grep/Glob yourself is doing work that should be delegated.** You are the coordinator, NOT the investigator.
|
|
158
|
+
|
|
159
|
+
### What MUST be delegated (NEVER do yourself):
|
|
160
|
+
- "Check how the CEP endpoint is implemented" → **Delegate to scout** (don't Read/Grep yourself)
|
|
161
|
+
- "Find where the payment flow is defined" → **Delegate to scout** (don't Glob yourself)
|
|
162
|
+
- "Investigate why the build fails" → **Delegate to debugger** (don't Bash yourself)
|
|
163
|
+
- "Understand the database schema" → **Delegate to scout** (don't Read yourself)
|
|
164
|
+
- "Look at what changed in the last PR" → **Delegate to scout** (don't use git log yourself)
|
|
165
|
+
- Any task where you'd use 2+ tool calls to explore → **DELEGATE IT**
|
|
166
|
+
|
|
167
|
+
### What's acceptable to do yourself:
|
|
168
|
+
- \`curl\` to check agent status via the Tide Commander API
|
|
169
|
+
- Reading a SHORT response/result that was sent directly to you
|
|
170
|
+
- Quick \`ls\` to verify a directory exists before delegating with correct paths
|
|
171
|
+
- Fetching agent history/details via \`/api/agents/\` endpoints
|
|
172
|
+
|
|
173
|
+
### The principle:
|
|
174
|
+
> **You are the boss. Bosses don't dig through filing cabinets — they send someone to get the information.**
|
|
175
|
+
> If a task involves exploring, researching, reading code, or investigating, that's your team's job.
|
|
176
|
+
> Your job is to DECIDE and DELEGATE, not to DO.
|
|
146
177
|
|
|
147
178
|
---
|
|
148
179
|
|
|
@@ -435,6 +466,31 @@ User: "Analyze the frontend, create a parallelizable plan, and assign tasks"
|
|
|
435
466
|
|
|
436
467
|
---
|
|
437
468
|
|
|
469
|
+
## ⚠️ PARALLELIZATION CAUTION
|
|
470
|
+
|
|
471
|
+
**Only parallelize when you are 100% certain:**
|
|
472
|
+
1. Tasks are truly independent with NO shared context or dependencies
|
|
473
|
+
2. Each task has ALL required information/context to complete independently
|
|
474
|
+
3. One task's output won't be needed as input for another task
|
|
475
|
+
4. Both agents can work simultaneously without blocking each other
|
|
476
|
+
5. You've verified both agents have the capabilities needed
|
|
477
|
+
|
|
478
|
+
**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.
|
|
479
|
+
|
|
480
|
+
**Default to SINGLE AGENT** for most work. Parallelization should be rare and intentional, not the default.
|
|
481
|
+
|
|
482
|
+
**Example - DON'T PARALLELIZE (BAD):**
|
|
483
|
+
- Task A: "Refactor the auth module"
|
|
484
|
+
- Task B: "Update the login form to match new auth API"
|
|
485
|
+
→ Task B depends on Task A being done first. Sequential only.
|
|
486
|
+
|
|
487
|
+
**Example - DO PARALLELIZE (GOOD):**
|
|
488
|
+
- Task A: "Add button styling to _buttons.scss"
|
|
489
|
+
- Task B: "Add input styling to _inputs.scss"
|
|
490
|
+
→ Independent files, no dependencies. Can parallelize.
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
438
494
|
## SPAWNING NEW AGENTS:
|
|
439
495
|
You can ONLY spawn new agents when the user EXPLICITLY requests it.
|
|
440
496
|
|
|
@@ -85,6 +85,54 @@ function buildEstimatedContextStats(totalTokens, contextWindow, model) {
|
|
|
85
85
|
lastUpdated: Date.now(),
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Update an existing contextStats with new totalTokens, keeping authoritative
|
|
90
|
+
* category breakdowns (from /context) if they exist, but always refreshing
|
|
91
|
+
* the top-level totalTokens/usedPercent/freeSpace so the value never goes stale.
|
|
92
|
+
*/
|
|
93
|
+
function updateContextStatsTokens(existing, totalTokens, contextWindow) {
|
|
94
|
+
const safeWindow = contextWindow && contextWindow > 0 ? contextWindow : existing.contextWindow;
|
|
95
|
+
const usedPercent = Math.min(100, Math.max(0, Math.round((totalTokens / safeWindow) * 100)));
|
|
96
|
+
const freeTokens = Math.max(0, safeWindow - totalTokens);
|
|
97
|
+
const freePercent = Number(((freeTokens / safeWindow) * 100).toFixed(1));
|
|
98
|
+
const cats = existing.categories;
|
|
99
|
+
const hasAuthoritativeBreakdown = (cats.systemPrompt?.tokens || 0) > 0 || (cats.systemTools?.tokens || 0) > 0;
|
|
100
|
+
let updatedCategories;
|
|
101
|
+
if (hasAuthoritativeBreakdown) {
|
|
102
|
+
// Authoritative breakdown from /context — keep systemPrompt/systemTools/autocompactBuffer,
|
|
103
|
+
// adjust messages to account for the difference
|
|
104
|
+
const fixedTokens = (cats.systemPrompt?.tokens || 0) + (cats.systemTools?.tokens || 0)
|
|
105
|
+
+ (cats.autocompactBuffer?.tokens || 0);
|
|
106
|
+
const messagesTokens = Math.max(0, totalTokens - fixedTokens);
|
|
107
|
+
const messagesPercent = Number(((messagesTokens / safeWindow) * 100).toFixed(1));
|
|
108
|
+
updatedCategories = {
|
|
109
|
+
systemPrompt: cats.systemPrompt,
|
|
110
|
+
systemTools: cats.systemTools,
|
|
111
|
+
messages: { tokens: messagesTokens, percent: messagesPercent },
|
|
112
|
+
freeSpace: { tokens: freeTokens, percent: freePercent },
|
|
113
|
+
autocompactBuffer: cats.autocompactBuffer,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// Estimated mode — all tokens attributed to messages
|
|
118
|
+
const messagesPercent = Number(((totalTokens / safeWindow) * 100).toFixed(1));
|
|
119
|
+
updatedCategories = {
|
|
120
|
+
systemPrompt: { tokens: 0, percent: 0 },
|
|
121
|
+
systemTools: { tokens: 0, percent: 0 },
|
|
122
|
+
messages: { tokens: totalTokens, percent: messagesPercent },
|
|
123
|
+
freeSpace: { tokens: freeTokens, percent: freePercent },
|
|
124
|
+
autocompactBuffer: { tokens: 0, percent: 0 },
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
...existing,
|
|
129
|
+
contextWindow: safeWindow,
|
|
130
|
+
totalTokens,
|
|
131
|
+
usedPercent,
|
|
132
|
+
categories: updatedCategories,
|
|
133
|
+
lastUpdated: Date.now(),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
88
136
|
export function createRuntimeEventHandlers(deps) {
|
|
89
137
|
const { log, emitEvent, emitOutput, emitComplete, emitError, parseUsageOutput, executeCommand, } = deps;
|
|
90
138
|
function handleEvent(agentId, event) {
|
|
@@ -148,9 +196,13 @@ export function createRuntimeEventHandlers(deps) {
|
|
|
148
196
|
const updates = {
|
|
149
197
|
contextUsed: safeContextUsed,
|
|
150
198
|
};
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
|
|
199
|
+
// Always keep contextStats.totalTokens in sync with contextUsed.
|
|
200
|
+
// If authoritative stats exist (from /context), merge the new total
|
|
201
|
+
// while preserving category breakdowns. Otherwise build estimated stats.
|
|
202
|
+
if (agent.contextStats && agent.contextStats.lastUpdated) {
|
|
203
|
+
updates.contextStats = updateContextStatsTokens(agent.contextStats, safeContextUsed, effectiveLimit);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
154
206
|
updates.contextStats = buildEstimatedContextStats(safeContextUsed, effectiveLimit, agent.model || 'claude');
|
|
155
207
|
}
|
|
156
208
|
agentService.updateAgent(agentId, updates, false);
|
|
@@ -259,11 +311,13 @@ export function createRuntimeEventHandlers(deps) {
|
|
|
259
311
|
contextUsed,
|
|
260
312
|
contextLimit,
|
|
261
313
|
};
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
314
|
+
// Always keep contextStats in sync. If authoritative stats exist (from
|
|
315
|
+
// /context), merge the updated totalTokens while preserving category
|
|
316
|
+
// breakdowns. Otherwise build fresh estimated stats.
|
|
317
|
+
if (agent.contextStats && agent.contextStats.lastUpdated) {
|
|
318
|
+
updates.contextStats = updateContextStatsTokens(agent.contextStats, Math.max(0, Math.round(contextUsed)), Math.max(1, Math.round(contextLimit)));
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
267
321
|
updates.contextStats = buildEstimatedContextStats(Math.max(0, Math.round(contextUsed)), Math.max(1, Math.round(contextLimit)), isClaudeProvider ? (agent.model || 'claude') : (agent.codexModel || agent.model));
|
|
268
322
|
}
|
|
269
323
|
agentService.updateAgent(agentId, updates);
|