tide-commander 1.147.1 → 1.149.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.
- package/CHANGELOG.md +26 -0
- package/README.md +6 -3
- package/dist/assets/BossLogsModal-Cs4kWugD.js +1 -0
- package/dist/assets/BossSpawnModal-BudMgJqj.js +1 -0
- package/dist/assets/ControlsModal-Bh6_3qtH.js +1 -0
- package/dist/assets/DockerLogsModal-Nf4wQFfz.js +2 -0
- package/dist/assets/{EmbeddedEditor-DfM3SrO7.js → EmbeddedEditor-BfRXRX50.js} +1 -1
- package/dist/assets/{GmailOAuthSetup-DBWs7uzU.js → GmailOAuthSetup-CXUtjA0r.js} +1 -1
- package/dist/assets/{GoogleOAuthSetup-yQjT5QzU.js → GoogleOAuthSetup-D-_rwicD.js} +1 -1
- package/dist/assets/{IframeModal-DUTIyP5I.js → IframeModal-CdaXsQK0.js} +1 -1
- package/dist/assets/{IntegrationsPanel-DPURuiaz.js → IntegrationsPanel-ZsSVxcWr.js} +2 -2
- package/dist/assets/{LogViewerModal-CDZvTdfO.js → LogViewerModal-BAf-klB2.js} +1 -1
- package/dist/assets/{MonitoringModal-Dq2EJgbH.js → MonitoringModal-BjRbh5z4.js} +1 -1
- package/dist/assets/{PM2LogsModal-C3dlYlGv.js → PM2LogsModal-SaywDZVL.js} +2 -2
- package/dist/assets/{RestoreArchivedAreaModal-BMFk0G8D.js → RestoreArchivedAreaModal-jru2Ez9a.js} +1 -1
- package/dist/assets/Scene2DCanvas-NJHoe2Qg.js +1 -0
- package/dist/assets/SceneManager-i9wVMa_V.js +104 -0
- package/dist/assets/{SkillsPanel-D326VBDa.js → SkillsPanel-BHfKLzWe.js} +3 -3
- package/dist/assets/{SlackMultiInstanceSetup-CA4nm925.js → SlackMultiInstanceSetup-BfVevCSo.js} +1 -1
- package/dist/assets/SpawnModal-29x5z53B.js +1 -0
- package/dist/assets/{StatisticsModal-BUpvkJXA.js → StatisticsModal-MbIByjWD.js} +1 -1
- package/dist/assets/{SubordinateAssignmentModal-DtVsKDqV.js → SubordinateAssignmentModal-DF0vYaM6.js} +1 -1
- package/dist/assets/{TriggerManagerPanel-OD14xVMw.js → TriggerManagerPanel-EGcKS1Pt.js} +1 -1
- package/dist/assets/{WorkflowEditorPanel-B4UF3rcS.js → WorkflowEditorPanel-BLmejfqe.js} +1 -1
- package/dist/assets/{area-logos-Uc9SAeYg.js → area-logos-C4fgpLgO.js} +1 -1
- package/dist/assets/grok.ico +0 -0
- package/dist/assets/grok.png +0 -0
- package/dist/assets/{index-xBtKu0I8.js → index-B-2H7O_Y.js} +2 -2
- package/dist/assets/{index-CuHJm43U.js → index-B9xpLAcH.js} +1 -1
- package/dist/assets/index-BZ4wZwRu.js +19 -0
- package/dist/assets/index-BiiLWTXJ.js +1 -0
- package/dist/assets/{index-BC3Y_BAQ.js → index-C6Kf4ewu.js} +5 -5
- package/dist/assets/index-C8CGfmXP.js +1 -0
- package/dist/assets/index-DThK5_yS.js +5 -0
- package/dist/assets/index-DYgVP0G3.js +2 -0
- package/dist/assets/index-DhD3m2Qx.js +1 -0
- package/dist/assets/main-B0UlZnfk.js +260 -0
- package/dist/assets/main-DeiAIdzy.css +1 -0
- package/dist/assets/{web-DlzqHyn8.js → web-CXC8P25z.js} +1 -1
- package/dist/assets/{web-B-xc0c6e.js → web-LGEDa25c.js} +1 -1
- package/dist/assets/{web-BuDeKWBN.js → web-NM4dUqWg.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/locales/de/tools.json +3 -1
- package/dist/locales/en/tools.json +7 -3
- package/dist/locales/es/tools.json +3 -1
- package/dist/locales/fr/tools.json +4 -2
- package/dist/locales/hi/tools.json +4 -2
- package/dist/locales/it/tools.json +19 -17
- package/dist/locales/ja/tools.json +4 -2
- package/dist/locales/pt/tools.json +3 -1
- package/dist/locales/ru/tools.json +3 -1
- package/dist/locales/zh-CN/tools.json +3 -1
- package/dist/src/packages/server/claude/runner/process-lifecycle.js +53 -0
- package/dist/src/packages/server/claude/runner/stdout-pipeline.js +125 -4
- package/dist/src/packages/server/claude/runner/watchdog.js +12 -0
- package/dist/src/packages/server/claude/session-loader.js +280 -0
- package/dist/src/packages/server/data/index.js +1 -0
- package/dist/src/packages/server/grok/backend.js +231 -0
- package/dist/src/packages/server/grok/index.js +4 -0
- package/dist/src/packages/server/grok/json-event-parser.js +138 -0
- package/dist/src/packages/server/grok/session-watcher.js +460 -0
- package/dist/src/packages/server/routes/agents.js +7 -2
- package/dist/src/packages/server/runtime/grok-runtime-provider.js +11 -0
- package/dist/src/packages/server/runtime/index.js +1 -0
- package/dist/src/packages/server/services/agent-service.js +26 -5
- package/dist/src/packages/server/services/runtime-command-execution.js +4 -2
- package/dist/src/packages/server/services/runtime-events.js +46 -7
- package/dist/src/packages/server/services/runtime-service.js +19 -3
- package/dist/src/packages/server/utils/tool-formatting.js +40 -12
- package/dist/src/packages/server/websocket/handlers/agent-handler.js +70 -17
- package/dist/src/packages/server/websocket/listeners/runtime-listeners.js +63 -7
- package/dist/src/packages/shared/agent-types.js +10 -0
- package/package.json +1 -1
- package/dist/assets/BossLogsModal-Cn8IVdqn.js +0 -1
- package/dist/assets/BossSpawnModal-Don-RZyh.js +0 -1
- package/dist/assets/ControlsModal-C9--xWPi.js +0 -1
- package/dist/assets/DockerLogsModal-DSGnpfm5.js +0 -2
- package/dist/assets/Scene2DCanvas-DlumJCbl.js +0 -1
- package/dist/assets/SceneManager-UnhMFja8.js +0 -104
- package/dist/assets/SpawnModal-B1QOjZPe.js +0 -1
- package/dist/assets/index-BD6swoQU.js +0 -19
- package/dist/assets/index-C4mf6B5U.js +0 -1
- package/dist/assets/index-COHImd74.js +0 -1
- package/dist/assets/index-CScFEdm8.js +0 -1
- package/dist/assets/index-CmmpVZ8w.js +0 -2
- package/dist/assets/index-DkDzXtdj.js +0 -5
- package/dist/assets/main-Bp6V_-sL.js +0 -256
- package/dist/assets/main-ijcbyjBn.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{dc as s}from"./main-B0UlZnfk.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class l 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{l as LocalNotificationsWeb};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{dc as t}from"./main-B0UlZnfk.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class o extends t{constructor(){super(),this.handleVisibilityChange=()=>{const e={isActive:document.hidden!==!0};this.notifyListeners("appStateChange",e),document.hidden?this.notifyListeners("pause",null):this.notifyListeners("resume",null)},document.addEventListener("visibilitychange",this.handleVisibilityChange,!1)}exitApp(){throw this.unimplemented("Not implemented on web.")}async getInfo(){throw this.unimplemented("Not implemented on web.")}async getLaunchUrl(){return{url:""}}async getState(){return{isActive:document.hidden!==!0}}async minimizeApp(){throw this.unimplemented("Not implemented on web.")}async toggleBackButtonHandler(){throw this.unimplemented("Not implemented on web.")}async getAppLanguage(){return{value:navigator.language.split("-")[0].toLowerCase()}}}export{o as AppWeb};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{dc as a}from"./main-B0UlZnfk.js";import{ImpactStyle as i,NotificationType as r}from"./index-B-2H7O_Y.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class h 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{h as HapticsWeb};
|
package/dist/index.html
CHANGED
|
@@ -22,10 +22,10 @@
|
|
|
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-B0UlZnfk.js"></script>
|
|
26
26
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react--Eh9ivFN.js">
|
|
27
27
|
<link rel="modulepreload" crossorigin href="/assets/vendor-three-Chj50gSY.js">
|
|
28
|
-
<link rel="stylesheet" crossorigin href="/assets/main-
|
|
28
|
+
<link rel="stylesheet" crossorigin href="/assets/main-DeiAIdzy.css">
|
|
29
29
|
</head>
|
|
30
30
|
<body>
|
|
31
31
|
<div id="app"></div>
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"listFiles": "Dateien auflisten",
|
|
46
46
|
"searchFiles": "Dateien durchsuchen",
|
|
47
47
|
"executeCommand": "Befehl ausführen"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"showOutputsInline": "Alle Bash-Ausgaben inline anzeigen",
|
|
50
|
+
"hideOutputsInline": "Inline-Bash-Ausgaben ausblenden"
|
|
49
51
|
},
|
|
50
52
|
"metadata": {
|
|
51
53
|
"messageInfo": "Nachrichteninfo",
|
|
@@ -43,13 +43,17 @@
|
|
|
43
43
|
"askFollowupQuestion": "AskFollowupQuestion",
|
|
44
44
|
"askUserQuestion": "AskUserQuestion",
|
|
45
45
|
"attemptCompletion": "AttemptCompletion",
|
|
46
|
-
"listFiles": "
|
|
47
|
-
"searchFiles": "
|
|
46
|
+
"listFiles": "List Files",
|
|
47
|
+
"searchFiles": "Search Files",
|
|
48
48
|
"executeCommand": "ExecuteCommand",
|
|
49
49
|
"spawnAgent": "Spawn Agent",
|
|
50
50
|
"sendInput": "Send Input",
|
|
51
|
+
"sendMessage": "Message Agent",
|
|
52
|
+
"taskOutput": "Task Output",
|
|
51
53
|
"wait": "Wait"
|
|
52
|
-
}
|
|
54
|
+
},
|
|
55
|
+
"showOutputsInline": "Show all bash outputs inline",
|
|
56
|
+
"hideOutputsInline": "Hide inline bash outputs"
|
|
53
57
|
},
|
|
54
58
|
"metadata": {
|
|
55
59
|
"messageInfo": "Message Info",
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"listFiles": "Listar archivos",
|
|
46
46
|
"searchFiles": "Buscar archivos",
|
|
47
47
|
"executeCommand": "Ejecutar comando"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"showOutputsInline": "Mostrar todos los outputs de bash en línea",
|
|
50
|
+
"hideOutputsInline": "Ocultar los outputs de bash en línea"
|
|
49
51
|
},
|
|
50
52
|
"metadata": {
|
|
51
53
|
"messageInfo": "Info del mensaje",
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"listFiles": "ListFiles",
|
|
46
46
|
"searchFiles": "SearchFiles",
|
|
47
47
|
"executeCommand": "ExecuteCommand"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"showOutputsInline": "Afficher toutes les sorties bash en ligne",
|
|
50
|
+
"hideOutputsInline": "Masquer les sorties bash en ligne"
|
|
49
51
|
},
|
|
50
52
|
"metadata": {
|
|
51
53
|
"messageInfo": "Infos du message",
|
|
@@ -272,4 +274,4 @@
|
|
|
272
274
|
"noContent": "Aucun contenu de réponse disponible.",
|
|
273
275
|
"rawMarkdown": "Markdown brut"
|
|
274
276
|
}
|
|
275
|
-
}
|
|
277
|
+
}
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"listFiles": "ListFiles",
|
|
46
46
|
"searchFiles": "SearchFiles",
|
|
47
47
|
"executeCommand": "ExecuteCommand"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"showOutputsInline": "सभी bash आउटपुट इनलाइन दिखाएँ",
|
|
50
|
+
"hideOutputsInline": "इनलाइन bash आउटपुट छिपाएँ"
|
|
49
51
|
},
|
|
50
52
|
"metadata": {
|
|
51
53
|
"messageInfo": "संदेश जानकारी",
|
|
@@ -272,4 +274,4 @@
|
|
|
272
274
|
"noContent": "कोई प्रतिक्रिया सामग्री उपलब्ध नहीं।",
|
|
273
275
|
"rawMarkdown": "रॉ Markdown"
|
|
274
276
|
}
|
|
275
|
-
}
|
|
277
|
+
}
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"listFiles": "ListFiles",
|
|
46
46
|
"searchFiles": "SearchFiles",
|
|
47
47
|
"executeCommand": "ExecuteCommand"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"showOutputsInline": "Mostra tutti gli output bash in linea",
|
|
50
|
+
"hideOutputsInline": "Nascondi gli output bash in linea"
|
|
49
51
|
},
|
|
50
52
|
"metadata": {
|
|
51
53
|
"messageInfo": "Info messaggio",
|
|
@@ -85,7 +87,7 @@
|
|
|
85
87
|
"builtIn": "Integrata",
|
|
86
88
|
"notAssigned": "Non assegnata",
|
|
87
89
|
"noSkillsDefined": "Nessuna skill definita ancora",
|
|
88
|
-
"createSkillsHint": "Crea skill per insegnare agli agenti
|
|
90
|
+
"createSkillsHint": "Crea skill per insegnare agli agenti capacità specifiche",
|
|
89
91
|
"noCustomClasses": "Nessuna classe agente personalizzata ancora",
|
|
90
92
|
"createClassesHint": "Crea classi personalizzate con skill predefinite associate",
|
|
91
93
|
"noClassesMatch": "Nessuna classe corrisponde a \"{{query}}\"",
|
|
@@ -121,7 +123,7 @@
|
|
|
121
123
|
"uploading": "Caricamento...",
|
|
122
124
|
"createClass": "Crea classe",
|
|
123
125
|
"viewBuiltInSkill": "Visualizza skill integrata",
|
|
124
|
-
"builtInNotice": "Questa
|
|
126
|
+
"builtInNotice": "Questa è una skill integrata di Tide Commander. Il contenuto non può essere modificato, ma puoi cambiare a quali agenti e classi è assegnata.",
|
|
125
127
|
"nameRequired": "Nome *",
|
|
126
128
|
"slugLabel": "Slug",
|
|
127
129
|
"slugHint": "Identificativo URL-safe (generato automaticamente)",
|
|
@@ -138,8 +140,8 @@
|
|
|
138
140
|
"disabledSkillsHint": "Le skill disabilitate non saranno disponibili per gli agenti",
|
|
139
141
|
"saveAssignments": "Salva assegnazioni",
|
|
140
142
|
"createSkill": "Crea skill",
|
|
141
|
-
"deleteSkillConfirm": "Eliminare questa skill? Questa azione non
|
|
142
|
-
"updateSkillConfirm": "L'aggiornamento di questa skill
|
|
143
|
+
"deleteSkillConfirm": "Eliminare questa skill? Questa azione non può essere annullata.",
|
|
144
|
+
"updateSkillConfirm": "L'aggiornamento di questa skill riavvierà tutti gli agenti che la utilizzano.\n\nDovrai riprendere manualmente gli agenti che stavano lavorando.\n\nContinuare?",
|
|
143
145
|
"deleteClassConfirm": "Sei sicuro di voler eliminare questa classe agente personalizzata?",
|
|
144
146
|
"classCount": "{{count}} classi",
|
|
145
147
|
"agentCount": "{{count}} agente/i",
|
|
@@ -164,7 +166,7 @@
|
|
|
164
166
|
"classScout": "Scout",
|
|
165
167
|
"classScoutDesc": "Esplorazione del codebase",
|
|
166
168
|
"classBuilder": "Builder",
|
|
167
|
-
"classBuilderDesc": "Implementazione
|
|
169
|
+
"classBuilderDesc": "Implementazione funzionalità",
|
|
168
170
|
"classDebugger": "Debugger",
|
|
169
171
|
"classDebuggerDesc": "Ricerca e correzione bug",
|
|
170
172
|
"classArchitect": "Architetto",
|
|
@@ -196,7 +198,7 @@
|
|
|
196
198
|
"customToolPlaceholder": "Strumento personalizzato (es. Bash(make:*))"
|
|
197
199
|
},
|
|
198
200
|
"subagent": {
|
|
199
|
-
"subagentTask": "
|
|
201
|
+
"subagentTask": "Attività sottoagente",
|
|
200
202
|
"spawned": "Generato",
|
|
201
203
|
"completed": "Completato",
|
|
202
204
|
"duration": "Durata"
|
|
@@ -223,24 +225,24 @@
|
|
|
223
225
|
"replaceAll": "Sostituisci tutto"
|
|
224
226
|
},
|
|
225
227
|
"todoList": {
|
|
226
|
-
"title": "Lista
|
|
228
|
+
"title": "Lista attività"
|
|
227
229
|
},
|
|
228
230
|
"bossContext": {
|
|
229
231
|
"teamContext": "Contesto team",
|
|
230
232
|
"injectedInstructions": "Istruzioni agente iniettate"
|
|
231
233
|
},
|
|
232
234
|
"delegation": {
|
|
233
|
-
"taskDelegated": "
|
|
235
|
+
"taskDelegated": "Attività delegata",
|
|
234
236
|
"to": "A:",
|
|
235
|
-
"task": "Attivit
|
|
236
|
-
"why": "Perch
|
|
237
|
+
"task": "Attività:",
|
|
238
|
+
"why": "Perché:",
|
|
237
239
|
"alternatives": "Alternative:",
|
|
238
240
|
"autoForwarding": "Inoltro automatico a {{name}}...",
|
|
239
241
|
"via": "tramite"
|
|
240
242
|
},
|
|
241
243
|
"workPlan": {
|
|
242
244
|
"phases": "{{count}} fasi",
|
|
243
|
-
"tasks": "{{count}}
|
|
245
|
+
"tasks": "{{count}} attività",
|
|
244
246
|
"parallel": "parallelo",
|
|
245
247
|
"sequential": "sequenziale",
|
|
246
248
|
"dependsOn": "dipende da:",
|
|
@@ -251,13 +253,13 @@
|
|
|
251
253
|
},
|
|
252
254
|
"progress": {
|
|
253
255
|
"workingOn": "sta lavorando su...",
|
|
254
|
-
"taskFinished": "
|
|
255
|
-
"taskFailed": "
|
|
256
|
+
"taskFinished": "Attività completata",
|
|
257
|
+
"taskFailed": "Attività fallita"
|
|
256
258
|
},
|
|
257
259
|
"exec": {
|
|
258
|
-
"runningTasks": "
|
|
260
|
+
"runningTasks": "Attività in esecuzione",
|
|
259
261
|
"running": "in esecuzione",
|
|
260
|
-
"stopTask": "Ferma
|
|
262
|
+
"stopTask": "Ferma attività",
|
|
261
263
|
"dismiss": "Chiudi",
|
|
262
264
|
"clearCompleted": "Cancella completate"
|
|
263
265
|
},
|
|
@@ -272,4 +274,4 @@
|
|
|
272
274
|
"noContent": "Nessun contenuto di risposta disponibile.",
|
|
273
275
|
"rawMarkdown": "Markdown grezzo"
|
|
274
276
|
}
|
|
275
|
-
}
|
|
277
|
+
}
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"listFiles": "ListFiles",
|
|
46
46
|
"searchFiles": "SearchFiles",
|
|
47
47
|
"executeCommand": "ExecuteCommand"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"showOutputsInline": "すべてのBash出力をインライン表示",
|
|
50
|
+
"hideOutputsInline": "インラインBash出力を非表示"
|
|
49
51
|
},
|
|
50
52
|
"metadata": {
|
|
51
53
|
"messageInfo": "メッセージ情報",
|
|
@@ -272,4 +274,4 @@
|
|
|
272
274
|
"noContent": "レスポンス内容がありません。",
|
|
273
275
|
"rawMarkdown": "生Markdown"
|
|
274
276
|
}
|
|
275
|
-
}
|
|
277
|
+
}
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"listFiles": "ListFiles",
|
|
46
46
|
"searchFiles": "SearchFiles",
|
|
47
47
|
"executeCommand": "ExecuteCommand"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"showOutputsInline": "Mostrar todas as saídas do bash em linha",
|
|
50
|
+
"hideOutputsInline": "Ocultar as saídas do bash em linha"
|
|
49
51
|
},
|
|
50
52
|
"metadata": {
|
|
51
53
|
"messageInfo": "Info da Mensagem",
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"listFiles": "ListFiles",
|
|
46
46
|
"searchFiles": "SearchFiles",
|
|
47
47
|
"executeCommand": "ExecuteCommand"
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"showOutputsInline": "Показывать все выводы bash в строке",
|
|
50
|
+
"hideOutputsInline": "Скрыть встроенные выводы bash"
|
|
49
51
|
},
|
|
50
52
|
"metadata": {
|
|
51
53
|
"messageInfo": "Информация о сообщении",
|
|
@@ -3,6 +3,7 @@ import * as path from 'path';
|
|
|
3
3
|
import { StringDecoder } from 'string_decoder';
|
|
4
4
|
import { createLogger } from '../../utils/logger.js';
|
|
5
5
|
import { isTmuxEnabled, checkTmuxAvailability, spawnInTmux, killTmuxSession, interruptTmuxSession, } from './tmux-helper.js';
|
|
6
|
+
import { startGrokSessionWatcher } from '../../grok/session-watcher.js';
|
|
6
7
|
const log = createLogger('Runner');
|
|
7
8
|
export class RunnerProcessLifecycle {
|
|
8
9
|
backend;
|
|
@@ -25,6 +26,35 @@ export class RunnerProcessLifecycle {
|
|
|
25
26
|
this.recoveryStore = deps.recoveryStore;
|
|
26
27
|
this.onDisableAutoRestart = deps.onDisableAutoRestart;
|
|
27
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Grok headless does not stream tool events on stdout. Tail session files
|
|
31
|
+
* and inject tool_start/tool_result into the same pipeline as stdout events.
|
|
32
|
+
*/
|
|
33
|
+
attachGrokSideChannel(activeProcess, agentId, workingDir, sessionId) {
|
|
34
|
+
if (this.backend.name !== 'grok')
|
|
35
|
+
return;
|
|
36
|
+
const watcher = startGrokSessionWatcher({
|
|
37
|
+
agentId,
|
|
38
|
+
workingDir,
|
|
39
|
+
sessionId,
|
|
40
|
+
startedAt: activeProcess.startTime,
|
|
41
|
+
onEvent: (event) => {
|
|
42
|
+
this.stdoutPipeline.emitStandardEvent(agentId, event);
|
|
43
|
+
},
|
|
44
|
+
onSessionId: (sid) => {
|
|
45
|
+
const proc = this.activeProcesses.get(agentId);
|
|
46
|
+
if (proc && !proc.sessionId) {
|
|
47
|
+
proc.sessionId = sid;
|
|
48
|
+
if (proc.lastRequest && !proc.lastRequest.sessionId) {
|
|
49
|
+
proc.lastRequest.sessionId = sid;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
this.bus.emit({ type: 'runner.session_id', agentId, sessionId: sid });
|
|
53
|
+
this.callbacks.onSessionId(agentId, sid);
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
activeProcess.sideChannelStop = () => watcher.stop();
|
|
57
|
+
}
|
|
28
58
|
async run(request) {
|
|
29
59
|
const { agentId, prompt, workingDir, sessionId, model, effort, useChrome, permissionMode = 'bypass', systemPrompt, forceNewSession, forkSession, customAgent, } = request;
|
|
30
60
|
await this.stop(agentId);
|
|
@@ -90,6 +120,7 @@ export class RunnerProcessLifecycle {
|
|
|
90
120
|
tmuxExpectedCommand: path.basename(executable),
|
|
91
121
|
};
|
|
92
122
|
this.activeProcesses.set(agentId, activeProcess);
|
|
123
|
+
this.attachGrokSideChannel(activeProcess, agentId, workingDir, forceNewSession ? undefined : sessionId);
|
|
93
124
|
// Use file-tailing stdout pipeline for tmux mode
|
|
94
125
|
const tailer = this.stdoutPipeline.handleTmuxLog(agentId, tmuxResult.logFile);
|
|
95
126
|
activeProcess.tmuxTailer = tailer;
|
|
@@ -136,10 +167,25 @@ export class RunnerProcessLifecycle {
|
|
|
136
167
|
turnState: 'processing',
|
|
137
168
|
};
|
|
138
169
|
this.activeProcesses.set(agentId, activeProcess);
|
|
170
|
+
this.attachGrokSideChannel(activeProcess, agentId, workingDir, forceNewSession ? undefined : sessionId);
|
|
139
171
|
const stdoutDone = this.stdoutPipeline.handleStdout(agentId, childProcess);
|
|
140
172
|
this.handleStderr(agentId, childProcess);
|
|
141
173
|
childProcess.on('close', async (code, signal) => {
|
|
142
174
|
await stdoutDone;
|
|
175
|
+
// Keep tailing session files briefly so the last tool_result lines flush to disk
|
|
176
|
+
// after the CLI exits (common race on Grok headless).
|
|
177
|
+
const sideStop = activeProcess.sideChannelStop;
|
|
178
|
+
activeProcess.sideChannelStop = undefined;
|
|
179
|
+
if (sideStop) {
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
try {
|
|
182
|
+
sideStop();
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// ignore
|
|
186
|
+
}
|
|
187
|
+
}, 2000);
|
|
188
|
+
}
|
|
143
189
|
this.bus.emit({
|
|
144
190
|
type: 'runner.process_closed',
|
|
145
191
|
agentId,
|
|
@@ -221,6 +267,13 @@ export class RunnerProcessLifecycle {
|
|
|
221
267
|
if (activeProcess.tmuxTailer) {
|
|
222
268
|
activeProcess.tmuxTailer.stop();
|
|
223
269
|
}
|
|
270
|
+
try {
|
|
271
|
+
activeProcess.sideChannelStop?.();
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
// ignore
|
|
275
|
+
}
|
|
276
|
+
activeProcess.sideChannelStop = undefined;
|
|
224
277
|
this.activeProcesses.delete(agentId);
|
|
225
278
|
this.activityCallbacks.delete(agentId);
|
|
226
279
|
// tmux mode: kill the tmux session and clean up
|
|
@@ -16,11 +16,24 @@ export class RunnerStdoutPipeline {
|
|
|
16
16
|
// loops (respond → notify → respond → notify → ...). Once the notification is sent,
|
|
17
17
|
// suppress all further text/tool output until a new user message arrives.
|
|
18
18
|
notificationSent = new Set();
|
|
19
|
+
// Streaming thinking blocks share a uuid across token deltas. The UI marks a
|
|
20
|
+
// row as thinking via a single leading `[thinking]` prefix — only the first
|
|
21
|
+
// chunk of each stream should get it, otherwise merges become
|
|
22
|
+
// `[thinking] a[thinking] b…`.
|
|
23
|
+
thinkingStreamPrefixed = new Set();
|
|
24
|
+
// High-frequency token streams (Grok headless) produce dozens of tiny deltas
|
|
25
|
+
// per second. Coalesce them into ~one flush every STREAM_COALESCE_MS so the
|
|
26
|
+
// client doesn't remeasure/redraw the virtual list on every token.
|
|
27
|
+
streamCoalesce = new Map();
|
|
19
28
|
constructor(deps) {
|
|
20
29
|
this.backend = deps.backend;
|
|
21
30
|
this.callbacks = deps.callbacks;
|
|
22
31
|
this.bus = deps.bus;
|
|
23
32
|
}
|
|
33
|
+
/** Backends that emit token-sized streaming-json deltas. */
|
|
34
|
+
shouldCoalesceStreaming() {
|
|
35
|
+
return this.backend.name === 'grok';
|
|
36
|
+
}
|
|
24
37
|
handleStdout(agentId, process) {
|
|
25
38
|
return new Promise((resolve) => {
|
|
26
39
|
const decoder = new StringDecoder('utf8');
|
|
@@ -134,25 +147,75 @@ export class RunnerStdoutPipeline {
|
|
|
134
147
|
case 'init':
|
|
135
148
|
this.lastEmittedText.delete(agentId);
|
|
136
149
|
this.notificationSent.delete(agentId);
|
|
150
|
+
this.clearThinkingPrefixState(agentId);
|
|
137
151
|
this.callbacks.onOutput(agentId, `Session started: ${event.sessionId} (${event.model})`);
|
|
138
152
|
break;
|
|
139
153
|
case 'text':
|
|
140
154
|
if (event.text) {
|
|
141
155
|
// Suppress consecutive identical text (extra safety for OpenCode agentic loop)
|
|
156
|
+
// Skip for streaming chunks — token-level deltas are intentionally small and
|
|
157
|
+
// may legitimately repeat, and they are merged client-side by uuid.
|
|
142
158
|
const prevText = this.lastEmittedText.get(agentId);
|
|
143
|
-
if (prevText && prevText === event.text.trim()) {
|
|
159
|
+
if (!event.isStreaming && prevText && prevText === event.text.trim()) {
|
|
144
160
|
log.log(`[text] Suppressing duplicate text for agent ${agentId.slice(0, 4)}`);
|
|
145
161
|
this.textEmittedInTurn.add(agentId);
|
|
146
162
|
break;
|
|
147
163
|
}
|
|
148
|
-
|
|
149
|
-
|
|
164
|
+
if (event.isStreaming && event.uuid && this.shouldCoalesceStreaming()) {
|
|
165
|
+
this.enqueueStreamChunk(agentId, event.uuid, 'text', event.text);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// Flush any pending coalesced deltas before a final/non-stream emit
|
|
169
|
+
// so the client never applies final full-text over a stale partial.
|
|
170
|
+
if (event.uuid) {
|
|
171
|
+
this.flushStreamCoalesce(`${agentId}:text:${event.uuid}`);
|
|
172
|
+
}
|
|
173
|
+
if (!event.isStreaming) {
|
|
174
|
+
this.lastEmittedText.set(agentId, event.text.trim());
|
|
175
|
+
}
|
|
176
|
+
this.callbacks.onOutput(agentId, event.text, event.isStreaming, undefined, event.uuid);
|
|
177
|
+
}
|
|
150
178
|
this.textEmittedInTurn.add(agentId);
|
|
151
179
|
}
|
|
152
180
|
break;
|
|
153
181
|
case 'thinking':
|
|
154
182
|
if (event.text) {
|
|
155
|
-
|
|
183
|
+
const streamKey = event.uuid ? `${agentId}:${event.uuid}` : undefined;
|
|
184
|
+
if (!event.isStreaming) {
|
|
185
|
+
if (event.uuid) {
|
|
186
|
+
this.flushStreamCoalesce(`${agentId}:thinking:${event.uuid}`);
|
|
187
|
+
}
|
|
188
|
+
const thinkingOut = event.text.startsWith('[thinking]')
|
|
189
|
+
? event.text
|
|
190
|
+
: `[thinking] ${event.text}`;
|
|
191
|
+
this.callbacks.onOutput(agentId, thinkingOut, false, undefined, event.uuid);
|
|
192
|
+
if (streamKey) {
|
|
193
|
+
this.thinkingStreamPrefixed.delete(streamKey);
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
// Streaming path
|
|
198
|
+
if (event.uuid && this.shouldCoalesceStreaming()) {
|
|
199
|
+
let chunk = event.text;
|
|
200
|
+
if (streamKey && !this.thinkingStreamPrefixed.has(streamKey)) {
|
|
201
|
+
this.thinkingStreamPrefixed.add(streamKey);
|
|
202
|
+
chunk = `[thinking] ${event.text}`;
|
|
203
|
+
}
|
|
204
|
+
this.enqueueStreamChunk(agentId, event.uuid, 'thinking', chunk);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
let thinkingOut = event.text;
|
|
208
|
+
if (streamKey) {
|
|
209
|
+
if (!this.thinkingStreamPrefixed.has(streamKey)) {
|
|
210
|
+
this.thinkingStreamPrefixed.add(streamKey);
|
|
211
|
+
thinkingOut = `[thinking] ${event.text}`;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else if (!event.text.startsWith('[thinking]')) {
|
|
215
|
+
thinkingOut = `[thinking] ${event.text}`;
|
|
216
|
+
}
|
|
217
|
+
this.callbacks.onOutput(agentId, thinkingOut, true, undefined, event.uuid);
|
|
218
|
+
}
|
|
156
219
|
}
|
|
157
220
|
break;
|
|
158
221
|
case 'tool_start': {
|
|
@@ -195,6 +258,8 @@ export class RunnerStdoutPipeline {
|
|
|
195
258
|
break;
|
|
196
259
|
}
|
|
197
260
|
case 'step_complete': {
|
|
261
|
+
// Flush any pending coalesced stream chunks before finalizing the turn
|
|
262
|
+
this.flushAllStreamCoalesceForAgent(agentId);
|
|
198
263
|
const hasErrorResultText = this.isLikelyErrorResultText(event.resultText);
|
|
199
264
|
if (event.resultText && (!this.textEmittedInTurn.has(agentId) || hasErrorResultText)) {
|
|
200
265
|
log.log(`[step_complete] Emitting resultText as fallback (no prior text events) for agent ${agentId.slice(0, 4)}`);
|
|
@@ -203,6 +268,8 @@ export class RunnerStdoutPipeline {
|
|
|
203
268
|
else if (event.resultText) {
|
|
204
269
|
log.log(`[step_complete] Skipping resultText (already emitted via text events) for agent ${agentId.slice(0, 4)}`);
|
|
205
270
|
}
|
|
271
|
+
this.textEmittedInTurn.delete(agentId);
|
|
272
|
+
this.clearThinkingPrefixState(agentId);
|
|
206
273
|
if (event.permissionDenials && event.permissionDenials.length > 0) {
|
|
207
274
|
for (const denial of event.permissionDenials) {
|
|
208
275
|
// Suppress the "[System] Permission denied" line for the two tools
|
|
@@ -245,6 +312,60 @@ export class RunnerStdoutPipeline {
|
|
|
245
312
|
break;
|
|
246
313
|
}
|
|
247
314
|
}
|
|
315
|
+
clearThinkingPrefixState(agentId) {
|
|
316
|
+
const prefix = `${agentId}:`;
|
|
317
|
+
for (const key of this.thinkingStreamPrefixed) {
|
|
318
|
+
if (key.startsWith(prefix)) {
|
|
319
|
+
this.thinkingStreamPrefixed.delete(key);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Drop any pending coalesced chunks for this agent
|
|
323
|
+
for (const [key, buf] of this.streamCoalesce) {
|
|
324
|
+
if (buf.agentId === agentId) {
|
|
325
|
+
if (buf.timer)
|
|
326
|
+
clearTimeout(buf.timer);
|
|
327
|
+
this.streamCoalesce.delete(key);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
static STREAM_COALESCE_MS = 80;
|
|
332
|
+
enqueueStreamChunk(agentId, uuid, kind, chunk) {
|
|
333
|
+
const key = `${agentId}:${kind}:${uuid}`;
|
|
334
|
+
let buf = this.streamCoalesce.get(key);
|
|
335
|
+
if (!buf) {
|
|
336
|
+
buf = { agentId, uuid, kind, chunks: [], timer: null };
|
|
337
|
+
this.streamCoalesce.set(key, buf);
|
|
338
|
+
}
|
|
339
|
+
buf.chunks.push(chunk);
|
|
340
|
+
if (buf.timer)
|
|
341
|
+
return;
|
|
342
|
+
buf.timer = setTimeout(() => {
|
|
343
|
+
this.flushStreamCoalesce(key);
|
|
344
|
+
}, RunnerStdoutPipeline.STREAM_COALESCE_MS);
|
|
345
|
+
}
|
|
346
|
+
flushStreamCoalesce(key) {
|
|
347
|
+
const buf = this.streamCoalesce.get(key);
|
|
348
|
+
if (!buf)
|
|
349
|
+
return;
|
|
350
|
+
if (buf.timer) {
|
|
351
|
+
clearTimeout(buf.timer);
|
|
352
|
+
buf.timer = null;
|
|
353
|
+
}
|
|
354
|
+
if (buf.chunks.length === 0) {
|
|
355
|
+
this.streamCoalesce.delete(key);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const text = buf.chunks.join('');
|
|
359
|
+
buf.chunks = [];
|
|
360
|
+
this.streamCoalesce.delete(key);
|
|
361
|
+
this.callbacks.onOutput(buf.agentId, text, true, undefined, buf.uuid);
|
|
362
|
+
}
|
|
363
|
+
flushAllStreamCoalesceForAgent(agentId) {
|
|
364
|
+
const keys = [...this.streamCoalesce.keys()].filter((k) => k.startsWith(`${agentId}:`));
|
|
365
|
+
for (const key of keys) {
|
|
366
|
+
this.flushStreamCoalesce(key);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
248
369
|
isNotificationCurl(toolInput) {
|
|
249
370
|
const cmd = typeof toolInput?.command === 'string' ? toolInput.command : '';
|
|
250
371
|
return cmd.includes('/api/notify');
|
|
@@ -71,6 +71,12 @@ export class RunnerWatchdog {
|
|
|
71
71
|
log.error(`🐕 [WATCHDOG] Agent ${agentId}: tailer drain failed: ${String(err)}`);
|
|
72
72
|
}
|
|
73
73
|
activeProcess.tmuxTailer?.stop();
|
|
74
|
+
try {
|
|
75
|
+
activeProcess.sideChannelStop?.();
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// ignore
|
|
79
|
+
}
|
|
74
80
|
this.recordDeath({
|
|
75
81
|
agentId,
|
|
76
82
|
pid: activeProcess.process.pid ?? 0,
|
|
@@ -125,6 +131,12 @@ export class RunnerWatchdog {
|
|
|
125
131
|
timestamp: Date.now(),
|
|
126
132
|
stderr: this.lastStderr.get(agentId),
|
|
127
133
|
});
|
|
134
|
+
try {
|
|
135
|
+
activeProcess.sideChannelStop?.();
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// ignore
|
|
139
|
+
}
|
|
128
140
|
this.activeProcesses.delete(agentId);
|
|
129
141
|
this.lastStderr.delete(agentId);
|
|
130
142
|
const remaining = this.activeProcesses.size;
|