tide-commander 1.40.1 → 1.40.2

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 (38) hide show
  1. package/dist/assets/{BossLogsModal-BLoXzVDi.js → BossLogsModal-CaDrNfm1.js} +1 -1
  2. package/dist/assets/{BossSpawnModal-GX8xd5-3.js → BossSpawnModal-DLJInoVf.js} +1 -1
  3. package/dist/assets/{ControlsModal-D2OZkjSB.js → ControlsModal-Cnnhwfr_.js} +1 -1
  4. package/dist/assets/{DockerLogsModal-DFRYDm_0.js → DockerLogsModal-D4CbWK3-.js} +1 -1
  5. package/dist/assets/{EmbeddedEditor-Bu2Steh-.js → EmbeddedEditor-36YBGNE2.js} +1 -1
  6. package/dist/assets/{GmailOAuthSetup-BpVO-ImN.js → GmailOAuthSetup-DI5j7wkF.js} +1 -1
  7. package/dist/assets/{GoogleOAuthSetup-CVz-M1dA.js → GoogleOAuthSetup-Bsj02mND.js} +1 -1
  8. package/dist/assets/{IframeModal-Cp4KI8NP.js → IframeModal-BJ4oeDBn.js} +1 -1
  9. package/dist/assets/{IntegrationsPanel-DiHTKLMF.js → IntegrationsPanel-DLmIJEUy.js} +2 -2
  10. package/dist/assets/{LogViewerModal-DooK7sML.js → LogViewerModal-D7CXMmZf.js} +1 -1
  11. package/dist/assets/{MonitoringModal-B6MLZ6Y7.js → MonitoringModal-PnEKvezF.js} +1 -1
  12. package/dist/assets/{PM2LogsModal-BShyePWe.js → PM2LogsModal-EB_Au0iK.js} +1 -1
  13. package/dist/assets/{RestoreArchivedAreaModal-CFQMGTd2.js → RestoreArchivedAreaModal-C-X90Qxe.js} +1 -1
  14. package/dist/assets/{SaveSnapshotModal-CKqHyZtG.js → SaveSnapshotModal-D6XAjL2T.js} +1 -1
  15. package/dist/assets/{Scene2DCanvas-C-xWZm8x.js → Scene2DCanvas-DlVguRVM.js} +1 -1
  16. package/dist/assets/{SceneManager-CIIB-LQG.js → SceneManager-OOaJ_z8v.js} +1 -1
  17. package/dist/assets/{SkillsPanel-DooQJMai.js → SkillsPanel-D5wo2MHh.js} +1 -1
  18. package/dist/assets/{SnapshotManager-CRwW0RPM.js → SnapshotManager-BLjpctX_.js} +1 -1
  19. package/dist/assets/{SpawnModal-DhaFze2c.js → SpawnModal-DQ4uUm1y.js} +1 -1
  20. package/dist/assets/{SubordinateAssignmentModal-CWHea30V.js → SubordinateAssignmentModal-BDUDt6WC.js} +1 -1
  21. package/dist/assets/{SupervisorPanel-BuWTDrxg.js → SupervisorPanel-BZaBI9BA.js} +1 -1
  22. package/dist/assets/{TriggerManagerPanel--gA5MwsR.js → TriggerManagerPanel-DuBiclsE.js} +1 -1
  23. package/dist/assets/{WorkflowEditorPanel-CyMOYUTz.js → WorkflowEditorPanel-D49yDqth.js} +1 -1
  24. package/dist/assets/{index-Cw-aP1sy.js → index-BSl18-4e.js} +1 -1
  25. package/dist/assets/{index-COCNZugG.js → index-BiGvhrCO.js} +1 -1
  26. package/dist/assets/{index-Q30ssVZv.js → index-BwkNteiZ.js} +1 -1
  27. package/dist/assets/{index-Dr_PsjVa.js → index-BxbFh16W.js} +2 -2
  28. package/dist/assets/{index-CwlSb5Lu.js → index-Bxjd0N-j.js} +1 -1
  29. package/dist/assets/{index-CCkR98jo.js → index-DJdXbeWz.js} +3 -3
  30. package/dist/assets/{index-ZQJ8yJQi.js → index-DZ3f9mNd.js} +1 -1
  31. package/dist/assets/{index-CnjRNKN3.js → index-mQmnkGdF.js} +1 -1
  32. package/dist/assets/{main-5cgtKFqy.js → main-DULfVodw.js} +4 -4
  33. package/dist/assets/{web-Ok_llxB1.js → web-DAqM9uoZ.js} +1 -1
  34. package/dist/assets/{web-E0gsfAuh.js → web-DQ10iSod.js} +1 -1
  35. package/dist/index.html +1 -1
  36. package/dist/src/packages/server/claude/runner/stdout-pipeline.js +9 -12
  37. package/dist/src/packages/server/services/runtime-events.js +3 -2
  38. package/package.json +1 -1
@@ -1 +1 @@
1
- import{bx as s}from"./main-5cgtKFqy.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-DULfVodw.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-5cgtKFqy.js";import{ImpactStyle as i,NotificationType as r}from"./index-Dr_PsjVa.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-DULfVodw.js";import{ImpactStyle as i,NotificationType as r}from"./index-BxbFh16W.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,7 +22,7 @@
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-5cgtKFqy.js"></script>
25
+ <script type="module" crossorigin src="/assets/main-DULfVodw.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">
@@ -86,6 +86,13 @@ export class RunnerStdoutPipeline {
86
86
  }
87
87
  }
88
88
  handleEvent(agentId, event) {
89
+ // After notification is sent, suppress ALL further events from the agentic loop.
90
+ // This prevents status flickering (working → idle → working) caused by OpenCode
91
+ // giving the model additional turns after the completion notification.
92
+ // Only 'init' events (new user message) can reset this gate.
93
+ if (this.notificationSent.has(agentId) && event.type !== 'init') {
94
+ return;
95
+ }
89
96
  const now = Date.now();
90
97
  this.bus.emit({ type: 'runner.activity', agentId, timestamp: now });
91
98
  this.bus.emit({ type: 'runner.event', agentId, event });
@@ -98,12 +105,6 @@ export class RunnerStdoutPipeline {
98
105
  break;
99
106
  case 'text':
100
107
  if (event.text) {
101
- // After notification is sent, suppress all further text (prevents OpenCode loop)
102
- if (this.notificationSent.has(agentId)) {
103
- log.log(`[text] Suppressing post-notification text for agent ${agentId.slice(0, 4)}`);
104
- this.textEmittedInTurn.add(agentId);
105
- break;
106
- }
107
108
  // Suppress consecutive identical text (extra safety for OpenCode agentic loop)
108
109
  const prevText = this.lastEmittedText.get(agentId);
109
110
  if (prevText && prevText === event.text.trim()) {
@@ -125,12 +126,8 @@ export class RunnerStdoutPipeline {
125
126
  if ((event.toolName === 'Task' || event.toolName === 'Agent') && event.subagentName) {
126
127
  this.activeSubagentName.set(agentId, event.subagentName);
127
128
  }
128
- // Detect notification curl calls to prevent OpenCode agentic loop.
129
- // After notification is sent, suppress all further output for this agent.
130
- if (this.notificationSent.has(agentId)) {
131
- log.log(`[tool_start] Suppressing post-notification tool for agent ${agentId.slice(0, 4)}`);
132
- break;
133
- }
129
+ // Detect notification curl mark agent so the top-level gate in handleEvent
130
+ // suppresses all subsequent agentic loop turns (text, tools, status flips).
134
131
  if (event.toolName === 'Bash' && this.isNotificationCurl(event.toolInput)) {
135
132
  this.notificationSent.add(agentId);
136
133
  log.log(`[tool_start] Notification detected for agent ${agentId.slice(0, 4)} - will suppress subsequent turns`);
@@ -339,7 +339,8 @@ export function createRuntimeEventHandlers(deps) {
339
339
  updates.contextStats = buildEstimatedContextStats(Math.max(0, Math.round(contextUsed)), Math.max(1, Math.round(contextLimit)), isClaudeProvider ? (agent.model || 'claude') : (agent.codexModel || agent.model));
340
340
  }
341
341
  agentService.updateAgent(agentId, updates);
342
- if (!isCodexProvider) {
342
+ const isOpencodeProvider = (agent.provider ?? 'claude') === 'opencode';
343
+ if (!isCodexProvider && !isOpencodeProvider) {
343
344
  setTimeout(() => {
344
345
  log.log(`[step_complete] Setting status to idle for agent ${agentId} (lastTask: ${agent.lastAssignedTask})`);
345
346
  agentService.updateAgent(agentId, {
@@ -350,7 +351,7 @@ export function createRuntimeEventHandlers(deps) {
350
351
  }, 200);
351
352
  }
352
353
  else {
353
- log.log(`[step_complete] Codex agent ${agentId} will be set idle on process completion`);
354
+ log.log(`[step_complete] ${isCodexProvider ? 'Codex' : 'OpenCode'} agent ${agentId} will be set idle on process completion`);
354
355
  }
355
356
  // Real-time context tracking via usage_snapshot events replaces automatic /context refresh.
356
357
  // The /context command is now only triggered manually via the UI refresh button.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tide-commander",
3
- "version": "1.40.1",
3
+ "version": "1.40.2",
4
4
  "description": "Visual multi-agent orchestrator and manager for Claude Code with 3D/2D interface",
5
5
  "repository": {
6
6
  "type": "git",