@corbat-tech/coco 2.27.4 → 2.27.5

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.d.ts CHANGED
@@ -963,6 +963,8 @@ interface ToolUseContent {
963
963
  id: string;
964
964
  name: string;
965
965
  input: Record<string, unknown>;
966
+ /** Gemini-specific: preserve function-call thought signature across tool turns */
967
+ geminiThoughtSignature?: string;
966
968
  }
967
969
  /**
968
970
  * Tool result content block
@@ -999,6 +1001,8 @@ interface ToolCall {
999
1001
  id: string;
1000
1002
  name: string;
1001
1003
  input: Record<string, unknown>;
1004
+ /** Gemini-specific: preserve function-call thought signature across tool turns */
1005
+ geminiThoughtSignature?: string;
1002
1006
  }
1003
1007
  /**
1004
1008
  * Chat options
package/dist/index.js CHANGED
@@ -8,11 +8,11 @@ import fs16__default, { access, readFile, readdir, writeFile, mkdir } from 'fs/p
8
8
  import { randomUUID, randomBytes, createHash } from 'crypto';
9
9
  import * as http from 'http';
10
10
  import { fileURLToPath, URL as URL$1 } from 'url';
11
+ import { exec, execFile, execSync, spawn } from 'child_process';
12
+ import { promisify } from 'util';
11
13
  import { z } from 'zod';
12
14
  import * as p4 from '@clack/prompts';
13
15
  import chalk5 from 'chalk';
14
- import { exec, execFile, execSync, spawn } from 'child_process';
15
- import { promisify } from 'util';
16
16
  import { homedir } from 'os';
17
17
  import JSON5 from 'json5';
18
18
  import { execa } from 'execa';
@@ -676,6 +676,15 @@ async function exchangeForCopilotToken(githubToken) {
676
676
  }
677
677
  return await response.json();
678
678
  }
679
+ async function getGitHubCliToken() {
680
+ try {
681
+ const { stdout } = await execFileAsync("gh", ["auth", "token"], { timeout: 5e3 });
682
+ const token = stdout.trim();
683
+ return token.length > 0 ? token : null;
684
+ } catch {
685
+ return null;
686
+ }
687
+ }
679
688
  function getCopilotBaseUrl(accountType) {
680
689
  if (accountType && accountType in COPILOT_BASE_URLS) {
681
690
  return COPILOT_BASE_URLS[accountType];
@@ -713,10 +722,11 @@ function isCopilotTokenExpired(creds) {
713
722
  }
714
723
  async function getValidCopilotToken() {
715
724
  const creds = await loadCopilotCredentials();
716
- if (!creds) return null;
717
- const envToken = process.env["GITHUB_TOKEN"] || process.env["GH_TOKEN"];
718
- const githubToken = envToken || creds.githubToken;
719
- if (!isCopilotTokenExpired(creds) && creds.copilotToken) {
725
+ const envToken = process.env["COPILOT_GITHUB_TOKEN"] || process.env["GH_TOKEN"] || process.env["GITHUB_TOKEN"];
726
+ const fallbackGhToken = await getGitHubCliToken();
727
+ const githubToken = envToken || creds?.githubToken || fallbackGhToken;
728
+ if (!githubToken) return null;
729
+ if (creds && !isCopilotTokenExpired(creds) && creds.copilotToken) {
720
730
  return {
721
731
  token: creds.copilotToken,
722
732
  baseUrl: getCopilotBaseUrl(creds.accountType),
@@ -726,11 +736,11 @@ async function getValidCopilotToken() {
726
736
  try {
727
737
  const copilotToken = await exchangeForCopilotToken(githubToken);
728
738
  const updatedCreds = {
729
- ...creds,
730
- githubToken: creds.githubToken,
739
+ ...creds ?? { githubToken },
740
+ githubToken: creds?.githubToken ?? githubToken,
731
741
  copilotToken: copilotToken.token,
732
742
  copilotTokenExpiresAt: copilotToken.expires_at * 1e3,
733
- accountType: copilotToken.annotations?.copilot_plan ?? creds.accountType
743
+ accountType: copilotToken.annotations?.copilot_plan ?? creds?.accountType
734
744
  };
735
745
  await saveCopilotCredentials(updatedCreds);
736
746
  return {
@@ -746,7 +756,7 @@ async function getValidCopilotToken() {
746
756
  throw error;
747
757
  }
748
758
  }
749
- var COPILOT_TOKEN_URL, COPILOT_BASE_URLS, DEFAULT_COPILOT_BASE_URL, REFRESH_BUFFER_MS, CopilotAuthError, CopilotCredentialsSchema;
759
+ var COPILOT_TOKEN_URL, COPILOT_BASE_URLS, DEFAULT_COPILOT_BASE_URL, REFRESH_BUFFER_MS, execFileAsync, CopilotAuthError, CopilotCredentialsSchema;
750
760
  var init_copilot = __esm({
751
761
  "src/auth/copilot.ts"() {
752
762
  COPILOT_TOKEN_URL = "https://api.github.com/copilot_internal/v2/token";
@@ -757,6 +767,7 @@ var init_copilot = __esm({
757
767
  };
758
768
  DEFAULT_COPILOT_BASE_URL = "https://api.githubcopilot.com";
759
769
  REFRESH_BUFFER_MS = 6e4;
770
+ execFileAsync = promisify(execFile);
760
771
  CopilotAuthError = class extends Error {
761
772
  constructor(message, permanent) {
762
773
  super(message);
@@ -1482,7 +1493,7 @@ function getDefaultModel(provider) {
1482
1493
  case "anthropic":
1483
1494
  return process.env["ANTHROPIC_MODEL"] ?? "claude-opus-4-6";
1484
1495
  case "openai":
1485
- return process.env["OPENAI_MODEL"] ?? "gpt-5.4-codex";
1496
+ return process.env["OPENAI_MODEL"] ?? "gpt-5.3-codex";
1486
1497
  case "gemini":
1487
1498
  return process.env["GEMINI_MODEL"] ?? "gemini-3.1-pro-preview";
1488
1499
  case "vertex":
@@ -14107,7 +14118,7 @@ var ResponsesToolCallAssembler = class {
14107
14118
  };
14108
14119
 
14109
14120
  // src/providers/openai.ts
14110
- var DEFAULT_MODEL2 = "gpt-5.4-codex";
14121
+ var DEFAULT_MODEL2 = "gpt-5.3-codex";
14111
14122
  var CONTEXT_WINDOWS2 = {
14112
14123
  // OpenAI models
14113
14124
  "gpt-4o": 128e3,
@@ -15313,7 +15324,7 @@ function createKimiProvider(config) {
15313
15324
  init_errors();
15314
15325
  init_auth();
15315
15326
  var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
15316
- var DEFAULT_MODEL3 = "gpt-5.4-codex";
15327
+ var DEFAULT_MODEL3 = "gpt-5.3-codex";
15317
15328
  var CONTEXT_WINDOWS3 = {
15318
15329
  "gpt-5.4-codex": 2e5,
15319
15330
  "gpt-5.3-codex": 2e5,
@@ -16089,6 +16100,7 @@ var CopilotProvider = class extends OpenAIProvider {
16089
16100
  // src/providers/gemini.ts
16090
16101
  init_errors();
16091
16102
  var DEFAULT_MODEL5 = "gemini-3.1-pro-preview";
16103
+ var SKIP_THOUGHT_SIGNATURE_VALIDATOR = "skip_thought_signature_validator";
16092
16104
  var CONTEXT_WINDOWS5 = {
16093
16105
  "gemini-3.1-pro-preview": 1e6,
16094
16106
  "gemini-3.1-flash-lite-preview": 1e6,
@@ -16181,30 +16193,29 @@ var GeminiProvider = class {
16181
16193
  if (text) {
16182
16194
  yield { type: "text", text };
16183
16195
  }
16184
- const functionCalls = this.extractFunctionCalls(chunk);
16185
- for (const functionCall of functionCalls) {
16186
- const toolCallId = functionCall.id ?? `gemini_call_${++fallbackToolCounter}`;
16196
+ const toolCalls = this.extractToolCalls(chunk, { includeLegacyFunctionCalls: true });
16197
+ for (const toolCall of toolCalls) {
16198
+ const toolCallId = toolCall.id ?? `gemini_call_${++fallbackToolCounter}`;
16187
16199
  if (emittedToolIds.has(toolCallId)) continue;
16188
16200
  emittedToolIds.add(toolCallId);
16189
- const toolCall = {
16190
- id: toolCallId,
16191
- name: functionCall.name ?? "unknown_function",
16192
- input: functionCall.args ?? {}
16201
+ const normalizedToolCall = {
16202
+ ...toolCall,
16203
+ id: toolCallId
16193
16204
  };
16194
16205
  yield {
16195
16206
  type: "tool_use_start",
16196
16207
  toolCall: {
16197
- id: toolCall.id,
16198
- name: toolCall.name
16208
+ id: normalizedToolCall.id,
16209
+ name: normalizedToolCall.name
16199
16210
  }
16200
16211
  };
16201
16212
  yield {
16202
16213
  type: "tool_use_end",
16203
- toolCall
16214
+ toolCall: normalizedToolCall
16204
16215
  };
16205
16216
  }
16206
16217
  const finishReason = chunk.candidates?.[0]?.finishReason;
16207
- if (functionCalls.length > 0) {
16218
+ if (toolCalls.length > 0) {
16208
16219
  streamStopReason = "tool_use";
16209
16220
  } else if (finishReason) {
16210
16221
  streamStopReason = this.mapFinishReason(finishReason);
@@ -16328,13 +16339,18 @@ var GeminiProvider = class {
16328
16339
  });
16329
16340
  } else if (block.type === "tool_use") {
16330
16341
  const toolUse = block;
16331
- parts.push({
16332
- functionCall: {
16333
- id: toolUse.id,
16334
- name: toolUse.name,
16335
- args: toolUse.input
16336
- }
16337
- });
16342
+ const thoughtSignature = toolUse.geminiThoughtSignature ?? SKIP_THOUGHT_SIGNATURE_VALIDATOR;
16343
+ const functionCall = {
16344
+ id: toolUse.id,
16345
+ name: toolUse.name,
16346
+ args: toolUse.input
16347
+ };
16348
+ const part = {
16349
+ functionCall,
16350
+ thoughtSignature,
16351
+ thought_signature: thoughtSignature
16352
+ };
16353
+ parts.push(part);
16338
16354
  }
16339
16355
  }
16340
16356
  return parts.length > 0 ? parts : [{ text: "" }];
@@ -16358,13 +16374,31 @@ var GeminiProvider = class {
16358
16374
  allowedFunctionNames: [choice.name]
16359
16375
  };
16360
16376
  }
16361
- extractFunctionCalls(response) {
16362
- if (response.functionCalls && response.functionCalls.length > 0) {
16363
- return response.functionCalls;
16377
+ extractThoughtSignatureFromPart(part) {
16378
+ const withSignature = part;
16379
+ return withSignature.thoughtSignature ?? withSignature.thought_signature ?? withSignature.functionCall?.thoughtSignature ?? withSignature.functionCall?.thought_signature;
16380
+ }
16381
+ extractToolCalls(response, options) {
16382
+ const toolCallsFromParts = (response.candidates?.[0]?.content?.parts ?? []).filter((part) => !!part.functionCall).map((part, index) => ({
16383
+ id: part.functionCall.id ?? `gemini_call_${index + 1}`,
16384
+ name: part.functionCall.name ?? "unknown_function",
16385
+ input: part.functionCall.args ?? {},
16386
+ geminiThoughtSignature: this.extractThoughtSignatureFromPart(part)
16387
+ }));
16388
+ if (toolCallsFromParts.length > 0) {
16389
+ return toolCallsFromParts;
16364
16390
  }
16365
- const candidate = response.candidates?.[0];
16366
- const parts = candidate?.content?.parts ?? [];
16367
- return parts.filter((part) => !!part.functionCall).map((part) => part.functionCall).filter(Boolean);
16391
+ if (!options?.includeLegacyFunctionCalls || !response.functionCalls?.length) {
16392
+ return [];
16393
+ }
16394
+ return response.functionCalls.map((functionCall, index) => ({
16395
+ id: functionCall.id ?? `gemini_call_${index + 1}`,
16396
+ name: functionCall.name ?? "unknown_function",
16397
+ input: functionCall.args ?? {},
16398
+ geminiThoughtSignature: this.extractThoughtSignatureFromPart({
16399
+ functionCall
16400
+ })
16401
+ }));
16368
16402
  }
16369
16403
  parseResponse(response, model) {
16370
16404
  const usage = response.usageMetadata;
@@ -16381,11 +16415,7 @@ var GeminiProvider = class {
16381
16415
  }
16382
16416
  parseResponseWithTools(response, model) {
16383
16417
  const usage = response.usageMetadata;
16384
- const toolCalls = this.extractFunctionCalls(response).map((functionCall, index) => ({
16385
- id: functionCall.id ?? `gemini_call_${index + 1}`,
16386
- name: functionCall.name ?? "unknown_function",
16387
- input: functionCall.args ?? {}
16388
- }));
16418
+ const toolCalls = this.extractToolCalls(response, { includeLegacyFunctionCalls: true });
16389
16419
  return {
16390
16420
  id: `gemini-${Date.now()}`,
16391
16421
  content: response.text ?? "",
@@ -16437,12 +16467,22 @@ var DEFAULT_MODEL6 = "gemini-2.5-pro";
16437
16467
  var DEFAULT_BASE_URL = "https://aiplatform.googleapis.com/v1";
16438
16468
  var DEFAULT_LOCATION = "global";
16439
16469
  var CONTEXT_WINDOWS6 = {
16470
+ "gemini-3-pro-preview": 1048576,
16471
+ "gemini-3-flash-preview": 1048576,
16440
16472
  "gemini-2.5-pro": 1048576,
16441
16473
  "gemini-2.5-flash": 1048576,
16442
16474
  "gemini-2.5-flash-lite": 1048576,
16443
16475
  "gemini-2.0-flash-001": 1048576,
16444
16476
  "gemini-2.0-flash-lite-001": 1048576
16445
16477
  };
16478
+ var SKIP_THOUGHT_SIGNATURE_VALIDATOR2 = "skip_thought_signature_validator";
16479
+ function extractSseEventData(rawEvent) {
16480
+ const dataLines = rawEvent.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).filter(Boolean);
16481
+ if (dataLines.length === 0) {
16482
+ return null;
16483
+ }
16484
+ return dataLines.join("\n");
16485
+ }
16446
16486
  var VertexProvider = class {
16447
16487
  id = "vertex";
16448
16488
  name = "Google Vertex AI Gemini";
@@ -16527,12 +16567,14 @@ var VertexProvider = class {
16527
16567
  }
16528
16568
  if (part.functionCall) {
16529
16569
  streamToolCallCounter++;
16570
+ const geminiThoughtSignature = part.thoughtSignature ?? part.thought_signature ?? part.functionCall.thoughtSignature ?? part.functionCall.thought_signature;
16530
16571
  yield {
16531
16572
  type: "tool_use_start",
16532
16573
  toolCall: {
16533
16574
  id: `vertex_call_${streamToolCallCounter}`,
16534
16575
  name: part.functionCall.name,
16535
- input: part.functionCall.args ?? {}
16576
+ input: part.functionCall.args ?? {},
16577
+ geminiThoughtSignature
16536
16578
  }
16537
16579
  };
16538
16580
  yield {
@@ -16540,7 +16582,8 @@ var VertexProvider = class {
16540
16582
  toolCall: {
16541
16583
  id: `vertex_call_${streamToolCallCounter}`,
16542
16584
  name: part.functionCall.name,
16543
- input: part.functionCall.args ?? {}
16585
+ input: part.functionCall.args ?? {},
16586
+ geminiThoughtSignature
16544
16587
  }
16545
16588
  };
16546
16589
  }
@@ -16673,11 +16716,14 @@ var VertexProvider = class {
16673
16716
  });
16674
16717
  } else if (block.type === "tool_use") {
16675
16718
  const toolUse = block;
16719
+ const thoughtSignature = toolUse.geminiThoughtSignature ?? SKIP_THOUGHT_SIGNATURE_VALIDATOR2;
16676
16720
  parts.push({
16677
16721
  functionCall: {
16678
16722
  name: toolUse.name,
16679
16723
  args: toolUse.input
16680
- }
16724
+ },
16725
+ thoughtSignature,
16726
+ thought_signature: thoughtSignature
16681
16727
  });
16682
16728
  }
16683
16729
  }
@@ -16769,22 +16815,27 @@ var VertexProvider = class {
16769
16815
  if (done) break;
16770
16816
  buffer += decoder.decode(value, { stream: true });
16771
16817
  while (true) {
16772
- const eventBoundary = buffer.indexOf("\n\n");
16773
- if (eventBoundary === -1) break;
16774
- const rawEvent = buffer.slice(0, eventBoundary);
16775
- buffer = buffer.slice(eventBoundary + 2);
16776
- const dataLines = rawEvent.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).filter(Boolean);
16777
- for (const line of dataLines) {
16778
- if (line === "[DONE]") return;
16779
- yield JSON.parse(line);
16818
+ const boundaryMatch = /\r?\n\r?\n/.exec(buffer);
16819
+ if (!boundaryMatch || boundaryMatch.index === void 0) break;
16820
+ const rawEvent = buffer.slice(0, boundaryMatch.index);
16821
+ buffer = buffer.slice(boundaryMatch.index + boundaryMatch[0].length);
16822
+ const data = extractSseEventData(rawEvent);
16823
+ if (!data || data === "[DONE]") {
16824
+ if (data === "[DONE]") return;
16825
+ continue;
16826
+ }
16827
+ try {
16828
+ yield JSON.parse(data);
16829
+ } catch {
16830
+ continue;
16780
16831
  }
16781
16832
  }
16782
16833
  }
16783
- const trailing = buffer.trim();
16784
- if (trailing.startsWith("data:")) {
16785
- const line = trailing.slice(5).trim();
16786
- if (line && line !== "[DONE]") {
16787
- yield JSON.parse(line);
16834
+ const trailingData = extractSseEventData(buffer.trim());
16835
+ if (trailingData && trailingData !== "[DONE]") {
16836
+ try {
16837
+ yield JSON.parse(trailingData);
16838
+ } catch {
16788
16839
  }
16789
16840
  }
16790
16841
  }
@@ -16817,7 +16868,8 @@ var VertexProvider = class {
16817
16868
  toolCalls.push({
16818
16869
  id: `vertex_call_${toolIndex}`,
16819
16870
  name: part.functionCall.name,
16820
- input: part.functionCall.args ?? {}
16871
+ input: part.functionCall.args ?? {},
16872
+ geminiThoughtSignature: part.thoughtSignature ?? part.thought_signature ?? part.functionCall.thoughtSignature ?? part.functionCall.thought_signature
16821
16873
  });
16822
16874
  }
16823
16875
  }
@@ -21448,9 +21500,6 @@ var buildTools = [
21448
21500
  runGradleTool
21449
21501
  ];
21450
21502
 
21451
- // src/cli/repl/recommended-permissions.ts
21452
- init_paths();
21453
-
21454
21503
  // src/cli/repl/session.ts
21455
21504
  init_env();
21456
21505
  init_paths();
@@ -21485,6 +21534,7 @@ z.object({
21485
21534
  // src/cli/repl/session.ts
21486
21535
  path17__default.dirname(CONFIG_PATHS.trustedTools);
21487
21536
  CONFIG_PATHS.trustedTools;
21537
+ path17__default.join(".coco", "trusted-tools.json");
21488
21538
 
21489
21539
  // src/cli/repl/recommended-permissions.ts
21490
21540
  var RECOMMENDED_GLOBAL = [
@@ -27503,7 +27553,7 @@ init_errors2();
27503
27553
  init_callback_server();
27504
27554
  init_paths();
27505
27555
  init_logger();
27506
- var execFileAsync2 = promisify(execFile);
27556
+ var execFileAsync3 = promisify(execFile);
27507
27557
  var TOKEN_STORE_PATH = path17__default.join(CONFIG_PATHS.tokens, "mcp-oauth.json");
27508
27558
  var OAUTH_TIMEOUT_MS = 5 * 60 * 1e3;
27509
27559
  var logger = getLogger();
@@ -27600,7 +27650,7 @@ async function openBrowser(url) {
27600
27650
  }
27601
27651
  for (const { cmd, args } of commands) {
27602
27652
  try {
27603
- await execFileAsync2(cmd, args);
27653
+ await execFileAsync3(cmd, args);
27604
27654
  return true;
27605
27655
  } catch {
27606
27656
  continue;