@iaforged/context-code 1.0.100 → 1.1.3

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.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  import { existsSync } from 'fs'
3
3
  import { homedir } from 'os'
4
4
  import { dirname, join } from 'path'
@@ -48,7 +48,7 @@ export function Onboarding({ onDone }) {
48
48
  }
49
49
  const exitState = useExitOnCtrlCDWithKeybindings();
50
50
  // Define all onboarding steps
51
- const themeStep = _jsx(Box, { marginX: 1, children: _jsx(ThemePicker, { onThemeSelect: handleThemeSelection, showIntroText: true, helpText: "To change this later, run /theme", hideEscToCancel: true, skipExitHandling: true }) });
51
+ const themeStep = _jsx(Box, { marginX: 1, children: _jsx(ThemePicker, { onThemeSelect: handleThemeSelection, showIntroText: true, helpText: "Para cambiar esto despu\u00E9s, ejecuta /theme", hideEscToCancel: true, skipExitHandling: true }) });
52
52
  const securityStep = _jsxs(Box, { flexDirection: "column", gap: 1, paddingLeft: 1, children: [_jsx(Text, { bold: true, children: "Notas de seguridad:" }), _jsx(Box, { flexDirection: "column", width: 70, children: _jsxs(OrderedList, { children: [_jsxs(OrderedList.Item, { children: [_jsx(Text, { children: "Context Code puede cometer errores" }), _jsxs(Text, { dimColor: true, wrap: "wrap", children: ["Siempre debes revisar las respuestas de Context Code, especialmente", _jsx(Newline, {}), "al ejecutar c\u00F3digo.", _jsx(Newline, {})] })] }), _jsxs(OrderedList.Item, { children: [_jsx(Text, { children: "Debido a riesgos de inyecci\u00F3n de prompt, \u00FAsalo solo con c\u00F3digo de confianza" }), _jsxs(Text, { dimColor: true, wrap: "wrap", children: ["Para m\u00E1s detalles consulta:", _jsx(Newline, {}), _jsx(Link, { url: "https://github.com/LordDenihol/ContextCode" })] })] })] }) }), _jsx(PressEnterToContinue, {})] });
53
53
  const preflightStep = _jsx(PreflightStep, { onSuccess: goToNextStep });
54
54
  // Create the steps array - determine which steps to include based on reAuth and oauthEnabled
@@ -1548,13 +1548,13 @@ function teammateModelDisplayString(value) {
1548
1548
  return modelDisplayString(value);
1549
1549
  }
1550
1550
  const THEME_LABELS = {
1551
- auto: 'Auto (match terminal)',
1552
- dark: 'Dark mode',
1553
- light: 'Light mode',
1554
- 'dark-daltonized': 'Dark mode (colorblind-friendly)',
1555
- 'light-daltonized': 'Light mode (colorblind-friendly)',
1556
- 'dark-ansi': 'Dark mode (ANSI colors only)',
1557
- 'light-ansi': 'Light mode (ANSI colors only)'
1551
+ auto: 'Automático (según terminal)',
1552
+ dark: 'Modo oscuro',
1553
+ light: 'Modo claro',
1554
+ 'dark-daltonized': 'Modo oscuro (apto para daltonismo)',
1555
+ 'light-daltonized': 'Modo claro (apto para daltonismo)',
1556
+ 'dark-ansi': 'Modo oscuro (solo colores ANSI)',
1557
+ 'light-ansi': 'Modo claro (solo colores ANSI)'
1558
1558
  };
1559
1559
  function NotifChannelLabel(t0) {
1560
1560
  const $ = _c(4);
@@ -36,6 +36,17 @@ import { useAnimationFrame } from '../ink.js';
36
36
  import { getGlobalConfig } from '../utils/config.js';
37
37
  const DEFAULT_CHARACTERS = getDefaultCharacters();
38
38
  const SPINNER_FRAMES = [...DEFAULT_CHARACTERS, ...[...DEFAULT_CHARACTERS].reverse()];
39
+ function translateSpinnerTip(tip) {
40
+ if (tip ===
41
+ 'Double-tap esc to rewind the code and/or conversation to a previous point in time') {
42
+ return 'Pulsa dos veces Esc para rebobinar el código y/o la conversación a un punto anterior en el tiempo';
43
+ }
44
+ if (tip ===
45
+ 'Double-tap esc to rewind the conversation to a previous point in time') {
46
+ return 'Pulsa dos veces Esc para rebobinar la conversación a un punto anterior en el tiempo';
47
+ }
48
+ return tip;
49
+ }
39
50
  // Thin wrapper: branches on isBriefOnly so the two variants have independent
40
51
  // hook call chains. Without this split, toggling /brief mid-render would
41
52
  // violate Rules of Hooks (the inner variant calls ~10 more hooks).
@@ -216,7 +227,7 @@ function SpinnerWithVerbInner({ mode, loadingStartTimeRef, totalPausedMsRef, pau
216
227
  }
217
228
  }
218
229
  return _jsxs(Box, { flexDirection: "column", width: "100%", alignItems: "flex-start", children: [_jsx(SpinnerAnimationRow, { mode: mode, reducedMotion: reducedMotion, hasActiveTools: hasActiveTools, responseLengthRef: responseLengthRef, message: message, messageColor: messageColor, shimmerColor: shimmerColor, overrideColor: overrideColor, loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, spinnerSuffix: spinnerSuffix, verbose: verbose, columns: columns, hasRunningTeammates: hasRunningTeammates, teammateTokens: teammateTokens, foregroundedTeammate: foregroundedTeammate, leaderIsIdle: leaderIsIdle, thinkingStatus: thinkingStatus, effortSuffix: effortSuffix }), showSpinnerTree && hasRunningTeammates ? _jsx(TeammateSpinnerTree, { selectedIndex: selectedIPAgentIndex, isInSelectionMode: viewSelectionMode === 'selecting-agent', allIdle: allIdle, leaderVerb: leaderIsIdle ? undefined : leaderVerb, leaderIdleText: leaderIsIdle ? 'Inactivo' : undefined, leaderTokenCount: leaderTokenCount }) : showExpandedTodos && tasksV2 && tasksV2.length > 0 ? _jsx(Box, { width: "100%", flexDirection: "column", children: _jsx(MessageResponse, { children: _jsx(TaskListV2, { tasks: tasksV2 }) }) }) : nextTask || effectiveTip || budgetText ?
219
- _jsxs(Box, { width: "100%", flexDirection: "column", children: [budgetText && _jsx(MessageResponse, { children: _jsx(Text, { dimColor: true, children: budgetText }) }), (nextTask || effectiveTip) && _jsx(MessageResponse, { children: _jsx(Text, { dimColor: true, children: nextTask ? `Siguiente: ${nextTask.subject}` : `Consejo: ${effectiveTip}` }) })] }) : null] });
230
+ _jsxs(Box, { width: "100%", flexDirection: "column", children: [budgetText && _jsx(MessageResponse, { children: _jsx(Text, { dimColor: true, children: budgetText }) }), (nextTask || effectiveTip) && _jsx(MessageResponse, { children: _jsx(Text, { dimColor: true, children: nextTask ? `Siguiente: ${nextTask.subject}` : `Consejo: ${translateSpinnerTip(effectiveTip)}` }) })] }) : null] });
220
231
  }
221
232
  function BriefSpinner(t0) {
222
233
  const $ = _c(31);
@@ -89,25 +89,25 @@ export function ThemePicker(t0) {
89
89
  let t10;
90
90
  if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
91
91
  t10 = [...(feature("AUTO_THEME") ? [{
92
- label: "Auto (match terminal)",
92
+ label: "Automático (según terminal)",
93
93
  value: "auto"
94
94
  }] : []), {
95
- label: "Dark mode",
95
+ label: "Modo oscuro",
96
96
  value: "dark"
97
97
  }, {
98
- label: "Light mode",
98
+ label: "Modo claro",
99
99
  value: "light"
100
100
  }, {
101
- label: "Dark mode (colorblind-friendly)",
101
+ label: "Modo oscuro (apto para daltonismo)",
102
102
  value: "dark-daltonized"
103
103
  }, {
104
- label: "Light mode (colorblind-friendly)",
104
+ label: "Modo claro (apto para daltonismo)",
105
105
  value: "light-daltonized"
106
106
  }, {
107
- label: "Dark mode (ANSI colors only)",
107
+ label: "Modo oscuro (solo colores ANSI)",
108
108
  value: "dark-ansi"
109
109
  }, {
110
- label: "Light mode (ANSI colors only)",
110
+ label: "Modo claro (solo colores ANSI)",
111
111
  value: "light-ansi"
112
112
  }];
113
113
  $[7] = t10;
@@ -118,7 +118,7 @@ export function ThemePicker(t0) {
118
118
  const themeOptions = t10;
119
119
  let t11;
120
120
  if ($[8] !== showIntroText) {
121
- t11 = showIntroText ? _jsx(Text, { children: "Let's get started." }) : _jsx(Text, { bold: true, color: "permission", children: "Theme" });
121
+ t11 = showIntroText ? _jsx(Text, { children: "Empecemos." }) : _jsx(Text, { bold: true, color: "permission", children: "Tema" });
122
122
  $[8] = showIntroText;
123
123
  $[9] = t11;
124
124
  }
@@ -127,7 +127,7 @@ export function ThemePicker(t0) {
127
127
  }
128
128
  let t12;
129
129
  if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
130
- t12 = _jsx(Text, { bold: true, children: "Choose the text style that looks best with your terminal" });
130
+ t12 = _jsx(Text, { bold: true, children: "Elige el estilo de texto que mejor se vea en tu terminal" });
131
131
  $[10] = t12;
132
132
  }
133
133
  else {
@@ -6,9 +6,11 @@ import { getConfiguredProviderBaseUrl } from '../../utils/model/providerBaseUrls
6
6
  import { errorMessage } from '../../utils/errors.js';
7
7
  import { logForDebugging } from '../../utils/debug.js';
8
8
  import { logError } from '../../utils/log.js';
9
- import { createAssistantAPIErrorMessage, createAssistantMessage, } from '../../utils/messages.js';
9
+ import { createAssistantAPIErrorMessage, createAssistantMessage, createUserMessage, } from '../../utils/messages.js';
10
10
  import { toolToAPISchema } from '../../utils/api.js';
11
11
  import { jsonStringify } from '../../utils/slowOperations.js';
12
+ const OPENAI_EMPTY_CONTENT_MAX_ATTEMPTS = 2;
13
+ const OPENAI_EMPTY_CONTENT_RECOVERY_PROMPT = 'System reminder: your previous response for this turn was empty. Continue the current task without asking the user to repeat themselves. If a tool call is needed, emit the appropriate tool call now. Do not return an empty response.';
12
14
  function isRecord(value) {
13
15
  return typeof value === 'object' && value !== null && !Array.isArray(value);
14
16
  }
@@ -1752,24 +1754,39 @@ async function createOpenAIResponse(params) {
1752
1754
  }
1753
1755
  export async function* queryOpenAIModelWithStreaming({ messages, systemPrompt, thinkingConfig: _thinkingConfig, tools, signal, options, }) {
1754
1756
  try {
1755
- const response = await createOpenAIResponse({
1756
- messages,
1757
- systemPrompt,
1758
- tools,
1759
- signal,
1760
- options,
1761
- });
1762
- const { content } = parseOutputItems(response);
1763
- if (content.length === 0) {
1757
+ for (let attempt = 1; attempt <= OPENAI_EMPTY_CONTENT_MAX_ATTEMPTS; attempt++) {
1758
+ const response = await createOpenAIResponse({
1759
+ messages: attempt === 1
1760
+ ? messages
1761
+ : [
1762
+ ...messages,
1763
+ createUserMessage({
1764
+ content: OPENAI_EMPTY_CONTENT_RECOVERY_PROMPT,
1765
+ isMeta: true,
1766
+ }),
1767
+ ],
1768
+ systemPrompt,
1769
+ tools,
1770
+ signal,
1771
+ options,
1772
+ });
1773
+ const { content } = parseOutputItems(response);
1774
+ if (content.length > 0) {
1775
+ yield createAssistantMessage({
1776
+ content,
1777
+ usage: getUsage(response),
1778
+ });
1779
+ return;
1780
+ }
1781
+ if (attempt < OPENAI_EMPTY_CONTENT_MAX_ATTEMPTS) {
1782
+ logForDebugging(`[${getOpenAICompatibleProviderLabel(getOpenAICompatibleProvider())}] empty model response with no content; retrying request (${attempt}/${OPENAI_EMPTY_CONTENT_MAX_ATTEMPTS - 1})`, { level: 'warn' });
1783
+ continue;
1784
+ }
1764
1785
  yield createAssistantAPIErrorMessage({
1765
- content: 'OpenAI returned no content.',
1786
+ content: 'OpenAI returned no content after retrying.',
1766
1787
  });
1767
1788
  return;
1768
1789
  }
1769
- yield createAssistantMessage({
1770
- content,
1771
- usage: getUsage(response),
1772
- });
1773
1790
  }
1774
1791
  catch (error) {
1775
1792
  if (signal.aborted) {
@@ -28,6 +28,7 @@ function rowToTask(row) {
28
28
  parentTaskId: typed.parent_task_id ?? null,
29
29
  scopeType: typed.scope_type,
30
30
  teamUnitId: typed.team_unit_id ?? null,
31
+ teamDomainId: typed.team_unit_id ?? null,
31
32
  assignedAgentId: typed.assigned_agent_id ?? null,
32
33
  title: typed.title,
33
34
  instructions: typed.instructions,
@@ -80,6 +81,7 @@ function rowToTeamReport(row) {
80
81
  id: typed.id,
81
82
  runId: typed.run_id,
82
83
  teamUnitId: typed.team_unit_id,
84
+ teamDomainId: typed.team_unit_id,
83
85
  localOrchestratorAgentId: typed.local_orchestrator_agent_id ?? null,
84
86
  status: typed.status,
85
87
  summary: typed.summary,
@@ -275,7 +277,7 @@ export async function createOrchestrationTask(input) {
275
277
  const createdAt = nowIso();
276
278
  db.prepare(`INSERT INTO orchestration_tasks (
277
279
  id, run_id, parent_task_id, scope_type, team_unit_id, assigned_agent_id, title, instructions, status, result_summary, created_at, finished_at
278
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, requireText(input.runId, 'runId'), toNullableText(input.parentTaskId), requireText(input.scopeType, 'scopeType'), toNullableText(input.teamUnitId), toNullableText(input.assignedAgentId), requireText(input.title, 'title'), requireText(input.instructions, 'instructions'), input.status ?? 'pending', toNullableText(input.resultSummary), createdAt, toNullableText(input.finishedAt));
280
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, requireText(input.runId, 'runId'), toNullableText(input.parentTaskId), requireText(input.scopeType, 'scopeType'), toNullableText(input.teamUnitId ?? input.teamDomainId), toNullableText(input.assignedAgentId), requireText(input.title, 'title'), requireText(input.instructions, 'instructions'), input.status ?? 'pending', toNullableText(input.resultSummary), createdAt, toNullableText(input.finishedAt));
279
281
  const created = (await listOrchestrationTasks(input.runId)).find(task => task.id === id);
280
282
  if (!created) {
281
283
  throw new Error('Failed to create orchestration task.');
@@ -295,7 +297,9 @@ export async function updateOrchestrationTask(id, input) {
295
297
  }
296
298
  db.prepare(`UPDATE orchestration_tasks
297
299
  SET parent_task_id = ?, scope_type = ?, team_unit_id = ?, assigned_agent_id = ?, title = ?, instructions = ?, status = ?, result_summary = ?, finished_at = ?
298
- WHERE id = ?`).run(input.parentTaskId === undefined ? existing.parentTaskId : toNullableText(input.parentTaskId), input.scopeType === undefined ? existing.scopeType : requireText(input.scopeType, 'scopeType'), input.teamUnitId === undefined ? existing.teamUnitId : toNullableText(input.teamUnitId), input.assignedAgentId === undefined ? existing.assignedAgentId : toNullableText(input.assignedAgentId), input.title === undefined ? existing.title : requireText(input.title, 'title'), input.instructions === undefined ? existing.instructions : requireText(input.instructions, 'instructions'), input.status ?? existing.status, input.resultSummary === undefined ? existing.resultSummary : toNullableText(input.resultSummary), input.finishedAt === undefined ? existing.finishedAt : toNullableText(input.finishedAt), id);
300
+ WHERE id = ?`).run(input.parentTaskId === undefined ? existing.parentTaskId : toNullableText(input.parentTaskId), input.scopeType === undefined ? existing.scopeType : requireText(input.scopeType, 'scopeType'), input.teamUnitId === undefined && input.teamDomainId === undefined
301
+ ? existing.teamUnitId
302
+ : toNullableText(input.teamUnitId ?? input.teamDomainId), input.assignedAgentId === undefined ? existing.assignedAgentId : toNullableText(input.assignedAgentId), input.title === undefined ? existing.title : requireText(input.title, 'title'), input.instructions === undefined ? existing.instructions : requireText(input.instructions, 'instructions'), input.status ?? existing.status, input.resultSummary === undefined ? existing.resultSummary : toNullableText(input.resultSummary), input.finishedAt === undefined ? existing.finishedAt : toNullableText(input.finishedAt), id);
299
303
  const updated = (await listOrchestrationTasks(existing.runId)).find(task => task.id === id);
300
304
  if (!updated) {
301
305
  throw new Error(`Failed to reload orchestration task: ${id}`);
@@ -375,7 +379,8 @@ export async function listOrchestrationTaskResultsByTeamUnit(runId, teamUnitId)
375
379
  export async function upsertOrchestrationTeamReport(input) {
376
380
  const db = await getOrchestrationDatabase();
377
381
  const now = nowIso();
378
- const existing = await getOrchestrationTeamReport(input.runId, input.teamUnitId);
382
+ const teamUnitId = requireText(input.teamUnitId ?? input.teamDomainId, 'teamUnitId');
383
+ const existing = await getOrchestrationTeamReport(input.runId, teamUnitId);
379
384
  if (existing) {
380
385
  db.prepare(`UPDATE orchestration_team_reports
381
386
  SET local_orchestrator_agent_id = ?, status = ?, summary = ?, blockers = ?, output = ?, metrics_json = ?, updated_at = ?, submitted_at = ?
@@ -386,9 +391,9 @@ export async function upsertOrchestrationTeamReport(input) {
386
391
  else {
387
392
  db.prepare(`INSERT INTO orchestration_team_reports (
388
393
  id, run_id, team_unit_id, local_orchestrator_agent_id, status, summary, blockers, output, metrics_json, created_at, updated_at, submitted_at
389
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(randomUUID(), requireText(input.runId, 'runId'), requireText(input.teamUnitId, 'teamUnitId'), toNullableText(input.localOrchestratorAgentId), input.status ?? 'submitted', requireText(input.summary, 'summary'), toNullableText(input.blockers), toNullableText(input.output), toNullableText(input.metricsJson), now, now, toNullableText(input.submittedAt));
394
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(randomUUID(), requireText(input.runId, 'runId'), teamUnitId, toNullableText(input.localOrchestratorAgentId), input.status ?? 'submitted', requireText(input.summary, 'summary'), toNullableText(input.blockers), toNullableText(input.output), toNullableText(input.metricsJson), now, now, toNullableText(input.submittedAt));
390
395
  }
391
- const saved = await getOrchestrationTeamReport(input.runId, input.teamUnitId);
396
+ const saved = await getOrchestrationTeamReport(input.runId, teamUnitId);
392
397
  if (!saved) {
393
398
  throw new Error('Failed to save orchestration team report.');
394
399
  }
@@ -484,3 +489,22 @@ export async function deleteOrchestrationRun(id) {
484
489
  });
485
490
  return true;
486
491
  }
492
+ export async function listOrchestrationTasksByDomain(runId, teamDomainId) {
493
+ return listOrchestrationTasksByTeamUnit(runId, teamDomainId);
494
+ }
495
+ export async function listOrchestrationMessagesByDomain(runId, teamDomainId) {
496
+ return listOrchestrationMessagesByTeamUnit(runId, teamDomainId);
497
+ }
498
+ export async function listOrchestrationTaskResultsByDomain(runId, teamDomainId) {
499
+ return listOrchestrationTaskResultsByTeamUnit(runId, teamDomainId);
500
+ }
501
+ export async function upsertOrchestrationDomainReport(input) {
502
+ return (await upsertOrchestrationTeamReport({
503
+ ...input,
504
+ teamUnitId: input.teamUnitId ?? input.teamDomainId ?? null,
505
+ }));
506
+ }
507
+ export async function getOrchestrationDomainReport(runId, teamDomainId) {
508
+ const report = await getOrchestrationTeamReport(runId, teamDomainId);
509
+ return report;
510
+ }
@@ -33,6 +33,12 @@ function rowToTeamUnit(row) {
33
33
  updatedAt: typed.updated_at,
34
34
  };
35
35
  }
36
+ function unitToDomain(unit) {
37
+ return {
38
+ ...unit,
39
+ domainName: unit.unitName,
40
+ };
41
+ }
36
42
  function rowToTeamUnitMember(row) {
37
43
  if (!row) {
38
44
  return null;
@@ -48,6 +54,12 @@ function rowToTeamUnitMember(row) {
48
54
  updatedAt: typed.updated_at,
49
55
  };
50
56
  }
57
+ function unitMemberToDomainMember(member) {
58
+ return {
59
+ ...member,
60
+ teamDomainId: member.teamUnitId,
61
+ };
62
+ }
51
63
  function resolveRequiredText(value, fallback, fieldName) {
52
64
  if (value === undefined) {
53
65
  return fallback;
@@ -174,9 +186,16 @@ export async function listTeamUnits(teamId) {
174
186
  .map(rowToTeamUnit)
175
187
  .filter((unit) => unit !== null);
176
188
  }
189
+ export async function listTeamDomains(teamId) {
190
+ return (await listTeamUnits(teamId)).map(unitToDomain);
191
+ }
177
192
  export async function getTeamUnitById(id) {
178
193
  return getTeamUnitRowById(id);
179
194
  }
195
+ export async function getTeamDomainById(id) {
196
+ const unit = await getTeamUnitById(id);
197
+ return unit ? unitToDomain(unit) : null;
198
+ }
180
199
  export async function createTeamUnit(input) {
181
200
  const db = await getOrchestrationDatabase();
182
201
  const id = randomUUID();
@@ -240,6 +259,9 @@ export async function listTeamUnitMembers(teamUnitId) {
240
259
  .map(rowToTeamUnitMember)
241
260
  .filter((member) => member !== null);
242
261
  }
262
+ export async function listTeamDomainMembers(teamDomainId) {
263
+ return (await listTeamUnitMembers(teamDomainId)).map(unitMemberToDomainMember);
264
+ }
243
265
  export async function getTeamUnitMemberById(id) {
244
266
  return getTeamUnitMemberRowById(id);
245
267
  }
@@ -227,7 +227,7 @@ Una ejecucion es un objetivo guardado con sus tareas, mensajes, resultados y est
227
227
  `/orchestrate` toma un team y un objetivo, planifica el trabajo, **te muestra el plan en pantalla** y te pregunta si quieres ejecutarlo ya:
228
228
 
229
229
  ```sh
230
- /orchestrate core-dev crear endpoint de login y UI de acceso
230
+ /orchestrate core-dev crear endpoint de login y UI de acceso en la raiz de la carpeta
231
231
  ```
232
232
 
233
233
  Que pasa cuando lo ejecutas:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iaforged/context-code",
3
- "version": "1.0.100",
3
+ "version": "1.1.3",
4
4
  "description": "Context Code es un asistente de desarrollo para la terminal. Puede revisar tu proyecto, editar archivos, ejecutar comandos y apoyarte en tareas reales de programacion.",
5
5
  "author": "Context AI",
6
6
  "license": "MIT",