tide-commander 1.153.0 → 1.155.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 +20 -0
- package/dist/assets/{BossLogsModal-Dgz-N5gw.js → BossLogsModal-OFobifVq.js} +1 -1
- package/dist/assets/{BossSpawnModal-BK_rYu8s.js → BossSpawnModal-Dho-x6rm.js} +1 -1
- package/dist/assets/{ControlsModal-hC_AiCpk.js → ControlsModal-DJBDhvNO.js} +1 -1
- package/dist/assets/{DockerLogsModal-D7ogyaZr.js → DockerLogsModal-C9TRTcsO.js} +1 -1
- package/dist/assets/{EmbeddedEditor-BFzUOmwz.js → EmbeddedEditor-GDE_Khwz.js} +1 -1
- package/dist/assets/{GmailOAuthSetup-C_Yc5Ypv.js → GmailOAuthSetup-D9m5zMWC.js} +1 -1
- package/dist/assets/{GoogleOAuthSetup-CefQSOYm.js → GoogleOAuthSetup-BxkN7LjY.js} +1 -1
- package/dist/assets/{IframeModal-BbeuiE04.js → IframeModal-Do_I_wI7.js} +1 -1
- package/dist/assets/{IntegrationsPanel-xh3TgJLH.js → IntegrationsPanel-jRrwC2-G.js} +2 -2
- package/dist/assets/{LogViewerModal-CE2L8nWJ.js → LogViewerModal-BtcUe5i2.js} +1 -1
- package/dist/assets/{MonitoringModal-A2SN3uAJ.js → MonitoringModal-BTmSXrzv.js} +1 -1
- package/dist/assets/{PM2LogsModal-DdlhCa8u.js → PM2LogsModal-CUf7NGHz.js} +1 -1
- package/dist/assets/{RestoreArchivedAreaModal-BvHo-OxE.js → RestoreArchivedAreaModal-B72UKeRP.js} +1 -1
- package/dist/assets/{Scene2DCanvas-t6RuUegr.js → Scene2DCanvas-BCfxX7JU.js} +1 -1
- package/dist/assets/{SceneManager-TQ2_AvFn.js → SceneManager-BQubdlgd.js} +4 -4
- package/dist/assets/{SkillsPanel-PjzjcaoG.js → SkillsPanel-3qreMiJs.js} +1 -1
- package/dist/assets/{SlackMultiInstanceSetup-ms4r32Z8.js → SlackMultiInstanceSetup-BSCT5nAB.js} +1 -1
- package/dist/assets/{SpawnModal-B1FS8m9h.js → SpawnModal-DaWjnugM.js} +1 -1
- package/dist/assets/{StatisticsModal-mmz8hnD5.js → StatisticsModal-DCjCAU2o.js} +1 -1
- package/dist/assets/{SubordinateAssignmentModal-BXoG-Xgd.js → SubordinateAssignmentModal-9iPXraIi.js} +1 -1
- package/dist/assets/{TriggerManagerPanel-ODJyjvY-.js → TriggerManagerPanel-B4dCLEi_.js} +1 -1
- package/dist/assets/{WorkflowEditorPanel-9wtY0Tn3.js → WorkflowEditorPanel-BaYXKfYH.js} +1 -1
- package/dist/assets/{area-logos-BLyzmh47.js → area-logos-CgVT13bp.js} +1 -1
- package/dist/assets/{index-CN2p2fxH.js → index-0y0WY2XK.js} +1 -1
- package/dist/assets/index-BPjQZacc.css +1 -0
- package/dist/assets/{index-CdbLxNJr.js → index-C-tbJxGb.js} +1 -1
- package/dist/assets/{index-1hwiSf7o.js → index-C3Yb-3TP.js} +1 -1
- package/dist/assets/index-C3jAbuv2.js +1 -0
- package/dist/assets/{index-Ci2ZKu0n.js → index-C7t_6aP3.js} +2 -2
- package/dist/assets/{index-CBkh8xcE.js → index-CetQ5OX1.js} +1 -1
- package/dist/assets/{index-Cf-PINah.js → index-D8dlRudN.js} +3 -3
- package/dist/assets/index-DNjdlOwh.js +1 -0
- package/dist/assets/{index-D8vFfLs4.js → index-DiZy3nuB.js} +1 -1
- package/dist/assets/main-BHBs2E1L.css +1 -0
- package/dist/assets/{main-9TcmAtcq.js → main-DDwa0x9e.js} +113 -113
- package/dist/assets/{web-BVIPIXA1.js → web-Dj2DYQG1.js} +1 -1
- package/dist/assets/{web-Cz3TYK-R.js → web-EBdZk56y.js} +1 -1
- package/dist/assets/{web-BAkfcL4w.js → web-PXjd4vZ8.js} +1 -1
- package/dist/build-info.json +1 -1
- package/dist/index.html +2 -2
- package/dist/locales/de/config.json +1 -0
- package/dist/locales/en/config.json +6 -1
- package/dist/locales/en/terminal.json +7 -1
- package/dist/locales/es/config.json +4 -1
- package/dist/locales/es/terminal.json +8 -0
- package/dist/locales/fr/config.json +1 -0
- package/dist/locales/hi/config.json +1 -0
- package/dist/locales/it/config.json +1 -0
- package/dist/locales/ja/config.json +1 -0
- package/dist/locales/pt/config.json +1 -0
- package/dist/locales/ru/config.json +1 -0
- package/dist/locales/zh-CN/config.json +1 -0
- package/dist/src/packages/server/codex/app-server/app-server-event-adapter.js +222 -0
- package/dist/src/packages/server/codex/app-server/app-server-process.js +304 -0
- package/dist/src/packages/server/codex/app-server/app-server-recovery-store.js +76 -0
- package/dist/src/packages/server/codex/app-server/codex-app-server-runner.js +453 -0
- package/dist/src/packages/server/opencode/json-event-parser.js +3 -1
- package/dist/src/packages/server/opencode/server/opencode-server-event-adapter.js +127 -0
- package/dist/src/packages/server/opencode/server/opencode-server-process.js +285 -0
- package/dist/src/packages/server/opencode/server/opencode-server-recovery-store.js +73 -0
- package/dist/src/packages/server/opencode/server/opencode-server-runner.js +384 -0
- package/dist/src/packages/server/routes/agents.js +57 -1
- package/dist/src/packages/server/routes/system.js +110 -1
- package/dist/src/packages/server/runtime/codex-runner-router.js +99 -0
- package/dist/src/packages/server/runtime/codex-runtime-provider.js +5 -3
- package/dist/src/packages/server/runtime/opencode-runner-router.js +93 -0
- package/dist/src/packages/server/runtime/opencode-runtime-provider.js +5 -3
- package/dist/src/packages/server/services/claude-credentials-service.js +208 -1
- package/dist/src/packages/server/services/claude-usage-service.js +35 -28
- package/dist/src/packages/server/services/provider-credentials-service.js +338 -0
- package/dist/src/packages/server/services/system-prompt-service.js +94 -0
- package/package.json +1 -1
- package/dist/assets/index-CbfoJ_Vc.js +0 -1
- package/dist/assets/index-E5IMeM80.js +0 -1
- package/dist/assets/index-XI0_ICy6.css +0 -1
- package/dist/assets/main-DP0iv8Le.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{df as a}from"./main-
|
|
1
|
+
import{df as a}from"./main-DDwa0x9e.js";import{ImpactStyle as i,NotificationType as r}from"./index-C7t_6aP3.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};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{df as s}from"./main-
|
|
1
|
+
import{df as s}from"./main-DDwa0x9e.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{df as t}from"./main-
|
|
1
|
+
import{df as t}from"./main-DDwa0x9e.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};
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.
|
|
1
|
+
{"version":"1.155.0"}
|
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-DDwa0x9e.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-BHBs2E1L.css">
|
|
29
29
|
</head>
|
|
30
30
|
<body>
|
|
31
31
|
<div id="app"></div>
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
"integrations": "Integrations",
|
|
22
22
|
"experimental": "Experimental",
|
|
23
23
|
"about": "About",
|
|
24
|
-
"sky": "Sky Color"
|
|
24
|
+
"sky": "Sky Color",
|
|
25
|
+
"grokAccounts": "Grok Accounts",
|
|
26
|
+
"codexAccounts": "Codex Accounts"
|
|
25
27
|
},
|
|
26
28
|
"general": {
|
|
27
29
|
"history": "History",
|
|
@@ -32,8 +34,11 @@
|
|
|
32
34
|
"showFPS": "Show FPS",
|
|
33
35
|
"fpsLimit": "FPS Limit",
|
|
34
36
|
"powerSaving": "Power Saving",
|
|
37
|
+
"lowPowerMode": "Low Power Mode",
|
|
35
38
|
"tmuxMode": "Tmux Process Persistence",
|
|
36
39
|
"interactiveMode": "Interactive TUI Mode (Experimental)",
|
|
40
|
+
"codexAppServerMode": "Codex Streaming / app-server (Experimental)",
|
|
41
|
+
"opencodeServerMode": "OpenCode Streaming / serve (Experimental)",
|
|
37
42
|
"tts": "Text-to-Speech",
|
|
38
43
|
"stt": "Speech-to-Text",
|
|
39
44
|
"externalEditor": "External Editor",
|
|
@@ -1323,6 +1323,12 @@
|
|
|
1323
1323
|
"renamed": "Renamed \"{{from}}\" → \"{{to}}\".",
|
|
1324
1324
|
"deleted": "Deleted profile \"{{name}}\".",
|
|
1325
1325
|
"noProfiles": "No named profiles yet. Save the active account with a name (e.g. david, jc) to create one.",
|
|
1326
|
-
"tokenExpires": "token expires {{time}}"
|
|
1326
|
+
"tokenExpires": "token expires {{time}}",
|
|
1327
|
+
"gaugeSession": "Session",
|
|
1328
|
+
"gaugeWeek": "Week",
|
|
1329
|
+
"gaugeWeekOpus": "Opus wk",
|
|
1330
|
+
"gaugeNoSession": "no active session",
|
|
1331
|
+
"providerTitle": "{{provider}} Accounts",
|
|
1332
|
+
"providerHelp": "Named copies of {{dir}}/auth.json. Switch the active {{provider}} account when you hit rate limits — same as renaming the file manually."
|
|
1327
1333
|
}
|
|
1328
1334
|
}
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
"experimental": "Experimental",
|
|
17
17
|
"about": "Acerca de",
|
|
18
18
|
"sky": "Color del Cielo",
|
|
19
|
-
"systemPrompt": "Prompt de sistema"
|
|
19
|
+
"systemPrompt": "Prompt de sistema",
|
|
20
|
+
"grokAccounts": "Cuentas de Grok",
|
|
21
|
+
"codexAccounts": "Cuentas de Codex"
|
|
20
22
|
},
|
|
21
23
|
"general": {
|
|
22
24
|
"history": "Historial",
|
|
@@ -27,6 +29,7 @@
|
|
|
27
29
|
"showFPS": "Mostrar FPS",
|
|
28
30
|
"fpsLimit": "Limite de FPS",
|
|
29
31
|
"powerSaving": "Ahorro de energia",
|
|
32
|
+
"lowPowerMode": "Modo bajo consumo",
|
|
30
33
|
"tts": "Texto a voz",
|
|
31
34
|
"stt": "Voz a texto",
|
|
32
35
|
"externalEditor": "Editor externo",
|
|
@@ -1132,5 +1132,13 @@
|
|
|
1132
1132
|
"can-clear-context": "Completado — contexto listo para limpiar",
|
|
1133
1133
|
"waiting-subordinates": "Esperando trabajo delegado",
|
|
1134
1134
|
"working": "Trabajando"
|
|
1135
|
+
},
|
|
1136
|
+
"credentials": {
|
|
1137
|
+
"gaugeSession": "Sesión",
|
|
1138
|
+
"gaugeWeek": "Semana",
|
|
1139
|
+
"gaugeWeekOpus": "Opus sem",
|
|
1140
|
+
"gaugeNoSession": "sin sesión activa",
|
|
1141
|
+
"providerTitle": "Cuentas de {{provider}}",
|
|
1142
|
+
"providerHelp": "Copias nombradas de {{dir}}/auth.json. Cambia la cuenta activa de {{provider}} cuando llegues a los límites — igual que renombrar el archivo a mano."
|
|
1135
1143
|
}
|
|
1136
1144
|
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodexAppServerEventAdapter
|
|
3
|
+
*
|
|
4
|
+
* Translates `codex app-server` JSON-RPC notifications (v2 protocol, camelCase
|
|
5
|
+
* items) into Tide `StandardEvent`s, one adapter instance per agent (it holds
|
|
6
|
+
* per-turn state: the last agent-message text for boss delegation, and the most
|
|
7
|
+
* recent token-usage snapshot).
|
|
8
|
+
*
|
|
9
|
+
* The uuid conventions match the exec parser
|
|
10
|
+
* (src/packages/server/codex/json-event-parser.ts): `codex-text-<itemId>` for
|
|
11
|
+
* assistant text and `codex-thinking-<itemId>` for reasoning, so streaming
|
|
12
|
+
* deltas merge into one terminal row and the final `isStreaming:false` event
|
|
13
|
+
* finalizes it — identical downstream behaviour to the exec path, just with
|
|
14
|
+
* real token-level streaming.
|
|
15
|
+
*/
|
|
16
|
+
import { createLogger } from '../../utils/logger.js';
|
|
17
|
+
const log = createLogger('CodexAppServerAdapter');
|
|
18
|
+
function asString(v) {
|
|
19
|
+
return typeof v === 'string' ? v : undefined;
|
|
20
|
+
}
|
|
21
|
+
function asNumber(v) {
|
|
22
|
+
return typeof v === 'number' ? v : undefined;
|
|
23
|
+
}
|
|
24
|
+
export class CodexAppServerEventAdapter {
|
|
25
|
+
lastAgentMessageText;
|
|
26
|
+
lastErrorText;
|
|
27
|
+
tokenSnapshot;
|
|
28
|
+
/** Map one app-server notification to zero or more Tide events. */
|
|
29
|
+
handle(method, params) {
|
|
30
|
+
switch (method) {
|
|
31
|
+
// ---- Streaming deltas (the whole point) --------------------------------
|
|
32
|
+
case 'item/agentMessage/delta': {
|
|
33
|
+
const delta = asString(params.delta);
|
|
34
|
+
const itemId = asString(params.itemId) || 'anon';
|
|
35
|
+
if (!delta)
|
|
36
|
+
return [];
|
|
37
|
+
return [{ type: 'text', text: delta, isStreaming: true, uuid: `codex-text-${itemId}` }];
|
|
38
|
+
}
|
|
39
|
+
case 'item/reasoning/textDelta':
|
|
40
|
+
case 'item/reasoning/summaryTextDelta': {
|
|
41
|
+
const delta = asString(params.delta);
|
|
42
|
+
const itemId = asString(params.itemId) || 'anon';
|
|
43
|
+
if (!delta)
|
|
44
|
+
return [];
|
|
45
|
+
return [{ type: 'thinking', text: delta, isStreaming: true, uuid: `codex-thinking-${itemId}` }];
|
|
46
|
+
}
|
|
47
|
+
// ---- Item lifecycle ----------------------------------------------------
|
|
48
|
+
case 'item/started':
|
|
49
|
+
return this.handleItemStarted(params.item || {});
|
|
50
|
+
case 'item/completed':
|
|
51
|
+
return this.handleItemCompleted(params.item || {});
|
|
52
|
+
// ---- Turn + usage ------------------------------------------------------
|
|
53
|
+
case 'thread/tokenUsage/updated':
|
|
54
|
+
this.captureTokenUsage(params.tokenUsage);
|
|
55
|
+
return [];
|
|
56
|
+
case 'turn/completed':
|
|
57
|
+
return this.handleTurnCompleted(params.turn);
|
|
58
|
+
// ---- Errors ------------------------------------------------------------
|
|
59
|
+
case 'error': {
|
|
60
|
+
const errorMessage = asString(params.message) || 'Codex app-server error';
|
|
61
|
+
this.lastErrorText = errorMessage;
|
|
62
|
+
return [{ type: 'error', errorMessage }];
|
|
63
|
+
}
|
|
64
|
+
// Informational / handled elsewhere — stay silent (no raw dumps).
|
|
65
|
+
case 'thread/started':
|
|
66
|
+
case 'turn/started':
|
|
67
|
+
case 'thread/status/changed':
|
|
68
|
+
case 'thread/tokenUsage':
|
|
69
|
+
case 'item/plan/delta':
|
|
70
|
+
case 'turn/plan/updated':
|
|
71
|
+
case 'turn/diff/updated':
|
|
72
|
+
case 'item/reasoning/summaryPartAdded':
|
|
73
|
+
case 'item/commandExecution/outputDelta':
|
|
74
|
+
case 'account/rateLimits/updated':
|
|
75
|
+
case 'remoteControl/status/changed':
|
|
76
|
+
return [];
|
|
77
|
+
default:
|
|
78
|
+
// Unknown notification: swallow it (the exec parser dumps unknowns to the
|
|
79
|
+
// terminal, but at the notification layer that would be far too noisy).
|
|
80
|
+
log.debug(`Unhandled app-server notification: ${method}`);
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
handleItemStarted(item) {
|
|
85
|
+
switch (item.type) {
|
|
86
|
+
case 'commandExecution': {
|
|
87
|
+
const command = item.command || '';
|
|
88
|
+
return [{ type: 'tool_start', toolName: 'Bash', toolInput: { command, status: item.status } }];
|
|
89
|
+
}
|
|
90
|
+
case 'webSearch':
|
|
91
|
+
return [{ type: 'tool_start', toolName: 'web_search', toolInput: this.webSearchInput(item) }];
|
|
92
|
+
// agentMessage / reasoning: deltas carry the content; fileChange diff lands
|
|
93
|
+
// on completion. Everything else stays silent on start.
|
|
94
|
+
default:
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
handleItemCompleted(item) {
|
|
99
|
+
switch (item.type) {
|
|
100
|
+
case 'agentMessage': {
|
|
101
|
+
const text = (item.text || '').trim();
|
|
102
|
+
if (!text)
|
|
103
|
+
return [];
|
|
104
|
+
this.lastAgentMessageText = text;
|
|
105
|
+
return [{ type: 'text', text, isStreaming: false, uuid: item.id ? `codex-text-${item.id}` : undefined }];
|
|
106
|
+
}
|
|
107
|
+
case 'reasoning': {
|
|
108
|
+
const text = (item.content && item.content.length ? item.content : item.summary || []).join('\n').trim();
|
|
109
|
+
if (!text)
|
|
110
|
+
return [];
|
|
111
|
+
return [{ type: 'thinking', text, isStreaming: false, uuid: item.id ? `codex-thinking-${item.id}` : undefined }];
|
|
112
|
+
}
|
|
113
|
+
case 'commandExecution': {
|
|
114
|
+
const output = item.aggregatedOutput ??
|
|
115
|
+
(item.exitCode !== undefined ? `[exit ${item.exitCode}]` : item.status ? `Command status: ${item.status}` : '');
|
|
116
|
+
return [{ type: 'tool_result', toolName: 'Bash', toolOutput: output }];
|
|
117
|
+
}
|
|
118
|
+
case 'fileChange':
|
|
119
|
+
return this.handleFileChange(item);
|
|
120
|
+
case 'webSearch':
|
|
121
|
+
return [{ type: 'tool_result', toolName: 'web_search', toolOutput: JSON.stringify(this.webSearchInput(item)) }];
|
|
122
|
+
case 'collabAgentToolCall': {
|
|
123
|
+
const toolName = item.tool || 'collab_tool';
|
|
124
|
+
const toolInput = { tool: item.tool, status: item.status };
|
|
125
|
+
if (item.prompt)
|
|
126
|
+
toolInput.prompt = item.prompt;
|
|
127
|
+
if (item.receiverThreadIds?.length)
|
|
128
|
+
toolInput.receiver_thread_ids = item.receiverThreadIds;
|
|
129
|
+
return [
|
|
130
|
+
{ type: 'tool_start', toolName, toolInput },
|
|
131
|
+
{ type: 'tool_result', toolName, toolOutput: `Status: ${item.status || 'unknown'}` },
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
case 'error': {
|
|
135
|
+
const errorMessage = item.message || item.text || item.error || 'Codex emitted an error';
|
|
136
|
+
this.lastErrorText = errorMessage;
|
|
137
|
+
return [{ type: 'error', errorMessage }];
|
|
138
|
+
}
|
|
139
|
+
default:
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
handleFileChange(item) {
|
|
144
|
+
if (!item.changes || item.changes.length === 0)
|
|
145
|
+
return [];
|
|
146
|
+
if (item.status && item.status !== 'completed')
|
|
147
|
+
return [];
|
|
148
|
+
const events = [];
|
|
149
|
+
for (const change of item.changes) {
|
|
150
|
+
if (!change.path)
|
|
151
|
+
continue;
|
|
152
|
+
const toolInput = { file_path: change.path };
|
|
153
|
+
// v2 fileChange carries a per-file unified diff inline — no git shell-out
|
|
154
|
+
// needed (the exec path has to reconstruct it via `git diff`).
|
|
155
|
+
if (change.diff)
|
|
156
|
+
toolInput.unified_diff = change.diff;
|
|
157
|
+
const kind = change.kind?.type || 'update';
|
|
158
|
+
events.push({ type: 'tool_start', toolName: 'Edit', toolInput }, { type: 'tool_result', toolName: 'Edit', toolOutput: `File ${kind}: ${change.path}` });
|
|
159
|
+
}
|
|
160
|
+
return events;
|
|
161
|
+
}
|
|
162
|
+
webSearchInput(item) {
|
|
163
|
+
return {
|
|
164
|
+
query: item.query,
|
|
165
|
+
actionType: item.action?.type,
|
|
166
|
+
actionQuery: item.action?.query,
|
|
167
|
+
actionQueries: item.action?.queries,
|
|
168
|
+
actionUrl: item.action?.url,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
captureTokenUsage(tokenUsage) {
|
|
172
|
+
if (typeof tokenUsage !== 'object' || tokenUsage === null)
|
|
173
|
+
return;
|
|
174
|
+
const tu = tokenUsage;
|
|
175
|
+
const last = tu.last || {};
|
|
176
|
+
this.tokenSnapshot = {
|
|
177
|
+
contextWindow: asNumber(tu.modelContextWindow) ?? this.tokenSnapshot?.contextWindow,
|
|
178
|
+
inputTokens: asNumber(last.inputTokens),
|
|
179
|
+
outputTokens: asNumber(last.outputTokens),
|
|
180
|
+
cacheReadInputTokens: asNumber(last.cachedInputTokens),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
handleTurnCompleted(turn) {
|
|
184
|
+
const events = [];
|
|
185
|
+
// A failed turn carries its error inline — surface it before finalizing.
|
|
186
|
+
if (turn && asString(turn.status) === 'failed') {
|
|
187
|
+
const err = turn.error;
|
|
188
|
+
const errorMessage = (err && asString(err.message)) || 'Codex turn failed';
|
|
189
|
+
this.lastErrorText = errorMessage;
|
|
190
|
+
events.push({ type: 'error', errorMessage });
|
|
191
|
+
}
|
|
192
|
+
const snap = this.tokenSnapshot;
|
|
193
|
+
const event = {
|
|
194
|
+
type: 'step_complete',
|
|
195
|
+
tokens: {
|
|
196
|
+
input: snap?.inputTokens ?? 0,
|
|
197
|
+
output: snap?.outputTokens ?? 0,
|
|
198
|
+
cacheRead: snap?.cacheReadInputTokens,
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
if (this.lastAgentMessageText || this.lastErrorText) {
|
|
202
|
+
const parts = [];
|
|
203
|
+
if (this.lastAgentMessageText)
|
|
204
|
+
parts.push(this.lastAgentMessageText);
|
|
205
|
+
if (this.lastErrorText)
|
|
206
|
+
parts.push(`[Error] ${this.lastErrorText}`);
|
|
207
|
+
event.resultText = parts.join('\n\n');
|
|
208
|
+
}
|
|
209
|
+
if (snap && (snap.contextWindow || snap.inputTokens !== undefined || snap.outputTokens !== undefined)) {
|
|
210
|
+
event.modelUsage = {
|
|
211
|
+
contextWindow: snap.contextWindow,
|
|
212
|
+
inputTokens: snap.inputTokens ?? 0,
|
|
213
|
+
outputTokens: snap.outputTokens ?? 0,
|
|
214
|
+
cacheReadInputTokens: snap.cacheReadInputTokens ?? 0,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
this.lastAgentMessageText = undefined;
|
|
218
|
+
this.lastErrorText = undefined;
|
|
219
|
+
events.push(event);
|
|
220
|
+
return events;
|
|
221
|
+
}
|
|
222
|
+
}
|