@corbat-tech/coco 2.5.0 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -12,8 +12,8 @@ import fs32__default, { mkdir, writeFile, readFile, access, readdir, rm } from '
12
12
  import JSON5 from 'json5';
13
13
  import { Logger } from 'tslog';
14
14
  import Anthropic from '@anthropic-ai/sdk';
15
- import OpenAI from 'openai';
16
15
  import { jsonrepair } from 'jsonrepair';
16
+ import OpenAI from 'openai';
17
17
  import * as crypto from 'crypto';
18
18
  import { randomUUID } from 'crypto';
19
19
  import * as http from 'http';
@@ -1079,10 +1079,21 @@ var init_anthropic = __esm({
1079
1079
  try {
1080
1080
  currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
1081
1081
  } catch {
1082
- getLogger().warn(
1083
- `Failed to parse tool call arguments: ${currentToolInputJson?.slice(0, 100)}`
1084
- );
1085
- currentToolCall.input = {};
1082
+ let repaired = false;
1083
+ if (currentToolInputJson) {
1084
+ try {
1085
+ currentToolCall.input = JSON.parse(jsonrepair(currentToolInputJson));
1086
+ repaired = true;
1087
+ getLogger().debug(`Repaired JSON for tool ${currentToolCall.name}`);
1088
+ } catch {
1089
+ }
1090
+ }
1091
+ if (!repaired) {
1092
+ getLogger().warn(
1093
+ `Failed to parse tool call arguments for ${currentToolCall.name}: ${currentToolInputJson?.slice(0, 300)}`
1094
+ );
1095
+ currentToolCall.input = {};
1096
+ }
1086
1097
  }
1087
1098
  yield {
1088
1099
  type: "tool_use_end",
@@ -1692,7 +1703,7 @@ var init_openai = __esm({
1692
1703
  input = builder.arguments ? JSON.parse(builder.arguments) : {};
1693
1704
  } catch (error) {
1694
1705
  console.warn(
1695
- `[${this.name}] Failed to parse tool call arguments for ${builder.name}: ${builder.arguments?.slice(0, 100)}`
1706
+ `[${this.name}] Failed to parse tool call arguments for ${builder.name}: ${builder.arguments?.slice(0, 300)}`
1696
1707
  );
1697
1708
  try {
1698
1709
  if (builder.arguments) {
@@ -8165,6 +8176,12 @@ var init_registry4 = __esm({
8165
8176
  return `${field} (${issue.message.toLowerCase()})`;
8166
8177
  });
8167
8178
  errorMessage = `Invalid tool input \u2014 ${fields.join(", ")}`;
8179
+ const allUndefined = error.issues.every(
8180
+ (i) => i.message.toLowerCase().includes("received undefined")
8181
+ );
8182
+ if (allUndefined && error.issues.length > 1) {
8183
+ errorMessage += ". All parameters are missing \u2014 this is likely a JSON serialization error on our side. Please retry with the same arguments.";
8184
+ }
8168
8185
  } else {
8169
8186
  const rawMessage = error instanceof Error ? error.message : String(error);
8170
8187
  errorMessage = humanizeError(rawMessage, name);
@@ -43267,18 +43284,21 @@ var INTENT_PATTERNS = {
43267
43284
  /run\s+(the\s+)?(complete|build)\s+phase/i
43268
43285
  ],
43269
43286
  // Task
43287
+ // NOTE: patterns must require an explicit task ID (number or code like "AUTH-001")
43288
+ // to avoid false-positive matches on natural language like "implementa la tarea de X".
43289
+ // Generic phrases like "do the task" or "haz la tarea" intentionally omitted.
43270
43290
  task: [
43271
- // Spanish
43272
- /^(haz|implementa|crea)\s+(la\s+)?tarea/i,
43273
- /^(trabaja\s+en|work\s+on)/i,
43274
- /^(ejecuta|execute)\s+(la\s+)?tarea/i,
43275
- /completa\s+(la\s+)?tarea/i,
43291
+ // Spanish — ID required
43292
+ /^(haz|ejecuta|completa)\s+(la\s+)?tarea\s+#?[a-zA-Z0-9][a-zA-Z0-9_-]*/i,
43293
+ /^(trabaja\s+en)\s+(la\s+)?tarea\s+#?[a-zA-Z0-9][a-zA-Z0-9_-]*/i,
43276
43294
  /marcar\s+tarea\s+como\s+(hecha|completada)/i,
43277
- // English
43278
- /^(do|complete|finish)\s+(the\s+)?task/i,
43279
- /work\s+on\s+(the\s+)?task/i,
43295
+ // English — ID required
43296
+ /^(do|complete|finish|run)\s+(the\s+)?task\s+#?[a-zA-Z0-9][a-zA-Z0-9_-]*/i,
43297
+ /^work\s+on\s+(the\s+)?task\s+#?[a-zA-Z0-9][a-zA-Z0-9_-]*/i,
43280
43298
  /mark\s+task\s+as\s+(done|complete)/i,
43281
- /start\s+(the\s+)?task/i
43299
+ // Explicit task reference with ID (e.g. "task 3", "task AUTH-001")
43300
+ /^task\s+#?[a-zA-Z0-9][a-zA-Z0-9_-]*/i,
43301
+ /^tarea\s+#?[a-zA-Z0-9][a-zA-Z0-9_-]*/i
43282
43302
  ],
43283
43303
  // Init
43284
43304
  init: [
@@ -43393,8 +43413,8 @@ var INTENT_PATTERNS = {
43393
43413
  var ENTITY_PATTERNS = {
43394
43414
  /** Extract sprint number */
43395
43415
  sprint: /(?:sprint|s)\s*(?:number|num|n)?\s*[:#]?\s*(\d+)/i,
43396
- /** Extract task ID */
43397
- taskId: /(?:task|tarea)\s*(?:id)?\s*[:#]?\s*([a-zA-Z0-9_-]+)/i,
43416
+ /** Extract task ID — requires at least 2 chars to avoid grabbing prepositions like "de" */
43417
+ taskId: /(?:task|tarea)\s*(?:id|#)?\s*:?\s*(\d+|[a-zA-Z][a-zA-Z0-9_-]{1,})/i,
43398
43418
  /** Extract project name */
43399
43419
  projectName: /(?:project|proyecto)\s*(?:name|nombre)?\s*[:\s]+([a-zA-Z0-9_-]+)/i,
43400
43420
  /** Extract flags like --dry-run, --yes */
@@ -43404,9 +43424,7 @@ function calculateConfidenceBoost(input) {
43404
43424
  if (input.length < 20) {
43405
43425
  boost += 0.1;
43406
43426
  }
43407
- if (/^(haz|crea|genera|construye|implementa|ejecuta|inicializa|abre|create|make|build|run|start|open|exec)/i.test(
43408
- input
43409
- )) {
43427
+ if (/^(haz|genera|construye|ejecuta|inicializa|build|run|start|open|exec)\b/i.test(input)) {
43410
43428
  boost += 0.15;
43411
43429
  }
43412
43430
  if (/(converge|orchestrate|complete|output|plan|build|init|ship|release|publish|open|exec)/i.test(
@@ -43430,7 +43448,8 @@ var DEFAULT_INTENT_CONFIG = {
43430
43448
  autoExecute: false,
43431
43449
  autoExecuteThreshold: CONFIDENCE["HIGH"],
43432
43450
  alwaysConfirm: ["init", "build", "output", "status"],
43433
- autoExecutePreferences: {}
43451
+ // exit always runs immediately — no confirmation dialog
43452
+ autoExecutePreferences: { exit: true }
43434
43453
  };
43435
43454
  function createIntentRecognizer(config = {}) {
43436
43455
  const fullConfig = { ...DEFAULT_INTENT_CONFIG, ...config };
@@ -43507,26 +43526,24 @@ function createIntentRecognizer(config = {}) {
43507
43526
  raw: input
43508
43527
  };
43509
43528
  }
43510
- const intentTypes = [
43511
- "plan",
43512
- "build",
43513
- "task",
43514
- "init",
43515
- "output",
43516
- "status",
43517
- "trust",
43518
- "ship",
43519
- "help",
43520
- "exit"
43521
- ];
43529
+ if (!trimmedInput.startsWith("/")) {
43530
+ return {
43531
+ type: "chat",
43532
+ confidence: 1,
43533
+ entities: {},
43534
+ raw: input
43535
+ };
43536
+ }
43537
+ const commandPart = trimmedInput.slice(1);
43538
+ const intentTypes = ["status", "trust", "help", "exit"];
43522
43539
  let bestMatch = null;
43523
43540
  for (const type of intentTypes) {
43524
- const match = matchIntent(trimmedInput, type);
43541
+ const match = matchIntent(commandPart, type);
43525
43542
  if (match.matched && match.confidence > (bestMatch?.confidence || 0)) {
43526
43543
  bestMatch = {
43527
43544
  type,
43528
43545
  confidence: match.confidence,
43529
- entities: extractEntities(trimmedInput),
43546
+ entities: extractEntities(commandPart),
43530
43547
  raw: input,
43531
43548
  matchedPattern: match.pattern
43532
43549
  };
@@ -43537,7 +43554,7 @@ function createIntentRecognizer(config = {}) {
43537
43554
  return {
43538
43555
  type: "chat",
43539
43556
  confidence: bestMatch?.confidence || 0.3,
43540
- entities: extractEntities(trimmedInput),
43557
+ entities: extractEntities(commandPart),
43541
43558
  raw: input
43542
43559
  };
43543
43560
  }