@corbat-tech/coco 2.28.0 → 2.28.1

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
@@ -29710,8 +29710,7 @@ var PROVIDER_DEFINITIONS = {
29710
29710
  name: "Gemini 3 Pro (Preview)",
29711
29711
  description: "Most capable Vertex Gemini 3 model (preview)",
29712
29712
  contextWindow: 1048576,
29713
- maxOutputTokens: 65536,
29714
- recommended: true
29713
+ maxOutputTokens: 65536
29715
29714
  },
29716
29715
  {
29717
29716
  id: "gemini-3-flash-preview",
@@ -29725,7 +29724,8 @@ var PROVIDER_DEFINITIONS = {
29725
29724
  name: "Gemini 2.5 Pro",
29726
29725
  description: "Stable high-quality Vertex model for coding and complex reasoning",
29727
29726
  contextWindow: 1048576,
29728
- maxOutputTokens: 65536
29727
+ maxOutputTokens: 65536,
29728
+ recommended: true
29729
29729
  },
29730
29730
  {
29731
29731
  id: "gemini-2.5-flash",
@@ -35948,7 +35948,7 @@ Using existing API key...`));
35948
35948
  }
35949
35949
  const rememberedModel = await getLastUsedModel(newProvider.id);
35950
35950
  const recommendedModel = getRecommendedModel(newProvider.id);
35951
- const newModel = rememberedModel || recommendedModel?.id || newProvider.models[0]?.id || "";
35951
+ let newModel = rememberedModel || recommendedModel?.id || newProvider.models[0]?.id || "";
35952
35952
  const resolvedVertexProject = newProvider.id === "vertex" ? (vertexSettings?.project ?? session.config.provider.project ?? process.env["VERTEX_PROJECT"] ?? process.env["GOOGLE_CLOUD_PROJECT"] ?? process.env["GCLOUD_PROJECT"] ?? "").trim() : void 0;
35953
35953
  const resolvedVertexLocation = newProvider.id === "vertex" ? (vertexSettings?.location ?? session.config.provider.location ?? process.env["VERTEX_LOCATION"] ?? process.env["GOOGLE_CLOUD_LOCATION"] ?? "global").trim() : void 0;
35954
35954
  const spinner18 = p26.spinner();
@@ -35959,7 +35959,31 @@ Using existing API key...`));
35959
35959
  project: resolvedVertexProject,
35960
35960
  location: resolvedVertexLocation
35961
35961
  });
35962
- const available = await testProvider.isAvailable();
35962
+ let available = await testProvider.isAvailable();
35963
+ if (!available && newProvider.id === "vertex") {
35964
+ const fallbackModels = ["gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.0-flash-001"].filter(
35965
+ (modelId) => modelId !== newModel
35966
+ );
35967
+ for (const fallbackModel of fallbackModels) {
35968
+ const fallbackProvider = await createProvider(internalProviderId, {
35969
+ model: fallbackModel,
35970
+ project: resolvedVertexProject,
35971
+ location: resolvedVertexLocation
35972
+ });
35973
+ const fallbackAvailable = await fallbackProvider.isAvailable();
35974
+ if (fallbackAvailable) {
35975
+ newModel = fallbackModel;
35976
+ available = true;
35977
+ console.log(
35978
+ chalk.yellow(
35979
+ `
35980
+ \u26A0\uFE0F The selected Vertex model was not available. Using fallback model: ${fallbackModel}`
35981
+ )
35982
+ );
35983
+ break;
35984
+ }
35985
+ }
35986
+ }
35963
35987
  if (!available) {
35964
35988
  spinner18.stop(chalk.red("Connection failed"));
35965
35989
  console.log(chalk.red(`
@@ -53296,6 +53320,30 @@ async function executeAgentTurn(session, userMessage, provider, toolRegistry, op
53296
53320
  [... ${omitted.toLocaleString()} characters omitted \u2014 use read_file with offset/limit to retrieve more of '${toolName}' output ...]
53297
53321
  ${tail}`;
53298
53322
  }
53323
+ function stableSerialize(value) {
53324
+ if (value === null || typeof value !== "object") {
53325
+ try {
53326
+ return JSON.stringify(value);
53327
+ } catch {
53328
+ return "null";
53329
+ }
53330
+ }
53331
+ if (Array.isArray(value)) {
53332
+ return `[${value.map((item) => stableSerialize(item)).join(",")}]`;
53333
+ }
53334
+ const objectValue = value;
53335
+ const keys = Object.keys(objectValue).sort();
53336
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${stableSerialize(objectValue[key])}`).join(",")}}`;
53337
+ }
53338
+ function getToolCallDedupeFingerprint(toolCall) {
53339
+ if (toolCall.name === "bash_exec") {
53340
+ const input = toolCall.input ?? {};
53341
+ const command = String(input.command ?? "").replace(/\s+/g, " ").trim();
53342
+ const cwd = String(input.cwd ?? "").replace(/\s+/g, " ").trim();
53343
+ return `bash_exec:${command}:cwd=${cwd}`;
53344
+ }
53345
+ return `${toolCall.name}:${stableSerialize(toolCall.input ?? {})}`;
53346
+ }
53299
53347
  function shouldRecoverNoToolTurn(stopReason, content) {
53300
53348
  const trimmed = content.trim();
53301
53349
  if (stopReason === "tool_use") {
@@ -53497,13 +53545,7 @@ ${tail}`;
53497
53545
  const dedupedToolCalls = [];
53498
53546
  const seenToolCallFingerprints = /* @__PURE__ */ new Set();
53499
53547
  for (const toolCall of collectedToolCalls) {
53500
- let inputSerialized = "{}";
53501
- try {
53502
- inputSerialized = JSON.stringify(toolCall.input ?? {});
53503
- } catch {
53504
- inputSerialized = "{}";
53505
- }
53506
- const fingerprint = `${toolCall.name}:${inputSerialized}`;
53548
+ const fingerprint = getToolCallDedupeFingerprint(toolCall);
53507
53549
  if (seenToolCallFingerprints.has(fingerprint)) {
53508
53550
  continue;
53509
53551
  }