tide-commander 1.148.0 → 1.150.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 +33 -0
- package/README.md +6 -3
- package/dist/assets/{BossLogsModal-CZMHgMBE.js → BossLogsModal-DvczRUvP.js} +1 -1
- package/dist/assets/BossSpawnModal-B2autFKk.js +1 -0
- package/dist/assets/{ControlsModal-DJ8Scm16.js → ControlsModal-BaREMQxc.js} +1 -1
- package/dist/assets/{DockerLogsModal-Vb4gqdFz.js → DockerLogsModal-DZ0udMCo.js} +1 -1
- package/dist/assets/{EmbeddedEditor-D4sHERAj.js → EmbeddedEditor-CEjr0ZSZ.js} +1 -1
- package/dist/assets/{GmailOAuthSetup-COIYIbJS.js → GmailOAuthSetup-76BP8J8C.js} +1 -1
- package/dist/assets/{GoogleOAuthSetup-DJS59Soi.js → GoogleOAuthSetup-D45GImPI.js} +1 -1
- package/dist/assets/{IframeModal-CFysTkn9.js → IframeModal-De63RfJZ.js} +1 -1
- package/dist/assets/{IntegrationsPanel-BK8g9ceY.js → IntegrationsPanel-DYrw1Sqk.js} +2 -2
- package/dist/assets/{LogViewerModal-DRxR0HYq.js → LogViewerModal-DW-2lpln.js} +1 -1
- package/dist/assets/{MonitoringModal-CL7UMOdX.js → MonitoringModal-B0-XXyd3.js} +1 -1
- package/dist/assets/{PM2LogsModal-I3aouUlw.js → PM2LogsModal-DOfOhkCY.js} +1 -1
- package/dist/assets/{RestoreArchivedAreaModal-PWAg6w6b.js → RestoreArchivedAreaModal-DNGmIJmM.js} +1 -1
- package/dist/assets/Scene2DCanvas-BW1E76CQ.js +1 -0
- package/dist/assets/SceneManager-DAvc9-Wp.js +104 -0
- package/dist/assets/{SkillsPanel-EQ74sIa6.js → SkillsPanel-Br-gLCLA.js} +3 -3
- package/dist/assets/{SlackMultiInstanceSetup-CLMUteI0.js → SlackMultiInstanceSetup-DG_bIfDu.js} +1 -1
- package/dist/assets/SpawnModal-lWM8OuZW.js +1 -0
- package/dist/assets/{StatisticsModal-D6MgA_o0.js → StatisticsModal-LvA0Fcvn.js} +1 -1
- package/dist/assets/{SubordinateAssignmentModal-C6n0pMn3.js → SubordinateAssignmentModal-8YxNXcR3.js} +1 -1
- package/dist/assets/{TriggerManagerPanel-Umd8iUg1.js → TriggerManagerPanel-DftIuKUG.js} +1 -1
- package/dist/assets/{WorkflowEditorPanel-CxjBxs9O.js → WorkflowEditorPanel-oLwyO_C6.js} +1 -1
- package/dist/assets/{area-logos-CThPeqIM.js → area-logos-mcpQqUMZ.js} +1 -1
- package/dist/assets/grok.ico +0 -0
- package/dist/assets/grok.png +0 -0
- package/dist/assets/index-Ay7dKyeR.js +1 -0
- package/dist/assets/index-BMw7AAAK.js +5 -0
- package/dist/assets/{index-Cz-ypmob.js → index-BQpd34Mc.js} +1 -1
- package/dist/assets/{index-BUN7MVf5.js → index-C6-68CXL.js} +3 -3
- package/dist/assets/index-CIon0DLf.js +2 -0
- package/dist/assets/{index-maZSt2YW.js → index-Cwt-E2td.js} +5 -5
- package/dist/assets/{index-DelocTaH.js → index-DFVroqA5.js} +1 -1
- package/dist/assets/index-DR6_WeF_.js +1 -0
- package/dist/assets/{index-h3Cuh2Zn.js → index-O0t07OB_.js} +2 -2
- package/dist/assets/main-D5sqeuwB.js +286 -0
- package/dist/assets/main-JBkwGXfE.css +1 -0
- package/dist/assets/{web-CfvEypdU.js → web-BkrshujV.js} +1 -1
- package/dist/assets/{web-CNjTPilF.js → web-DPETNqOf.js} +1 -1
- package/dist/assets/{web-bcYaAwP6.js → web-vG1Smf_N.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/locales/de/config.json +3 -1
- package/dist/locales/en/config.json +2 -0
- package/dist/locales/en/terminal.json +6 -0
- package/dist/locales/en/tools.json +4 -2
- package/dist/locales/es/config.json +2 -0
- package/dist/locales/fr/config.json +3 -1
- package/dist/locales/hi/config.json +3 -1
- package/dist/locales/it/config.json +3 -1
- package/dist/locales/ja/config.json +3 -1
- package/dist/locales/pt/config.json +3 -1
- package/dist/locales/ru/config.json +3 -1
- package/dist/locales/zh-CN/config.json +3 -1
- package/dist/src/packages/server/claude/backend.js +114 -10
- package/dist/src/packages/server/claude/runner/process-lifecycle.js +62 -0
- package/dist/src/packages/server/claude/runner/stdout-pipeline.js +148 -7
- package/dist/src/packages/server/claude/runner/watchdog.js +12 -0
- package/dist/src/packages/server/claude/session-loader.js +295 -0
- package/dist/src/packages/server/codex/json-event-parser.js +149 -4
- package/dist/src/packages/server/data/index.js +1 -0
- package/dist/src/packages/server/grok/backend.js +235 -0
- package/dist/src/packages/server/grok/index.js +4 -0
- package/dist/src/packages/server/grok/json-event-parser.js +153 -0
- package/dist/src/packages/server/grok/session-watcher.js +493 -0
- package/dist/src/packages/server/opencode/json-event-parser.js +184 -15
- package/dist/src/packages/server/routes/agents.js +19 -11
- 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/grok-usage-service.js +374 -0
- 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 +73 -14
- package/dist/src/packages/shared/agent-types.js +10 -0
- package/package.json +1 -1
- package/dist/assets/BossSpawnModal-C6DxqtKP.js +0 -1
- package/dist/assets/Scene2DCanvas-DYPHkU3i.js +0 -1
- package/dist/assets/SceneManager-QqKygyaw.js +0 -104
- package/dist/assets/SpawnModal-BOeStihN.js +0 -1
- package/dist/assets/index-DOzFBkSH.js +0 -1
- package/dist/assets/index-DP7kd91h.js +0 -1
- package/dist/assets/index-DRyMARFk.js +0 -5
- package/dist/assets/index-DuWmOZdY.js +0 -2
- package/dist/assets/main-C2zgPci-.js +0 -256
- package/dist/assets/main-C3JO2TRI.css +0 -1
|
@@ -9,6 +9,7 @@ import { agentService, runtimeService, skillService, customClassService, bossSer
|
|
|
9
9
|
import { markInstructionsDirty } from '../../services/instruction-refresh.js';
|
|
10
10
|
import { createLogger } from '../../utils/index.js';
|
|
11
11
|
import { ClaudeBackend, parseContextOutput } from '../../claude/backend.js';
|
|
12
|
+
import { getGrokSessionDir, readGrokSignalsUsage } from '../../grok/session-watcher.js';
|
|
12
13
|
const log = createLogger('AgentHandler');
|
|
13
14
|
const claudeBackend = new ClaudeBackend();
|
|
14
15
|
// Test change: Server restart validation - if you see this log, the server restarted successfully
|
|
@@ -58,12 +59,14 @@ export async function handleSpawnAgent(ctx, payload) {
|
|
|
58
59
|
position: payload.position,
|
|
59
60
|
initialSkillIds: payload.initialSkillIds,
|
|
60
61
|
model: payload.model,
|
|
62
|
+
opencodeModel: payload.opencodeModel,
|
|
63
|
+
grokModel: payload.grokModel,
|
|
61
64
|
customInstructions: payload.customInstructions ? `${payload.customInstructions.length} chars` : undefined,
|
|
62
65
|
});
|
|
63
66
|
try {
|
|
64
67
|
const agent = await agentService.createAgent(payload.name, payload.class, payload.cwd, payload.position, payload.sessionId, payload.useChrome, payload.permissionMode, undefined, // initialSkillIds handled separately below
|
|
65
68
|
undefined, // isBoss
|
|
66
|
-
payload.model, payload.codexModel, payload.customInstructions, payload.provider, payload.codexConfig, payload.effort);
|
|
69
|
+
payload.model, payload.codexModel, payload.customInstructions, payload.provider, payload.codexConfig, payload.effort, payload.opencodeModel, payload.grokModel);
|
|
67
70
|
log.log('Agent created successfully:', {
|
|
68
71
|
id: agent.id,
|
|
69
72
|
name: agent.name,
|
|
@@ -119,7 +122,7 @@ async function duplicateAgentConfig(source, name, position) {
|
|
|
119
122
|
.map((skill) => skill.id);
|
|
120
123
|
const agent = await agentService.createAgent(name, source.class, source.cwd, position, undefined, // sessionId - never share the source's; clone=fresh, fork=set below
|
|
121
124
|
source.useChrome, source.permissionMode, undefined, // initialSkillIds handled separately below
|
|
122
|
-
source.isBoss, source.model, source.codexModel, source.customInstructions, source.provider, source.codexConfig, source.effort, source.opencodeModel);
|
|
125
|
+
source.isBoss, source.model, source.codexModel, source.customInstructions, source.provider, source.codexConfig, source.effort, source.opencodeModel, source.grokModel);
|
|
123
126
|
// Re-apply skills: copied direct assignments + class defaults.
|
|
124
127
|
const classDefaultSkills = customClassService.getClassDefaultSkillIds(agent.class);
|
|
125
128
|
const allSkillIds = [...new Set([...directSkillIds, ...classDefaultSkills])];
|
|
@@ -135,7 +138,7 @@ function duplicateOffset(source) {
|
|
|
135
138
|
// Providers whose conversation history can be forked (resume + native fork flag).
|
|
136
139
|
// Codex is intentionally excluded for now (no headless fork; would need rollout
|
|
137
140
|
// duplication) — forking a Codex agent gracefully degrades to a plain clone.
|
|
138
|
-
const FORKABLE_PROVIDERS = new Set(['claude', 'opencode']);
|
|
141
|
+
const FORKABLE_PROVIDERS = new Set(['claude', 'opencode', 'grok']);
|
|
139
142
|
/**
|
|
140
143
|
* Handle clone_agent message - duplicates an existing agent's configuration
|
|
141
144
|
* into a brand-new agent (fresh session, no inherited context/memory).
|
|
@@ -614,8 +617,11 @@ function buildStatsFromTrackedData(agent) {
|
|
|
614
617
|
// Do NOT prefer agent.contextStats here — those can become stale when previous
|
|
615
618
|
// fallback calls save their (potentially wrong) output back to agent.contextStats
|
|
616
619
|
// via broadcastContextStats, creating a self-reinforcing feedback loop.
|
|
617
|
-
const
|
|
618
|
-
|
|
620
|
+
const provider = agent.provider ?? 'claude';
|
|
621
|
+
const defaultContextLimit = provider === 'codex' ? 258400
|
|
622
|
+
: provider === 'opencode' ? 200000
|
|
623
|
+
: provider === 'grok' ? 500000
|
|
624
|
+
: 200000;
|
|
619
625
|
const contextLimit = Math.max(1, Math.round(agent.contextLimit || defaultContextLimit));
|
|
620
626
|
const rawContextUsed = Math.max(0, Math.round(agent.contextUsed || 0));
|
|
621
627
|
// Guard: contextUsed can never exceed contextLimit. Values above the limit are
|
|
@@ -629,7 +635,7 @@ function buildStatsFromTrackedData(agent) {
|
|
|
629
635
|
}
|
|
630
636
|
const usedPercent = Math.min(100, Math.round((contextUsed / contextLimit) * 100));
|
|
631
637
|
const freeTokens = Math.max(0, contextLimit - contextUsed);
|
|
632
|
-
const model = agent.model || agent.codexModel || agent.opencodeModel || 'unknown';
|
|
638
|
+
const model = agent.model || agent.codexModel || agent.opencodeModel || agent.grokModel || 'unknown';
|
|
633
639
|
return {
|
|
634
640
|
model,
|
|
635
641
|
contextWindow: contextLimit,
|
|
@@ -748,12 +754,47 @@ export async function handleRequestContextStats(ctx, payload) {
|
|
|
748
754
|
return;
|
|
749
755
|
}
|
|
750
756
|
}
|
|
757
|
+
// Grok: streaming-json has no usage events. Read signals.json from the session dir.
|
|
758
|
+
const isGrokProvider = (agent.provider ?? 'claude') === 'grok';
|
|
759
|
+
if (isGrokProvider && agent.sessionId && agent.cwd) {
|
|
760
|
+
try {
|
|
761
|
+
const sessionDir = getGrokSessionDir(agent.cwd, agent.sessionId);
|
|
762
|
+
const usage = readGrokSignalsUsage(sessionDir);
|
|
763
|
+
if (usage) {
|
|
764
|
+
const contextLimit = Math.max(1, usage.contextWindowTokens);
|
|
765
|
+
const contextUsed = Math.max(0, Math.min(usage.contextTokensUsed, contextLimit));
|
|
766
|
+
const usedPercent = Math.min(100, Math.round(usage.contextWindowUsage ?? (contextUsed / contextLimit) * 100));
|
|
767
|
+
const freeTokens = Math.max(0, contextLimit - contextUsed);
|
|
768
|
+
const stats = {
|
|
769
|
+
model: agent.grokModel || agent.model || 'grok',
|
|
770
|
+
contextWindow: contextLimit,
|
|
771
|
+
totalTokens: contextUsed,
|
|
772
|
+
usedPercent,
|
|
773
|
+
categories: {
|
|
774
|
+
systemPrompt: { tokens: 0, percent: 0 },
|
|
775
|
+
systemTools: { tokens: 0, percent: 0 },
|
|
776
|
+
messages: { tokens: contextUsed, percent: Number(((contextUsed / contextLimit) * 100).toFixed(1)) },
|
|
777
|
+
freeSpace: { tokens: freeTokens, percent: Number(((freeTokens / contextLimit) * 100).toFixed(1)) },
|
|
778
|
+
autocompactBuffer: { tokens: 0, percent: 0 },
|
|
779
|
+
},
|
|
780
|
+
lastUpdated: Date.now(),
|
|
781
|
+
};
|
|
782
|
+
log.log(`[contextStats] Grok signals.json for ${agent.name}: ${contextUsed}/${contextLimit}`);
|
|
783
|
+
broadcastContextStats(ctx, payload.agentId, stats, 'from Grok signals.json');
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
log.warn(`[contextStats] Grok signals.json missing/unreadable for ${agent.name} session=${agent.sessionId}`);
|
|
787
|
+
}
|
|
788
|
+
catch (err) {
|
|
789
|
+
log.error(`[contextStats] Grok signals read failed: ${err}`);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
751
792
|
// Fallback: generate from tracked data
|
|
752
793
|
const latestAgent = agentService.getAgent(payload.agentId) || agent;
|
|
753
794
|
const stats = buildStatsFromTrackedData(latestAgent);
|
|
754
|
-
const label = latestAgent.provider === 'codex'
|
|
755
|
-
|
|
756
|
-
|
|
795
|
+
const label = latestAgent.provider === 'codex' || latestAgent.provider === 'opencode' || latestAgent.provider === 'grok'
|
|
796
|
+
? 'estimated from turn usage'
|
|
797
|
+
: 'tracked from token usage';
|
|
757
798
|
broadcastContextStats(ctx, payload.agentId, stats, label);
|
|
758
799
|
}
|
|
759
800
|
/**
|
|
@@ -813,10 +854,14 @@ export async function handleUpdateAgentProperties(ctx, payload) {
|
|
|
813
854
|
const normalizedUpdatedOpencodeModel = updates.opencodeModel !== undefined
|
|
814
855
|
? agentService.sanitizeOpencodeModel(updates.opencodeModel)
|
|
815
856
|
: undefined;
|
|
857
|
+
const normalizedUpdatedGrokModel = updates.grokModel !== undefined
|
|
858
|
+
? agentService.sanitizeGrokModel(updates.grokModel)
|
|
859
|
+
: undefined;
|
|
816
860
|
// Track if model changed (requires hot restart to apply new model while preserving context)
|
|
817
861
|
const modelChanged = updates.model !== undefined && normalizedUpdatedModel !== agent.model;
|
|
818
862
|
const codexModelChanged = updates.codexModel !== undefined && normalizedUpdatedCodexModel !== agent.codexModel;
|
|
819
863
|
const opencodeModelChanged = updates.opencodeModel !== undefined && normalizedUpdatedOpencodeModel !== agent.opencodeModel;
|
|
864
|
+
const grokModelChanged = updates.grokModel !== undefined && normalizedUpdatedGrokModel !== agent.grokModel;
|
|
820
865
|
const providerChanged = updates.provider !== undefined && updates.provider !== agent.provider;
|
|
821
866
|
const classChanged = updates.class !== undefined && updates.class !== agent.class;
|
|
822
867
|
const codexConfigChanged = updates.codexConfig !== undefined
|
|
@@ -878,6 +923,9 @@ export async function handleUpdateAgentProperties(ctx, payload) {
|
|
|
878
923
|
if (updates.opencodeModel !== undefined) {
|
|
879
924
|
agentUpdates.opencodeModel = normalizedUpdatedOpencodeModel;
|
|
880
925
|
}
|
|
926
|
+
if (updates.grokModel !== undefined) {
|
|
927
|
+
agentUpdates.grokModel = normalizedUpdatedGrokModel;
|
|
928
|
+
}
|
|
881
929
|
if (updates.effort !== undefined) {
|
|
882
930
|
agentUpdates.effort = updates.effort;
|
|
883
931
|
}
|
|
@@ -920,7 +968,8 @@ export async function handleUpdateAgentProperties(ctx, payload) {
|
|
|
920
968
|
}
|
|
921
969
|
// If model changed, do a hot restart: stop process, resume with new model
|
|
922
970
|
// This preserves context by using --resume with the existing sessionId
|
|
923
|
-
|
|
971
|
+
const modelLikeChanged = modelChanged || codexModelChanged || opencodeModelChanged || grokModelChanged || providerChanged || codexConfigChanged || classChanged;
|
|
972
|
+
if (modelLikeChanged && sessionId) {
|
|
924
973
|
const reason = providerChanged
|
|
925
974
|
? `runtime changed to ${updates.provider}`
|
|
926
975
|
: classChanged
|
|
@@ -931,7 +980,9 @@ export async function handleUpdateAgentProperties(ctx, payload) {
|
|
|
931
980
|
? `Codex model changed to ${updates.codexModel}`
|
|
932
981
|
: opencodeModelChanged
|
|
933
982
|
? `OpenCode model changed to ${updates.opencodeModel}`
|
|
934
|
-
:
|
|
983
|
+
: grokModelChanged
|
|
984
|
+
? `Grok model changed to ${updates.grokModel}`
|
|
985
|
+
: `model changed to ${updates.model}`;
|
|
935
986
|
log.log(`Agent ${agent.name}: ${reason}, hot restarting with --resume to preserve context`);
|
|
936
987
|
try {
|
|
937
988
|
await runtimeService.stopAgent(agentId);
|
|
@@ -946,7 +997,7 @@ export async function handleUpdateAgentProperties(ctx, payload) {
|
|
|
946
997
|
log.error(`Failed to hot restart agent ${agent.name} after runtime config change:`, err);
|
|
947
998
|
}
|
|
948
999
|
}
|
|
949
|
-
else if (
|
|
1000
|
+
else if (modelLikeChanged && !sessionId) {
|
|
950
1001
|
const reason = providerChanged
|
|
951
1002
|
? `runtime changed to ${updates.provider}`
|
|
952
1003
|
: classChanged
|
|
@@ -957,12 +1008,14 @@ export async function handleUpdateAgentProperties(ctx, payload) {
|
|
|
957
1008
|
? `Codex model changed to ${updates.codexModel}`
|
|
958
1009
|
: opencodeModelChanged
|
|
959
1010
|
? `OpenCode model changed to ${updates.opencodeModel}`
|
|
960
|
-
:
|
|
1011
|
+
: grokModelChanged
|
|
1012
|
+
? `Grok model changed to ${updates.grokModel}`
|
|
1013
|
+
: `model changed to ${updates.model}`;
|
|
961
1014
|
log.log(`Agent ${agent.name}: ${reason}, will apply on next session start`);
|
|
962
1015
|
}
|
|
963
1016
|
// If Chrome flag changed, do a hot restart to add/remove --chrome flag
|
|
964
1017
|
// Only restart if model didn't already trigger a restart
|
|
965
|
-
if (useChromeChanged && !modelChanged && !codexModelChanged && !opencodeModelChanged && !providerChanged && !codexConfigChanged && sessionId) {
|
|
1018
|
+
if (useChromeChanged && !modelChanged && !codexModelChanged && !opencodeModelChanged && !grokModelChanged && !providerChanged && !codexConfigChanged && sessionId) {
|
|
966
1019
|
const chromeStatus = updates.useChrome ? 'enabled' : 'disabled';
|
|
967
1020
|
log.log(`Agent ${agent.name}: Chrome ${chromeStatus}, hot restarting with --resume to apply change`);
|
|
968
1021
|
try {
|
|
@@ -982,13 +1035,13 @@ export async function handleUpdateAgentProperties(ctx, payload) {
|
|
|
982
1035
|
log.error(`Failed to hot restart agent ${agent.name} after Chrome change:`, err);
|
|
983
1036
|
}
|
|
984
1037
|
}
|
|
985
|
-
else if (useChromeChanged && !providerChanged && !codexConfigChanged && !codexModelChanged && !opencodeModelChanged && !sessionId) {
|
|
1038
|
+
else if (useChromeChanged && !providerChanged && !codexConfigChanged && !codexModelChanged && !opencodeModelChanged && !grokModelChanged && !sessionId) {
|
|
986
1039
|
// No existing session, chrome flag will apply on next start
|
|
987
1040
|
const chromeStatus = updates.useChrome ? 'enabled' : 'disabled';
|
|
988
1041
|
log.log(`Agent ${agent.name}: Chrome ${chromeStatus}, will apply on next session start`);
|
|
989
1042
|
}
|
|
990
1043
|
// If effort changed, hot restart to apply new --effort flag
|
|
991
|
-
if (effortChanged && !modelChanged && !codexModelChanged && !opencodeModelChanged && !providerChanged && !codexConfigChanged && !classChanged && !useChromeChanged && sessionId) {
|
|
1044
|
+
if (effortChanged && !modelChanged && !codexModelChanged && !opencodeModelChanged && !grokModelChanged && !providerChanged && !codexConfigChanged && !classChanged && !useChromeChanged && sessionId) {
|
|
992
1045
|
const effortLabel = updates.effort || 'default';
|
|
993
1046
|
log.log(`Agent ${agent.name}: effort changed to ${effortLabel}, hot restarting with --resume to apply change`);
|
|
994
1047
|
try {
|
|
@@ -1052,7 +1105,7 @@ export async function handleUpdateAgentProperties(ctx, payload) {
|
|
|
1052
1105
|
}
|
|
1053
1106
|
// If skills changed and we didn't already hot restart for model/chrome/cwd change, do it now
|
|
1054
1107
|
// Skills are injected into the system prompt, so we need to restart to apply them
|
|
1055
|
-
if (skillsChanged && !modelChanged && !codexModelChanged && !opencodeModelChanged && !providerChanged && !codexConfigChanged && !classChanged && !useChromeChanged && !cwdChanged && sessionId) {
|
|
1108
|
+
if (skillsChanged && !modelChanged && !codexModelChanged && !opencodeModelChanged && !grokModelChanged && !providerChanged && !codexConfigChanged && !classChanged && !useChromeChanged && !cwdChanged && sessionId) {
|
|
1056
1109
|
log.log(`Agent ${agent.name}: Skills changed, hot restarting with --resume to apply new system prompt`);
|
|
1057
1110
|
try {
|
|
1058
1111
|
// Stop the current Claude process
|
|
@@ -70,12 +70,10 @@ export function setupRuntimeListeners(ctx) {
|
|
|
70
70
|
}
|
|
71
71
|
// Mirror an agent's tracked tasks (id order) into latestTodos for display.
|
|
72
72
|
function pushTaskTodos(agentId, tasks) {
|
|
73
|
-
if (tasks.size === 0)
|
|
74
|
-
return;
|
|
75
73
|
const items = [...tasks.entries()]
|
|
76
74
|
.sort((a, b) => Number(a[0]) - Number(b[0]))
|
|
77
|
-
.map(([id, t]) => ({ content: t.subject || `Task #${id}`, status: t.status }));
|
|
78
|
-
agentService.updateAgent(agentId, { latestTodos: items }, false);
|
|
75
|
+
.map(([id, t]) => ({ id, content: t.subject || `Task #${id}`, status: t.status }));
|
|
76
|
+
agentService.updateAgent(agentId, { latestTodos: items.length > 0 ? items : undefined }, false);
|
|
79
77
|
}
|
|
80
78
|
function armSubagentJsonlWatcher(agentId, toolUseId, options) {
|
|
81
79
|
const parentAgent = agentService.getAgent(agentId);
|
|
@@ -142,8 +140,9 @@ export function setupRuntimeListeners(ctx) {
|
|
|
142
140
|
const details = formatToolActivity(event.toolName, event.toolInput);
|
|
143
141
|
ctx.sendActivity(agentId, details);
|
|
144
142
|
if (event.toolName === 'TodoWrite' && !event.parentToolUseId) {
|
|
145
|
-
const
|
|
146
|
-
|
|
143
|
+
const existing = agentService.getAgent(agentId)?.latestTodos || [];
|
|
144
|
+
const todos = parseTodoWriteInput(event.toolInput, existing);
|
|
145
|
+
if (todos && todos.length > 0) {
|
|
147
146
|
agentService.updateAgent(agentId, { latestTodos: todos }, false);
|
|
148
147
|
}
|
|
149
148
|
}
|
|
@@ -155,9 +154,14 @@ export function setupRuntimeListeners(ctx) {
|
|
|
155
154
|
const id = typeof rawId === 'string' || typeof rawId === 'number' ? String(rawId) : undefined;
|
|
156
155
|
if (id) {
|
|
157
156
|
const tasks = taskStateFor(agentId);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
if (ti?.status === 'deleted') {
|
|
158
|
+
tasks.delete(id);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const existing = tasks.get(id) ?? { status: 'pending' };
|
|
162
|
+
existing.status = normalizeTaskStatus(ti?.status);
|
|
163
|
+
tasks.set(id, existing);
|
|
164
|
+
}
|
|
161
165
|
pushTaskTodos(agentId, tasks);
|
|
162
166
|
}
|
|
163
167
|
}
|
|
@@ -652,29 +656,84 @@ function findGitRoot(startDir) {
|
|
|
652
656
|
return null;
|
|
653
657
|
}
|
|
654
658
|
}
|
|
655
|
-
function parseTodoWriteInput(toolInput) {
|
|
659
|
+
function parseTodoWriteInput(toolInput, existing = []) {
|
|
656
660
|
if (!toolInput || typeof toolInput !== 'object')
|
|
657
661
|
return null;
|
|
658
662
|
const rawTodos = toolInput.todos;
|
|
659
663
|
if (!Array.isArray(rawTodos))
|
|
660
664
|
return null;
|
|
661
665
|
const validStatuses = ['pending', 'in_progress', 'completed'];
|
|
662
|
-
const
|
|
666
|
+
const merge = toolInput.merge === true;
|
|
667
|
+
const existingById = new Map();
|
|
668
|
+
for (const t of existing) {
|
|
669
|
+
if (t.id)
|
|
670
|
+
existingById.set(t.id, t);
|
|
671
|
+
}
|
|
672
|
+
const pickContent = (item, id) => {
|
|
673
|
+
if (typeof item.content === 'string' && item.content)
|
|
674
|
+
return item.content;
|
|
675
|
+
if (typeof item.subject === 'string' && item.subject)
|
|
676
|
+
return item.subject;
|
|
677
|
+
if (typeof item.text === 'string' && item.text)
|
|
678
|
+
return item.text;
|
|
679
|
+
if (typeof item.description === 'string' && item.description)
|
|
680
|
+
return item.description;
|
|
681
|
+
if (id && existingById.has(id))
|
|
682
|
+
return existingById.get(id).content;
|
|
683
|
+
return id ? `Task ${id}` : '';
|
|
684
|
+
};
|
|
685
|
+
const incoming = [];
|
|
663
686
|
for (const raw of rawTodos) {
|
|
664
687
|
if (!raw || typeof raw !== 'object')
|
|
665
688
|
continue;
|
|
666
689
|
const item = raw;
|
|
667
|
-
const
|
|
690
|
+
const id = typeof item.id === 'string' || typeof item.id === 'number'
|
|
691
|
+
? String(item.id)
|
|
692
|
+
: undefined;
|
|
693
|
+
const content = pickContent(item, id);
|
|
668
694
|
const status = typeof item.status === 'string' ? item.status : 'pending';
|
|
669
695
|
if (!content || !validStatuses.includes(status))
|
|
670
696
|
continue;
|
|
671
697
|
const todo = { content, status };
|
|
698
|
+
if (id)
|
|
699
|
+
todo.id = id;
|
|
672
700
|
if (typeof item.activeForm === 'string' && item.activeForm.length > 0) {
|
|
673
701
|
todo.activeForm = item.activeForm;
|
|
674
702
|
}
|
|
675
|
-
|
|
703
|
+
incoming.push(todo);
|
|
704
|
+
}
|
|
705
|
+
if (incoming.length === 0) {
|
|
706
|
+
// Status-only empty parse should not wipe the banner.
|
|
707
|
+
return null;
|
|
708
|
+
}
|
|
709
|
+
if (!merge) {
|
|
710
|
+
return incoming;
|
|
711
|
+
}
|
|
712
|
+
// merge:true — overlay onto existing list by id (Grok partial updates).
|
|
713
|
+
const next = existing.map((t) => ({ ...t }));
|
|
714
|
+
const indexById = new Map();
|
|
715
|
+
next.forEach((t, i) => {
|
|
716
|
+
if (t.id)
|
|
717
|
+
indexById.set(t.id, i);
|
|
718
|
+
});
|
|
719
|
+
for (const t of incoming) {
|
|
720
|
+
if (t.id && indexById.has(t.id)) {
|
|
721
|
+
const idx = indexById.get(t.id);
|
|
722
|
+
next[idx] = {
|
|
723
|
+
...next[idx],
|
|
724
|
+
status: t.status,
|
|
725
|
+
content: t.content || next[idx].content,
|
|
726
|
+
activeForm: t.activeForm ?? next[idx].activeForm,
|
|
727
|
+
id: t.id,
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
else {
|
|
731
|
+
if (t.id)
|
|
732
|
+
indexById.set(t.id, next.length);
|
|
733
|
+
next.push(t);
|
|
734
|
+
}
|
|
676
735
|
}
|
|
677
|
-
return
|
|
736
|
+
return next;
|
|
678
737
|
}
|
|
679
738
|
function readHeadFileIfSmall(gitRoot, relativePath) {
|
|
680
739
|
const gitPath = relativePath.split(path.sep).join(path.posix.sep);
|
|
@@ -16,6 +16,16 @@ 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 GROK_MODELS = {
|
|
20
|
+
'grok-4.5': {
|
|
21
|
+
label: 'Grok 4.5',
|
|
22
|
+
description: 'Default Grok Build model',
|
|
23
|
+
icon: '⚡',
|
|
24
|
+
// Authoritative window from live Grok Build signals.json (contextWindowTokens).
|
|
25
|
+
contextWindow: 500000,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
export const DEFAULT_GROK_MODEL = 'grok-4.5';
|
|
19
29
|
export const CODEX_REASONING_EFFORTS = {
|
|
20
30
|
none: { label: 'None', description: 'No reasoning', icon: '⚪' },
|
|
21
31
|
minimal: { label: 'Minimal', description: 'Least reasoning, fastest', icon: '💨' },
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as Be,aA as Oe,b3 as Re,b2 as Te,r as t,_ as re,S as W,be as O,k as Fe,s as v,b6 as G,A as de,bf as C,j as s,a9 as y,b7 as Pe,b9 as ze,I as R,ba as K,aQ as A,aO as T,bc as H,$ as Ue}from"./main-C2zgPci-.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";function ue(d){const w=C.filter(E=>!d.has(`Boss ${E}`));return w.length===0?`Boss ${C[Math.floor(Math.random()*C.length)]}-${Date.now()%1e3}`:`Boss ${w[Math.floor(Math.random()*w.length)]}`}function Ke({isOpen:d,onClose:w,onSpawnStart:E,onSpawnEnd:F,spawnPosition:me,spawnAreaId:N}){const{t:n}=Be(["terminal","common"]),J=Oe(),c=Re(),$=Te(),[u,p]=t.useState(""),[L,P]=t.useState(()=>re(W.LAST_CWD)),[r,I]=t.useState("boss"),[X,Q]=t.useState(!1),[pe,_]=t.useState(!1),[V,he]=t.useState(!0),[Y,we]=t.useState("bypass"),[m,z]=t.useState("claude"),[f,g]=t.useState({fullAuto:!0,sandbox:"workspace-write",approvalMode:"on-request",search:!1}),[Z,xe]=t.useState("claude-opus-4-8[1m]"),[ee,fe]=t.useState("gpt-5.6-luna"),[k,D]=t.useState(new Set),[se,U]=t.useState(new Set),[h,be]=t.useState(""),[S,je]=t.useState(""),[ae,Ne]=t.useState(""),B=t.useRef(null),q=t.useRef(!1),ne=t.useRef(!1),b=t.useMemo(()=>$.filter(e=>e.enabled),[$]),le=t.useMemo(()=>{if(!S.trim())return b;const e=S.toLowerCase();return b.filter(a=>a.name.toLowerCase().includes(e)||a.description.toLowerCase().includes(e)||a.slug.toLowerCase().includes(e))},[b,S]),ge=t.useMemo(()=>{var a;const e=c.find(l=>l.id===r);return(a=e==null?void 0:e.defaultSkillIds)!=null&&a.length?$.filter(l=>e.defaultSkillIds.includes(l.id)):[]},[c,r,$]),Se=["full-notifications","streaming-exec","task-label","report-task-to-boss","agent-tracking","agent-memory","send-message-to-agent"];t.useEffect(()=>{if(d&&!ne.current){if(b.length>0){const l=b.filter(i=>Se.includes(i.slug)).map(i=>i.id);l.length>0&&U(new Set(l))}if(re(W.DEFAULT_AGENT_CLASS)==="random"){const i=[...Object.keys(O).filter(j=>j!=="boss"),...c.map(j=>j.id)];i.length>0&&I(i[Math.floor(Math.random()*i.length)])}}ne.current=d},[d,b,c]);const ve=t.useCallback(e=>{U(a=>{const l=new Set(a);return l.has(e)?l.delete(e):l.add(e),l})},[]),o=t.useMemo(()=>c.find(e=>e.id===r),[c,r]),Ce=t.useMemo(()=>{if(o!=null&&o.model)return o.model},[o]),ke=t.useMemo(()=>{if(o!=null&&o.customModelPath)return Fe(`/api/custom-models/${o.id}`)},[o]),Me=o==null?void 0:o.modelScale,ye=t.useMemo(()=>o?"scout":r==="boss"?"architect":r,[r,o]);t.useEffect(()=>{if(!d||!N)return;const e=v.getState().areas.get(N);if(e!=null&&e.directories&&e.directories.length>0){P(e.directories[0]);return}const a=Array.from(v.getState().agents.values()).filter(x=>{var M;return((M=v.getAreaForAgent(x.id))==null?void 0:M.id)===N&&x.cwd});if(a.length===0)return;const l=new Map;for(const x of a)l.set(x.cwd,(l.get(x.cwd)||0)+1);let i="",j=0;for(const[x,M]of l)M>j&&(i=x,j=M);i&&P(i)},[d,N]);const te=t.useMemo(()=>Array.from(J.values()).filter(e=>!e.isBoss&&e.class!=="boss"&&!e.bossId),[J]),ie=t.useMemo(()=>{if(!h.trim())return c;const e=h.toLowerCase();return c.filter(a=>a.name.toLowerCase().includes(e)||a.description.toLowerCase().includes(e)||a.id.toLowerCase().includes(e))},[c,h]),ce=t.useMemo(()=>{if(!h.trim())return G;const e=h.toLowerCase();return G.filter(a=>{const l=de[a.id];return l?a.name.toLowerCase().includes(e)||a.id.toLowerCase().includes(e)||l.description.toLowerCase().includes(e):!1})},[h]),oe=t.useMemo(()=>{if(!h.trim())return!0;const e=h.toLowerCase(),a=O.boss;return"boss".includes(e)||a.description.toLowerCase().includes(e)},[h]);t.useEffect(()=>{if(d&&!q.current){q.current=!0;const e=new Set(Array.from(v.getState().agents.values()).map(l=>l.name)),a=c.find(l=>l.id===r);if(a){const l=C.filter(i=>!e.has(`${a.name} ${i}`));if(l.length===0){const i=C[Math.floor(Math.random()*C.length)];p(`${a.name} ${i}-${Date.now()%1e3}`)}else p(`${a.name} ${l[Math.floor(Math.random()*l.length)]}`)}else p(ue(e));D(new Set),B.current&&(B.current.focus(),B.current.select())}else d||(q.current=!1)},[d]),t.useEffect(()=>{if(!d)return;const e=c.find(a=>a.id===r);if(e)if(u.startsWith("Boss ")){const a=u.substring(5);p(`${e.name} ${a}`)}else{const a=c.find(l=>u.startsWith(l.name+" "));if(a){const l=u.substring(a.name.length+1);p(`${e.name} ${l}`)}else p(`${e.name} ${u}`)}else{const a=c.find(l=>u.startsWith(l.name+" "));if(a){const l=u.substring(a.name.length+1);p(`Boss ${l}`)}else u.startsWith("Boss ")||p(`Boss ${u}`)}},[r]);const Ae=()=>{if(_(!1),!L.trim()){_(!0);return}if(!u.trim()){const l=new Set(Array.from(v.getState().agents.values()).map(i=>i.name));p(ue(l));return}Ue(W.LAST_CWD,L),E(),window.__spawnModalAreaContext=N?{areaId:N}:null;const e=ae.trim()||void 0,a=Array.from(se);v.spawnBossAgent(u.trim(),r,L.trim(),me||void 0,Array.from(k),m==="claude"?V:!1,Y,m,m==="codex"?f:void 0,m==="codex"?ee:void 0,m==="claude"?Z:void 0,e,a),p(""),D(new Set),U(new Set),F(),w()},Ee=()=>{Q(!1),p(""),D(new Set),F(),w()},$e=()=>{Q(!1),_(!0),F()};t.useEffect(()=>(window.__bossSpawnModalSuccess=Ee,window.__bossSpawnModalError=$e,()=>{delete window.__bossSpawnModalSuccess,delete window.__bossSpawnModalError}),[u]);const Le=e=>{e.target===e.currentTarget&&w()},Ie=e=>{e.key==="Escape"&&w()},_e=e=>{const a=new Set(k);a.has(e)?a.delete(e):a.add(e),D(a)};if(!d)return null;const De=O.boss;return s.jsx("div",{className:`modal-overlay ${d?"visible":""}`,onClick:Le,onKeyDown:Ie,children:s.jsxs("div",{className:"modal boss-spawn-modal",children:[s.jsxs("div",{className:"modal-header",children:[s.jsx(y,{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(Pe,{agentClass:ye,modelFile:Ce,customModelUrl:ke,modelScale:Me,width:100,height:120})}),s.jsxs("div",{className:"spawn-class-section",children:[s.jsx("div",{className:"spawn-class-label",children:n("terminal:spawn.bossClass")}),c.length+G.length+1>6&&s.jsx("input",{type:"text",className:"spawn-input class-search-input",placeholder:n("terminal:spawn.filterClasses"),value:h,onChange:e=>be(e.target.value)}),s.jsxs("div",{className:"class-selector-inline",children:[ie.map(e=>s.jsxs("button",{className:`class-chip ${r===e.id?"selected":""}`,onClick:()=>I(e.id),title:e.description,children:[s.jsx(y,{classId:e.id,size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id)),oe&&s.jsxs("button",{className:`class-chip ${r==="boss"?"selected":""}`,onClick:()=>I("boss"),title:De.description,children:[s.jsx(y,{classId:"boss",size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:n("terminal:spawn.bossClassName")})]}),ce.map(e=>{const a=de[e.id];return a?s.jsxs("button",{className:`class-chip ${r===e.id?"selected":""}`,onClick:()=>I(e.id),title:a.description,children:[s.jsx(y,{classId:e.id,size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id):null}),h&&ie.length===0&&!oe&&ce.length===0&&s.jsx("div",{className:"class-search-empty",children:n("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:n("common:labels.name")}),s.jsx("input",{ref:B,type:"text",className:"spawn-input",placeholder:n("terminal:spawn.bossNamePlaceholder"),value:u,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(ze,{value:L,onChange:e=>{P(e),_(!1)},placeholder:n("terminal:spawn.workingDirPlaceholder"),className:"spawn-input",hasError:pe,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 ${m==="claude"?"selected":""}`,onClick:()=>z("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 ${m==="codex"?"selected":""}`,onClick:()=>z("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 ${m==="opencode"?"selected":""}`,onClick:()=>z("opencode"),title:"Use OpenCode CLI (multi-provider)",children:[s.jsx("span",{children:s.jsx(R,{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(K).map(e=>s.jsxs("button",{className:`spawn-select-btn ${Y===e?"selected":""}`,onClick:()=>we(e),title:K[e].description,children:[s.jsx("span",{children:s.jsx(R,{name:e==="bypass"?"bolt":"lock",size:14})}),s.jsx("span",{children:K[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")}),m==="claude"?s.jsx("div",{className:"spawn-select-row spawn-select-row--wrap",children:Object.keys(A).filter(e=>!A[e].deprecated).map(e=>s.jsxs("button",{className:`spawn-select-btn ${Z===e?"selected":""}`,onClick:()=>xe(e),title:A[e].description,children:[s.jsx("span",{children:A[e].icon}),s.jsx("span",{children:A[e].label})]},e))}):m==="codex"?s.jsx("div",{className:"spawn-select-row spawn-select-row--codex-models",children:Object.keys(T).map(e=>s.jsxs("button",{className:`spawn-select-btn ${ee===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))}):m==="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:V,onChange:e=>he(e.target.checked),disabled:m!=="claude"}),s.jsx("span",{children:n("terminal:spawn.chromeBrowser")})]})})]})]}),m==="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:f.fullAuto!==!1,onChange:e=>g(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:!!f.search,onChange:e=>g(a=>({...a,search:e.target.checked}))}),s.jsx("span",{children:n("terminal:spawn.codex.enableSearch")})]}),f.fullAuto===!1&&s.jsxs(s.Fragment,{children:[s.jsxs("select",{className:"spawn-input",value:f.sandbox||"workspace-write",onChange:e=>g(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:f.approvalMode||"on-request",onChange:e=>g(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:f.profile||"",onChange:e=>g(a=>({...a,profile:e.target.value||void 0}))}),s.jsxs("select",{className:"spawn-input",value:f.reasoningEffort||"",onChange:e=>g(a=>({...a,reasoningEffort:e.target.value||void 0})),children:[s.jsx("option",{value:"",children:n("terminal:spawn.codex.reasoningEffortDefault")}),Object.keys(H).map(e=>s.jsxs("option",{value:e,children:[H[e].icon," ",n("terminal:spawn.codex.reasoningEffort"),": ",H[e].label]},e))]})]})]})}),b.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"),")"]})]}),b.length>6&&s.jsx("input",{type:"text",className:"spawn-input skill-search-input",placeholder:n("terminal:spawn.filterSkills"),value:S,onChange:e=>je(e.target.value)}),s.jsxs("div",{className:"spawn-skills-inline",children:[le.map(e=>{const a=se.has(e.id);return ge.some(i=>i.id===e.id)?null:s.jsxs("button",{className:`spawn-skill-chip ${a?"selected":""}`,onClick:()=>ve(e.id),title:e.description,children:[a&&s.jsx("span",{className:"spawn-skill-check",children:s.jsx(R,{name:"check",size:12})}),s.jsx("span",{children:e.name}),e.builtin&&s.jsx("span",{className:"spawn-skill-builtin",children:"TC"})]},e.id)}),S&&le.length===0&&s.jsx("div",{className:"skill-search-empty",children:n("terminal:spawn.noSkillsMatch",{query:S})})]})]}),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:ae,onChange:e=>Ne(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:te.length===0?s.jsx("div",{className:"subordinates-empty",children:n("terminal:spawn.noAvailableAgents")}):te.map(e=>{const a=k.has(e.id),l=O[e.class],i=c.find(x=>x.id===e.class),j=l||i||{color:"#888888"};return s.jsxs("button",{className:`subordinate-chip ${a?"selected":""}`,onClick:()=>_e(e.id),children:[a&&s.jsx("span",{className:"subordinate-check",children:s.jsx(R,{name:"check",size:12})}),s.jsx("span",{className:"subordinate-chip-icon",style:{color:j.color},children:s.jsx(y,{classId:e.class,size:16})}),s.jsx("span",{className:"subordinate-chip-name",children:e.name})]},e.id)})}),k.size>0&&s.jsxs("div",{className:"subordinates-count",children:[k.size," ",n("common:labels.selected").toLowerCase()]})]})]})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:w,children:n("common:buttons.cancel")}),s.jsx("button",{className:"btn btn-boss",onClick:Ae,disabled:X,children:n(X?"common:buttons.deploying":"common:buttons2.deployBoss")})]})]})})}export{Ke as BossSpawnModal};
|