@iaforged/context-code 1.0.80 → 1.0.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/src/components/LogoV2/FeedColumn.js +3 -4
  2. package/dist/src/components/LogoV2/LogoV2.js +10 -10
  3. package/dist/src/components/LogoV2/WelcomeV2.js +1 -1
  4. package/dist/src/components/agents/AgentDetail.js +19 -210
  5. package/dist/src/components/agents/AgentEditor.js +60 -70
  6. package/dist/src/components/agents/AgentsList.js +3 -2
  7. package/dist/src/components/agents/AgentsMenu.js +10 -10
  8. package/dist/src/components/agents/ColorPicker.js +2 -2
  9. package/dist/src/components/agents/ModelSelector.js +204 -52
  10. package/dist/src/components/agents/ToolSelector.js +13 -13
  11. package/dist/src/components/agents/agentFileUtils.js +12 -11
  12. package/dist/src/components/agents/new-agent-creation/CreateAgentWizard.js +1 -1
  13. package/dist/src/components/agents/new-agent-creation/types.js +1 -0
  14. package/dist/src/components/agents/new-agent-creation/wizard-steps/ColorStep.js +22 -68
  15. package/dist/src/components/agents/new-agent-creation/wizard-steps/ConfirmStep.js +30 -369
  16. package/dist/src/components/agents/new-agent-creation/wizard-steps/ConfirmStepWrapper.js +13 -15
  17. package/dist/src/components/agents/new-agent-creation/wizard-steps/DescriptionStep.js +4 -4
  18. package/dist/src/components/agents/new-agent-creation/wizard-steps/GenerateStep.js +15 -22
  19. package/dist/src/components/agents/new-agent-creation/wizard-steps/LocationStep.js +2 -2
  20. package/dist/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.js +9 -9
  21. package/dist/src/components/agents/new-agent-creation/wizard-steps/MethodStep.js +3 -3
  22. package/dist/src/components/agents/new-agent-creation/wizard-steps/ModelStep.js +8 -38
  23. package/dist/src/components/agents/new-agent-creation/wizard-steps/PromptStep.js +4 -4
  24. package/dist/src/components/agents/new-agent-creation/wizard-steps/ToolsStep.js +1 -1
  25. package/dist/src/components/agents/new-agent-creation/wizard-steps/TypeStep.js +3 -3
  26. package/dist/src/components/agents/validateAgent.js +16 -16
  27. package/dist/src/services/compact/compact.js +22 -20
  28. package/dist/src/tools/AgentTool/AgentTool.js +12 -8
  29. package/dist/src/tools/AgentTool/agentDisplay.js +5 -2
  30. package/dist/src/tools/AgentTool/loadAgentsDir.js +36 -0
  31. package/dist/src/tools/AgentTool/resumeAgent.js +7 -3
  32. package/dist/src/utils/model/agent.js +12 -3
  33. package/dist/src/utils/model/providerOverrideContext.js +11 -0
  34. package/dist/src/utils/model/providers.js +14 -0
  35. package/package.json +1 -1
@@ -21,19 +21,17 @@ export function GenerateStep() {
21
21
  const [cursorOffset, setCursorOffset] = useState(prompt.length);
22
22
  const model = useMainLoopModel();
23
23
  const abortControllerRef = useRef(null);
24
- // Cancel generation when escape pressed during generation
25
24
  const handleCancelGeneration = useCallback(() => {
26
25
  if (abortControllerRef.current) {
27
26
  abortControllerRef.current.abort();
28
27
  abortControllerRef.current = null;
29
28
  setIsGenerating(false);
30
- setError('Generation cancelled');
29
+ setError('Generacion cancelada');
31
30
  }
32
31
  }, []);
33
- // Use Settings context so 'n' key doesn't cancel (allows typing 'n' in prompt input)
34
32
  useKeybinding('confirm:no', handleCancelGeneration, {
35
33
  context: 'Settings',
36
- isActive: isGenerating
34
+ isActive: isGenerating,
37
35
  });
38
36
  const handleExternalEditor = useCallback(async () => {
39
37
  const result = await editPromptInEditor(prompt);
@@ -44,9 +42,8 @@ export function GenerateStep() {
44
42
  }, [prompt]);
45
43
  useKeybinding('chat:externalEditor', handleExternalEditor, {
46
44
  context: 'Chat',
47
- isActive: !isGenerating
45
+ isActive: !isGenerating,
48
46
  });
49
- // Go back when escape pressed while not generating
50
47
  const handleGoBack = useCallback(() => {
51
48
  updateWizardData({
52
49
  generationPrompt: '',
@@ -54,30 +51,28 @@ export function GenerateStep() {
54
51
  systemPrompt: '',
55
52
  whenToUse: '',
56
53
  generatedAgent: undefined,
57
- wasGenerated: false
54
+ wasGenerated: false,
58
55
  });
59
56
  setPrompt('');
60
57
  setError(null);
61
58
  goBack();
62
59
  }, [updateWizardData, goBack]);
63
- // Use Settings context so 'n' key doesn't cancel (allows typing 'n' in prompt input)
64
60
  useKeybinding('confirm:no', handleGoBack, {
65
61
  context: 'Settings',
66
- isActive: !isGenerating
62
+ isActive: !isGenerating,
67
63
  });
68
64
  const handleGenerate = async () => {
69
65
  const trimmedPrompt = prompt.trim();
70
66
  if (!trimmedPrompt) {
71
- setError('Please describe what the agent should do');
67
+ setError('Describe que debe hacer el agente');
72
68
  return;
73
69
  }
74
70
  setError(null);
75
71
  setIsGenerating(true);
76
72
  updateWizardData({
77
73
  generationPrompt: trimmedPrompt,
78
- isGenerating: true
74
+ isGenerating: true,
79
75
  });
80
- // Create abort controller for this generation
81
76
  const controller = createAbortController();
82
77
  abortControllerRef.current = controller;
83
78
  try {
@@ -88,21 +83,19 @@ export function GenerateStep() {
88
83
  systemPrompt: generated.systemPrompt,
89
84
  generatedAgent: generated,
90
85
  isGenerating: false,
91
- wasGenerated: true
86
+ wasGenerated: true,
92
87
  });
93
- // Skip directly to ToolsStep (index 6) - matching original flow
94
88
  goToStep(6);
95
89
  }
96
90
  catch (err) {
97
- // Don't show error if it was cancelled (already set in escape handler)
98
91
  if (err instanceof APIUserAbortError) {
99
- // User cancelled - no error to show
100
92
  }
101
- else if (err instanceof Error && !err.message.includes('No assistant message found')) {
102
- setError(err.message || 'Failed to generate agent');
93
+ else if (err instanceof Error &&
94
+ !err.message.includes('No assistant message found')) {
95
+ setError(err.message || 'No se pudo generar el agente');
103
96
  }
104
97
  updateWizardData({
105
- isGenerating: false
98
+ isGenerating: false,
106
99
  });
107
100
  }
108
101
  finally {
@@ -110,9 +103,9 @@ export function GenerateStep() {
110
103
  abortControllerRef.current = null;
111
104
  }
112
105
  };
113
- const subtitle = 'Describe what this agent should do and when it should be used (be comprehensive for best results)';
106
+ const subtitle = 'Describe que debe hacer este agente y cuando debe usarse (se detallado para obtener mejores resultados)';
114
107
  if (isGenerating) {
115
- return _jsx(WizardDialogLayout, { subtitle: subtitle, footerText: _jsx(ConfigurableShortcutHint, { action: "confirm:no", context: "Settings", fallback: "Esc", description: "cancelar" }), children: _jsxs(Box, { flexDirection: "row", alignItems: "center", children: [_jsx(Spinner, {}), _jsx(Text, { color: "suggestion", children: " Generando agente desde la descripci\u00F3n..." })] }) });
108
+ return (_jsx(WizardDialogLayout, { subtitle: subtitle, footerText: _jsx(ConfigurableShortcutHint, { action: "confirm:no", context: "Settings", fallback: "Esc", description: "cancelar" }), children: _jsxs(Box, { flexDirection: "row", alignItems: "center", children: [_jsx(Spinner, {}), _jsx(Text, { color: "suggestion", children: " Generando agente desde la descripcion..." })] }) }));
116
109
  }
117
- return _jsx(WizardDialogLayout, { subtitle: subtitle, footerText: _jsxs(Byline, { children: [_jsx(ConfigurableShortcutHint, { action: "confirm:yes", context: "Confirmation", fallback: "Enter", description: "enviar" }), _jsx(ConfigurableShortcutHint, { action: "chat:externalEditor", context: "Chat", fallback: "ctrl+g", description: "abrir en editor" }), _jsx(ConfigurableShortcutHint, { action: "confirm:no", context: "Settings", fallback: "Esc", description: "volver" })] }), children: _jsxs(Box, { flexDirection: "column", children: [error && _jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "error", children: error }) }), _jsx(TextInput, { value: prompt, onChange: setPrompt, onSubmit: handleGenerate, placeholder: "e.g., Help me write unit tests for my code...", columns: 80, cursorOffset: cursorOffset, onChangeCursorOffset: setCursorOffset, focus: true, showCursor: true })] }) });
110
+ return (_jsx(WizardDialogLayout, { subtitle: subtitle, footerText: _jsxs(Byline, { children: [_jsx(ConfigurableShortcutHint, { action: "confirm:yes", context: "Confirmation", fallback: "Enter", description: "enviar" }), _jsx(ConfigurableShortcutHint, { action: "chat:externalEditor", context: "Chat", fallback: "ctrl+g", description: "abrir en editor" }), _jsx(ConfigurableShortcutHint, { action: "confirm:no", context: "Settings", fallback: "Esc", description: "volver" })] }), children: _jsxs(Box, { flexDirection: "column", children: [error ? (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "error", children: error }) })) : null, _jsx(TextInput, { value: prompt, onChange: setPrompt, onSubmit: handleGenerate, placeholder: "p. ej., ayudame a escribir pruebas unitarias para mi codigo...", columns: 80, cursorOffset: cursorOffset, onChangeCursorOffset: setCursorOffset, focus: true, showCursor: true })] }) }));
118
111
  }
@@ -26,7 +26,7 @@ export function LocationStep() {
26
26
  let t0;
27
27
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28
28
  t0 = {
29
- label: `Project (${getProjectAgentFolderLabel()}/agents/)`,
29
+ label: `Proyecto (${getProjectAgentFolderLabel()}/agents/)`,
30
30
  value: "projectSettings"
31
31
  };
32
32
  $[0] = t0;
@@ -80,7 +80,7 @@ export function LocationStep() {
80
80
  }
81
81
  let t5;
82
82
  if ($[8] !== t3 || $[9] !== t4) {
83
- t5 = _jsx(WizardDialogLayout, { subtitle: "Choose location", footerText: t2, children: _jsx(Box, { children: _jsx(Select, { options: locationOptions, onChange: t3, onCancel: t4 }, "location-select") }) });
83
+ t5 = _jsx(WizardDialogLayout, { subtitle: "Elegir ubicacion", footerText: t2, children: _jsx(Box, { children: _jsx(Select, { options: locationOptions, onChange: t3, onCancel: t4 }, "location-select") }) });
84
84
  $[8] = t3;
85
85
  $[9] = t4;
86
86
  $[10] = t5;
@@ -41,28 +41,28 @@ export function MemoryStep() {
41
41
  if ($[1] !== isUserScope) {
42
42
  const folder = getProjectMemoryFolderLabel();
43
43
  t1 = isUserScope ? [{
44
- label: "User scope (~/.context/agent-memory/) (Recommended)",
44
+ label: "Alcance de usuario (~/.context/agent-memory/) (Recomendado)",
45
45
  value: "user"
46
46
  }, {
47
- label: "None (no persistent memory)",
47
+ label: "Ninguna (sin memoria persistente)",
48
48
  value: "none"
49
49
  }, {
50
- label: `Project scope (${folder}/agent-memory/)`,
50
+ label: `Alcance de proyecto (${folder}/agent-memory/)`,
51
51
  value: "project"
52
52
  }, {
53
- label: `Local scope (${folder}/agent-memory-local/)`,
53
+ label: `Alcance local (${folder}/agent-memory-local/)`,
54
54
  value: "local"
55
55
  }] : [{
56
- label: `Project scope (${folder}/agent-memory/) (Recommended)`,
56
+ label: `Alcance de proyecto (${folder}/agent-memory/) (Recomendado)`,
57
57
  value: "project"
58
58
  }, {
59
- label: "None (no persistent memory)",
59
+ label: "Ninguna (sin memoria persistente)",
60
60
  value: "none"
61
61
  }, {
62
- label: "User scope (~/.context/agent-memory/)",
62
+ label: "Alcance de usuario (~/.context/agent-memory/)",
63
63
  value: "user"
64
64
  }, {
65
- label: `Local scope (${folder}/agent-memory-local/)`,
65
+ label: `Alcance local (${folder}/agent-memory-local/)`,
66
66
  value: "local"
67
67
  }];
68
68
  $[1] = isUserScope;
@@ -107,7 +107,7 @@ export function MemoryStep() {
107
107
  }
108
108
  let t4;
109
109
  if ($[9] !== goBack || $[10] !== handleSelect || $[11] !== memoryOptions) {
110
- t4 = _jsx(WizardDialogLayout, { subtitle: "Configure agent memory", footerText: t3, children: _jsx(Box, { children: _jsx(Select, { options: memoryOptions, onChange: handleSelect, onCancel: goBack }, "memory-select") }) });
110
+ t4 = _jsx(WizardDialogLayout, { subtitle: "Configurar memoria del agente", footerText: t3, children: _jsx(Box, { children: _jsx(Select, { options: memoryOptions, onChange: handleSelect, onCancel: goBack }, "memory-select") }) });
111
111
  $[9] = goBack;
112
112
  $[10] = handleSelect;
113
113
  $[11] = memoryOptions;
@@ -13,10 +13,10 @@ export function MethodStep() {
13
13
  let t0;
14
14
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
15
15
  t0 = [{
16
- label: "Generate with Claude (recommended)",
16
+ label: "Generar con Claude (recomendado)",
17
17
  value: "generate"
18
18
  }, {
19
- label: "Manual configuration",
19
+ label: "Configuracion manual",
20
20
  value: "manual"
21
21
  }];
22
22
  $[0] = t0;
@@ -67,7 +67,7 @@ export function MethodStep() {
67
67
  }
68
68
  let t4;
69
69
  if ($[8] !== t2 || $[9] !== t3) {
70
- t4 = _jsx(WizardDialogLayout, { subtitle: "Creation method", footerText: t1, children: _jsx(Box, { children: _jsx(Select, { options: methodOptions, onChange: t2, onCancel: t3 }, "method-select") }) });
70
+ t4 = _jsx(WizardDialogLayout, { subtitle: "Metodo de creacion", footerText: t1, children: _jsx(Box, { children: _jsx(Select, { options: methodOptions, onChange: t2, onCancel: t3 }, "method-select") }) });
71
71
  $[8] = t2;
72
72
  $[9] = t3;
73
73
  $[10] = t4;
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { c as _c } from "react/compiler-runtime";
3
2
  import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
4
3
  import { Byline } from '../../../design-system/Byline.js';
5
4
  import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
@@ -7,42 +6,13 @@ import { useWizard } from '../../../wizard/index.js';
7
6
  import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
8
7
  import { ModelSelector } from '../../ModelSelector.js';
9
8
  export function ModelStep() {
10
- const $ = _c(8);
11
9
  const { goNext, goBack, updateWizardData, wizardData } = useWizard();
12
- let t0;
13
- if ($[0] !== goNext || $[1] !== updateWizardData) {
14
- t0 = model => {
15
- updateWizardData({
16
- selectedModel: model
17
- });
18
- goNext();
19
- };
20
- $[0] = goNext;
21
- $[1] = updateWizardData;
22
- $[2] = t0;
23
- }
24
- else {
25
- t0 = $[2];
26
- }
27
- const handleComplete = t0;
28
- let t1;
29
- if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
30
- t1 = _jsxs(Byline, { children: [_jsx(KeyboardShortcutHint, { shortcut: "\u2191\u2193", action: "navegar" }), _jsx(KeyboardShortcutHint, { shortcut: "Enter", action: "seleccionar" }), _jsx(ConfigurableShortcutHint, { action: "confirm:no", context: "Confirmation", fallback: "Esc", description: "volver" })] });
31
- $[3] = t1;
32
- }
33
- else {
34
- t1 = $[3];
35
- }
36
- let t2;
37
- if ($[4] !== goBack || $[5] !== handleComplete || $[6] !== wizardData.selectedModel) {
38
- t2 = _jsx(WizardDialogLayout, { subtitle: "Select model", footerText: t1, children: _jsx(ModelSelector, { initialModel: wizardData.selectedModel, onComplete: handleComplete, onCancel: goBack }) });
39
- $[4] = goBack;
40
- $[5] = handleComplete;
41
- $[6] = wizardData.selectedModel;
42
- $[7] = t2;
43
- }
44
- else {
45
- t2 = $[7];
46
- }
47
- return t2;
10
+ const handleComplete = (selection) => {
11
+ updateWizardData({
12
+ selectedModel: selection.model,
13
+ selectedProvider: selection.provider,
14
+ });
15
+ goNext();
16
+ };
17
+ return (_jsx(WizardDialogLayout, { subtitle: "Proveedor y modelo", footerText: _jsxs(Byline, { children: [_jsx(KeyboardShortcutHint, { shortcut: "\u2191\u2193", action: "navegar" }), _jsx(KeyboardShortcutHint, { shortcut: "Enter", action: "seleccionar" }), _jsx(ConfigurableShortcutHint, { action: "confirm:no", context: "Confirmation", fallback: "Esc", description: "volver" })] }), children: _jsx(ModelSelector, { initialModel: wizardData.selectedModel, initialProvider: wizardData.selectedProvider, onComplete: handleComplete, onCancel: goBack }) }));
48
18
  }
@@ -59,7 +59,7 @@ export function PromptStep() {
59
59
  t3 = () => {
60
60
  const trimmedPrompt = systemPrompt.trim();
61
61
  if (!trimmedPrompt) {
62
- setError("System prompt is required");
62
+ setError("El system prompt es obligatorio");
63
63
  return;
64
64
  }
65
65
  setError(null);
@@ -88,8 +88,8 @@ export function PromptStep() {
88
88
  let t5;
89
89
  let t6;
90
90
  if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
91
- t5 = _jsx(Text, { children: "Enter the system prompt for your agent:" });
92
- t6 = _jsx(Text, { dimColor: true, children: "Be comprehensive for best results" });
91
+ t5 = _jsx(Text, { children: "Escribe el system prompt de tu agente:" });
92
+ t6 = _jsx(Text, { dimColor: true, children: "Se detallado para obtener mejores resultados" });
93
93
  $[9] = t5;
94
94
  $[10] = t6;
95
95
  }
@@ -99,7 +99,7 @@ export function PromptStep() {
99
99
  }
100
100
  let t7;
101
101
  if ($[11] !== cursorOffset || $[12] !== handleSubmit || $[13] !== systemPrompt) {
102
- t7 = _jsx(Box, { marginTop: 1, children: _jsx(TextInput, { value: systemPrompt, onChange: setSystemPrompt, onSubmit: handleSubmit, placeholder: "You are a helpful code reviewer who...", columns: 80, cursorOffset: cursorOffset, onChangeCursorOffset: setCursorOffset, focus: true, showCursor: true }) });
102
+ t7 = _jsx(Box, { marginTop: 1, children: _jsx(TextInput, { value: systemPrompt, onChange: setSystemPrompt, onSubmit: handleSubmit, placeholder: "Eres un revisor de codigo util que...", columns: 80, cursorOffset: cursorOffset, onChangeCursorOffset: setCursorOffset, focus: true, showCursor: true }) });
103
103
  $[11] = cursorOffset;
104
104
  $[12] = handleSubmit;
105
105
  $[13] = systemPrompt;
@@ -37,7 +37,7 @@ export function ToolsStep(t0) {
37
37
  }
38
38
  let t3;
39
39
  if ($[4] !== goBack || $[5] !== handleComplete || $[6] !== initialTools || $[7] !== tools) {
40
- t3 = _jsx(WizardDialogLayout, { subtitle: "Select tools", footerText: t2, children: _jsx(ToolSelector, { tools: tools, initialTools: initialTools, onComplete: handleComplete, onCancel: goBack }) });
40
+ t3 = _jsx(WizardDialogLayout, { subtitle: "Seleccionar herramientas", footerText: t2, children: _jsx(ToolSelector, { tools: tools, initialTools: initialTools, onComplete: handleComplete, onCancel: goBack }) });
41
41
  $[4] = goBack;
42
42
  $[5] = handleComplete;
43
43
  $[6] = initialTools;
@@ -60,7 +60,7 @@ export function TypeStep(_props) {
60
60
  }
61
61
  let t3;
62
62
  if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
63
- t3 = _jsx(Text, { children: "Enter a unique identifier for your agent:" });
63
+ t3 = _jsx(Text, { children: "Escribe un identificador unico para tu agente:" });
64
64
  $[5] = t3;
65
65
  }
66
66
  else {
@@ -68,7 +68,7 @@ export function TypeStep(_props) {
68
68
  }
69
69
  let t4;
70
70
  if ($[6] !== agentType || $[7] !== cursorOffset || $[8] !== handleSubmit) {
71
- t4 = _jsx(Box, { marginTop: 1, children: _jsx(TextInput, { value: agentType, onChange: setAgentType, onSubmit: handleSubmit, placeholder: "e.g., test-runner, tech-lead, etc", columns: 60, cursorOffset: cursorOffset, onChangeCursorOffset: setCursorOffset, focus: true, showCursor: true }) });
71
+ t4 = _jsx(Box, { marginTop: 1, children: _jsx(TextInput, { value: agentType, onChange: setAgentType, onSubmit: handleSubmit, placeholder: "p. ej., test-runner, tech-lead, etc", columns: 60, cursorOffset: cursorOffset, onChangeCursorOffset: setCursorOffset, focus: true, showCursor: true }) });
72
72
  $[6] = agentType;
73
73
  $[7] = cursorOffset;
74
74
  $[8] = handleSubmit;
@@ -88,7 +88,7 @@ export function TypeStep(_props) {
88
88
  }
89
89
  let t6;
90
90
  if ($[12] !== t4 || $[13] !== t5) {
91
- t6 = _jsx(WizardDialogLayout, { subtitle: "Agent type (identifier)", footerText: t2, children: _jsxs(Box, { flexDirection: "column", children: [t3, t4, t5] }) });
91
+ t6 = _jsx(WizardDialogLayout, { subtitle: "Tipo de agente (identificador)", footerText: t2, children: _jsxs(Box, { flexDirection: "column", children: [t3, t4, t5] }) });
92
92
  $[12] = t4;
93
93
  $[13] = t5;
94
94
  $[14] = t6;
@@ -2,16 +2,16 @@ import { resolveAgentTools } from '../../tools/AgentTool/agentToolUtils.js';
2
2
  import { getAgentSourceDisplayName } from './utils.js';
3
3
  export function validateAgentType(agentType) {
4
4
  if (!agentType) {
5
- return 'Agent type is required';
5
+ return 'El tipo de agente es obligatorio';
6
6
  }
7
7
  if (!/^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$/.test(agentType)) {
8
- return 'Agent type must start and end with alphanumeric characters and contain only letters, numbers, and hyphens';
8
+ return 'El tipo de agente debe iniciar y terminar con caracteres alfanumericos y solo puede contener letras, numeros y guiones';
9
9
  }
10
10
  if (agentType.length < 3) {
11
- return 'Agent type must be at least 3 characters long';
11
+ return 'El tipo de agente debe tener al menos 3 caracteres';
12
12
  }
13
13
  if (agentType.length > 50) {
14
- return 'Agent type must be less than 50 characters';
14
+ return 'El tipo de agente debe tener menos de 50 caracteres';
15
15
  }
16
16
  return null;
17
17
  }
@@ -20,7 +20,7 @@ export function validateAgent(agent, availableTools, existingAgents) {
20
20
  const warnings = [];
21
21
  // Validate agent type
22
22
  if (!agent.agentType) {
23
- errors.push('Agent type is required');
23
+ errors.push('El tipo de agente es obligatorio');
24
24
  }
25
25
  else {
26
26
  const typeError = validateAgentType(agent.agentType);
@@ -30,46 +30,46 @@ export function validateAgent(agent, availableTools, existingAgents) {
30
30
  // Check for duplicates (excluding self for editing)
31
31
  const duplicate = existingAgents.find(a => a.agentType === agent.agentType && a.source !== agent.source);
32
32
  if (duplicate) {
33
- errors.push(`Agent type "${agent.agentType}" already exists in ${getAgentSourceDisplayName(duplicate.source)}`);
33
+ errors.push(`El tipo de agente "${agent.agentType}" ya existe en ${getAgentSourceDisplayName(duplicate.source)}`);
34
34
  }
35
35
  }
36
36
  // Validate description
37
37
  if (!agent.whenToUse) {
38
- errors.push('Description (description) is required');
38
+ errors.push('La descripcion es obligatoria');
39
39
  }
40
40
  else if (agent.whenToUse.length < 10) {
41
- warnings.push('Description should be more descriptive (at least 10 characters)');
41
+ warnings.push('La descripcion deberia ser mas clara (al menos 10 caracteres)');
42
42
  }
43
43
  else if (agent.whenToUse.length > 5000) {
44
- warnings.push('Description is very long (over 5000 characters)');
44
+ warnings.push('La descripcion es muy larga (mas de 5000 caracteres)');
45
45
  }
46
46
  // Validate tools
47
47
  if (agent.tools !== undefined && !Array.isArray(agent.tools)) {
48
- errors.push('Tools must be an array');
48
+ errors.push('Las herramientas deben ser un arreglo');
49
49
  }
50
50
  else {
51
51
  if (agent.tools === undefined) {
52
- warnings.push('Agent has access to all tools');
52
+ warnings.push('El agente tendra acceso a todas las herramientas');
53
53
  }
54
54
  else if (agent.tools.length === 0) {
55
- warnings.push('No tools selected - agent will have very limited capabilities');
55
+ warnings.push('No hay herramientas seleccionadas: el agente tendra capacidades muy limitadas');
56
56
  }
57
57
  // Check for invalid tools
58
58
  const resolvedTools = resolveAgentTools(agent, availableTools, false);
59
59
  if (resolvedTools.invalidTools.length > 0) {
60
- errors.push(`Invalid tools: ${resolvedTools.invalidTools.join(', ')}`);
60
+ errors.push(`Herramientas no validas: ${resolvedTools.invalidTools.join(', ')}`);
61
61
  }
62
62
  }
63
63
  // Validate system prompt
64
64
  const systemPrompt = agent.getSystemPrompt();
65
65
  if (!systemPrompt) {
66
- errors.push('System prompt is required');
66
+ errors.push('El system prompt es obligatorio');
67
67
  }
68
68
  else if (systemPrompt.length < 20) {
69
- errors.push('System prompt is too short (minimum 20 characters)');
69
+ errors.push('El system prompt es demasiado corto (minimo 20 caracteres)');
70
70
  }
71
71
  else if (systemPrompt.length > 10000) {
72
- warnings.push('System prompt is very long (over 10,000 characters)');
72
+ warnings.push('El system prompt es muy largo (mas de 10,000 caracteres)');
73
73
  }
74
74
  return {
75
75
  isValid: errors.length === 0,
@@ -49,6 +49,7 @@ import { getCompactPrompt, getCompactUserSummaryMessage, getPartialCompactPrompt
49
49
  export const POST_COMPACT_MAX_FILES_TO_RESTORE = 5;
50
50
  export const POST_COMPACT_TOKEN_BUDGET = 50_000;
51
51
  export const POST_COMPACT_MAX_TOKENS_PER_FILE = 5_000;
52
+ export const POST_COMPACT_MAX_TOKENS_FOR_PLAN = 5_000;
52
53
  // Skills can be large (verify=18.7KB, claude-api=20.1KB). Previously re-injected
53
54
  // unbounded on every compact → 5-10K tok/compact. Per-skill truncation beats
54
55
  // dropping — instructions at the top of a skill file are usually the critical
@@ -120,22 +121,23 @@ export function stripImagesFromMessages(messages) {
120
121
  };
121
122
  });
122
123
  }
123
- /**
124
- * Strip attachment types that are re-injected post-compaction anyway.
125
- * skill_discovery/skill_listing are re-surfaced by resetSentSkillNames()
126
- * + the next turn's discovery signal, so feeding them to the summarizer
127
- * wastes tokens and pollutes the summary with stale skill suggestions.
128
- *
129
- * No-op when EXPERIMENTAL_SKILL_SEARCH is off (the attachment types
130
- * don't exist on external builds).
131
- */
132
124
  export function stripReinjectedAttachments(messages) {
133
- if (feature('EXPERIMENTAL_SKILL_SEARCH')) {
134
- return messages.filter(m => !(m.type === 'attachment' &&
125
+ const stripSkillSearchAttachments = feature('EXPERIMENTAL_SKILL_SEARCH');
126
+ return messages.filter(m => {
127
+ if (m.type !== 'attachment') {
128
+ return true;
129
+ }
130
+ if (m.attachment.type === 'plan_file_reference' ||
131
+ m.attachment.type === 'invoked_skills') {
132
+ return false;
133
+ }
134
+ if (stripSkillSearchAttachments &&
135
135
  (m.attachment.type === 'skill_discovery' ||
136
- m.attachment.type === 'skill_listing')));
137
- }
138
- return messages;
136
+ m.attachment.type === 'skill_listing')) {
137
+ return false;
138
+ }
139
+ return true;
140
+ });
139
141
  }
140
142
  export const ERROR_MESSAGE_NOT_ENOUGH_MESSAGES = 'Not enough messages to compact.';
141
143
  const MAX_PTL_RETRIES = 3;
@@ -1070,11 +1072,12 @@ export async function createPostCompactFileAttachments(readFileState, toolUseCon
1070
1072
  * This ensures the plan is preserved after compaction.
1071
1073
  */
1072
1074
  export function createPlanAttachmentIfNeeded(agentId) {
1073
- const planContent = getPlan(agentId);
1074
- if (!planContent) {
1075
+ const rawPlanContent = getPlan(agentId);
1076
+ if (!rawPlanContent) {
1075
1077
  return null;
1076
1078
  }
1077
1079
  const planFilePath = getPlanFilePath(agentId);
1080
+ const planContent = truncateToTokens(rawPlanContent, POST_COMPACT_MAX_TOKENS_FOR_PLAN, '\n\n[... plan content truncated for compaction; use Read on the plan path if you need the full text]');
1078
1081
  return createAttachmentMessage({
1079
1082
  type: 'plan_file_reference',
1080
1083
  planFilePath,
@@ -1216,19 +1219,18 @@ function collectReadToolFilePaths(messages) {
1216
1219
  }
1217
1220
  return paths;
1218
1221
  }
1219
- const SKILL_TRUNCATION_MARKER = '\n\n[... skill content truncated for compaction; use Read on the skill path if you need the full text]';
1220
1222
  /**
1221
1223
  * Truncate content to roughly maxTokens, keeping the head. roughTokenCountEstimation
1222
1224
  * uses ~4 chars/token (its default bytesPerToken), so char budget = maxTokens * 4
1223
1225
  * minus the marker so the result stays within budget. Marker tells the model it
1224
1226
  * can Read the full file if needed.
1225
1227
  */
1226
- function truncateToTokens(content, maxTokens) {
1228
+ function truncateToTokens(content, maxTokens, marker = '\n\n[... skill content truncated for compaction; use Read on the skill path if you need the full text]') {
1227
1229
  if (roughTokenCountEstimation(content) <= maxTokens) {
1228
1230
  return content;
1229
1231
  }
1230
- const charBudget = maxTokens * 4 - SKILL_TRUNCATION_MARKER.length;
1231
- return content.slice(0, charBudget) + SKILL_TRUNCATION_MARKER;
1232
+ const charBudget = maxTokens * 4 - marker.length;
1233
+ return content.slice(0, Math.max(0, charBudget)) + marker;
1232
1234
  }
1233
1235
  function shouldExcludeFromPostCompactRestore(filename, agentId) {
1234
1236
  const normalizedFilename = expandPath(filename);
@@ -25,6 +25,8 @@ import { AbortError, errorMessage, toError } from '../../utils/errors.js';
25
25
  import { lazySchema } from '../../utils/lazySchema.js';
26
26
  import { createUserMessage, extractTextContent, isSyntheticMessage, normalizeMessages } from '../../utils/messages.js';
27
27
  import { getAgentModel } from '../../utils/model/agent.js';
28
+ import { runWithProviderOverride } from '../../utils/model/providerOverrideContext.js';
29
+ import { providerPreferenceToApiProvider } from '../../utils/model/providers.js';
28
30
  import { permissionModeSchema } from '../../utils/permissions/PermissionMode.js';
29
31
  import { filterDeniedAgents, getDenyRuleForAgent } from '../../utils/permissions/permissions.js';
30
32
  import { enqueueSdkEvent } from '../../utils/sdkEventQueue.js';
@@ -316,8 +318,10 @@ export const AgentTool = buildTool({
316
318
  if (selectedAgent.color) {
317
319
  setAgentColor(selectedAgent.agentType, selectedAgent.color);
318
320
  }
321
+ const agentProviderOverride = providerPreferenceToApiProvider(selectedAgent.provider);
322
+ const withAgentProvider = (fn => runWithProviderOverride(agentProviderOverride, fn));
319
323
  // Resolve agent params for logging (these are already resolved in runAgent)
320
- const resolvedAgentModel = getAgentModel(selectedAgent.model, toolUseContext.options.mainLoopModel, isForkPath ? undefined : model, permissionMode);
324
+ const resolvedAgentModel = withAgentProvider(() => getAgentModel(selectedAgent.model, toolUseContext.options.mainLoopModel, isForkPath ? undefined : model, permissionMode));
321
325
  logEvent('tengu_agent_tool_selected', {
322
326
  agent_type: selectedAgent.agentType,
323
327
  model: resolvedAgentModel,
@@ -425,7 +429,7 @@ export const AgentTool = buildTool({
425
429
  });
426
430
  }
427
431
  // Apply environment details enhancement
428
- enhancedSystemPrompt = await enhanceSystemPromptWithEnvDetails([agentPrompt], resolvedAgentModel, additionalWorkingDirectories);
432
+ enhancedSystemPrompt = await withAgentProvider(() => enhanceSystemPromptWithEnvDetails([agentPrompt], resolvedAgentModel, additionalWorkingDirectories));
429
433
  }
430
434
  catch (error) {
431
435
  logForDebugging(`Failed to get system prompt for agent ${selectedAgent.agentType}: ${errorMessage(error)}`);
@@ -600,7 +604,7 @@ export const AgentTool = buildTool({
600
604
  // invocation time — when this `void` fires — and survives every await
601
605
  // inside. No capture/restore needed; the detached closure sees the
602
606
  // parent turn's workload automatically, isolated from its finally.
603
- void runWithAgentContext(asyncAgentContext, () => wrapWithCwd(() => runAsyncAgentLifecycle({
607
+ void withAgentProvider(() => runWithAgentContext(asyncAgentContext, () => wrapWithCwd(() => runAsyncAgentLifecycle({
604
608
  taskId: agentBackgroundTask.agentId,
605
609
  abortController: agentBackgroundTask.abortController,
606
610
  makeStream: onCacheSafeParams => runAgent({
@@ -619,7 +623,7 @@ export const AgentTool = buildTool({
619
623
  agentIdForCleanup: asyncAgentId,
620
624
  enableSummarization: isCoordinator || isForkSubagentEnabled() || getSdkAgentProgressSummariesEnabled(),
621
625
  getWorktreeResult: cleanupWorktreeIfNeeded
622
- })));
626
+ }))));
623
627
  const canReadOutputFile = toolUseContext.options.tools.some(t => toolMatchesName(t, FILE_READ_TOOL_NAME) || toolMatchesName(t, BASH_TOOL_NAME));
624
628
  return {
625
629
  data: {
@@ -651,7 +655,7 @@ export const AgentTool = buildTool({
651
655
  };
652
656
  // Wrap entire sync agent execution in context for analytics attribution
653
657
  // and optionally in a worktree cwd override for filesystem isolation
654
- return runWithAgentContext(syncAgentContext, () => wrapWithCwd(async () => {
658
+ return withAgentProvider(() => runWithAgentContext(syncAgentContext, () => wrapWithCwd(async () => {
655
659
  const agentMessages = [];
656
660
  const agentStartTime = Date.now();
657
661
  const syncTracker = createProgressTracker();
@@ -761,7 +765,7 @@ export const AgentTool = buildTool({
761
765
  // Workload: inherited via ALS at `void` invocation time,
762
766
  // same as the async-from-start path above.
763
767
  // Continue agent in background and return async result
764
- void runWithAgentContext(syncAgentContext, async () => {
768
+ void withAgentProvider(() => runWithAgentContext(syncAgentContext, async () => {
765
769
  let stopBackgroundedSummarization;
766
770
  try {
767
771
  // Clean up the foreground iterator so its finally block runs
@@ -883,7 +887,7 @@ export const AgentTool = buildTool({
883
887
  // Note: worktree cleanup is done before enqueueAgentNotification
884
888
  // in both try and catch paths so we can include worktree info
885
889
  }
886
- });
890
+ }));
887
891
  // Return async_launched result immediately
888
892
  const canReadOutputFile = toolUseContext.options.tools.some(t => toolMatchesName(t, FILE_READ_TOOL_NAME) || toolMatchesName(t, BASH_TOOL_NAME));
889
893
  return {
@@ -1091,7 +1095,7 @@ export const AgentTool = buildTool({
1091
1095
  ...worktreeResult
1092
1096
  }
1093
1097
  };
1094
- }));
1098
+ })));
1095
1099
  }
1096
1100
  },
1097
1101
  isReadOnly() {
@@ -2,7 +2,7 @@
2
2
  * Shared utilities for displaying agent information.
3
3
  * Used by both the CLI `claude agents` handler and the interactive `/agents` command.
4
4
  */
5
- import { getDefaultSubagentModel } from '../../utils/model/agent.js';
5
+ import { getAgentProviderDisplay, getDefaultSubagentModel, } from '../../utils/model/agent.js';
6
6
  const OVERRIDE_SOURCE_LABELS = {
7
7
  userSettings: 'usuario',
8
8
  projectSettings: 'proyecto',
@@ -61,7 +61,10 @@ export function resolveAgentModelDisplay(agent) {
61
61
  const model = agent.model || getDefaultSubagentModel();
62
62
  if (!model)
63
63
  return undefined;
64
- return model === 'inherit' ? 'heredar' : model;
64
+ return model === 'inherit' ? 'Heredar del padre' : model;
65
+ }
66
+ export function resolveAgentProviderDisplay(agent) {
67
+ return getAgentProviderDisplay(agent.provider);
65
68
  }
66
69
  /**
67
70
  * Get a human-readable label for the source that overrides an agent.