tide-commander 1.69.0 → 1.71.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/dist/assets/{BossLogsModal-CMDdkhTL.js → BossLogsModal-DoW-oomk.js} +1 -1
- package/dist/assets/BossSpawnModal-Boc6sIfS.js +1 -0
- package/dist/assets/{ControlsModal-BtJJYkcM.js → ControlsModal-C6o3uZcq.js} +1 -1
- package/dist/assets/{DockerLogsModal-Lw19ZQVz.js → DockerLogsModal-D0Qo_MwC.js} +1 -1
- package/dist/assets/{EmbeddedEditor-UwKqvTkJ.js → EmbeddedEditor-CekqD_9x.js} +1 -1
- package/dist/assets/{GmailOAuthSetup-BOlxzJ7D.js → GmailOAuthSetup-9-5bh2P-.js} +1 -1
- package/dist/assets/{GoogleOAuthSetup-DYvaSFQp.js → GoogleOAuthSetup-3dJ_OKsM.js} +1 -1
- package/dist/assets/{IframeModal-DRJROx67.js → IframeModal-DbXb7CwV.js} +1 -1
- package/dist/assets/{IntegrationsPanel-Bp1O-I5s.js → IntegrationsPanel-Bbu-YttD.js} +2 -2
- package/dist/assets/{LogViewerModal-BIlhbii5.js → LogViewerModal-Bz-phlyW.js} +1 -1
- package/dist/assets/{MonitoringModal-CuDrTaVn.js → MonitoringModal-DPufvsx3.js} +1 -1
- package/dist/assets/{PM2LogsModal-C1VLY7hc.js → PM2LogsModal-BRJEoIGZ.js} +1 -1
- package/dist/assets/{RestoreArchivedAreaModal-ObvIYj2V.js → RestoreArchivedAreaModal-DcsT_-25.js} +1 -1
- package/dist/assets/{Scene2DCanvas-BM_GFevb.js → Scene2DCanvas-DNsc8p5F.js} +1 -1
- package/dist/assets/{SceneManager-FeZQ9HI1.js → SceneManager-DPvh-m5A.js} +1 -1
- package/dist/assets/{SkillsPanel-CtFwVaQj.js → SkillsPanel-B_xQv-7n.js} +2 -2
- package/dist/assets/SpawnModal-B9jRwDuS.js +1 -0
- package/dist/assets/{SubordinateAssignmentModal-aDkxc3YR.js → SubordinateAssignmentModal-nNA0eQY3.js} +1 -1
- package/dist/assets/TriggerManagerPanel-CRYqCuDW.js +3 -0
- package/dist/assets/{WorkflowEditorPanel-D_8Bnuzv.js → WorkflowEditorPanel-DMj6QkhB.js} +1 -1
- package/dist/assets/{index-Br8WLiXq.js → index-B0Bgs8A9.js} +1 -1
- package/dist/assets/{index-BIkn0arf.js → index-BKI7mhTU.js} +3 -3
- package/dist/assets/{index-9Bftos7u.js → index-BSDP6H43.js} +6 -6
- package/dist/assets/index-BXuHHEGh.css +1 -0
- package/dist/assets/{index-K0KrIo24.js → index-BwN_ChZo.js} +3 -3
- package/dist/assets/index-CAYhCfSA.js +2 -0
- package/dist/assets/{index-BYR78OCI.js → index-CIDXn3G0.js} +1 -1
- package/dist/assets/{index-CX4tk_vI.js → index-QhVjGjw2.js} +1 -1
- package/dist/assets/{index-BMayWtlQ.js → index-VvpWwviS.js} +1 -1
- package/dist/assets/{index-YH8hJh62.js → index-fFQ_bGrk.js} +2 -2
- package/dist/assets/main-C2_Gs1Uu.css +1 -0
- package/dist/assets/{main--_0rf6yB.js → main-DchkmHia.js} +89 -89
- package/dist/assets/{web-BuuzpQy3.js → web-BYNdUdPc.js} +1 -1
- package/dist/assets/{web-Dn-wQDim.js → web-DPcQ0gLD.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/locales/en/config.json +6 -1
- package/dist/locales/en/terminal.json +4 -1
- package/dist/src/packages/server/claude/runner.js +42 -33
- package/dist/src/packages/server/codex/backend.js +17 -8
- package/dist/src/packages/server/services/cron-service.js +49 -0
- package/dist/src/packages/server/services/runtime-command-execution.js +29 -12
- package/dist/src/packages/server/services/trigger-service.js +65 -0
- package/dist/src/packages/shared/agent-types.js +8 -0
- package/package.json +1 -1
- package/dist/assets/BossSpawnModal-C7lw2Wzh.js +0 -1
- package/dist/assets/SpawnModal-37ChIpU2.js +0 -1
- package/dist/assets/TriggerManagerPanel-CQxcjiJu.js +0 -3
- package/dist/assets/index-D8fn_Wjl.js +0 -1
- package/dist/assets/index-DDfjGtDT.css +0 -1
- package/dist/assets/main-BXDdkAuE.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{c1 as a}from"./main-DchkmHia.js";import{ImpactStyle as i,NotificationType as r}from"./index-fFQ_bGrk.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{
|
|
1
|
+
import{c1 as s}from"./main-DchkmHia.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};
|
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-DchkmHia.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-C2_Gs1Uu.css">
|
|
29
29
|
</head>
|
|
30
30
|
<body>
|
|
31
31
|
<div id="app"></div>
|
|
@@ -68,7 +68,12 @@
|
|
|
68
68
|
"hideToken": "Hide token",
|
|
69
69
|
"codexBinaryPath": "Codex Binary Path",
|
|
70
70
|
"codexBinaryPathPlaceholder": "Leave empty for auto-detect",
|
|
71
|
-
"codexBinaryPathHint": "Path to the native Codex binary. Bypasses the Node.js wrapper for better session persistence."
|
|
71
|
+
"codexBinaryPathHint": "Path to the native Codex binary. Bypasses the Node.js wrapper for better session persistence.",
|
|
72
|
+
"connectScreen": {
|
|
73
|
+
"authTokenLabel": "Auth Token",
|
|
74
|
+
"authTokenPlaceholder": "X-Auth-Token (optional)",
|
|
75
|
+
"authTokenHint": "Optional. Required if your server enforces auth."
|
|
76
|
+
}
|
|
72
77
|
},
|
|
73
78
|
"scene": {
|
|
74
79
|
"characterSize": "Character Size",
|
|
@@ -220,7 +220,9 @@
|
|
|
220
220
|
"approvalsUntrusted": "Approvals: untrusted",
|
|
221
221
|
"approvalsOnFailure": "Approvals: on-failure",
|
|
222
222
|
"approvalsOnRequest": "Approvals: on-request",
|
|
223
|
-
"approvalsNever": "Approvals: never"
|
|
223
|
+
"approvalsNever": "Approvals: never",
|
|
224
|
+
"reasoningEffort": "Reasoning Effort",
|
|
225
|
+
"reasoningEffortDefault": "Reasoning Effort: default"
|
|
224
226
|
}
|
|
225
227
|
},
|
|
226
228
|
"overview": {
|
|
@@ -247,6 +249,7 @@
|
|
|
247
249
|
"clickToSwitch": "Click to switch to this agent",
|
|
248
250
|
"sameAreaOnly": "Same Area",
|
|
249
251
|
"subagentsCompleted": "{{count}} subagents (all completed)",
|
|
252
|
+
"hasDraft": "Has unsent draft",
|
|
250
253
|
"statusLabels": {
|
|
251
254
|
"working": "Working",
|
|
252
255
|
"idle": "Idle",
|
|
@@ -305,26 +305,33 @@ export class ClaudeRunner {
|
|
|
305
305
|
log.error(`❌ [SEND_MESSAGE] No active process for agent ${agentId}`);
|
|
306
306
|
return false;
|
|
307
307
|
}
|
|
308
|
-
// tmux mode:
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
//
|
|
308
|
+
// tmux mode dispatch:
|
|
309
|
+
// - Stdin-closed backends (codex, opencode) MUST queue. They were
|
|
310
|
+
// launched as `cat <file> | codex …` so their stdin is the pipe, not
|
|
311
|
+
// the tmux pane. Once cat hits EOF they receive EOF; tmux send-keys
|
|
312
|
+
// would write to a pane they aren't reading. Delivery happens via
|
|
313
|
+
// respawn-with-session-resume when the session dies (handled by the
|
|
314
|
+
// watchdog_missing_process branch).
|
|
315
|
+
// - Stdin-open backends (claude) are launched as
|
|
316
|
+
// `(cat <file>; cat) | claude --input-format stream-json …` — the
|
|
317
|
+
// trailing `cat` reads from the tmux pane, so send-keys writes are
|
|
318
|
+
// fed to claude's stdin as additional stream-json lines. Claude
|
|
319
|
+
// handles mid-turn `{type:"user",…}` messages natively (queues them
|
|
320
|
+
// internally for post-turn or injects them per its own protocol), so
|
|
321
|
+
// we write immediately regardless of turnState instead of blocking
|
|
322
|
+
// the user until step_complete.
|
|
316
323
|
if (activeProcess.tmuxSession) {
|
|
317
324
|
const tmuxTurnState = activeProcess.turnState || 'processing';
|
|
318
325
|
const tmuxBackendClosesStdin = this.backend.shouldCloseStdinAfterPrompt?.() === true;
|
|
319
|
-
if (
|
|
326
|
+
if (tmuxBackendClosesStdin) {
|
|
320
327
|
const queue = this.messageQueue.get(agentId) ?? [];
|
|
321
328
|
queue.push(message);
|
|
322
329
|
this.messageQueue.set(agentId, queue);
|
|
323
|
-
log.log(`📋 [QUEUE-TMUX] Agent ${agentId}: queued message (turnState=${tmuxTurnState},
|
|
330
|
+
log.log(`📋 [QUEUE-TMUX] Agent ${agentId}: queued message (stdin-closed backend, turnState=${tmuxTurnState}, queue=${queue.length}, ${message.length} chars)`);
|
|
324
331
|
return true;
|
|
325
332
|
}
|
|
326
333
|
const stdinInput = this.backend.formatStdinInput(message);
|
|
327
|
-
log.log(`📨 [SEND_MESSAGE] Agent ${agentId} (tmux
|
|
334
|
+
log.log(`📨 [SEND_MESSAGE] Agent ${agentId} (tmux, turnState=${tmuxTurnState}), sending via tmux send-keys (${stdinInput.length} chars)`);
|
|
328
335
|
const ok = sendToTmux(agentId, stdinInput);
|
|
329
336
|
if (ok) {
|
|
330
337
|
activeProcess.turnState = 'processing';
|
|
@@ -334,35 +341,37 @@ export class ClaudeRunner {
|
|
|
334
341
|
const turnState = activeProcess.turnState || 'processing';
|
|
335
342
|
const messageLen = message.length;
|
|
336
343
|
const backendClosesStdin = this.backend.shouldCloseStdinAfterPrompt?.() === true;
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
|
|
344
|
-
// respawn-with-queue path is skipped (cleanTurnEnd requires a clean exit).
|
|
345
|
-
// The queue is the source of truth; drain happens after the current turn ends
|
|
346
|
-
// (via stdin for stdin-open backends, or via session-resume respawn for
|
|
347
|
-
// stdin-closed ones).
|
|
348
|
-
if (turnState === 'processing' || backendClosesStdin) {
|
|
344
|
+
// Stdin-closed backends (codex, opencode) MUST always queue: there is
|
|
345
|
+
// literally no open stdin to write to after the initial prompt.
|
|
346
|
+
// sendCommand's interrupt-and-restart branch handles mid-turn prompts for
|
|
347
|
+
// these by stopping+respawning; this queue catches the narrow
|
|
348
|
+
// step_complete/process_exit race window where respawn is the only
|
|
349
|
+
// delivery path (cleanTurnEnd in runner.ts:248 picks it up).
|
|
350
|
+
if (backendClosesStdin) {
|
|
349
351
|
const queue = this.messageQueue.get(agentId) ?? [];
|
|
350
352
|
queue.push(message);
|
|
351
353
|
this.messageQueue.set(agentId, queue);
|
|
352
|
-
log.log(`📋 [QUEUE] Agent ${agentId}: queued message for
|
|
354
|
+
log.log(`📋 [QUEUE] Agent ${agentId}: queued message for respawn delivery (stdin-closed backend, turnState=${turnState}, queue=${queue.length}, ${messageLen} chars)`);
|
|
353
355
|
return true;
|
|
354
356
|
}
|
|
355
|
-
//
|
|
357
|
+
// Stdin-open backends (claude): write directly regardless of turnState.
|
|
358
|
+
// Claude's --input-format stream-json accepts additional
|
|
359
|
+
// {type:"user",...} JSON lines at any time and interleaves them with the
|
|
360
|
+
// current turn per its own protocol. Blocking on 'waiting_for_input'
|
|
361
|
+
// previously made the user wait for step_complete before Claude even saw
|
|
362
|
+
// the message; now it goes straight to Claude's stdin.
|
|
356
363
|
const stdin = activeProcess.process.stdin;
|
|
357
|
-
if (!stdin) {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
+
if (!stdin || !stdin.writable) {
|
|
365
|
+
// Defensive fallback: if stdin unexpectedly isn't writable (pipe
|
|
366
|
+
// closed, process dying), queue so the respawn path can recover the
|
|
367
|
+
// message instead of dropping it.
|
|
368
|
+
log.warn(`⚠️ [SEND_MESSAGE] Agent ${agentId}: stdin not writable (stdin=${!!stdin}, writable=${stdin?.writable}); queueing for recovery path (turnState=${turnState}, ${messageLen} chars)`);
|
|
369
|
+
const queue = this.messageQueue.get(agentId) ?? [];
|
|
370
|
+
queue.push(message);
|
|
371
|
+
this.messageQueue.set(agentId, queue);
|
|
372
|
+
return true;
|
|
364
373
|
}
|
|
365
|
-
log.log(`📨 [SEND_MESSAGE] Agent ${agentId}
|
|
374
|
+
log.log(`📨 [SEND_MESSAGE] Agent ${agentId} (turnState=${turnState}), sending directly via stdin (${messageLen} chars)`);
|
|
366
375
|
return this.writeToStdin(agentId, activeProcess, message);
|
|
367
376
|
}
|
|
368
377
|
/**
|
|
@@ -85,6 +85,11 @@ export class CodexBackend {
|
|
|
85
85
|
if (codexConfig?.profile) {
|
|
86
86
|
args.push('--profile', codexConfig.profile);
|
|
87
87
|
}
|
|
88
|
+
if (codexConfig?.reasoningEffort) {
|
|
89
|
+
// Pass as a two-arg pair so the spawned process receives the flag and
|
|
90
|
+
// value as separate argv entries — no shell-level quoting needed.
|
|
91
|
+
args.push('-c', `model_reasoning_effort=${codexConfig.reasoningEffort}`);
|
|
92
|
+
}
|
|
88
93
|
if (config.workingDir) {
|
|
89
94
|
args.push('-C', config.workingDir);
|
|
90
95
|
}
|
|
@@ -115,15 +120,18 @@ export class CodexBackend {
|
|
|
115
120
|
return null;
|
|
116
121
|
}
|
|
117
122
|
getExecutablePath() {
|
|
118
|
-
// Priority: 1)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
+
// Priority: 1) Settings UI 2) CODEX_BINARY env var 3) auto-detect
|
|
124
|
+
// The Settings UI value is an explicit user override and must win over
|
|
125
|
+
// the env var default so the user can point Tide Commander at a specific
|
|
126
|
+
// codex install without clearing their shell environment.
|
|
123
127
|
const settingsBinary = getCodexBinaryPath();
|
|
124
128
|
if (settingsBinary && fs.existsSync(settingsBinary)) {
|
|
125
129
|
return settingsBinary;
|
|
126
130
|
}
|
|
131
|
+
const envBinary = process.env.CODEX_BINARY;
|
|
132
|
+
if (envBinary && fs.existsSync(envBinary)) {
|
|
133
|
+
return envBinary;
|
|
134
|
+
}
|
|
127
135
|
return this.detectInstallation() || 'codex';
|
|
128
136
|
}
|
|
129
137
|
detectInstallation() {
|
|
@@ -149,10 +157,11 @@ export class CodexBackend {
|
|
|
149
157
|
getExtraEnv() {
|
|
150
158
|
// When using the native binary directly, we need to add
|
|
151
159
|
// the vendor path directory to PATH so codex can find bundled tools like rg.
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
// Match the precedence used by getExecutablePath(): Settings UI wins over env var.
|
|
161
|
+
const binary = getCodexBinaryPath() || process.env.CODEX_BINARY;
|
|
162
|
+
if (!binary)
|
|
154
163
|
return {};
|
|
155
|
-
const codexDir = path.dirname(
|
|
164
|
+
const codexDir = path.dirname(binary); // .../codex/
|
|
156
165
|
const archRoot = path.dirname(codexDir); // .../x86_64-unknown-linux-musl/
|
|
157
166
|
const pathDir = path.join(archRoot, 'path');
|
|
158
167
|
if (fs.existsSync(pathDir)) {
|
|
@@ -132,6 +132,55 @@ function getDateInTimezone(timezone) {
|
|
|
132
132
|
}
|
|
133
133
|
// ─── Public API ───
|
|
134
134
|
const CHECK_INTERVAL_MS = 30_000; // Check every 30 seconds
|
|
135
|
+
// Max safe setTimeout delay (2^31-1 ms ≈ 24.8 days). Longer waits are chained.
|
|
136
|
+
const MAX_SETTIMEOUT_MS = 2_147_483_647;
|
|
137
|
+
/**
|
|
138
|
+
* Schedule a callback to fire exactly once at the given absolute datetime.
|
|
139
|
+
* If the time is already in the past, the callback is fired immediately (next tick).
|
|
140
|
+
* Returns a CronJob-compatible handle that can be stopped via `stop(job)`.
|
|
141
|
+
*/
|
|
142
|
+
export function scheduleOnce(runAtIso, callback) {
|
|
143
|
+
const id = `once_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
144
|
+
const runAtMs = new Date(runAtIso).getTime();
|
|
145
|
+
const job = {
|
|
146
|
+
id,
|
|
147
|
+
expression: `@once ${runAtIso}`,
|
|
148
|
+
timezone: 'UTC',
|
|
149
|
+
callback,
|
|
150
|
+
timer: null,
|
|
151
|
+
lastFired: null,
|
|
152
|
+
};
|
|
153
|
+
const fire = (reason) => {
|
|
154
|
+
job.lastFired = Date.now();
|
|
155
|
+
log.log(`One-shot cron ${id} fired (runAt=${runAtIso}, ${reason})`);
|
|
156
|
+
activeJobs.delete(id);
|
|
157
|
+
try {
|
|
158
|
+
callback();
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
log.error(`One-shot cron ${id} callback error:`, err);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
const armTimer = () => {
|
|
165
|
+
const remaining = runAtMs - Date.now();
|
|
166
|
+
// Always schedule via setTimeout (delay clamped to >= 0) so the callback
|
|
167
|
+
// never runs synchronously within scheduleOnce — callers often update state
|
|
168
|
+
// after this returns, and a sync callback would race that.
|
|
169
|
+
const delay = Math.max(0, Math.min(remaining, MAX_SETTIMEOUT_MS));
|
|
170
|
+
job.timer = setTimeout(() => {
|
|
171
|
+
if (remaining > MAX_SETTIMEOUT_MS) {
|
|
172
|
+
// Chained wait: re-arm for the remaining interval
|
|
173
|
+
armTimer();
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
fire('scheduled');
|
|
177
|
+
}, delay);
|
|
178
|
+
};
|
|
179
|
+
armTimer();
|
|
180
|
+
activeJobs.set(id, job);
|
|
181
|
+
log.log(`Scheduled one-shot cron ${id} for ${runAtIso}`);
|
|
182
|
+
return job;
|
|
183
|
+
}
|
|
135
184
|
export function schedule(expression, timezone, callback) {
|
|
136
185
|
const id = `cron_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
137
186
|
const job = {
|
|
@@ -69,10 +69,29 @@ export function createRuntimeCommandExecution(deps) {
|
|
|
69
69
|
}
|
|
70
70
|
const processRunning = runner.isRunning(agentId);
|
|
71
71
|
// For backends that close stdin after the initial prompt (codex, opencode),
|
|
72
|
-
// a new user prompt arriving
|
|
73
|
-
// RESTART the session with the new prompt — not wait
|
|
74
|
-
// to finish and then deliver the queued message via
|
|
75
|
-
// is the default queue-based behavior
|
|
72
|
+
// a new user prompt arriving while the process is alive should INTERRUPT
|
|
73
|
+
// the current work and RESTART the session with the new prompt — not wait
|
|
74
|
+
// for the current turn to finish and then deliver the queued message via
|
|
75
|
+
// session-resume (which is the default queue-based behavior).
|
|
76
|
+
//
|
|
77
|
+
// Why no turnState gate: stdin is closed, so there's literally no way to
|
|
78
|
+
// deliver a follow-up prompt without respawning. 'waiting_for_input' is
|
|
79
|
+
// also not a reliable "turn is over" signal across these backends —
|
|
80
|
+
// opencode's NDJSON emits `step_finish` per LLM step (see
|
|
81
|
+
// src/packages/server/opencode/json-event-parser.ts:197-207), so during a
|
|
82
|
+
// single conversational turn the runner's turnState oscillates
|
|
83
|
+
// processing → waiting_for_input → processing → … between steps. Gating
|
|
84
|
+
// on 'waiting_for_input' would strand the new prompt on those mid-turn
|
|
85
|
+
// windows: sendMessage would queue it, but the process isn't exiting
|
|
86
|
+
// (it's starting the next step), so the queue-respawn path never fires.
|
|
87
|
+
// Codex happens to emit `step_complete` once per turn (via
|
|
88
|
+
// src/packages/server/codex/json-event-parser.ts:300-301), so the old
|
|
89
|
+
// gate looked fine there — but the correct invariant for ALL stdin-closed
|
|
90
|
+
// backends is: process-alive + new-prompt ⇒ interrupt + respawn.
|
|
91
|
+
//
|
|
92
|
+
// SIGINT on a process already at true turn-end (about to exit cleanly on
|
|
93
|
+
// its own) is harmless — process-lifecycle's stop() just short-circuits
|
|
94
|
+
// the natural exit, and the fresh spawn still resumes the same sessionId.
|
|
76
95
|
//
|
|
77
96
|
// Safe for tmux mode: runner.stop() routes through
|
|
78
97
|
// src/packages/server/claude/runner/process-lifecycle.ts:281-284 which
|
|
@@ -86,14 +105,12 @@ export function createRuntimeCommandExecution(deps) {
|
|
|
86
105
|
const backendClosesStdin = runner.closesStdinAfterPrompt?.() === true;
|
|
87
106
|
if (processRunning && backendClosesStdin && !forceNewSession) {
|
|
88
107
|
const turnState = runner.getTurnState?.(agentId);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
108
|
+
log.log(`[sendCommand] Agent ${agentId} (${agent.provider}): in-flight prompt (turnState=${turnState ?? 'unknown'}) — interrupting current work and restarting session with new prompt`);
|
|
109
|
+
emitOutput(agentId, '🛑 [System] Interrupting current work to process new prompt…', false, undefined, 'system-interrupt-restart');
|
|
110
|
+
await runner.stop(agentId, true);
|
|
111
|
+
agentService.updateAgent(agentId, { taskCount: (agent.taskCount || 0) + 1 });
|
|
112
|
+
await executeCommand(agentId, command, systemPrompt, forceNewSession, customAgent);
|
|
113
|
+
return;
|
|
97
114
|
}
|
|
98
115
|
if (processRunning && !forceNewSession) {
|
|
99
116
|
if (runner.supportsStdin()) {
|
|
@@ -615,9 +615,15 @@ function interpolateTemplate(template, variables) {
|
|
|
615
615
|
});
|
|
616
616
|
}
|
|
617
617
|
// ─── Cron Management ───
|
|
618
|
+
// Grace window for firing a one-shot whose runAt slipped past while the server was down.
|
|
619
|
+
const ONE_SHOT_MISS_GRACE_MS = 5 * 60 * 1000;
|
|
618
620
|
function startCronJob(trigger) {
|
|
619
621
|
// Stop existing job if any
|
|
620
622
|
stopCronJob(trigger.id);
|
|
623
|
+
if (trigger.config.runOnce) {
|
|
624
|
+
startOneShotJob(trigger);
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
621
627
|
const job = cronService.schedule(trigger.config.expression, trigger.config.timezone, () => {
|
|
622
628
|
const variables = {
|
|
623
629
|
'cron.expression': trigger.config.expression,
|
|
@@ -629,6 +635,65 @@ function startCronJob(trigger) {
|
|
|
629
635
|
cronJobs.set(trigger.id, job);
|
|
630
636
|
log.log(`Started cron job for trigger ${trigger.name}: ${trigger.config.expression}`);
|
|
631
637
|
}
|
|
638
|
+
function startOneShotJob(trigger) {
|
|
639
|
+
const runAt = trigger.config.runAt;
|
|
640
|
+
if (!runAt) {
|
|
641
|
+
log.warn(`One-shot trigger ${trigger.name} has no runAt; skipping schedule`);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
// Already completed — do not re-arm.
|
|
645
|
+
if (trigger.config.completedAt) {
|
|
646
|
+
log.log(`One-shot trigger ${trigger.name} already completed at ${new Date(trigger.config.completedAt).toISOString()}`);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
const runAtMs = new Date(runAt).getTime();
|
|
650
|
+
if (Number.isNaN(runAtMs)) {
|
|
651
|
+
log.error(`One-shot trigger ${trigger.name} has invalid runAt: ${runAt}`);
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
const now = Date.now();
|
|
655
|
+
const overdueMs = now - runAtMs;
|
|
656
|
+
if (overdueMs > ONE_SHOT_MISS_GRACE_MS) {
|
|
657
|
+
// Missed by more than the grace window — mark missed and disable.
|
|
658
|
+
log.warn(`One-shot trigger ${trigger.name} missed (overdue by ${Math.round(overdueMs / 1000)}s); marking as missed`);
|
|
659
|
+
const updatedConfig = { ...trigger.config, missedAt: now };
|
|
660
|
+
updateTrigger(trigger.id, {
|
|
661
|
+
enabled: false,
|
|
662
|
+
status: 'error',
|
|
663
|
+
lastError: 'missed: server was down at runAt',
|
|
664
|
+
config: updatedConfig,
|
|
665
|
+
});
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
const job = cronService.scheduleOnce(runAt, () => {
|
|
669
|
+
const variables = {
|
|
670
|
+
'cron.runAt': runAt,
|
|
671
|
+
'cron.scheduledAt': new Date().toISOString(),
|
|
672
|
+
...(trigger.config.payload || {}),
|
|
673
|
+
};
|
|
674
|
+
void handleOneShotFire(trigger.id, variables);
|
|
675
|
+
});
|
|
676
|
+
cronJobs.set(trigger.id, job);
|
|
677
|
+
log.log(`Armed one-shot trigger ${trigger.name} for ${runAt}${overdueMs > 0 ? ' (within grace window, firing immediately)' : ''}`);
|
|
678
|
+
}
|
|
679
|
+
async function handleOneShotFire(triggerId, variables) {
|
|
680
|
+
const trigger = triggers.get(triggerId);
|
|
681
|
+
if (!trigger || trigger.type !== 'cron')
|
|
682
|
+
return;
|
|
683
|
+
const cronTrigger = trigger;
|
|
684
|
+
if (!cronTrigger.config.runOnce)
|
|
685
|
+
return;
|
|
686
|
+
// Mark completed + disabled BEFORE firing. fireTrigger internally calls
|
|
687
|
+
// updateTrigger which would otherwise re-enter startCronJob and re-arm the
|
|
688
|
+
// one-shot. The completedAt guard in startOneShotJob short-circuits that.
|
|
689
|
+
const updatedConfig = { ...cronTrigger.config, completedAt: Date.now() };
|
|
690
|
+
updateTrigger(triggerId, {
|
|
691
|
+
enabled: false,
|
|
692
|
+
config: updatedConfig,
|
|
693
|
+
});
|
|
694
|
+
cronJobs.delete(triggerId);
|
|
695
|
+
await fireTrigger(triggerId, variables);
|
|
696
|
+
}
|
|
632
697
|
function stopCronJob(triggerId) {
|
|
633
698
|
const job = cronJobs.get(triggerId);
|
|
634
699
|
if (job) {
|
|
@@ -16,6 +16,14 @@ export const PERMISSION_MODES = {
|
|
|
16
16
|
bypass: { label: 'Permissionless', description: 'Skip all permission prompts (less safe, faster)' },
|
|
17
17
|
interactive: { label: 'Interactive', description: 'Ask for approval before sensitive operations' },
|
|
18
18
|
};
|
|
19
|
+
export const CODEX_REASONING_EFFORTS = {
|
|
20
|
+
none: { label: 'None', description: 'No reasoning', icon: '⚪' },
|
|
21
|
+
minimal: { label: 'Minimal', description: 'Least reasoning, fastest', icon: '💨' },
|
|
22
|
+
low: { label: 'Low', description: 'Light reasoning', icon: '🏃' },
|
|
23
|
+
medium: { label: 'Medium', description: 'Balanced reasoning', icon: '⚖️' },
|
|
24
|
+
high: { label: 'High', description: 'Deep reasoning', icon: '🔬' },
|
|
25
|
+
xhigh: { label: 'X-High', description: 'Extra-high reasoning, slowest', icon: '🧠' },
|
|
26
|
+
};
|
|
19
27
|
export const CODEX_MODELS = {
|
|
20
28
|
'gpt-5.5': {
|
|
21
29
|
label: 'GPT-5.5',
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as Ee,a4 as Ie,as as De,ar as _e,r as t,C as Be,S as ae,l as Re,av as z,A as ne,aD as O,s as T,aE as j,j as s,N as S,ax as ze,az as Oe,I as L,aA as P,ac as g,aa as E,E as Te}from"./main--_0rf6yB.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";function le(u){const h=j.filter(C=>!u.has(`Boss ${C}`));return h.length===0?`Boss ${j[Math.floor(Math.random()*j.length)]}-${Date.now()%1e3}`:`Boss ${h[Math.floor(Math.random()*h.length)]}`}function Ue({isOpen:u,onClose:h,onSpawnStart:C,onSpawnEnd:I,spawnPosition:te}){const{t:n}=Ee(["terminal","common"]),q=Ie(),o=De(),k=_e(),[r,p]=t.useState(""),[M,ie]=t.useState(()=>Be(ae.LAST_CWD)),[c,D]=t.useState("boss"),[F,U]=t.useState(!1),[ce,y]=t.useState(!1),[W,oe]=t.useState(!0),[G,re]=t.useState("bypass"),[d,_]=t.useState("claude"),[b,N]=t.useState({fullAuto:!0,sandbox:"workspace-write",approvalMode:"on-request",search:!1}),[K,de]=t.useState("opus[1m]"),[H,pe]=t.useState("gpt-5.3-codex"),[v,A]=t.useState(new Set),[J,B]=t.useState(new Set),[m,me]=t.useState(""),[f,ue]=t.useState(""),[V,he]=t.useState(""),$=t.useRef(null),R=t.useRef(!1),X=t.useRef(!1),w=t.useMemo(()=>k.filter(e=>e.enabled),[k]),Y=t.useMemo(()=>{if(!f.trim())return w;const e=f.toLowerCase();return w.filter(a=>a.name.toLowerCase().includes(e)||a.description.toLowerCase().includes(e)||a.slug.toLowerCase().includes(e))},[w,f]),xe=t.useMemo(()=>{var a;const e=o.find(l=>l.id===c);return(a=e==null?void 0:e.defaultSkillIds)!=null&&a.length?k.filter(l=>e.defaultSkillIds.includes(l.id)):[]},[o,c,k]),we=["full-notifications","streaming-exec","task-label","report-task-to-boss","send-message-to-agent"];t.useEffect(()=>{if(u&&!X.current&&w.length>0){const a=w.filter(l=>we.includes(l.slug)).map(l=>l.id);a.length>0&&B(new Set(a))}X.current=u},[u,w]);const be=t.useCallback(e=>{B(a=>{const l=new Set(a);return l.has(e)?l.delete(e):l.add(e),l})},[]),i=t.useMemo(()=>o.find(e=>e.id===c),[o,c]),fe=t.useMemo(()=>{if(i!=null&&i.model)return i.model},[i]),je=t.useMemo(()=>{if(i!=null&&i.customModelPath)return Re(`/api/custom-models/${i.id}`)},[i]),Ne=i==null?void 0:i.modelScale,ve=t.useMemo(()=>i?"scout":c==="boss"?"architect":c,[c,i]),Q=t.useMemo(()=>Array.from(q.values()).filter(e=>!e.isBoss&&e.class!=="boss"&&!e.bossId),[q]),Z=t.useMemo(()=>{if(!m.trim())return o;const e=m.toLowerCase();return o.filter(a=>a.name.toLowerCase().includes(e)||a.description.toLowerCase().includes(e)||a.id.toLowerCase().includes(e))},[o,m]),ee=t.useMemo(()=>{if(!m.trim())return z;const e=m.toLowerCase();return z.filter(a=>{const l=ne[a.id];return l?a.name.toLowerCase().includes(e)||a.id.toLowerCase().includes(e)||l.description.toLowerCase().includes(e):!1})},[m]),se=t.useMemo(()=>{if(!m.trim())return!0;const e=m.toLowerCase(),a=O.boss;return"boss".includes(e)||a.description.toLowerCase().includes(e)},[m]);t.useEffect(()=>{if(u&&!R.current){R.current=!0;const e=new Set(Array.from(T.getState().agents.values()).map(l=>l.name)),a=o.find(l=>l.id===c);if(a){const l=j.filter(x=>!e.has(`${a.name} ${x}`));if(l.length===0){const x=j[Math.floor(Math.random()*j.length)];p(`${a.name} ${x}-${Date.now()%1e3}`)}else p(`${a.name} ${l[Math.floor(Math.random()*l.length)]}`)}else p(le(e));A(new Set),$.current&&($.current.focus(),$.current.select())}else u||(R.current=!1)},[u]),t.useEffect(()=>{if(!u)return;const e=o.find(a=>a.id===c);if(e)if(r.startsWith("Boss ")){const a=r.substring(5);p(`${e.name} ${a}`)}else{const a=o.find(l=>r.startsWith(l.name+" "));if(a){const l=r.substring(a.name.length+1);p(`${e.name} ${l}`)}else p(`${e.name} ${r}`)}else{const a=o.find(l=>r.startsWith(l.name+" "));if(a){const l=r.substring(a.name.length+1);p(`Boss ${l}`)}else r.startsWith("Boss ")||p(`Boss ${r}`)}},[c]);const Se=()=>{if(y(!1),!M.trim()){y(!0);return}if(!r.trim()){const l=new Set(Array.from(T.getState().agents.values()).map(x=>x.name));p(le(l));return}Te(ae.LAST_CWD,M),C();const e=V.trim()||void 0,a=Array.from(J);T.spawnBossAgent(r.trim(),c,M.trim(),te||void 0,Array.from(v),d==="claude"?W:!1,G,d,d==="codex"?b:void 0,d==="codex"?H:void 0,d==="claude"?K:void 0,e,a),p(""),A(new Set),B(new Set),I(),h()},ge=()=>{U(!1),p(""),A(new Set),I(),h()},Ce=()=>{U(!1),y(!0),I()};t.useEffect(()=>(window.__bossSpawnModalSuccess=ge,window.__bossSpawnModalError=Ce,()=>{delete window.__bossSpawnModalSuccess,delete window.__bossSpawnModalError}),[r]);const ke=e=>{e.target===e.currentTarget&&h()},Me=e=>{e.key==="Escape"&&h()},ye=e=>{const a=new Set(v);a.has(e)?a.delete(e):a.add(e),A(a)};if(!u)return null;const Ae=O.boss;return s.jsx("div",{className:`modal-overlay ${u?"visible":""}`,onClick:ke,onKeyDown:Me,children:s.jsxs("div",{className:"modal boss-spawn-modal",children:[s.jsxs("div",{className:"modal-header",children:[s.jsx(S,{classId:"boss",size:22,className:"boss-header-icon"}),n("terminal:spawn.deployBossTitle")]}),s.jsxs("div",{className:"modal-body spawn-modal-body",children:[s.jsxs("div",{className:"spawn-top-section",children:[s.jsx("div",{className:"spawn-preview-compact",children:s.jsx(ze,{agentClass:ve,modelFile:fe,customModelUrl:je,modelScale:Ne,width:100,height:120})}),s.jsxs("div",{className:"spawn-class-section",children:[s.jsx("div",{className:"spawn-class-label",children:n("terminal:spawn.bossClass")}),o.length+z.length+1>6&&s.jsx("input",{type:"text",className:"spawn-input class-search-input",placeholder:n("terminal:spawn.filterClasses"),value:m,onChange:e=>me(e.target.value)}),s.jsxs("div",{className:"class-selector-inline",children:[Z.map(e=>s.jsxs("button",{className:`class-chip ${c===e.id?"selected":""}`,onClick:()=>D(e.id),title:e.description,children:[s.jsx(S,{classId:e.id,size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id)),se&&s.jsxs("button",{className:`class-chip ${c==="boss"?"selected":""}`,onClick:()=>D("boss"),title:Ae.description,children:[s.jsx(S,{classId:"boss",size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:n("terminal:spawn.bossClassName")})]}),ee.map(e=>{const a=ne[e.id];return a?s.jsxs("button",{className:`class-chip ${c===e.id?"selected":""}`,onClick:()=>D(e.id),title:a.description,children:[s.jsx(S,{classId:e.id,size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id):null}),m&&Z.length===0&&!se&&ee.length===0&&s.jsx("div",{className:"class-search-empty",children:n("terminal:spawn.noClassesMatch",{query:m})})]})]})]}),s.jsxs("div",{className:"spawn-form-section",children:[s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.name")}),s.jsx("input",{ref:$,type:"text",className:"spawn-input",placeholder:n("terminal:spawn.bossNamePlaceholder"),value:r,onChange:e=>p(e.target.value)})]}),s.jsxs("div",{className:"spawn-field spawn-field-wide",children:[s.jsx("label",{className:"spawn-label",children:n("terminal:spawn.workingDir")}),s.jsx(Oe,{value:M,onChange:e=>{ie(e),y(!1)},placeholder:n("terminal:spawn.workingDirPlaceholder"),className:"spawn-input",hasError:ce,directoriesOnly:!0})]})]}),s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.runtime")}),s.jsxs("div",{className:"spawn-select-row",children:[s.jsxs("button",{className:`spawn-select-btn ${d==="claude"?"selected":""}`,onClick:()=>_("claude"),title:n("terminal:spawn.useClaudeCli"),children:[s.jsx("img",{src:"/assets/claude.ico",alt:"Claude",className:"spawn-provider-icon"}),s.jsx("span",{children:"Claude"})]}),s.jsxs("button",{className:`spawn-select-btn ${d==="codex"?"selected":""}`,onClick:()=>_("codex"),title:n("terminal:spawn.useCodexCli"),children:[s.jsx("img",{src:"/assets/codex.ico",alt:"Codex",className:"spawn-provider-icon"}),s.jsx("span",{children:"Codex"})]}),s.jsxs("button",{className:`spawn-select-btn spawn-select-btn--opencode ${d==="opencode"?"selected":""}`,onClick:()=>_("opencode"),title:"Use OpenCode CLI (multi-provider)",children:[s.jsx("span",{children:s.jsx(L,{name:"status-pending",size:14,weight:"fill",color:"#4ade80"})}),s.jsx("span",{children:"OpenCode"})]})]})]}),s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.permissions")}),s.jsx("div",{className:"spawn-select-row",children:Object.keys(P).map(e=>s.jsxs("button",{className:`spawn-select-btn ${G===e?"selected":""}`,onClick:()=>re(e),title:P[e].description,children:[s.jsx("span",{children:s.jsx(L,{name:e==="bypass"?"bolt":"lock",size:14})}),s.jsx("span",{children:P[e].label})]},e))})]})]}),s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.model")}),d==="claude"?s.jsx("div",{className:"spawn-select-row",children:Object.keys(g).filter(e=>!g[e].deprecated).map(e=>s.jsxs("button",{className:`spawn-select-btn ${K===e?"selected":""}`,onClick:()=>de(e),title:g[e].description,children:[s.jsx("span",{children:g[e].icon}),s.jsx("span",{children:g[e].label})]},e))}):d==="codex"?s.jsx("div",{className:"spawn-select-row spawn-select-row--codex-models",children:Object.keys(E).map(e=>s.jsxs("button",{className:`spawn-select-btn ${H===e?"selected":""}`,onClick:()=>pe(e),title:E[e].description,children:[s.jsx("span",{children:E[e].icon}),s.jsx("span",{children:E[e].label})]},e))}):d==="opencode"?s.jsx("input",{type:"text",className:"spawn-input",defaultValue:"minimax/MiniMax-M1-80k",placeholder:"provider/model (e.g., minimax/MiniMax-M1-80k)"}):s.jsx("div",{className:"spawn-inline-hint",children:n("terminal:spawn.codex.configuration")})]}),s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.browser")}),s.jsx("div",{className:"spawn-form-row spawn-options-row",children:s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:W,onChange:e=>oe(e.target.checked),disabled:d!=="claude"}),s.jsx("span",{children:n("terminal:spawn.chromeBrowser")})]})})]})]}),d==="codex"&&s.jsx("div",{className:"spawn-form-row",children:s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("terminal:spawn.codex.config")}),s.jsxs("div",{className:"spawn-options-row",style:{display:"flex",flexDirection:"column",gap:8},children:[s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:b.fullAuto!==!1,onChange:e=>N(a=>({...a,fullAuto:e.target.checked}))}),s.jsx("span",{children:n("terminal:spawn.codex.useFullAuto")})]}),s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:!!b.search,onChange:e=>N(a=>({...a,search:e.target.checked}))}),s.jsx("span",{children:n("terminal:spawn.codex.enableSearch")})]}),b.fullAuto===!1&&s.jsxs(s.Fragment,{children:[s.jsxs("select",{className:"spawn-input",value:b.sandbox||"workspace-write",onChange:e=>N(a=>({...a,sandbox:e.target.value})),children:[s.jsx("option",{value:"read-only",children:n("terminal:spawn.codex.sandboxReadOnly")}),s.jsx("option",{value:"workspace-write",children:n("terminal:spawn.codex.sandboxWorkspaceWrite")}),s.jsx("option",{value:"danger-full-access",children:n("terminal:spawn.codex.sandboxDangerFullAccess")})]}),s.jsxs("select",{className:"spawn-input",value:b.approvalMode||"on-request",onChange:e=>N(a=>({...a,approvalMode:e.target.value})),children:[s.jsx("option",{value:"untrusted",children:n("terminal:spawn.codex.approvalsUntrusted")}),s.jsx("option",{value:"on-failure",children:n("terminal:spawn.codex.approvalsOnFailure")}),s.jsx("option",{value:"on-request",children:n("terminal:spawn.codex.approvalsOnRequest")}),s.jsx("option",{value:"never",children:n("terminal:spawn.codex.approvalsNever")})]})]}),s.jsx("input",{type:"text",className:"spawn-input",placeholder:n("terminal:spawn.codex.profileOptional"),value:b.profile||"",onChange:e=>N(a=>({...a,profile:e.target.value||void 0}))})]})]})}),w.length>0&&s.jsxs("div",{className:"spawn-skills-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.skills")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]})]}),w.length>6&&s.jsx("input",{type:"text",className:"spawn-input skill-search-input",placeholder:n("terminal:spawn.filterSkills"),value:f,onChange:e=>ue(e.target.value)}),s.jsxs("div",{className:"spawn-skills-inline",children:[Y.map(e=>{const a=J.has(e.id);return xe.some(x=>x.id===e.id)?null:s.jsxs("button",{className:`spawn-skill-chip ${a?"selected":""}`,onClick:()=>be(e.id),title:e.description,children:[a&&s.jsx("span",{className:"spawn-skill-check",children:s.jsx(L,{name:"check",size:12})}),s.jsx("span",{children:e.name}),e.builtin&&s.jsx("span",{className:"spawn-skill-builtin",children:"TC"})]},e.id)}),f&&Y.length===0&&s.jsx("div",{className:"skill-search-empty",children:n("terminal:spawn.noSkillsMatch",{query:f})})]})]}),s.jsxs("div",{className:"spawn-custom-instructions-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.customInstructions")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]})]}),s.jsx("textarea",{className:"spawn-input spawn-textarea",placeholder:n("terminal:spawn.customInstructionsBossPlaceholder"),value:V,onChange:e=>he(e.target.value),rows:3})]}),s.jsxs("div",{className:"spawn-subordinates-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.initialSubordinates")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]})]}),s.jsx("div",{className:"subordinates-selector-compact",children:Q.length===0?s.jsx("div",{className:"subordinates-empty",children:n("terminal:spawn.noAvailableAgents")}):Q.map(e=>{const a=v.has(e.id),l=O[e.class],x=o.find(Le=>Le.id===e.class),$e=l||x||{color:"#888888"};return s.jsxs("button",{className:`subordinate-chip ${a?"selected":""}`,onClick:()=>ye(e.id),children:[a&&s.jsx("span",{className:"subordinate-check",children:s.jsx(L,{name:"check",size:12})}),s.jsx("span",{className:"subordinate-chip-icon",style:{color:$e.color},children:s.jsx(S,{classId:e.class,size:16})}),s.jsx("span",{className:"subordinate-chip-name",children:e.name})]},e.id)})}),v.size>0&&s.jsxs("div",{className:"subordinates-count",children:[v.size," ",n("common:labels.selected").toLowerCase()]})]})]})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:h,children:n("common:buttons.cancel")}),s.jsx("button",{className:"btn btn-boss",onClick:Se,disabled:F,children:n(F?"common:buttons.deploying":"common:buttons2.deployBoss")})]})]})})}export{Ue as BossSpawnModal};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as Ve,ar as Ze,as as es,at as ss,au as as,r as t,C as ye,S as ne,av as te,A as Ae,l as le,aw as ns,s as S,h as ts,j as s,ax as ls,N as De,ay as x,az as os,aA as oe,I as ie,ac as T,aa as K,aB as is,ab as ce,aC as cs,E as rs}from"./main--_0rf6yB.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";function Ee(r,g){const b=g.filter(C=>!r.has(C));return b.length===0?`${g[Math.floor(Math.random()*g.length)]}-${Date.now()%1e3}`:b[Math.floor(Math.random()*b.length)]}function us({isOpen:r,onClose:g,onSpawnStart:b,onSpawnEnd:C,spawnPosition:Ie,spawnAreaId:N}){const{t:a}=Ve(["terminal","common"]),P=Ze(),p=es(),re=ss(),H=re.length>0?re:as,[m,v]=t.useState(""),[M,F]=t.useState(()=>ye(ne.LAST_CWD)),[i,k]=t.useState("scout"),[de,E]=t.useState(!1),[Le,z]=t.useState(!1),[pe,J]=t.useState(!1),[me,ue]=t.useState(""),[y,Y]=t.useState([]),[A,R]=t.useState(null),[_e,he]=t.useState(!1),[I,we]=t.useState(""),[h,$e]=t.useState(""),[U,Te]=t.useState(!1),[q,Pe]=t.useState("bypass"),[o,X]=t.useState("claude"),[j,L]=t.useState({fullAuto:!0,sandbox:"workspace-write",approvalMode:"on-request",search:!1}),[xe,Q]=t.useState(new Set),[V,fe]=t.useState("opus[1m]"),[Z,ge]=t.useState("xHigh"),[ee,Fe]=t.useState("gpt-5.3-codex"),[se,ze]=t.useState("minimax/MiniMax-M1-80k"),[je,Re]=t.useState(""),[D,Ue]=t.useState(""),O=t.useRef(null),Ne=t.useRef(!1),_=t.useCallback(()=>{window.__spawnModalAreaContext=null},[]),w=t.useMemo(()=>P.filter(e=>e.enabled),[P]),qe=["full-notifications","streaming-exec","task-label","report-task-to-boss","agent-tracking","send-message-to-agent"];t.useEffect(()=>{if(r&&!Ne.current){if(w.length>0){const l=w.filter(c=>qe.includes(c.slug)).map(c=>c.id);l.length>0&&Q(new Set(l))}const n=ye(ne.DEFAULT_AGENT_CLASS);if(n==="random"){const c=[...Object.keys(cs),...p.map(u=>u.id)];k(c[Math.floor(Math.random()*c.length)])}else k(n||"scout")}Ne.current=r},[r,w,p]);const ve=t.useMemo(()=>{if(!D.trim())return w;const e=D.toLowerCase();return w.filter(n=>n.name.toLowerCase().includes(e)||n.description.toLowerCase().includes(e)||n.slug.toLowerCase().includes(e))},[w,D]),Oe=t.useCallback(e=>{Q(n=>{const l=new Set(n);return l.has(e)?l.delete(e):l.add(e),l})},[]);t.useMemo(()=>w.filter(e=>e.assignedAgentClasses.includes(i)),[w,i]);const We=t.useMemo(()=>{var n;const e=p.find(l=>l.id===i);return(n=e==null?void 0:e.defaultSkillIds)!=null&&n.length?P.filter(l=>e.defaultSkillIds.includes(l.id)):[]},[p,i,P]),Se=t.useMemo(()=>{if(!I.trim())return y;const e=I.toLowerCase();return y.filter(n=>n.sessionId.toLowerCase().includes(e)||n.projectPath.toLowerCase().includes(e)||n.firstMessage&&n.firstMessage.toLowerCase().includes(e))},[y,I]),W=t.useMemo(()=>{if(!h.trim())return p;const e=h.toLowerCase();return p.filter(n=>n.name.toLowerCase().includes(e)||n.description.toLowerCase().includes(e)||n.id.toLowerCase().includes(e))},[p,h]),B=t.useMemo(()=>{if(!h.trim())return te;const e=h.toLowerCase();return te.filter(n=>{const l=Ae[n.id];return n.name.toLowerCase().includes(e)||n.id.toLowerCase().includes(e)||l.description.toLowerCase().includes(e)})},[h]);t.useEffect(()=>{if(!r||!h.trim())return;const e=[...W.map(n=>n.id),...B.map(n=>n.id)];e.length===1&&e[0]!==i&&k(e[0])},[r,h,W,B,i]);const d=t.useMemo(()=>p.find(e=>e.id===i),[p,i]),Be=t.useMemo(()=>{if(d!=null&&d.model)return d.model},[d]),Ge=t.useMemo(()=>{if(d!=null&&d.customModelPath)return le(`/api/custom-models/${d.id}`)},[d]),Ke=d==null?void 0:d.modelScale,He=t.useMemo(()=>d?"scout":i,[i,d]),G=t.useCallback(async e=>{he(!0);try{const n=e?le(`/api/agents/claude-sessions?cwd=${encodeURIComponent(e)}`):le("/api/agents/claude-sessions"),c=await(await ns(n)).json();Y(c.sessions||[])}catch(n){console.error("Failed to fetch sessions:",n),Y([])}finally{he(!1)}},[]);t.useEffect(()=>{r?G(M||void 0):(Y([]),R(null),we(""))},[r,G]),t.useEffect(()=>{if(!r)return;const e=setTimeout(()=>{G(M||void 0),R(null)},300);return()=>clearTimeout(e)},[M,r,G]),t.useEffect(()=>{if(!r||!N)return;const e=S.getState().areas.get(N);if(e!=null&&e.directories&&e.directories.length>0){F(e.directories[0]);return}const n=Array.from(S.getState().agents.values()).filter(f=>{var $;return(($=S.getAreaForAgent(f.id))==null?void 0:$.id)===N&&f.cwd});if(n.length===0)return;const l=new Map;for(const f of n)l.set(f.cwd,(l.get(f.cwd)||0)+1);let c="",u=0;for(const[f,$]of l)$>u&&(c=f,u=$);c&&F(c)},[r,N]),t.useEffect(()=>{if(r){const e=new Set(Array.from(S.getState().agents.values()).map(u=>u.name)),n=Ee(e,H),l=p.find(u=>u.id===i),c=l?`${l.name} ${n}`:n;v(c),O.current&&(O.current.focus(),O.current.select())}},[r,H]),t.useEffect(()=>{if(!r)return;const e=p.find(n=>n.id===i);if(e){const n=p.find(l=>m.startsWith(l.name+" "));if(n){const l=m.substring(n.name.length+1);v(`${e.name} ${l}`)}else v(`${e.name} ${m}`)}else{const n=p.find(l=>m.startsWith(l.name+" "));if(n){const l=m.substring(n.name.length+1);v(l)}}},[i]),t.useEffect(()=>{i==="boss"&&fe("claude-opus-4-7")},[i]);const Je=()=>{var c;console.log("[SpawnModal] handleSpawn called"),z(!1);const e=A&&((c=y.find(u=>u.sessionId===A))==null?void 0:c.projectPath)||M;if(console.log("[SpawnModal] Effective CWD:",e),console.log("[SpawnModal] Agent name:",m),console.log("[SpawnModal] Agent class:",i),console.log("[SpawnModal] Permission mode:",q),console.log("[SpawnModal] Provider:",o),console.log("[SpawnModal] Use Chrome:",U),console.log("[SpawnModal] Session ID:",A||"none"),!e.trim()){console.error("[SpawnModal] Empty CWD, showing error"),z(!0);return}if(!m.trim()){console.log("[SpawnModal] Empty name, regenerating");const u=new Set(Array.from(S.getState().agents.values()).map(f=>f.name));v(Ee(u,H));return}rs(ne.LAST_CWD,e),E(!0),b();const n=Array.from(xe),l=je.trim()||void 0;console.log("[SpawnModal] Calling store.spawnAgent with:",{name:m.trim(),class:i,cwd:e.trim(),sessionId:A||void 0,useChrome:o==="claude"?U:!1,permissionMode:q,provider:o,codexConfig:o==="codex"?j:void 0,codexModel:o==="codex"?ee:void 0,opencodeModel:o==="opencode"?se:void 0,initialSkillIds:n,model:o==="claude"?V:void 0,customInstructions:l?`${l.length} chars`:void 0,spawnAreaId:N||void 0}),window.__spawnModalAreaContext=N?{areaId:N}:null,S.spawnAgent(m.trim(),i,e.trim(),Ie||void 0,A||void 0,o==="claude"?U:!1,q,n,o,o==="codex"?j:void 0,o==="codex"?ee:void 0,o==="claude"?V:void 0,l,o==="claude"?Z:void 0,o==="opencode"?se:void 0)},be=()=>{console.log("[SpawnModal] Agent creation successful"),E(!1),v(""),Q(new Set),_(),C(),g()},Ce=()=>{console.error("[SpawnModal] Agent creation failed"),E(!1),z(!0),_(),C()},Me=e=>{console.log("[SpawnModal] Directory not found:",e),E(!1),ue(e),J(!0),C()},ke=()=>{J(!1),E(!0),b(),S.createDirectoryAndSpawn(me,m.trim(),i)},ae=()=>{J(!1),ue(""),_()};t.useEffect(()=>(window.__spawnModalSuccess=be,window.__spawnModalError=Ce,window.__spawnModalDirNotFound=Me,()=>{_(),delete window.__spawnModalSuccess,delete window.__spawnModalError,delete window.__spawnModalDirNotFound}),[m,i,be,Ce,Me,_]);const{handleMouseDown:Ye,handleClick:Xe}=ts(g),Qe=e=>{e.key==="Escape"&&g()};return!r&&!pe?null:pe?s.jsx("div",{className:"modal-overlay visible",onClick:ae,onKeyDown:e=>{e.key==="Escape"&&ae(),e.key==="Enter"&&ke()},children:s.jsxs("div",{className:"modal confirm-modal",onClick:e=>e.stopPropagation(),children:[s.jsx("div",{className:"modal-header",children:a("terminal:spawn.directoryNotFound")}),s.jsxs("div",{className:"modal-body confirm-modal-body",children:[s.jsx("p",{children:a("terminal:spawn.directoryNotExist")}),s.jsx("code",{className:"confirm-modal-path",children:me}),s.jsx("p",{children:a("terminal:spawn.wouldYouCreate")})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:ae,children:a("common:buttons.cancel")}),s.jsx("button",{className:"btn btn-primary",onClick:ke,autoFocus:!0,children:a("terminal:spawn.createDirectory")})]})]})}):s.jsx("div",{className:`modal-overlay ${r?"visible":""}`,onMouseDown:Ye,onClick:Xe,onKeyDown:Qe,children:s.jsxs("div",{className:"modal spawn-modal",children:[s.jsx("div",{className:"modal-header",children:a("terminal:spawn.deployTitle")}),s.jsxs("div",{className:"modal-body spawn-modal-body",children:[s.jsxs("div",{className:"spawn-top-section",children:[s.jsx("div",{className:"spawn-preview-compact",children:s.jsx(ls,{agentClass:He,modelFile:Be,customModelUrl:Ge,modelScale:Ke,width:100,height:120})}),s.jsxs("div",{className:"spawn-class-section",children:[s.jsx("div",{className:"spawn-class-label",children:a("terminal:spawn.agentClass")}),p.length+te.length>6&&s.jsx("input",{type:"text",className:"spawn-input class-search-input",placeholder:a("terminal:spawn.filterClasses"),value:h,onChange:e=>$e(e.target.value)}),s.jsxs("div",{className:"class-selector-inline",children:[W.map(e=>s.jsxs("button",{className:`class-chip ${i===e.id?"selected":""}`,onClick:()=>k(e.id),title:e.description,children:[s.jsx(De,{classId:e.id,size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id)),B.map(e=>{const n=Ae[e.id];return s.jsxs("button",{className:`class-chip ${i===e.id?"selected":""}`,onClick:()=>k(e.id),title:n.description,children:[s.jsx(De,{classId:e.id,size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id)}),h&&W.length===0&&B.length===0&&s.jsx("div",{className:"class-search-empty",children:a("terminal:spawn.noClassesMatch",{query:h})})]})]})]}),s.jsxs("div",{className:"spawn-form-section",children:[s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:a("common:labels.name")}),s.jsx("input",{ref:O,type:"text",className:"spawn-input",placeholder:a("terminal:spawn.agentNamePlaceholder"),value:m,onChange:e=>v(e.target.value)})]}),s.jsxs("div",{className:"spawn-field spawn-field-wide",children:[s.jsxs("label",{className:"spawn-label",children:[a("terminal:spawn.workingDir"),s.jsx(x,{text:a("terminal:spawn.helpWorkingDir"),title:a("terminal:spawn.workingDir"),position:"top",size:"sm"})]}),s.jsx(os,{value:M,onChange:e=>{F(e),z(!1)},placeholder:a("terminal:spawn.workingDirPlaceholder"),className:`spawn-input ${Le?"error":""}`,directoriesOnly:!0})]})]}),s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsxs("label",{className:"spawn-label",children:[a("terminal:spawn.selectRuntime"),s.jsx(x,{text:a("terminal:spawn.helpRuntime"),title:a("terminal:spawn.runtimeTitle"),position:"top",size:"sm"})]}),s.jsxs("div",{className:"spawn-select-row",children:[s.jsxs("button",{className:`spawn-select-btn ${o==="claude"?"selected":""}`,onClick:()=>X("claude"),title:a("terminal:spawn.useClaudeCli"),children:[s.jsx("img",{src:"/assets/claude.ico",alt:"Claude",className:"spawn-provider-icon"}),s.jsx("span",{children:"Claude"})]}),s.jsxs("button",{className:`spawn-select-btn ${o==="codex"?"selected":""}`,onClick:()=>X("codex"),title:a("terminal:spawn.useCodexCli"),children:[s.jsx("img",{src:"/assets/codex.ico",alt:"Codex",className:"spawn-provider-icon"}),s.jsx("span",{children:"Codex"})]}),s.jsxs("button",{className:`spawn-select-btn spawn-select-btn--opencode ${o==="opencode"?"selected":""}`,onClick:()=>X("opencode"),title:"Use OpenCode CLI (multi-provider)",children:[s.jsx("img",{src:"/assets/opencode.svg",alt:"OpenCode",className:"spawn-provider-icon"}),s.jsx("span",{children:"OpenCode"})]})]})]}),s.jsxs("div",{className:"spawn-field",children:[s.jsxs("label",{className:"spawn-label",children:[a("common:labels.permissions"),s.jsx(x,{text:a("terminal:spawn.helpPermission"),title:a("terminal:spawn.permissionMode"),position:"top",size:"sm"})]}),s.jsx("div",{className:"spawn-select-row",children:Object.keys(oe).map(e=>s.jsxs("button",{className:`spawn-select-btn ${q===e?"selected":""}`,onClick:()=>Pe(e),title:oe[e].description,children:[s.jsx("span",{children:s.jsx(ie,{name:e==="bypass"?"bolt":"lock",size:12})}),s.jsx("span",{children:oe[e].label})]},e))})]})]}),s.jsx("div",{className:"spawn-form-row",children:s.jsxs("div",{className:"spawn-field",children:[s.jsxs("label",{className:"spawn-label",children:[a("common:labels.model"),s.jsx(x,{text:a("terminal:spawn.helpModel"),title:a("terminal:spawn.modelTitle"),position:"top",size:"sm"})]}),o==="claude"?s.jsx("div",{className:"spawn-select-row spawn-select-row--wrap",children:Object.keys(T).filter(e=>!T[e].deprecated).map(e=>s.jsxs("button",{className:`spawn-select-btn ${V===e?"selected":""}`,onClick:()=>fe(e),title:T[e].description,children:[s.jsx("span",{children:T[e].icon}),s.jsx("span",{children:T[e].label})]},e))}):o==="codex"?s.jsx("div",{className:"spawn-select-row spawn-select-row--codex-models",children:Object.keys(K).map(e=>s.jsxs("button",{className:`spawn-select-btn ${ee===e?"selected":""}`,onClick:()=>Fe(e),title:K[e].description,children:[s.jsx("span",{children:K[e].icon}),s.jsx("span",{children:K[e].label})]},e))}):o==="opencode"?s.jsx(is,{value:se,onChange:ze,inputId:"spawn-opencode-model"}):s.jsx("div",{className:"spawn-inline-hint",children:a("terminal:spawn.chooseCodexModel")})]})}),s.jsxs("div",{className:"spawn-form-row",children:[o==="claude"&&s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:"Effort"}),s.jsxs("div",{className:"spawn-select-row spawn-select-row--effort",children:[s.jsx("button",{className:`spawn-select-btn spawn-select-btn--compact ${Z===void 0?"selected":""}`,onClick:()=>ge(void 0),title:"Use default effort level",children:s.jsx("span",{children:"Default"})}),Object.keys(ce).map(e=>s.jsx("button",{className:`spawn-select-btn spawn-select-btn--compact ${Z===e?"selected":""}`,onClick:()=>ge(e),title:ce[e].description,children:s.jsx("span",{children:ce[e].label})},e))]})]}),s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:a("terminal:spawn.browser")}),s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:U,onChange:e=>Te(e.target.checked),disabled:o!=="claude"}),s.jsxs("span",{children:[s.jsx(ie,{name:"globe",size:12})," ",a("terminal:spawn.chromeBrowser")]}),s.jsx(x,{text:a(o==="claude"?"terminal:spawn.helpChrome":"terminal:spawn.helpChromeDisabled"),title:a("terminal:spawn.chromeBrowser"),position:"top",size:"sm"})]})]})]}),o==="codex"&&s.jsxs("div",{className:"codex-config-section",children:[s.jsx("div",{className:"codex-config-title",children:a("terminal:spawn.codex.configuration")}),s.jsxs("div",{className:"codex-config-options",children:[s.jsxs("div",{className:"codex-option-group",children:[s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:j.fullAuto!==!1,onChange:e=>L(n=>({...n,fullAuto:e.target.checked}))}),s.jsx("span",{children:a("terminal:spawn.codex.fullAuto")}),s.jsx(x,{text:a("terminal:spawn.helpFullAuto"),title:a("terminal:spawn.fullAutoTitle"),position:"top",size:"sm"})]}),s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:!!j.search,onChange:e=>L(n=>({...n,search:e.target.checked}))}),s.jsx("span",{children:a("terminal:spawn.codex.search")}),s.jsx(x,{text:a("terminal:spawn.helpSearch"),title:a("terminal:spawn.searchTitle"),position:"top",size:"sm"})]})]}),j.fullAuto===!1&&s.jsxs("div",{className:"codex-option-group",children:[s.jsx("div",{className:"codex-option-header",children:a("terminal:spawn.codex.restrictions")}),s.jsxs("select",{className:"spawn-input codex-select",value:j.sandbox||"workspace-write",onChange:e=>L(n=>({...n,sandbox:e.target.value})),children:[s.jsxs("option",{value:"read-only",children:["📖 ",a("terminal:spawn.codex.sandboxReadOnly")]}),s.jsxs("option",{value:"workspace-write",children:["✏️ ",a("terminal:spawn.codex.sandboxWorkspaceWrite")]}),s.jsxs("option",{value:"danger-full-access",children:["⚡ ",a("terminal:spawn.codex.sandboxDangerFullAccess")]})]}),s.jsxs("select",{className:"spawn-input codex-select",value:j.approvalMode||"on-request",onChange:e=>L(n=>({...n,approvalMode:e.target.value})),children:[s.jsxs("option",{value:"untrusted",children:["🔒 ",a("terminal:spawn.codex.approvalsUntrusted")]}),s.jsxs("option",{value:"on-failure",children:["⚠️ ",a("terminal:spawn.codex.approvalsOnFailure")]}),s.jsxs("option",{value:"on-request",children:["🤔 ",a("terminal:spawn.codex.approvalsOnRequest")]}),s.jsxs("option",{value:"never",children:["✅ ",a("terminal:spawn.codex.approvalsNever")]})]})]}),s.jsxs("div",{className:"codex-option-group",children:[s.jsx("div",{className:"codex-option-header",children:a("terminal:spawn.codex.profile")}),s.jsx("input",{type:"text",className:"spawn-input codex-profile-input",placeholder:a("terminal:spawn.codex.profilePlaceholder"),value:j.profile||"",onChange:e=>L(n=>({...n,profile:e.target.value||void 0}))})]})]})]}),w.length>0&&s.jsxs("div",{className:"spawn-skills-section",children:[s.jsxs("label",{className:"spawn-label",children:[a("terminal:spawn.skills")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",a("common:labels.optional"),")"]}),s.jsx(x,{text:a("terminal:spawn.helpSkills"),title:a("terminal:spawn.skillsTitle"),position:"top",size:"sm"})]}),w.length>6&&s.jsx("input",{type:"text",className:"spawn-input skill-search-input",placeholder:a("terminal:spawn.filterSkills"),value:D,onChange:e=>Ue(e.target.value)}),s.jsxs("div",{className:"spawn-skills-inline",children:[ve.map(e=>{const n=xe.has(e.id);return We.some(c=>c.id===e.id)?null:s.jsxs("button",{className:`spawn-skill-chip ${n?"selected":""}`,onClick:()=>Oe(e.id),title:e.description,children:[n&&s.jsx("span",{className:"spawn-skill-check",children:s.jsx(ie,{name:"check",size:10})}),s.jsx("span",{children:e.name}),e.builtin&&s.jsx("span",{className:"spawn-skill-builtin",children:"TC"})]},e.id)}),D&&ve.length===0&&s.jsx("div",{className:"skill-search-empty",children:a("terminal:spawn.noSkillsMatch",{query:D})})]})]}),s.jsxs("div",{className:"spawn-custom-instructions-section",children:[s.jsxs("label",{className:"spawn-label",children:[a("terminal:spawn.customInstructions")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",a("common:labels.optional"),")"]}),s.jsx(x,{text:a("terminal:spawn.helpCustomInstructions"),title:a("terminal:spawn.customInstructions"),position:"top",size:"sm"})]}),s.jsx("textarea",{className:"spawn-input spawn-textarea",placeholder:a("terminal:spawn.customInstructionsPlaceholder"),value:je,onChange:e=>Re(e.target.value),rows:3})]}),s.jsxs("div",{className:"spawn-sessions-section",children:[s.jsxs("label",{className:"spawn-label",children:[a("terminal:spawn.linkSession")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",a("common:labels.optional"),")"]}),s.jsx(x,{text:a("terminal:spawn.helpLinkSession"),title:a("terminal:spawn.linkSessionTitle"),position:"top",size:"sm"})]}),y.length>0&&s.jsx("input",{type:"text",className:"spawn-input session-search-input",placeholder:a("terminal:spawn.searchSessions"),value:I,onChange:e=>we(e.target.value)}),s.jsx("div",{className:"sessions-list",children:_e?s.jsx("div",{className:"sessions-loading",children:a("terminal:spawn.loadingSessions")}):y.length===0?s.jsx("div",{className:"sessions-empty",children:a("terminal:spawn.noSessions")}):Se.length===0?s.jsx("div",{className:"sessions-empty",children:a("terminal:spawn.noSessionsMatch",{query:I})}):Se.map(e=>{const n=A===e.sessionId,l=Date.now()-new Date(e.lastModified).getTime(),c=l<6e4?a("common:time.justNow"):l<36e5?a("common:time.minutesAgo",{count:Math.floor(l/6e4)}):l<864e5?a("common:time.hoursAgo",{count:Math.floor(l/36e5)}):a("common:time.daysAgo",{count:Math.floor(l/864e5)});return s.jsxs("div",{className:`session-item ${n?"selected":""}`,onClick:()=>{n?R(null):(R(e.sessionId),F(e.projectPath))},children:[s.jsxs("div",{className:"session-item-header",children:[s.jsx("span",{className:"session-item-path",children:e.projectPath}),s.jsx("span",{className:"session-item-age",children:c})]}),s.jsx("div",{className:"session-item-preview",children:e.firstMessage||a("terminal:spawn.messagesCount",{count:e.messageCount})})]},e.sessionId)})})]})]})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:g,children:a("common:buttons.cancel")}),s.jsx("button",{className:"btn btn-primary",onClick:Je,disabled:de,children:a(de?"common:buttons.deploying":"common:buttons2.deploy")})]})]})})}export{us as SpawnModal};
|