@corbat-tech/coco 2.33.1 → 2.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -858,6 +858,22 @@ function isCopilotTokenExpired(creds) {
858
858
  if (!creds.copilotToken || !creds.copilotTokenExpiresAt) return true;
859
859
  return Date.now() >= creds.copilotTokenExpiresAt - REFRESH_BUFFER_MS;
860
860
  }
861
+ function exchangeForCopilotTokenViaGhCli() {
862
+ return new Promise((resolve3) => {
863
+ execFile("gh", ["api", "/copilot_internal/v2/token"], { timeout: 1e4 }, (err, stdout) => {
864
+ if (err || !stdout) {
865
+ resolve3(null);
866
+ return;
867
+ }
868
+ try {
869
+ const parsed = JSON.parse(stdout);
870
+ resolve3(parsed.token && parsed.expires_at ? parsed : null);
871
+ } catch {
872
+ resolve3(null);
873
+ }
874
+ });
875
+ });
876
+ }
861
877
  async function getValidCopilotToken() {
862
878
  const creds = await loadCopilotCredentials();
863
879
  const envToken = process.env["COPILOT_GITHUB_TOKEN"] || process.env["GH_TOKEN"] || process.env["GITHUB_TOKEN"];
@@ -871,8 +887,7 @@ async function getValidCopilotToken() {
871
887
  isNew: false
872
888
  };
873
889
  }
874
- try {
875
- const copilotToken = await exchangeForCopilotToken(githubToken);
890
+ const saveAndReturn = async (copilotToken) => {
876
891
  const updatedCreds = {
877
892
  ...creds ?? { githubToken },
878
893
  githubToken: creds?.githubToken ?? githubToken,
@@ -886,11 +901,23 @@ async function getValidCopilotToken() {
886
901
  baseUrl: getCopilotBaseUrl(updatedCreds.accountType),
887
902
  isNew: true
888
903
  };
904
+ };
905
+ try {
906
+ const copilotToken = await exchangeForCopilotToken(githubToken);
907
+ return saveAndReturn(copilotToken);
889
908
  } catch (error) {
890
909
  if (error instanceof CopilotAuthError && error.permanent) {
910
+ const ghCliToken2 = await exchangeForCopilotTokenViaGhCli();
911
+ if (ghCliToken2) {
912
+ return saveAndReturn(ghCliToken2);
913
+ }
891
914
  await deleteCopilotCredentials();
892
915
  return null;
893
916
  }
917
+ const ghCliToken = await exchangeForCopilotTokenViaGhCli();
918
+ if (ghCliToken) {
919
+ return saveAndReturn(ghCliToken);
920
+ }
894
921
  throw error;
895
922
  }
896
923
  }
@@ -1680,6 +1707,18 @@ function getDefaultProvider() {
1680
1707
  }
1681
1708
  return "anthropic";
1682
1709
  }
1710
+ function getEditorModel() {
1711
+ const raw = process.env["COCO_EDITOR_MODEL"]?.trim();
1712
+ if (!raw || raw.length === 0) return void 0;
1713
+ if (["none", "default", "null", "undefined"].includes(raw.toLowerCase())) return void 0;
1714
+ return raw;
1715
+ }
1716
+ function getWeakModel() {
1717
+ const raw = process.env["COCO_WEAK_MODEL"]?.trim();
1718
+ if (!raw || raw.length === 0) return void 0;
1719
+ if (["none", "default", "null", "undefined"].includes(raw.toLowerCase())) return void 0;
1720
+ return raw;
1721
+ }
1683
1722
  var VALID_PROVIDERS;
1684
1723
  var init_env = __esm({
1685
1724
  "src/config/env.ts"() {
@@ -1709,7 +1748,9 @@ var init_env = __esm({
1709
1748
  provider: getDefaultProvider(),
1710
1749
  getApiKey,
1711
1750
  getBaseUrl,
1712
- getDefaultModel
1751
+ getDefaultModel,
1752
+ getWeakModel,
1753
+ getEditorModel
1713
1754
  });
1714
1755
  }
1715
1756
  });
@@ -10316,13 +10357,21 @@ var ToolRegistry = class {
10316
10357
  const field = issue.path.join(".") || "input";
10317
10358
  return `${field} (${issue.message.toLowerCase()})`;
10318
10359
  });
10319
- errorMessage = `Invalid tool input \u2014 ${fields.join(", ")}`;
10360
+ errorMessage = `Invalid tool input for '${name}' \u2014 ${fields.join(", ")}`;
10320
10361
  const allUndefined = error.issues.every(
10321
10362
  (i) => i.message.toLowerCase().includes("received undefined")
10322
10363
  );
10323
10364
  if (allUndefined && error.issues.length > 1) {
10324
10365
  errorMessage += ". All parameters are missing \u2014 this is likely a JSON serialization error on our side. Please retry with the same arguments.";
10325
10366
  }
10367
+ try {
10368
+ const schema = zodToJsonSchema(tool.parameters);
10369
+ errorMessage += `
10370
+
10371
+ Expected schema for '${name}':
10372
+ ${JSON.stringify(schema, null, 2)}`;
10373
+ } catch {
10374
+ }
10326
10375
  } else if (isCocoError(error)) {
10327
10376
  const causeMsg = error.cause instanceof Error ? error.cause.message : "";
10328
10377
  const isRawEnoent = causeMsg.startsWith("ENOENT:");
@@ -14368,6 +14417,129 @@ var ResponsesToolCallAssembler = class {
14368
14417
  }
14369
14418
  };
14370
14419
 
14420
+ // src/providers/model-tier.ts
14421
+ var TIER_CONFIGS = {
14422
+ mini: {
14423
+ maxTools: 12,
14424
+ parallelToolCalls: false,
14425
+ compactionThreshold: 0.5,
14426
+ supportsCoT: false
14427
+ },
14428
+ standard: {
14429
+ maxTools: 40,
14430
+ parallelToolCalls: true,
14431
+ compactionThreshold: 0.75,
14432
+ supportsCoT: true
14433
+ },
14434
+ advanced: {
14435
+ maxTools: 128,
14436
+ parallelToolCalls: true,
14437
+ compactionThreshold: 0.8,
14438
+ supportsCoT: true
14439
+ }
14440
+ };
14441
+ var ANTHROPIC_TIERS = [
14442
+ // Haiku — mini tier
14443
+ { prefix: "claude-haiku", tier: "mini" },
14444
+ { prefix: "claude-3-haiku", tier: "mini" },
14445
+ // Sonnet / Claude 3.5 — standard tier
14446
+ { prefix: "claude-3-5-sonnet", tier: "standard" },
14447
+ { prefix: "claude-3-7-sonnet", tier: "standard" },
14448
+ { prefix: "claude-sonnet", tier: "standard" },
14449
+ // Opus — advanced tier
14450
+ { prefix: "claude-opus", tier: "advanced" },
14451
+ { prefix: "claude-3-opus", tier: "advanced" }
14452
+ // claude-4+ (future) — default to standard unless matched above
14453
+ ];
14454
+ var OPENAI_TIERS = [
14455
+ // Mini models
14456
+ { prefix: "gpt-4o-mini", tier: "mini" },
14457
+ { prefix: "gpt-5-mini", tier: "mini" },
14458
+ { prefix: "gpt-5.4-mini", tier: "mini" },
14459
+ { prefix: "gpt-5.3-mini", tier: "mini" },
14460
+ { prefix: "o1-mini", tier: "mini" },
14461
+ { prefix: "o3-mini", tier: "mini" },
14462
+ // Advanced / reasoning models
14463
+ { prefix: "o1", tier: "advanced" },
14464
+ { prefix: "o3", tier: "advanced" },
14465
+ { prefix: "o4", tier: "advanced" },
14466
+ { prefix: "gpt-4.1", tier: "advanced" },
14467
+ { prefix: "gpt-5.4-codex", tier: "advanced" },
14468
+ { prefix: "gpt-5.3-codex", tier: "advanced" },
14469
+ { prefix: "gpt-5.2-codex", tier: "advanced" },
14470
+ { prefix: "gpt-5.1-codex", tier: "advanced" },
14471
+ { prefix: "gpt-5.4", tier: "advanced" },
14472
+ { prefix: "gpt-5.3", tier: "advanced" },
14473
+ { prefix: "gpt-5.2", tier: "advanced" },
14474
+ { prefix: "gpt-5.1", tier: "advanced" },
14475
+ // GPT-5 catch-all (non-mini/codex) — advanced
14476
+ { prefix: "gpt-5", tier: "advanced" },
14477
+ // GPT-4o — standard
14478
+ { prefix: "gpt-4o", tier: "standard" },
14479
+ // GPT-4 — standard
14480
+ { prefix: "gpt-4", tier: "standard" }
14481
+ ];
14482
+ var GEMINI_TIERS = [
14483
+ // Flash — mini tier
14484
+ { prefix: "gemini-3-flash", tier: "mini" },
14485
+ { prefix: "gemini-2.5-flash", tier: "mini" },
14486
+ { prefix: "gemini-2.0-flash", tier: "mini" },
14487
+ { prefix: "gemini-1.5-flash", tier: "mini" },
14488
+ // Pro — standard/advanced
14489
+ { prefix: "gemini-3.1-pro", tier: "advanced" },
14490
+ { prefix: "gemini-3-pro", tier: "advanced" },
14491
+ { prefix: "gemini-2.5-pro", tier: "standard" },
14492
+ { prefix: "gemini-2.0-pro", tier: "standard" },
14493
+ { prefix: "gemini-1.5-pro", tier: "standard" }
14494
+ ];
14495
+ var KIMI_TIERS = [
14496
+ { prefix: "kimi-for-coding", tier: "advanced" },
14497
+ { prefix: "kimi-k2", tier: "advanced" },
14498
+ { prefix: "kimi-latest", tier: "standard" },
14499
+ { prefix: "kimi", tier: "standard" }
14500
+ ];
14501
+ var EVAL_TIERS = [
14502
+ { prefix: "grok-code", tier: "standard" },
14503
+ { prefix: "raptor", tier: "mini" },
14504
+ { prefix: "goldeneye", tier: "standard" }
14505
+ ];
14506
+ function matchTier(model, table) {
14507
+ const lower = model.toLowerCase();
14508
+ const sorted = [...table].sort((a, b) => b.prefix.length - a.prefix.length);
14509
+ for (const { prefix, tier } of sorted) {
14510
+ if (lower.startsWith(prefix.toLowerCase())) return tier;
14511
+ }
14512
+ return null;
14513
+ }
14514
+ function getModelTier(provider, model) {
14515
+ if (!model) return "standard";
14516
+ const p5 = provider.toLowerCase();
14517
+ if (p5 === "anthropic") {
14518
+ return matchTier(model, ANTHROPIC_TIERS) ?? "standard";
14519
+ }
14520
+ if (p5 === "kimi-code") {
14521
+ return matchTier(model, KIMI_TIERS) ?? matchTier(model, ANTHROPIC_TIERS) ?? "standard";
14522
+ }
14523
+ if (p5 === "openai" || p5 === "copilot" || p5 === "codex") {
14524
+ if (model.startsWith("claude-")) {
14525
+ return matchTier(model, ANTHROPIC_TIERS) ?? "standard";
14526
+ }
14527
+ const evalMatch = matchTier(model, EVAL_TIERS);
14528
+ if (evalMatch) return evalMatch;
14529
+ return matchTier(model, OPENAI_TIERS) ?? "standard";
14530
+ }
14531
+ if (p5 === "gemini" || p5 === "vertex") {
14532
+ return matchTier(model, GEMINI_TIERS) ?? "standard";
14533
+ }
14534
+ if (p5 === "kimi" || p5 === "moonshot") {
14535
+ return matchTier(model, KIMI_TIERS) ?? "standard";
14536
+ }
14537
+ return "standard";
14538
+ }
14539
+ function getTierConfig(provider, model) {
14540
+ return TIER_CONFIGS[getModelTier(provider, model)];
14541
+ }
14542
+
14371
14543
  // src/providers/openai.ts
14372
14544
  var DEFAULT_MODEL2 = "gpt-5.3-codex";
14373
14545
  var CONTEXT_WINDOWS2 = {
@@ -14532,6 +14704,14 @@ var OpenAIProvider = class {
14532
14704
  supportsTemperature(model) {
14533
14705
  return !MODELS_WITHOUT_TEMPERATURE.some((m) => model.toLowerCase().includes(m.toLowerCase()));
14534
14706
  }
14707
+ /**
14708
+ * Whether this provider instance supports the Responses API for the given model.
14709
+ * Subclasses (e.g. CopilotProvider) can override to force Chat Completions
14710
+ * when their endpoint does not expose /v1/responses.
14711
+ */
14712
+ modelNeedsResponsesApi(model) {
14713
+ return needsResponsesApi(model);
14714
+ }
14535
14715
  /**
14536
14716
  * Get extra body parameters for API calls.
14537
14717
  * Honors the user's ThinkingMode for Kimi models; defaults to disabled
@@ -14551,7 +14731,7 @@ var OpenAIProvider = class {
14551
14731
  async chat(messages, options) {
14552
14732
  this.ensureInitialized();
14553
14733
  const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
14554
- if (needsResponsesApi(model)) {
14734
+ if (this.modelNeedsResponsesApi(model)) {
14555
14735
  return this.chatViaResponses(messages, options);
14556
14736
  }
14557
14737
  return withRetry(async () => {
@@ -14591,21 +14771,24 @@ var OpenAIProvider = class {
14591
14771
  async chatWithTools(messages, options) {
14592
14772
  this.ensureInitialized();
14593
14773
  const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
14594
- if (needsResponsesApi(model)) {
14774
+ if (this.modelNeedsResponsesApi(model)) {
14595
14775
  return this.chatWithToolsViaResponses(messages, options);
14596
14776
  }
14777
+ const tierCfg = getTierConfig(this.id, model);
14597
14778
  return withRetry(async () => {
14598
14779
  try {
14599
14780
  const supportsTemp = this.supportsTemperature(model);
14600
14781
  const extraBody = this.getExtraBody(model, options?.thinking);
14601
14782
  const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
14602
14783
  const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
14784
+ const tools = this.limitTools(options.tools, tierCfg.maxTools);
14603
14785
  const requestParams = {
14604
14786
  model,
14605
14787
  ...buildMaxTokensParam(model, maxTokens),
14606
14788
  messages: this.convertMessages(messages, options?.system),
14607
- tools: this.convertTools(options.tools),
14608
- tool_choice: this.convertToolChoice(options.toolChoice)
14789
+ tools: this.convertTools(tools),
14790
+ tool_choice: this.convertToolChoice(options.toolChoice),
14791
+ parallel_tool_calls: tierCfg.parallelToolCalls
14609
14792
  };
14610
14793
  if (supportsTemp) {
14611
14794
  requestParams.temperature = options?.temperature ?? this.config.temperature ?? 0;
@@ -14643,7 +14826,7 @@ var OpenAIProvider = class {
14643
14826
  async *stream(messages, options) {
14644
14827
  this.ensureInitialized();
14645
14828
  const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
14646
- if (needsResponsesApi(model)) {
14829
+ if (this.modelNeedsResponsesApi(model)) {
14647
14830
  yield* this.streamViaResponses(messages, options);
14648
14831
  return;
14649
14832
  }
@@ -14681,22 +14864,25 @@ var OpenAIProvider = class {
14681
14864
  async *streamWithTools(messages, options) {
14682
14865
  this.ensureInitialized();
14683
14866
  const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
14684
- if (needsResponsesApi(model)) {
14867
+ if (this.modelNeedsResponsesApi(model)) {
14685
14868
  yield* this.streamWithToolsViaResponses(messages, options);
14686
14869
  return;
14687
14870
  }
14871
+ const tierCfg = getTierConfig(this.id, model);
14688
14872
  let timeoutTriggered = false;
14689
14873
  try {
14690
14874
  const supportsTemp = this.supportsTemperature(model);
14691
14875
  const extraBody = this.getExtraBody(model, options?.thinking);
14692
14876
  const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
14693
14877
  const maxTokens = options?.maxTokens ?? this.config.maxTokens ?? 8192;
14878
+ const tools = this.limitTools(options.tools, tierCfg.maxTools);
14694
14879
  const requestParams = {
14695
14880
  model,
14696
14881
  ...buildMaxTokensParam(model, maxTokens),
14697
14882
  messages: this.convertMessages(messages, options?.system),
14698
- tools: this.convertTools(options.tools),
14883
+ tools: this.convertTools(tools),
14699
14884
  tool_choice: this.convertToolChoice(options.toolChoice),
14885
+ parallel_tool_calls: tierCfg.parallelToolCalls,
14700
14886
  stream: true
14701
14887
  };
14702
14888
  if (supportsTemp) {
@@ -14933,7 +15119,7 @@ var OpenAIProvider = class {
14933
15119
  } catch {
14934
15120
  try {
14935
15121
  const model = this.config.model || DEFAULT_MODEL2;
14936
- if (needsResponsesApi(model)) {
15122
+ if (this.modelNeedsResponsesApi(model)) {
14937
15123
  await this.client.responses.create({
14938
15124
  model,
14939
15125
  input: [{ role: "user", content: [{ type: "input_text", text: "Hi" }] }],
@@ -15066,6 +15252,17 @@ var OpenAIProvider = class {
15066
15252
  }
15067
15253
  return content.filter((block) => block.type === "text").map((block) => block.text).join("");
15068
15254
  }
15255
+ /**
15256
+ * Limit the tool list to at most `max` entries.
15257
+ * Built-in tools (those without an `mcp_server` tag) are prioritised over
15258
+ * MCP tools so core capabilities are never dropped.
15259
+ */
15260
+ limitTools(tools, max) {
15261
+ if (tools.length <= max) return tools;
15262
+ const builtin = tools.filter((t) => !("serverName" in t && t.serverName));
15263
+ const mcp = tools.filter((t) => "serverName" in t && t.serverName);
15264
+ return [...builtin, ...mcp].slice(0, max);
15265
+ }
15069
15266
  /**
15070
15267
  * Convert tools to OpenAI format
15071
15268
  */
@@ -15074,8 +15271,9 @@ var OpenAIProvider = class {
15074
15271
  type: "function",
15075
15272
  function: {
15076
15273
  name: tool.name,
15077
- description: tool.description,
15078
- parameters: tool.input_schema
15274
+ description: truncateToolDescription(tool.description),
15275
+ parameters: tool.input_schema,
15276
+ strict: true
15079
15277
  }
15080
15278
  }));
15081
15279
  }
@@ -15208,8 +15406,11 @@ var OpenAIProvider = class {
15208
15406
  return withRetry(async () => {
15209
15407
  try {
15210
15408
  const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
15409
+ const tierCfg = getTierConfig(this.id, model);
15211
15410
  const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
15212
- const tools = this.convertToolsForResponses(options.tools);
15411
+ const tools = this.convertToolsForResponses(
15412
+ this.limitTools(options.tools, tierCfg.maxTools)
15413
+ );
15213
15414
  const supportsTemp = this.supportsTemperature(model);
15214
15415
  const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
15215
15416
  const response = await this.client.responses.create({
@@ -15329,8 +15530,10 @@ var OpenAIProvider = class {
15329
15530
  let timeoutTriggered = false;
15330
15531
  try {
15331
15532
  const model = options?.model ?? this.config.model ?? DEFAULT_MODEL2;
15533
+ const tierCfg = getTierConfig(this.id, model);
15332
15534
  const { input, instructions } = this.convertToResponsesInput(messages, options?.system);
15333
- const tools = options.tools.length > 0 ? this.convertToolsForResponses(options.tools) : void 0;
15535
+ const limitedTools = this.limitTools(options.tools, tierCfg.maxTools);
15536
+ const tools = limitedTools.length > 0 ? this.convertToolsForResponses(limitedTools) : void 0;
15334
15537
  const supportsTemp = this.supportsTemperature(model);
15335
15538
  const reasoningEffort = mapToOpenAIEffort(options?.thinking, model);
15336
15539
  const requestParams = {
@@ -15560,12 +15763,17 @@ var OpenAIProvider = class {
15560
15763
  return tools.map((tool) => ({
15561
15764
  type: "function",
15562
15765
  name: tool.name,
15563
- description: tool.description ?? void 0,
15766
+ description: tool.description ? truncateToolDescription(tool.description) : void 0,
15564
15767
  parameters: tool.input_schema ?? null,
15565
- strict: false
15768
+ strict: true
15566
15769
  }));
15567
15770
  }
15568
15771
  };
15772
+ var MAX_TOOL_DESCRIPTION_LENGTH = 1024;
15773
+ function truncateToolDescription(description) {
15774
+ if (description.length <= MAX_TOOL_DESCRIPTION_LENGTH) return description;
15775
+ return description.slice(0, MAX_TOOL_DESCRIPTION_LENGTH - 1) + "\u2026";
15776
+ }
15569
15777
  function createKimiProvider(config) {
15570
15778
  const provider = new OpenAIProvider("kimi", "Kimi (Moonshot)");
15571
15779
  const kimiConfig = {
@@ -16334,6 +16542,14 @@ var CopilotProvider = class extends OpenAIProvider {
16334
16542
  /**
16335
16543
  * Count tokens (approximate — Copilot models vary in tokenizer)
16336
16544
  */
16545
+ /**
16546
+ * The GitHub Copilot endpoint (api.githubcopilot.com) does not expose the
16547
+ * OpenAI Responses API (/v1/responses). Always use Chat Completions so that
16548
+ * gpt-5-mini and similar models work correctly with MCP tools.
16549
+ */
16550
+ modelNeedsResponsesApi(_model) {
16551
+ return false;
16552
+ }
16337
16553
  countTokens(text) {
16338
16554
  if (!text) return 0;
16339
16555
  return Math.ceil(text.length / 3.5);
@@ -18401,7 +18617,7 @@ Use list_dir or glob to find the correct path.`;
18401
18617
  }
18402
18618
  var readFileTool = defineTool({
18403
18619
  name: "read_file",
18404
- description: `Read the contents of a file.
18620
+ description: `Read the full text content of a file at the given path and return it as a string. Use this when you need the actual source code, configuration values, or text content of a specific file you already know the path to. Do NOT use this to list files in a directory (use list_directory), to check if a file exists (use file_exists), or to search for files by name pattern (use find_files). Returns an error if the path does not exist or is not a readable text file.
18405
18621
 
18406
18622
  Examples:
18407
18623
  - Read config: { "path": "package.json" }
@@ -18459,7 +18675,7 @@ Examples:
18459
18675
  });
18460
18676
  var writeFileTool = defineTool({
18461
18677
  name: "write_file",
18462
- description: `Write content to a file, creating it if it doesn't exist.
18678
+ description: `Write text content to a file, replacing it entirely if it already exists or creating it if it does not. Use this when you want to create a new file or fully replace an existing file's content. Do NOT use this to make a small change to an existing file (use edit_file instead, which performs a targeted find-and-replace without rewriting the whole file). Set createDirs: true to automatically create missing parent directories; otherwise the parent directory must already exist.
18463
18679
 
18464
18680
  Examples:
18465
18681
  - Create file: { "path": "src/utils.ts", "content": "export const foo = 1;" }
@@ -18520,7 +18736,7 @@ Examples:
18520
18736
  });
18521
18737
  var editFileTool = defineTool({
18522
18738
  name: "edit_file",
18523
- description: `Edit a file by replacing text (find and replace).
18739
+ description: `Make a targeted text replacement inside an existing file by finding oldText and replacing it with newText. Use this for surgical edits to source code, configuration files, or documentation \u2014 it is much safer than rewriting the whole file with write_file because it only touches the exact bytes you specify. The oldText must match exactly (including whitespace and indentation); if it appears more than once in the file, use all: true to replace every occurrence or make oldText longer to be unique. Do NOT use this to create new files (use write_file) or to rename/move files (use move_path).
18524
18740
 
18525
18741
  Examples:
18526
18742
  - Single replace: { "path": "src/app.ts", "oldText": "TODO:", "newText": "DONE:" }
@@ -18604,7 +18820,7 @@ Hint: Use read_file first to verify the exact content.`
18604
18820
  });
18605
18821
  var globTool = defineTool({
18606
18822
  name: "glob",
18607
- description: `Find files matching a glob pattern.
18823
+ description: `Find files whose paths match a glob pattern and return their relative paths as a list. Use this when you know the file extension or naming convention but not the exact path (e.g. find all TypeScript test files, all JSON configs). Do NOT use this to search inside file contents \u2014 use grep or search for that. Returns an empty list when nothing matches; does not throw an error for zero results. node_modules, .git, and dist directories are excluded by default.
18608
18824
 
18609
18825
  Examples:
18610
18826
  - All TypeScript: { "pattern": "**/*.ts" }
@@ -18646,7 +18862,7 @@ Examples:
18646
18862
  });
18647
18863
  var fileExistsTool = defineTool({
18648
18864
  name: "file_exists",
18649
- description: `Check if a file or directory exists.
18865
+ description: `Check whether a path exists on disk and whether it is a file or directory. Use this before attempting to read or write a path when you are unsure it exists \u2014 it never throws, always returning { exists: false } for missing paths. Do NOT use this to read file contents (use read_file) or to list directory contents (use list_directory). Returns isFile and isDirectory flags so you can distinguish files from directories in a single call.
18650
18866
 
18651
18867
  Examples:
18652
18868
  - Check file: { "path": "package.json" } \u2192 { "exists": true, "isFile": true, "isDirectory": false }
@@ -18676,7 +18892,7 @@ Examples:
18676
18892
  });
18677
18893
  var listDirTool = defineTool({
18678
18894
  name: "list_dir",
18679
- description: `List contents of a directory.
18895
+ description: `List the immediate entries (files and subdirectories) inside a directory and return their names, types, and sizes. Use this to understand what's in a folder before deciding which files to read. Do NOT use this to find files matching a pattern across the whole project (use glob) or to read file contents (use read_file). Returns an error if the path does not exist or is not a directory.
18680
18896
 
18681
18897
  Examples:
18682
18898
  - List src: { "path": "src" }
@@ -19109,16 +19325,11 @@ var SENSITIVE_ENV_PATTERNS = [
19109
19325
  ];
19110
19326
  var bashExecTool = defineTool({
19111
19327
  name: "bash_exec",
19112
- description: `Execute a bash/shell command in the user's shell environment.
19328
+ description: `Execute a shell command and return its stdout, stderr, and exit code. Use this for running build scripts, test runners, linters, package managers, CLI tools, git commands, or any other shell operation. Runs in the user's shell environment with their full PATH and locally-configured credentials (kubeconfig, gcloud auth, AWS profiles, SSH keys) so never claim you cannot run a command due to missing credentials \u2014 always attempt and report the actual exit code. Do NOT use this to read or write files (use read_file / write_file / edit_file which are safer); prefer specific file tools for file operations.
19113
19329
 
19114
19330
  Runs with the user's full PATH and inherited environment \u2014 any tool installed
19115
19331
  on the user's machine is available: kubectl, gcloud, aws, docker, git, node,
19116
- pnpm, and others. Credentials configured locally are inherited automatically:
19117
- kubeconfig contexts, gcloud auth, AWS profiles, SSH keys, etc.
19118
-
19119
- IMPORTANT: never claim you cannot run a command because you lack credentials
19120
- or access \u2014 the environment is the user's own shell. Always attempt; report
19121
- failure only if the command actually returns a non-zero exit code.
19332
+ pnpm, and others.
19122
19333
 
19123
19334
  Examples:
19124
19335
  - List files: { "command": "ls -la" }
@@ -19387,7 +19598,7 @@ function getGit(cwd) {
19387
19598
  }
19388
19599
  var gitStatusTool = defineTool({
19389
19600
  name: "git_status",
19390
- description: `Get the current git repository status including branch, staged, modified, and untracked files.
19601
+ description: `Return the current git repository state: branch name, staged files, modified files, and untracked files. Use this before committing to see what has changed, or to check which branch is active. Do NOT use this to see the content of changes (use git_diff), or to view history (use git_log). Returns isClean: true when the working tree is clean with nothing to commit.
19391
19602
 
19392
19603
  Examples:
19393
19604
  - Current dir: {} \u2192 { "branch": "main", "isClean": false, "modified": ["src/app.ts"] }
@@ -19421,7 +19632,7 @@ Examples:
19421
19632
  });
19422
19633
  var gitDiffTool = defineTool({
19423
19634
  name: "git_diff",
19424
- description: `Get git diff showing file changes.
19635
+ description: `Show the unified diff of changes in the working tree or staging area. Use this to see exactly what lines changed in files before committing, or to review changes the user just made. Use staged: true to see only what has been staged (git add), or omit it to see all unstaged changes. Do NOT use this to see commit history (use git_log) or file status summary (use git_status).
19425
19636
 
19426
19637
  Examples:
19427
19638
  - All changes: {} \u2192 { "diff": "...", "filesChanged": 3, "insertions": 42, "deletions": 10 }
@@ -19458,7 +19669,7 @@ Examples:
19458
19669
  });
19459
19670
  var gitAddTool = defineTool({
19460
19671
  name: "git_add",
19461
- description: `Stage files for commit.
19672
+ description: `Stage one or more files (or patterns) so they are included in the next git commit. Use this after making file edits to mark them ready for commit. Pass ["."] to stage all changes, or list specific file paths to stage selectively. Do NOT use this to commit (use git_commit after staging) or to view what is staged (use git_status or git_diff with staged: true).
19462
19673
 
19463
19674
  Examples:
19464
19675
  - Stage all: { "files": ["."] }
@@ -19484,7 +19695,7 @@ Examples:
19484
19695
  });
19485
19696
  var gitCommitTool = defineTool({
19486
19697
  name: "git_commit",
19487
- description: `Create a git commit with the staged changes.
19698
+ description: `Create a git commit from whatever is currently staged (git add must run first). Use conventional commit format (feat/fix/docs/chore). Do NOT use this when nothing is staged \u2014 check git_status first; do NOT use this to stage files (use git_add) or to see what will be committed (use git_diff with staged: true).
19488
19699
 
19489
19700
  Examples:
19490
19701
  - Simple commit: { "message": "fix: resolve auth bug" }
@@ -19517,7 +19728,7 @@ Examples:
19517
19728
  });
19518
19729
  var gitLogTool = defineTool({
19519
19730
  name: "git_log",
19520
- description: `Get git commit history.
19731
+ description: `Show git commit history with hashes, messages, authors, and dates. Use this to understand what changed recently, find the commit that introduced a bug, or check whether a feature was already merged. Do NOT use this to see the content of changes \u2014 use git_diff; do NOT use this to check current file state \u2014 use git_status.
19521
19732
 
19522
19733
  Examples:
19523
19734
  - Last 10 commits: {} (default)
@@ -19557,7 +19768,7 @@ Examples:
19557
19768
  });
19558
19769
  var gitBranchTool = defineTool({
19559
19770
  name: "git_branch",
19560
- description: `Manage git branches (list, create, delete).
19771
+ description: `List all local branches, create a new branch from the current HEAD, or delete a branch. Use this to see available branches before checking out, or to create a feature branch. Do NOT use this to switch the active branch \u2014 use git_checkout; do NOT delete branches that have unmerged work.
19561
19772
 
19562
19773
  Examples:
19563
19774
  - List branches: {} \u2192 { "branches": ["main", "feature/x"], "current": "main" }
@@ -19601,7 +19812,7 @@ Examples:
19601
19812
  });
19602
19813
  var gitCheckoutTool = defineTool({
19603
19814
  name: "git_checkout",
19604
- description: `Switch branches or create and switch to a new branch.
19815
+ description: `Switch the working directory to an existing branch, or create a new branch and switch to it in one step. Use this to move between branches or start a new feature branch. Do NOT use this with unsaved file edits (stage or stash first); do NOT use this to just list branches \u2014 use git_branch.
19605
19816
 
19606
19817
  Examples:
19607
19818
  - Switch branch: { "branch": "main" }
@@ -19631,7 +19842,7 @@ Examples:
19631
19842
  });
19632
19843
  var gitPushTool = defineTool({
19633
19844
  name: "git_push",
19634
- description: `Push commits to remote repository.
19845
+ description: `Upload local commits to a remote repository. Use setUpstream: true the first time you push a new branch to create the tracking relationship. Do NOT use this on main/master without explicit user confirmation \u2014 it modifies shared history; do NOT push without first checking git_status to confirm all commits are clean.
19635
19846
 
19636
19847
  Examples:
19637
19848
  - Push current: {} \u2192 pushes to origin
@@ -19669,7 +19880,7 @@ Examples:
19669
19880
  });
19670
19881
  var gitPullTool = defineTool({
19671
19882
  name: "git_pull",
19672
- description: `Pull changes from remote repository.
19883
+ description: `Fetch and integrate remote commits into the current branch. Use rebase: true to keep a linear history (preferred for feature branches). Do NOT use this when you have uncommitted local changes \u2014 stage or stash them first; if a merge conflict is reported, use read_file / edit_file to resolve then git_add and git_commit.
19673
19884
 
19674
19885
  Examples:
19675
19886
  - Pull current: {} \u2192 pulls from origin
@@ -20792,7 +21003,7 @@ var qualityTools = [runLinterTool, analyzeComplexityTool, calculateQualityTool];
20792
21003
  init_errors();
20793
21004
  var grepTool = defineTool({
20794
21005
  name: "grep",
20795
- description: `Search for text patterns in files using regex.
21006
+ description: `Search for a regex pattern across all files in a directory and return matching lines with file paths and line numbers. Use this when you know a symbol name, string literal, or pattern and want to find where it appears in the codebase (function definitions, imports, error messages, config keys). Do NOT use this to find files by name \u2014 use glob for that. Do NOT use this when you already know the file path \u2014 use read_file directly. Searches are recursive by default; narrow with the include glob to restrict to specific file types.
20796
21007
 
20797
21008
  Examples:
20798
21009
  - Simple search: { "pattern": "TODO" }
@@ -20925,7 +21136,7 @@ Examples:
20925
21136
  });
20926
21137
  var findInFileTool = defineTool({
20927
21138
  name: "find_in_file",
20928
- description: `Search for a pattern in a single file.
21139
+ description: `Search for a text or regex pattern inside a single known file and return matching line numbers and content. Use this when you already have the file path and want to quickly find which lines match (e.g. locate a function signature, find an import, or confirm a value exists). Do NOT use this to search across the whole project \u2014 use grep for that. Returns line numbers so you can navigate directly to the match.
20929
21140
 
20930
21141
  Examples:
20931
21142
  - Find text: { "file": "src/app.ts", "pattern": "export" }
@@ -22426,7 +22637,7 @@ async function searchSerpApi(query, maxResults, timeout) {
22426
22637
  }
22427
22638
  var webSearchTool = defineTool({
22428
22639
  name: "web_search",
22429
- description: `Search the web for information, documentation, error solutions, and API references.
22640
+ description: `Search the web using a natural-language query and return a list of result titles, URLs, and short excerpts. Use this when you need to find documentation, research an error message, discover API references, or learn about a library before you have a specific URL. Do NOT use this when you already have the URL \u2014 use web_fetch to read a known page directly. Returns result titles and URLs you can then fetch with web_fetch for full content.
22430
22641
 
22431
22642
  Examples:
22432
22643
  - Basic search: { "query": "typescript zod validation examples" }
@@ -22707,7 +22918,7 @@ ${rows.join("\n")}
22707
22918
  }
22708
22919
  var webFetchTool = defineTool({
22709
22920
  name: "web_fetch",
22710
- description: `Fetch a URL and convert its content to clean markdown. Extracts main content, strips navigation/ads, and returns readable text.
22921
+ description: `Fetch the content of a specific URL and return it as clean, readable markdown text. Use this when you already have the exact URL \u2014 for example a documentation page, a GitHub file, or an API response \u2014 and want to read its content. Do NOT use this to find information without a URL; use web_search instead to discover relevant URLs first. By default strips navigation menus, headers, and ads to return only the main content; set extractContent: false to get the raw HTML/text.
22711
22922
 
22712
22923
  Examples:
22713
22924
  - Fetch documentation: { "url": "https://docs.example.com/api" }
@@ -24418,8 +24629,7 @@ async function saveMemory(scope, memory) {
24418
24629
  }
24419
24630
  var createMemoryTool = defineTool({
24420
24631
  name: "create_memory",
24421
- description: `Save a memory (key-value pair) that persists between sessions.
24422
- Use for storing project conventions, patterns, preferences, and learnings.
24632
+ description: `Persist a named key-value fact that survives across sessions \u2014 use this for project conventions, patterns, user preferences, or discovered constraints you'll need later. If the key already exists the value is overwritten. Do NOT use this for temporary scratch data within a single session; do NOT use this to store file contents \u2014 use write_file for that.
24423
24633
 
24424
24634
  Examples:
24425
24635
  - Save convention: { "key": "naming-convention", "value": "Use camelCase for variables", "tags": ["style"] }
@@ -24476,7 +24686,7 @@ Examples:
24476
24686
  });
24477
24687
  var recallMemoryTool = defineTool({
24478
24688
  name: "recall_memory",
24479
- description: `Search and recall stored memories by key, tags, or free text query.
24689
+ description: `Search previously saved memories by key substring, tags, or free-text value match. Use this at the start of a task to check if relevant conventions or patterns were already learned. Returns full memory content. Do NOT use this to list all memories (use list_memories) or to search file content (use grep).
24480
24690
 
24481
24691
  Examples:
24482
24692
  - By key substring: { "query": "naming" }
@@ -24531,7 +24741,7 @@ Examples:
24531
24741
  });
24532
24742
  var listMemoriesTool = defineTool({
24533
24743
  name: "list_memories",
24534
- description: `List all stored memories with optional filtering. Returns lightweight index entries.
24744
+ description: `List stored memory keys and tags without loading full values \u2014 useful for browsing what has been saved before recalling specific entries. Do NOT use this to get memory content (use recall_memory for that).
24535
24745
 
24536
24746
  Examples:
24537
24747
  - List all: { "scope": "all" }
@@ -27053,7 +27263,7 @@ async function ghExec(args, cwd) {
27053
27263
  }
27054
27264
  var ghCheckAuthTool = defineTool({
27055
27265
  name: "gh_check_auth",
27056
- description: "Check if the GitHub CLI is installed and authenticated.",
27266
+ description: "Verify the gh CLI is installed and the user is logged into GitHub. Call this before any other gh_ tool to confirm authentication is working. Returns the logged-in username if authenticated.",
27057
27267
  category: "git",
27058
27268
  parameters: z.object({
27059
27269
  cwd: z.string().optional()
@@ -27073,7 +27283,7 @@ var ghCheckAuthTool = defineTool({
27073
27283
  });
27074
27284
  var ghRepoInfoTool = defineTool({
27075
27285
  name: "gh_repo_info",
27076
- description: "Get GitHub repository information (name, default branch, URL).",
27286
+ description: "Get the remote GitHub repository's name, owner, default branch, and URL from within the current git working directory. Use before creating PRs to confirm the target repo. Requires gh_check_auth to pass first.",
27077
27287
  category: "git",
27078
27288
  parameters: z.object({
27079
27289
  cwd: z.string().optional()
@@ -27095,7 +27305,7 @@ var ghRepoInfoTool = defineTool({
27095
27305
  });
27096
27306
  var ghPrCreateTool = defineTool({
27097
27307
  name: "gh_pr_create",
27098
- description: "Create a GitHub pull request.",
27308
+ description: "Open a pull request on GitHub from the current branch. Requires commits to be pushed first (use git_push with setUpstream: true). Do NOT use this if a PR for this branch already exists \u2014 use gh_pr_list to check first. Use draft: true for work in progress.",
27099
27309
  category: "git",
27100
27310
  parameters: z.object({
27101
27311
  title: z.string().describe("PR title"),
@@ -27119,7 +27329,7 @@ var ghPrCreateTool = defineTool({
27119
27329
  });
27120
27330
  var ghPrMergeTool = defineTool({
27121
27331
  name: "gh_pr_merge",
27122
- description: "Merge a GitHub pull request.",
27332
+ description: "Merge a pull request into its base branch. Use squash (default) for feature branches to keep history clean. Always confirm with gh_pr_checks first to ensure CI passed. Do NOT merge if anyFailed is true.",
27123
27333
  category: "git",
27124
27334
  parameters: z.object({
27125
27335
  number: z.number().describe("PR number"),
@@ -27140,7 +27350,7 @@ var ghPrMergeTool = defineTool({
27140
27350
  });
27141
27351
  var ghPrChecksTool = defineTool({
27142
27352
  name: "gh_pr_checks",
27143
- description: "Get CI check statuses for a pull request.",
27353
+ description: "Poll the CI check results for a pull request \u2014 returns pass/fail/pending per check and convenience flags (allPassed, anyFailed). Call this after pushing to confirm CI is green before merging. Check anyPending to know if results are still arriving.",
27144
27354
  category: "git",
27145
27355
  parameters: z.object({
27146
27356
  number: z.number().describe("PR number"),
@@ -27174,7 +27384,7 @@ var ghPrChecksTool = defineTool({
27174
27384
  });
27175
27385
  var ghPrListTool = defineTool({
27176
27386
  name: "gh_pr_list",
27177
- description: "List pull requests, optionally filtered by head branch.",
27387
+ description: "List open (or all) pull requests for this repository, optionally filtered to a specific branch. Use before gh_pr_create to ensure a PR for the current branch doesn't already exist. Returns PR number, title, URL, and state.",
27178
27388
  category: "git",
27179
27389
  parameters: z.object({
27180
27390
  head: z.string().optional().describe("Filter by head branch name"),
@@ -27191,7 +27401,7 @@ var ghPrListTool = defineTool({
27191
27401
  });
27192
27402
  var ghReleaseCreateTool = defineTool({
27193
27403
  name: "gh_release_create",
27194
- description: "Create a GitHub release with notes.",
27404
+ description: "Publish a versioned GitHub release attached to a tag. The tag must already exist in the repo (push it with git_push first). Provide markdown release notes. Use prerelease: true for release candidates or beta builds.",
27195
27405
  category: "git",
27196
27406
  parameters: z.object({
27197
27407
  tag: z.string().describe("Tag name (e.g., v1.2.3)"),