claudish 7.40.0 → 7.42.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.
Files changed (2) hide show
  1. package/dist/index.js +1866 -424
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -729,7 +729,7 @@ var init_onepassword_config = __esm(() => {
729
729
  });
730
730
 
731
731
  // src/version.ts
732
- var VERSION = "7.40.0";
732
+ var VERSION = "7.42.0";
733
733
 
734
734
  // src/logger.ts
735
735
  var exports_logger = {};
@@ -27958,6 +27958,26 @@ var init_provider_definitions = __esm(() => {
27958
27958
  isDirectApi: true,
27959
27959
  description: "Antigravity subscription (ag@; go@ deprecated)"
27960
27960
  },
27961
+ {
27962
+ name: "devin",
27963
+ displayName: "Devin",
27964
+ transport: "devin",
27965
+ baseUrl: "https://server.codeium.com",
27966
+ baseUrlEnvVars: ["WINDSURF_API_SERVER_URL"],
27967
+ apiPath: "/exa.api_server_pb.ApiServerService/GetChatMessage",
27968
+ apiKeyEnvVar: "",
27969
+ apiKeyDescription: "Devin CLI session token (~/.local/share/devin/credentials.toml)",
27970
+ apiKeyUrl: "https://devin.ai/",
27971
+ shortcuts: ["dv", "devin"],
27972
+ shortestPrefix: "dv",
27973
+ legacyPrefixes: [
27974
+ { prefix: "dv/", stripPrefix: true },
27975
+ { prefix: "devin/", stripPrefix: true }
27976
+ ],
27977
+ modelDiscovery: { path: "", format: "devin-connect" },
27978
+ isDirectApi: true,
27979
+ description: "Devin subscription (dv@, devin@)"
27980
+ },
27961
27981
  {
27962
27982
  name: "gemini-codeassist",
27963
27983
  displayName: "Gemini Code Assist",
@@ -28570,7 +28590,8 @@ var init_remote_provider_types = __esm(() => {
28570
28590
  "minimax-coding",
28571
28591
  "kimi-coding",
28572
28592
  "glm-coding",
28573
- "qwen-cloud"
28593
+ "qwen-cloud",
28594
+ "devin"
28574
28595
  ]);
28575
28596
  PROVIDER_ALIAS = {
28576
28597
  google: "gemini",
@@ -29275,7 +29296,7 @@ class BaseAPIFormat {
29275
29296
  }
29276
29297
  }
29277
29298
  }
29278
- var EFFORT_ORDER, NON_ANTHROPIC_REASONING_FIELDS, DefaultAPIFormat;
29299
+ var EFFORT_ORDER, EFFORT_LEVELS, NON_ANTHROPIC_REASONING_FIELDS, DefaultAPIFormat;
29279
29300
  var init_base_api_format = __esm(() => {
29280
29301
  init_remote_provider_types();
29281
29302
  init_logger();
@@ -29283,6 +29304,7 @@ var init_base_api_format = __esm(() => {
29283
29304
  init_tool_name_utils();
29284
29305
  init_openai_tools();
29285
29306
  EFFORT_ORDER = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
29307
+ EFFORT_LEVELS = EFFORT_ORDER;
29286
29308
  NON_ANTHROPIC_REASONING_FIELDS = [
29287
29309
  "reasoning_effort",
29288
29310
  "enable_thinking",
@@ -31551,19 +31573,101 @@ var init_codex_credential = __esm(() => {
31551
31573
  init_api_key_credential();
31552
31574
  });
31553
31575
 
31554
- // src/auth/oauth-registry.ts
31555
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
31576
+ // src/providers/devin/devin-credentials.ts
31577
+ import { readFileSync as readFileSync9 } from "fs";
31556
31578
  import { homedir as homedir13 } from "os";
31557
31579
  import { join as join13 } from "path";
31580
+ function devinCredentialsPath() {
31581
+ return credentialsPathOverride ?? join13(homedir13(), ".local", "share", "devin", "credentials.toml");
31582
+ }
31583
+ function readTomlString(source, key) {
31584
+ const match = source.match(new RegExp(`^\\s*${key}\\s*=\\s*"([^"]*)"`, "m"));
31585
+ const value = match?.[1]?.trim();
31586
+ return value ? value : undefined;
31587
+ }
31588
+ function readCredentialsFile() {
31589
+ const path = devinCredentialsPath();
31590
+ if (fileCache && fileCache.path === path)
31591
+ return fileCache.value;
31592
+ let value = {};
31593
+ try {
31594
+ const source = readFileSync9(path, "utf8");
31595
+ value = {
31596
+ apiKey: readTomlString(source, "windsurf_api_key"),
31597
+ serverUrl: readTomlString(source, "api_server_url")
31598
+ };
31599
+ } catch {}
31600
+ fileCache = { path, value };
31601
+ return value;
31602
+ }
31603
+ function readDevinApiKey() {
31604
+ const fromEnv = realValue(process.env[DEVIN_API_KEY_ENV]);
31605
+ if (fromEnv?.trim())
31606
+ return fromEnv.trim();
31607
+ const fromConfig = realValue(getApiKey(DEVIN_API_KEY_ENV));
31608
+ if (fromConfig?.trim())
31609
+ return fromConfig.trim();
31610
+ const fromFile = readCredentialsFile().apiKey;
31611
+ return fromFile?.trim() ? fromFile.trim() : undefined;
31612
+ }
31613
+ function hasDevinCredentials() {
31614
+ return readDevinApiKey() !== undefined;
31615
+ }
31616
+ function readDevinServerUrl() {
31617
+ const fromEnv = realValue(process.env[DEVIN_SERVER_URL_ENV])?.trim();
31618
+ const url2 = fromEnv || readCredentialsFile().serverUrl || DEFAULT_DEVIN_SERVER_URL;
31619
+ return url2.replace(/\/+$/, "");
31620
+ }
31621
+ var DEVIN_API_KEY_ENV = "WINDSURF_API_KEY", DEVIN_SERVER_URL_ENV = "WINDSURF_API_SERVER_URL", DEFAULT_DEVIN_SERVER_URL = "https://server.codeium.com", credentialsPathOverride = null, fileCache = null;
31622
+ var init_devin_credentials = __esm(() => {
31623
+ init_env_placeholder();
31624
+ init_profile_config();
31625
+ });
31626
+
31627
+ // src/auth/credentials/devin-credential.ts
31628
+ function devinAuthHeaders(apiKey) {
31629
+ return {
31630
+ authorization: `Basic ${apiKey}-${apiKey}`,
31631
+ "connect-protocol-version": "1"
31632
+ };
31633
+ }
31634
+
31635
+ class DevinCredentialProvider {
31636
+ catalogName = "devin";
31637
+ async isAvailable() {
31638
+ try {
31639
+ return hasDevinCredentials();
31640
+ } catch {
31641
+ return false;
31642
+ }
31643
+ }
31644
+ async getRequestAuth() {
31645
+ const apiKey = readDevinApiKey();
31646
+ if (!apiKey) {
31647
+ const err = new Error("No Devin credential. Sign in with the Devin CLI (`devin login`), or set WINDSURF_API_KEY. " + "Expected ~/.local/share/devin/credentials.toml.");
31648
+ err.terminal = true;
31649
+ throw err;
31650
+ }
31651
+ return { headers: devinAuthHeaders(apiKey) };
31652
+ }
31653
+ }
31654
+ var init_devin_credential = __esm(() => {
31655
+ init_devin_credentials();
31656
+ });
31657
+
31658
+ // src/auth/oauth-registry.ts
31659
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
31660
+ import { homedir as homedir14 } from "os";
31661
+ import { join as join14 } from "path";
31558
31662
  function hasValidOAuthCredentials(descriptor) {
31559
- const credPath = join13(homedir13(), ".claudish", descriptor.credentialFile);
31663
+ const credPath = join14(homedir14(), ".claudish", descriptor.credentialFile);
31560
31664
  if (!existsSync11(credPath))
31561
31665
  return false;
31562
31666
  if (descriptor.validationMode === "file-exists") {
31563
31667
  return true;
31564
31668
  }
31565
31669
  try {
31566
- const data = JSON.parse(readFileSync9(credPath, "utf-8"));
31670
+ const data = JSON.parse(readFileSync10(credPath, "utf-8"));
31567
31671
  if (!data.access_token)
31568
31672
  return false;
31569
31673
  if (data.refresh_token)
@@ -31668,9 +31772,9 @@ var init_gemini_credential = __esm(() => {
31668
31772
  // src/auth/kimi-oauth.ts
31669
31773
  import { exec as exec3 } from "child_process";
31670
31774
  import { randomBytes as randomBytes3 } from "crypto";
31671
- import { closeSync as closeSync4, existsSync as existsSync12, openSync as openSync4, readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeSync as writeSync4 } from "fs";
31672
- import { homedir as homedir14, hostname as hostname3, platform, release as release2 } from "os";
31673
- import { join as join14 } from "path";
31775
+ import { closeSync as closeSync4, existsSync as existsSync12, openSync as openSync4, readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeSync as writeSync4 } from "fs";
31776
+ import { homedir as homedir15, hostname as hostname3, platform, release as release2 } from "os";
31777
+ import { join as join15 } from "path";
31674
31778
  import { promisify as promisify3 } from "util";
31675
31779
 
31676
31780
  class KimiOAuth {
@@ -31698,23 +31802,23 @@ class KimiOAuth {
31698
31802
  return this.credentials !== null && !!this.credentials.refresh_token;
31699
31803
  }
31700
31804
  getCredentialsPath() {
31701
- const claudishDir = join14(homedir14(), ".claudish");
31702
- return join14(claudishDir, "kimi-oauth.json");
31805
+ const claudishDir = join15(homedir15(), ".claudish");
31806
+ return join15(claudishDir, "kimi-oauth.json");
31703
31807
  }
31704
31808
  getDeviceIdPath() {
31705
- const claudishDir = join14(homedir14(), ".claudish");
31706
- return join14(claudishDir, "kimi-device-id");
31809
+ const claudishDir = join15(homedir15(), ".claudish");
31810
+ return join15(claudishDir, "kimi-device-id");
31707
31811
  }
31708
31812
  loadOrCreateDeviceId() {
31709
31813
  const deviceIdPath = this.getDeviceIdPath();
31710
- const claudishDir = join14(homedir14(), ".claudish");
31814
+ const claudishDir = join15(homedir15(), ".claudish");
31711
31815
  if (!existsSync12(claudishDir)) {
31712
31816
  const { mkdirSync: mkdirSync7 } = __require("fs");
31713
31817
  mkdirSync7(claudishDir, { recursive: true });
31714
31818
  }
31715
31819
  if (existsSync12(deviceIdPath)) {
31716
31820
  try {
31717
- const deviceId2 = readFileSync10(deviceIdPath, "utf-8").trim();
31821
+ const deviceId2 = readFileSync11(deviceIdPath, "utf-8").trim();
31718
31822
  if (deviceId2) {
31719
31823
  return deviceId2;
31720
31824
  }
@@ -31973,7 +32077,7 @@ Details: ${e.message}`);
31973
32077
  return null;
31974
32078
  }
31975
32079
  try {
31976
- const data = readFileSync10(credPath, "utf-8");
32080
+ const data = readFileSync11(credPath, "utf-8");
31977
32081
  const credentials2 = JSON.parse(data);
31978
32082
  if (!credentials2.access_token || !credentials2.refresh_token || !credentials2.expires_at || !credentials2.scope || !credentials2.token_type) {
31979
32083
  log("[KimiOAuth] Invalid credentials file structure");
@@ -31988,7 +32092,7 @@ Details: ${e.message}`);
31988
32092
  }
31989
32093
  saveCredentials(credentials2) {
31990
32094
  const credPath = this.getCredentialsPath();
31991
- const claudishDir = join14(homedir14(), ".claudish");
32095
+ const claudishDir = join15(homedir15(), ".claudish");
31992
32096
  if (!existsSync12(claudishDir)) {
31993
32097
  const { mkdirSync: mkdirSync7 } = __require("fs");
31994
32098
  mkdirSync7(claudishDir, { recursive: true });
@@ -32164,8 +32268,8 @@ var init_native_anthropic_credential = __esm(() => {
32164
32268
  // src/auth/vertex-auth.ts
32165
32269
  import { exec as exec4 } from "child_process";
32166
32270
  import { existsSync as existsSync13 } from "fs";
32167
- import { homedir as homedir15 } from "os";
32168
- import { join as join15 } from "path";
32271
+ import { homedir as homedir16 } from "os";
32272
+ import { join as join16 } from "path";
32169
32273
  import { promisify as promisify4 } from "util";
32170
32274
 
32171
32275
  class VertexAuthManager {
@@ -32220,7 +32324,7 @@ class VertexAuthManager {
32220
32324
  }
32221
32325
  async tryADC() {
32222
32326
  try {
32223
- const adcPath = join15(homedir15(), ".config/gcloud/application_default_credentials.json");
32327
+ const adcPath = join16(homedir16(), ".config/gcloud/application_default_credentials.json");
32224
32328
  if (!existsSync13(adcPath)) {
32225
32329
  log("[VertexAuth] ADC credentials file not found");
32226
32330
  return null;
@@ -32284,7 +32388,7 @@ function validateVertexOAuthConfig() {
32284
32388
  ` + ` export VERTEX_PROJECT='your-gcp-project-id'
32285
32389
  ` + " export VERTEX_LOCATION='us-central1' # optional";
32286
32390
  }
32287
- const adcPath = join15(homedir15(), ".config/gcloud/application_default_credentials.json");
32391
+ const adcPath = join16(homedir16(), ".config/gcloud/application_default_credentials.json");
32288
32392
  const hasADC = existsSync13(adcPath);
32289
32393
  const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
32290
32394
  if (!hasADC && !hasServiceAccount) {
@@ -32405,6 +32509,7 @@ class CredentialAuthority {
32405
32509
  authority.register(makeCodexCredential(), ["openai-codex"]);
32406
32510
  authority.register(new GeminiCodeAssistCredentialProvider, ["gemini-codeassist"]);
32407
32511
  authority.register(new AntigravityCredentialProvider, ["antigravity"]);
32512
+ authority.register(new DevinCredentialProvider, ["devin"]);
32408
32513
  authority.register(makeKimiCredential(), ["kimi"]);
32409
32514
  authority.register(makeKimiCodingCredential(), ["kimi-coding"]);
32410
32515
  authority.register(new VertexCredentialProvider, ["vertex"]);
@@ -32416,6 +32521,7 @@ class CredentialAuthority {
32416
32521
  "openai-codex",
32417
32522
  "gemini-codeassist",
32418
32523
  "antigravity",
32524
+ "devin",
32419
32525
  "kimi",
32420
32526
  "kimi-coding",
32421
32527
  "vertex",
@@ -32447,6 +32553,7 @@ var init_authority = __esm(() => {
32447
32553
  init_antigravity_credential();
32448
32554
  init_api_key_credential();
32449
32555
  init_codex_credential();
32556
+ init_devin_credential();
32450
32557
  init_gemini_credential();
32451
32558
  init_kimi_credential();
32452
32559
  init_local_credential();
@@ -33282,7 +33389,8 @@ function createStreamingState() {
33282
33389
  tools: new Map,
33283
33390
  toolIds: new Set,
33284
33391
  lastActivity: Date.now(),
33285
- accumulatedText: ""
33392
+ accumulatedText: "",
33393
+ finishReason: null
33286
33394
  };
33287
33395
  }
33288
33396
  function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap, priorInputTokens, behavior) {
@@ -33440,7 +33548,12 @@ data: ${JSON.stringify(d)}
33440
33548
  send("error", { type: "error", error: { type: "api_error", message: err } });
33441
33549
  } else {
33442
33550
  const hasStructuredTools = Array.from(state.tools.values()).some((t) => t.started);
33443
- const stopReason = textToolCalls.length > 0 || hasStructuredTools ? "tool_use" : "end_turn";
33551
+ const truncated = state.finishReason === "length";
33552
+ const refused = state.finishReason === "content_filter";
33553
+ const stopReason = refused ? "refusal" : truncated ? "max_tokens" : textToolCalls.length > 0 || hasStructuredTools ? "tool_use" : "end_turn";
33554
+ if (truncated || refused) {
33555
+ log(`[Streaming] Upstream finish_reason=${state.finishReason} \u2192 stop_reason=${stopReason} (${state.accumulatedText.length} chars produced)`);
33556
+ }
33444
33557
  send("message_delta", {
33445
33558
  type: "message_delta",
33446
33559
  delta: { stop_reason: stopReason, stop_sequence: null },
@@ -33503,6 +33616,8 @@ data: ${JSON.stringify(d)}
33503
33616
  }
33504
33617
  const delta = chunk.choices?.[0]?.delta;
33505
33618
  const finishReason = chunk.choices?.[0]?.finish_reason;
33619
+ if (finishReason)
33620
+ state.finishReason = finishReason;
33506
33621
  if (delta?.content || finishReason) {
33507
33622
  log(`[Streaming] Chunk: content=${delta?.content?.length || 0} chars, finish_reason=${finishReason || "null"}`);
33508
33623
  }
@@ -33515,8 +33630,9 @@ data: ${JSON.stringify(d)}
33515
33630
  metadata: streamMetadata
33516
33631
  });
33517
33632
  }
33518
- if (delta.reasoning_content) {
33519
- behavior?.onAssistantText?.(delta.reasoning_content, "reasoning");
33633
+ const reasoningText = delta.reasoning_content || delta.reasoning;
33634
+ if (reasoningText) {
33635
+ behavior?.onAssistantText?.(reasoningText, "reasoning");
33520
33636
  state.lastActivity = Date.now();
33521
33637
  if (!state.reasoningStarted) {
33522
33638
  state.reasoningIdx = state.curIdx++;
@@ -33530,7 +33646,7 @@ data: ${JSON.stringify(d)}
33530
33646
  send("content_block_delta", {
33531
33647
  type: "content_block_delta",
33532
33648
  index: state.reasoningIdx,
33533
- delta: { type: "thinking_delta", thinking: delta.reasoning_content }
33649
+ delta: { type: "thinking_delta", thinking: reasoningText }
33534
33650
  });
33535
33651
  }
33536
33652
  const txt = delta.content || "";
@@ -33799,54 +33915,14 @@ var init_openai_compat = __esm(() => {
33799
33915
  });
33800
33916
 
33801
33917
  // src/adapters/gemini-api-format.ts
33802
- var REASONING_PATTERNS, REASONING_CONTINUATION_PATTERNS, GeminiAPIFormat;
33918
+ var GeminiAPIFormat;
33803
33919
  var init_gemini_api_format = __esm(() => {
33804
33920
  init_gemini_schema();
33805
33921
  init_openai_compat();
33806
33922
  init_logger();
33807
33923
  init_base_api_format();
33808
- REASONING_PATTERNS = [
33809
- /^Wait,?\s+I(?:'m|\s+am)\s+\w+ing\b/i,
33810
- /^Wait,?\s+(?:if|that|the|this|I\s+(?:need|should|will|have|already))/i,
33811
- /^Wait[.!]?\s*$/i,
33812
- /^Let\s+me\s+(think|check|verify|see|look|analyze|consider|first|start)/i,
33813
- /^Let's\s+(check|see|look|start|first|try|think|verify|examine|analyze)/i,
33814
- /^I\s+need\s+to\s+/i,
33815
- /^O[kK](?:ay)?[.,!]?\s*(?:so|let|I|now|first)?/i,
33816
- /^[Hh]mm+/,
33817
- /^So[,.]?\s+(?:I|let|first|now|the)/i,
33818
- /^(?:First|Next|Then|Now)[,.]?\s+(?:I|let|we)/i,
33819
- /^(?:Thinking\s+about|Considering)/i,
33820
- /^I(?:'ll|\s+will)\s+(?:first|now|start|begin|try|check|fix|look|examine|modify|create|update|read|investigate|adjust|improve|integrate|mark|also|verify|need|rethink|add|help|use|run|search|find|explore|analyze|review|test|implement|write|make|set|get|see|open|close|save|load|fetch|call|send|build|compile|execute|process|handle|parse|format|validate|clean|clear|remove|delete|move|copy|rename|install|configure|setup|initialize|prepare|work|continue|proceed|ensure|confirm)/i,
33821
- /^I\s+should\s+/i,
33822
- /^I\s+will\s+(?:first|now|start|verify|check|create|modify|look|need|also|add|help|use|run|search|find|explore|analyze|review|test|implement|write)/i,
33823
- /^(?:Debug|Checking|Verifying|Looking\s+at):/i,
33824
- /^I\s+also\s+(?:notice|need|see|want)/i,
33825
- /^The\s+(?:goal|issue|problem|idea|plan)\s+is/i,
33826
- /^In\s+the\s+(?:old|current|previous|new|existing)\s+/i,
33827
- /^`[^`]+`\s+(?:is|has|does|needs|should|will|doesn't|hasn't)/i
33828
- ];
33829
- REASONING_CONTINUATION_PATTERNS = [
33830
- /^And\s+(?:then|I|now|so)/i,
33831
- /^And\s+I(?:'ll|\s+will)/i,
33832
- /^But\s+(?:I|first|wait|actually|the|if)/i,
33833
- /^Actually[,.]?\s+/i,
33834
- /^Also[,.]?\s+(?:I|the|check|note)/i,
33835
- /^\d+\.\s+(?:I|First|Check|Run|Create|Update|Read|Modify|Add|Fix|Look)/i,
33836
- /^-\s+(?:I|First|Check|Run|Create|Update|Read|Modify|Add|Fix)/i,
33837
- /^Or\s+(?:I|just|we|maybe|perhaps)/i,
33838
- /^Since\s+(?:I|the|this|we|it)/i,
33839
- /^Because\s+(?:I|the|this|we|it)/i,
33840
- /^If\s+(?:I|the|this|we|it)\s+/i,
33841
- /^This\s+(?:is|means|requires|should|will|confirms|suggests)/i,
33842
- /^That\s+(?:means|is|should|will|explains|confirms)/i,
33843
- /^Lines?\s+\d+/i,
33844
- /^The\s+`[^`]+`\s+(?:is|has|contains|needs|should)/i
33845
- ];
33846
33924
  GeminiAPIFormat = class GeminiAPIFormat extends BaseAPIFormat {
33847
33925
  toolCallMap = new Map;
33848
- inReasoningBlock = false;
33849
- reasoningBlockDepth = 0;
33850
33926
  convertMessages(claudeRequest, _filterIdentityFn) {
33851
33927
  const messages = [];
33852
33928
  if (claudeRequest.messages) {
@@ -34056,58 +34132,12 @@ CRITICAL INSTRUCTION FOR OUTPUT FORMAT:
34056
34132
  }
34057
34133
  }
34058
34134
  processTextContent(textContent, _accumulatedText) {
34059
- if (!textContent || textContent.trim() === "") {
34060
- return { cleanedText: textContent, extractedToolCalls: [], wasTransformed: false };
34061
- }
34062
- const lines = textContent.split(`
34063
- `);
34064
- const cleanedLines = [];
34065
- let wasFiltered = false;
34066
- for (const line of lines) {
34067
- const trimmed2 = line.trim();
34068
- if (!trimmed2) {
34069
- cleanedLines.push(line);
34070
- continue;
34071
- }
34072
- if (this.isReasoningLine(trimmed2)) {
34073
- log(`[GeminiAPIFormat] Filtered reasoning: "${trimmed2.substring(0, 50)}..."`);
34074
- wasFiltered = true;
34075
- this.inReasoningBlock = true;
34076
- this.reasoningBlockDepth++;
34077
- continue;
34078
- }
34079
- if (this.inReasoningBlock && this.isReasoningContinuation(trimmed2)) {
34080
- log(`[GeminiAPIFormat] Filtered reasoning continuation: "${trimmed2.substring(0, 50)}..."`);
34081
- wasFiltered = true;
34082
- continue;
34083
- }
34084
- if (this.inReasoningBlock && trimmed2.length > 20 && !this.isReasoningContinuation(trimmed2)) {
34085
- this.inReasoningBlock = false;
34086
- this.reasoningBlockDepth = 0;
34087
- }
34088
- cleanedLines.push(line);
34089
- }
34090
- const cleanedText = cleanedLines.join(`
34091
- `);
34092
- return {
34093
- cleanedText: wasFiltered ? cleanedText : textContent,
34094
- extractedToolCalls: [],
34095
- wasTransformed: wasFiltered
34096
- };
34097
- }
34098
- isReasoningLine(line) {
34099
- return REASONING_PATTERNS.some((pattern) => pattern.test(line));
34100
- }
34101
- isReasoningContinuation(line) {
34102
- return REASONING_CONTINUATION_PATTERNS.some((pattern) => pattern.test(line));
34135
+ return { cleanedText: textContent, extractedToolCalls: [], wasTransformed: false };
34103
34136
  }
34104
34137
  getStreamFormat() {
34105
34138
  return "gemini-sse";
34106
34139
  }
34107
- reset() {
34108
- this.inReasoningBlock = false;
34109
- this.reasoningBlockDepth = 0;
34110
- }
34140
+ reset() {}
34111
34141
  getContextWindow() {
34112
34142
  return 1048576;
34113
34143
  }
@@ -34690,9 +34720,9 @@ var init_antigravity2 = __esm(() => {
34690
34720
  });
34691
34721
 
34692
34722
  // src/auth/quota/sources/codex.ts
34693
- import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
34694
- import { homedir as homedir16 } from "os";
34695
- import { join as join16 } from "path";
34723
+ import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
34724
+ import { homedir as homedir17 } from "os";
34725
+ import { join as join17 } from "path";
34696
34726
  function formatWindowMinutes(minutes) {
34697
34727
  if (!Number.isFinite(minutes) || minutes <= 0)
34698
34728
  return "";
@@ -34706,7 +34736,7 @@ function formatWindowMinutes(minutes) {
34706
34736
  return `${hours}h${minutes % 60}m`;
34707
34737
  }
34708
34738
  function credentialsPath() {
34709
- return join16(homedir16(), ".claudish", "codex-oauth.json");
34739
+ return join17(homedir17(), ".claudish", "codex-oauth.json");
34710
34740
  }
34711
34741
  function planLabel(planType) {
34712
34742
  if (!planType)
@@ -34758,10 +34788,10 @@ function scrapeCodexHeaders(headers) {
34758
34788
  }
34759
34789
  function resolveProbeModel() {
34760
34790
  try {
34761
- const cachePath = join16(homedir16(), ".codex", "models_cache.json");
34791
+ const cachePath = join17(homedir17(), ".codex", "models_cache.json");
34762
34792
  if (!existsSync14(cachePath))
34763
34793
  return;
34764
- const cache2 = JSON.parse(readFileSync11(cachePath, "utf-8"));
34794
+ const cache2 = JSON.parse(readFileSync12(cachePath, "utf-8"));
34765
34795
  for (const m of cache2.models ?? []) {
34766
34796
  const slug = m?.slug ?? m?.id;
34767
34797
  if (typeof slug === "string" && slug.length > 0)
@@ -34775,7 +34805,7 @@ function readCodexCredentials() {
34775
34805
  const path = credentialsPath();
34776
34806
  if (!existsSync14(path))
34777
34807
  return;
34778
- return JSON.parse(readFileSync11(path, "utf-8"));
34808
+ return JSON.parse(readFileSync12(path, "utf-8"));
34779
34809
  } catch {
34780
34810
  return;
34781
34811
  }
@@ -35187,8 +35217,8 @@ var init_harness = __esm(() => {
35187
35217
 
35188
35218
  // src/behavior/journal.ts
35189
35219
  import { appendFile as appendFile2, mkdir, readFile, rename, stat, writeFile } from "fs/promises";
35190
- import { homedir as homedir17 } from "os";
35191
- import { dirname as dirname6, join as join17 } from "path";
35220
+ import { homedir as homedir18 } from "os";
35221
+ import { dirname as dirname6, join as join18 } from "path";
35192
35222
  function classifyPath(observed, expected) {
35193
35223
  if (!observed)
35194
35224
  return "not_applicable";
@@ -35200,7 +35230,7 @@ function classifyPath(observed, expected) {
35200
35230
  return dirOf(observed) === dirOf(expected) ? "same_dir_wrong_name" : "outside_expected_dir";
35201
35231
  }
35202
35232
  function journalPath() {
35203
- return join17(homedir17(), ".claudish", "behavior-journal.jsonl");
35233
+ return join18(homedir18(), ".claudish", "behavior-journal.jsonl");
35204
35234
  }
35205
35235
  async function prune(path) {
35206
35236
  const content = await readFile(path, "utf8");
@@ -35261,8 +35291,8 @@ __export(exports_aggregate, {
35261
35291
  });
35262
35292
  import { createHash as createHash4, randomBytes as randomBytes4 } from "crypto";
35263
35293
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7 } from "fs";
35264
- import { homedir as homedir18 } from "os";
35265
- import { dirname as dirname7, join as join18 } from "path";
35294
+ import { homedir as homedir19 } from "os";
35295
+ import { dirname as dirname7, join as join19 } from "path";
35266
35296
  function contextBucket(inputTokens) {
35267
35297
  if (inputTokens < 50000)
35268
35298
  return "0-50k";
@@ -35380,7 +35410,7 @@ function pendingReports() {
35380
35410
  return [...sessions.values()].map(toReport);
35381
35411
  }
35382
35412
  function outboxPath() {
35383
- return join18(homedir18(), ".claudish", "behavior-outbox.jsonl");
35413
+ return join19(homedir19(), ".claudish", "behavior-outbox.jsonl");
35384
35414
  }
35385
35415
  function spoolPendingSync(path = outboxPath()) {
35386
35416
  if (sessions.size === 0)
@@ -35603,10 +35633,10 @@ __export(exports_live_log, {
35603
35633
  recordLiveDivergence: () => recordLiveDivergence
35604
35634
  });
35605
35635
  import { appendFile as appendFile3 } from "fs/promises";
35606
- import { homedir as homedir19 } from "os";
35607
- import { join as join19 } from "path";
35636
+ import { homedir as homedir20 } from "os";
35637
+ import { join as join20 } from "path";
35608
35638
  function defaultPath() {
35609
- return join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
35639
+ return join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
35610
35640
  }
35611
35641
  async function recordLiveDivergence(entry, path = defaultPath()) {
35612
35642
  try {
@@ -36263,9 +36293,9 @@ var init_hooks = __esm(() => {
36263
36293
  });
36264
36294
 
36265
36295
  // src/behavior/observer/corpus.ts
36266
- import { appendFileSync as appendFileSync3, readFileSync as readFileSync12, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
36267
- import { homedir as homedir20 } from "os";
36268
- import { join as join20 } from "path";
36296
+ import { appendFileSync as appendFileSync3, readFileSync as readFileSync13, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
36297
+ import { homedir as homedir21 } from "os";
36298
+ import { join as join21 } from "path";
36269
36299
  function directoryOf2(filePath) {
36270
36300
  const slash = filePath.lastIndexOf("/");
36271
36301
  return slash > 0 ? filePath.slice(0, slash) : undefined;
@@ -36287,7 +36317,7 @@ function writeTargetsOf(row) {
36287
36317
  function replayTranscript(file2) {
36288
36318
  let text;
36289
36319
  try {
36290
- text = readFileSync12(file2, "utf8");
36320
+ text = readFileSync13(file2, "utf8");
36291
36321
  } catch {
36292
36322
  return [];
36293
36323
  }
@@ -36344,26 +36374,26 @@ function listTranscripts(root) {
36344
36374
  return files;
36345
36375
  }
36346
36376
  for (const project of projects) {
36347
- const dir = join20(root, project);
36377
+ const dir = join21(root, project);
36348
36378
  try {
36349
36379
  if (!statSync2(dir).isDirectory())
36350
36380
  continue;
36351
36381
  for (const f of readdirSync2(dir)) {
36352
36382
  if (f.endsWith(".jsonl"))
36353
- files.push(join20(dir, f));
36383
+ files.push(join21(dir, f));
36354
36384
  }
36355
36385
  } catch {}
36356
36386
  }
36357
36387
  return files;
36358
36388
  }
36359
36389
  function buildCorpus(options = {}) {
36360
- const root = options.projectsRoot ?? join20(homedir20(), ".claude", "projects");
36390
+ const root = options.projectsRoot ?? join21(homedir21(), ".claude", "projects");
36361
36391
  const files = listTranscripts(root);
36362
36392
  const records = [];
36363
36393
  for (const f of files)
36364
36394
  records.push(...replayTranscript(f));
36365
36395
  if (options.write && records.length > 0) {
36366
- const outputPath = options.outputPath ?? join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
36396
+ const outputPath = options.outputPath ?? join21(homedir21(), ".claudish", "behavior-divergences.jsonl");
36367
36397
  try {
36368
36398
  appendFileSync3(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
36369
36399
  `)}
@@ -37128,13 +37158,13 @@ var init_model_parser = __esm(() => {
37128
37158
  import {
37129
37159
  existsSync as existsSync15,
37130
37160
  mkdirSync as mkdirSync8,
37131
- readFileSync as readFileSync13,
37161
+ readFileSync as readFileSync14,
37132
37162
  renameSync,
37133
37163
  unlinkSync as unlinkSync5,
37134
37164
  writeFileSync as writeFileSync7
37135
37165
  } from "fs";
37136
- import { homedir as homedir21 } from "os";
37137
- import { join as join21 } from "path";
37166
+ import { homedir as homedir22 } from "os";
37167
+ import { join as join22 } from "path";
37138
37168
  function ensureDir() {
37139
37169
  if (!existsSync15(CLAUDISH_DIR)) {
37140
37170
  mkdirSync8(CLAUDISH_DIR, { recursive: true });
@@ -37144,7 +37174,7 @@ function readFromDisk() {
37144
37174
  try {
37145
37175
  if (!existsSync15(BUFFER_FILE))
37146
37176
  return [];
37147
- const raw = readFileSync13(BUFFER_FILE, "utf-8");
37177
+ const raw = readFileSync14(BUFFER_FILE, "utf-8");
37148
37178
  const parsed = JSON.parse(raw);
37149
37179
  if (!Array.isArray(parsed.events))
37150
37180
  return [];
@@ -37169,7 +37199,7 @@ function writeToDisk(events) {
37169
37199
  ensureDir();
37170
37200
  const trimmed2 = enforceSizeCap([...events]);
37171
37201
  const payload = { version: 1, events: trimmed2 };
37172
- const tmpFile = join21(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
37202
+ const tmpFile = join22(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
37173
37203
  writeFileSync7(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
37174
37204
  renameSync(tmpFile, BUFFER_FILE);
37175
37205
  memoryCache = trimmed2;
@@ -37242,8 +37272,8 @@ function syncFlushOnExit() {
37242
37272
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
37243
37273
  var init_stats_buffer = __esm(() => {
37244
37274
  BUFFER_MAX_BYTES = 64 * 1024;
37245
- CLAUDISH_DIR = join21(homedir21(), ".claudish");
37246
- BUFFER_FILE = join21(CLAUDISH_DIR, "stats-buffer.json");
37275
+ CLAUDISH_DIR = join22(homedir22(), ".claudish");
37276
+ BUFFER_FILE = join22(CLAUDISH_DIR, "stats-buffer.json");
37247
37277
  process.on("exit", syncFlushOnExit);
37248
37278
  process.on("SIGTERM", () => {
37249
37279
  try {
@@ -38357,9 +38387,9 @@ function compareByReleaseDateDesc(a, b) {
38357
38387
  }
38358
38388
 
38359
38389
  // src/model-loader.ts
38360
- import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "fs";
38361
- import { homedir as homedir22 } from "os";
38362
- import { join as join22 } from "path";
38390
+ import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "fs";
38391
+ import { homedir as homedir23 } from "os";
38392
+ import { join as join23 } from "path";
38363
38393
  function groupRecommendedModels(entries) {
38364
38394
  const byId = new Map;
38365
38395
  const categoryOrder = new Map;
@@ -38471,7 +38501,7 @@ async function getRecommendedModels(opts = {}) {
38471
38501
  }
38472
38502
  if (!forceRefresh && existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
38473
38503
  try {
38474
- const cacheData = JSON.parse(readFileSync14(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38504
+ const cacheData = JSON.parse(readFileSync15(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38475
38505
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
38476
38506
  _cachedRecommendedModels = cacheData;
38477
38507
  return cacheData;
@@ -38487,7 +38517,7 @@ async function getRecommendedModels(opts = {}) {
38487
38517
  if (data.models && data.models.length > 0) {
38488
38518
  _cachedRecommendedModels = data;
38489
38519
  try {
38490
- const cacheDir = join22(homedir22(), ".claudish");
38520
+ const cacheDir = join23(homedir23(), ".claudish");
38491
38521
  mkdirSync9(cacheDir, { recursive: true });
38492
38522
  writeFileSync8(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
38493
38523
  } catch {}
@@ -38502,7 +38532,7 @@ function getRecommendedModelsSync() {
38502
38532
  return _cachedRecommendedModels;
38503
38533
  if (existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
38504
38534
  try {
38505
- const cacheData = JSON.parse(readFileSync14(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38535
+ const cacheData = JSON.parse(readFileSync15(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38506
38536
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
38507
38537
  _cachedRecommendedModels = cacheData;
38508
38538
  return cacheData;
@@ -38626,7 +38656,7 @@ var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels =
38626
38656
  var init_model_loader = __esm(() => {
38627
38657
  init_cache_ttl();
38628
38658
  FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
38629
- RECOMMENDED_MODELS_CACHE_PATH = join22(homedir22(), ".claudish", "recommended-models-cache.json");
38659
+ RECOMMENDED_MODELS_CACHE_PATH = join23(homedir23(), ".claudish", "recommended-models-cache.json");
38630
38660
  FIREBASE_SLUG_TO_PROVIDER_NAME = {
38631
38661
  openai: "openai",
38632
38662
  google: "google",
@@ -38694,6 +38724,279 @@ var init_context_window_fallback = __esm(() => {
38694
38724
  inFlight2 = new Map;
38695
38725
  });
38696
38726
 
38727
+ // src/providers/devin/proto-codec.ts
38728
+ function cat(parts) {
38729
+ let total = 0;
38730
+ for (const part of parts)
38731
+ total += part.length;
38732
+ const out = new Uint8Array(total);
38733
+ let offset = 0;
38734
+ for (const part of parts) {
38735
+ out.set(part, offset);
38736
+ offset += part.length;
38737
+ }
38738
+ return out;
38739
+ }
38740
+ function varint(n) {
38741
+ let value = BigInt(n);
38742
+ const out = [];
38743
+ do {
38744
+ let byte = Number(value & 0x7fn);
38745
+ value >>= 7n;
38746
+ if (value > 0n)
38747
+ byte |= 128;
38748
+ out.push(byte);
38749
+ } while (value > 0n);
38750
+ return new Uint8Array(out);
38751
+ }
38752
+ function tag(fieldNumber, wireType) {
38753
+ return varint(fieldNumber << 3 | wireType);
38754
+ }
38755
+ function bytes(fieldNumber, value) {
38756
+ const body = typeof value === "string" ? textEncoder.encode(value) : value;
38757
+ return cat([tag(fieldNumber, 2), varint(body.length), body]);
38758
+ }
38759
+ function vint(fieldNumber, value) {
38760
+ return cat([tag(fieldNumber, 0), varint(value)]);
38761
+ }
38762
+ function msg(...parts) {
38763
+ return cat(parts);
38764
+ }
38765
+ function writeUint32BE(target, offset, value) {
38766
+ target[offset] = value >>> 24 & 255;
38767
+ target[offset + 1] = value >>> 16 & 255;
38768
+ target[offset + 2] = value >>> 8 & 255;
38769
+ target[offset + 3] = value & 255;
38770
+ }
38771
+ function readUint32BE(source, offset) {
38772
+ return (source[offset] << 24 | source[offset + 1] << 16 | source[offset + 2] << 8 | source[offset + 3]) >>> 0;
38773
+ }
38774
+ function envelope(payload, flags = 0) {
38775
+ const out = new Uint8Array(FRAME_HEADER_BYTES + payload.length);
38776
+ out[0] = flags;
38777
+ writeUint32BE(out, 1, payload.length);
38778
+ out.set(payload, FRAME_HEADER_BYTES);
38779
+ return out;
38780
+ }
38781
+ function readVarintAt(buf, p) {
38782
+ let value = 0n;
38783
+ let shift = 0n;
38784
+ let offset = p;
38785
+ while (offset < buf.length) {
38786
+ const byte = buf[offset++];
38787
+ value |= BigInt(byte & 127) << shift;
38788
+ if ((byte & 128) === 0)
38789
+ break;
38790
+ shift += 7n;
38791
+ }
38792
+ return [value, offset];
38793
+ }
38794
+ function parseTLV(buf) {
38795
+ const out = [];
38796
+ let p = 0;
38797
+ while (p < buf.length) {
38798
+ const start = p;
38799
+ let rawTag;
38800
+ [rawTag, p] = readVarintAt(buf, p);
38801
+ const no = Number(rawTag >> 3n);
38802
+ const wire = Number(rawTag & 7n);
38803
+ if (no === 0)
38804
+ break;
38805
+ let payloadStart = p;
38806
+ if (wire === 0) {
38807
+ [, p] = readVarintAt(buf, p);
38808
+ } else if (wire === 1) {
38809
+ p += 8;
38810
+ } else if (wire === 5) {
38811
+ p += 4;
38812
+ } else if (wire === 2) {
38813
+ let len;
38814
+ [len, p] = readVarintAt(buf, p);
38815
+ payloadStart = p;
38816
+ p += Number(len);
38817
+ } else {
38818
+ break;
38819
+ }
38820
+ if (p > buf.length)
38821
+ break;
38822
+ out.push({ no, wire, raw: buf.subarray(start, p), payload: buf.subarray(payloadStart, p) });
38823
+ }
38824
+ return out;
38825
+ }
38826
+ function readVarintValue(tlv) {
38827
+ if (tlv.wire !== 0)
38828
+ return 0;
38829
+ const [value] = readVarintAt(tlv.payload, 0);
38830
+ return Number(value);
38831
+ }
38832
+ function readFloat32LE(tlv) {
38833
+ if (tlv.wire !== 5 || tlv.payload.length < 4)
38834
+ return 0;
38835
+ const view = new DataView(tlv.payload.buffer, tlv.payload.byteOffset, tlv.payload.byteLength);
38836
+ return view.getFloat32(0, true);
38837
+ }
38838
+ function readString(tlv) {
38839
+ return textDecoder.decode(tlv.payload);
38840
+ }
38841
+ function createFrameReader() {
38842
+ let pending = new Uint8Array(0);
38843
+ return (chunk) => {
38844
+ if (chunk.length > 0) {
38845
+ if (pending.length === 0) {
38846
+ pending = chunk;
38847
+ } else {
38848
+ const merged = new Uint8Array(pending.length + chunk.length);
38849
+ merged.set(pending, 0);
38850
+ merged.set(chunk, pending.length);
38851
+ pending = merged;
38852
+ }
38853
+ }
38854
+ const frames = [];
38855
+ let offset = 0;
38856
+ while (offset + FRAME_HEADER_BYTES <= pending.length) {
38857
+ const flags = pending[offset];
38858
+ const length = readUint32BE(pending, offset + 1);
38859
+ const end = offset + FRAME_HEADER_BYTES + length;
38860
+ if (end > pending.length)
38861
+ break;
38862
+ frames.push({ flags, payload: pending.slice(offset + FRAME_HEADER_BYTES, end) });
38863
+ offset = end;
38864
+ }
38865
+ if (offset > 0)
38866
+ pending = pending.slice(offset);
38867
+ return frames;
38868
+ };
38869
+ }
38870
+ var FRAME_HEADER_BYTES = 5, FRAME_FLAG_END_OF_STREAM = 2, textEncoder, textDecoder;
38871
+ var init_proto_codec = __esm(() => {
38872
+ textEncoder = new TextEncoder;
38873
+ textDecoder = new TextDecoder;
38874
+ });
38875
+
38876
+ // src/handlers/shared/devin-stream-head-sniffer.ts
38877
+ function classifyDevinStreamError(code, message) {
38878
+ const lowerCode = code.toLowerCase();
38879
+ if (RETRYABLE_CODES.has(lowerCode))
38880
+ return "retryable";
38881
+ if (TERMINAL_CODES.has(lowerCode))
38882
+ return "terminal";
38883
+ if (lowerCode === "resource_exhausted") {
38884
+ return QUOTA_MESSAGE_RE.test(message) ? "terminal" : "retryable";
38885
+ }
38886
+ if (RETRYABLE_MESSAGE_RE.test(message))
38887
+ return "retryable";
38888
+ return "terminal";
38889
+ }
38890
+ async function sniffDevinStreamHead(response, opts = {}) {
38891
+ const budgetMs = opts.budgetMs ?? DEVIN_SNIFF_BUDGET_MS;
38892
+ const logMsg = opts.log ?? (() => {});
38893
+ if (!response.body)
38894
+ return { kind: "clean", response };
38895
+ const reader = response.body.getReader();
38896
+ const consumed = [];
38897
+ const nextFrames = createFrameReader();
38898
+ const decoder = new TextDecoder;
38899
+ const deadline = Date.now() + budgetMs;
38900
+ const replayResponse = () => {
38901
+ const buffered = consumed.slice();
38902
+ const body = new ReadableStream({
38903
+ start: async (controller) => {
38904
+ try {
38905
+ for (const chunk of buffered)
38906
+ controller.enqueue(chunk);
38907
+ while (true) {
38908
+ const { done, value } = await reader.read();
38909
+ if (done)
38910
+ break;
38911
+ if (value)
38912
+ controller.enqueue(value);
38913
+ }
38914
+ controller.close();
38915
+ } catch (error46) {
38916
+ try {
38917
+ controller.error(error46);
38918
+ } catch {}
38919
+ }
38920
+ },
38921
+ cancel: () => {
38922
+ reader.cancel().catch(() => {});
38923
+ }
38924
+ });
38925
+ return new Response(body, {
38926
+ status: response.status,
38927
+ statusText: response.statusText,
38928
+ headers: response.headers
38929
+ });
38930
+ };
38931
+ try {
38932
+ while (true) {
38933
+ const remaining = deadline - Date.now();
38934
+ if (remaining <= 0) {
38935
+ logMsg(`[DevinSniff] budget ${budgetMs}ms elapsed with no verdict \u2014 streaming through`);
38936
+ return { kind: "clean", response: replayResponse() };
38937
+ }
38938
+ let timer;
38939
+ const timeout = new Promise((resolve2) => {
38940
+ timer = setTimeout(() => resolve2("timeout"), remaining);
38941
+ });
38942
+ let result;
38943
+ try {
38944
+ result = await Promise.race([reader.read(), timeout]);
38945
+ } finally {
38946
+ if (timer)
38947
+ clearTimeout(timer);
38948
+ }
38949
+ if (result === "timeout") {
38950
+ logMsg(`[DevinSniff] budget ${budgetMs}ms elapsed mid-read \u2014 streaming through`);
38951
+ return { kind: "clean", response: replayResponse() };
38952
+ }
38953
+ if (result.done)
38954
+ return { kind: "clean", response: replayResponse() };
38955
+ if (!result.value)
38956
+ continue;
38957
+ consumed.push(result.value);
38958
+ for (const frame of nextFrames(result.value)) {
38959
+ if (frame.flags !== FRAME_FLAG_END_OF_STREAM) {
38960
+ return { kind: "clean", response: replayResponse() };
38961
+ }
38962
+ const raw = decoder.decode(frame.payload).trim();
38963
+ if (!raw || raw === "{}") {
38964
+ return { kind: "clean", response: replayResponse() };
38965
+ }
38966
+ let code = "unknown";
38967
+ let message = raw;
38968
+ try {
38969
+ const parsed = JSON.parse(raw);
38970
+ code = String(parsed?.error?.code ?? parsed?.code ?? "unknown");
38971
+ message = String(parsed?.error?.message ?? parsed?.message ?? raw);
38972
+ } catch {}
38973
+ const kind = classifyDevinStreamError(code, message);
38974
+ logMsg(`[DevinSniff] in-stream error ${code} classified ${kind}: ${message.slice(0, 200)}`);
38975
+ reader.cancel().catch(() => {});
38976
+ return { kind, code, message };
38977
+ }
38978
+ }
38979
+ } catch (error46) {
38980
+ logMsg(`[DevinSniff] read failed (${error46}) \u2014 handing stream to parser`);
38981
+ return { kind: "clean", response: replayResponse() };
38982
+ }
38983
+ }
38984
+ var DEVIN_SNIFF_BUDGET_MS = 12000, RETRYABLE_CODES, TERMINAL_CODES, RETRYABLE_MESSAGE_RE, QUOTA_MESSAGE_RE;
38985
+ var init_devin_stream_head_sniffer = __esm(() => {
38986
+ init_proto_codec();
38987
+ RETRYABLE_CODES = new Set(["unavailable", "internal", "deadline_exceeded", "aborted"]);
38988
+ TERMINAL_CODES = new Set([
38989
+ "permission_denied",
38990
+ "unauthenticated",
38991
+ "invalid_argument",
38992
+ "not_found",
38993
+ "failed_precondition",
38994
+ "unimplemented"
38995
+ ]);
38996
+ RETRYABLE_MESSAGE_RE = /third-party model provider is experiencing issues|overloaded|temporarily unavailable|try again|please retry/i;
38997
+ QUOTA_MESSAGE_RE = /quota|out of credits|credit balance|billing|plan limit|exceeded your/i;
38998
+ });
38999
+
38697
39000
  // src/handlers/shared/stream-head-sniffer.ts
38698
39001
  function isRetryableStreamError(code, type, message) {
38699
39002
  if (RETRYABLE_ERROR_CODES.has(code))
@@ -39166,6 +39469,350 @@ var init_anthropic_sse = __esm(() => {
39166
39469
  init_logger();
39167
39470
  });
39168
39471
 
39472
+ // src/handlers/shared/stream-parsers/devin-connect.ts
39473
+ function createDevinConnectStream(_c, response, opts) {
39474
+ const encoder = new TextEncoder;
39475
+ let isClosed = false;
39476
+ let pingInterval = null;
39477
+ const stream = new ReadableStream({
39478
+ async start(controller) {
39479
+ const send = (event, data) => {
39480
+ if (!isClosed) {
39481
+ controller.enqueue(encoder.encode(`event: ${event}
39482
+ data: ${JSON.stringify(data)}
39483
+
39484
+ `));
39485
+ }
39486
+ };
39487
+ const msgId = `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`;
39488
+ let finalized2 = false;
39489
+ let curIdx = 0;
39490
+ let textIdx = -1;
39491
+ let textStarted = false;
39492
+ let thinkingIdx = -1;
39493
+ let thinkingStarted = false;
39494
+ let inputTokens = 0;
39495
+ let outputTokens = 0;
39496
+ let sawUsage = false;
39497
+ let rawStopReason = null;
39498
+ let servedModel = "";
39499
+ let toolBlocksEmitted = 0;
39500
+ let current = null;
39501
+ let lastActivity = Date.now();
39502
+ const textDecoder2 = new TextDecoder;
39503
+ const reasoningDecoder = new TextDecoder;
39504
+ send("message_start", {
39505
+ type: "message_start",
39506
+ message: {
39507
+ id: msgId,
39508
+ type: "message",
39509
+ role: "assistant",
39510
+ content: [],
39511
+ model: opts.modelName,
39512
+ stop_reason: null,
39513
+ stop_sequence: null,
39514
+ usage: messageStartUsage(opts.priorInputTokens)
39515
+ }
39516
+ });
39517
+ send("ping", { type: "ping" });
39518
+ pingInterval = setInterval(() => {
39519
+ if (!isClosed && Date.now() - lastActivity > 1000) {
39520
+ send("ping", { type: "ping" });
39521
+ }
39522
+ }, 1000);
39523
+ const closeThinking = () => {
39524
+ if (!thinkingStarted)
39525
+ return;
39526
+ send("content_block_stop", { type: "content_block_stop", index: thinkingIdx });
39527
+ thinkingStarted = false;
39528
+ };
39529
+ const closeText = () => {
39530
+ if (!textStarted)
39531
+ return;
39532
+ send("content_block_stop", { type: "content_block_stop", index: textIdx });
39533
+ textStarted = false;
39534
+ };
39535
+ const closeCurrentTool = () => {
39536
+ if (!current || current.closed)
39537
+ return;
39538
+ const call = current;
39539
+ current = null;
39540
+ if (call.buffered) {
39541
+ let args = call.args;
39542
+ if (opts.repairToolArgs) {
39543
+ try {
39544
+ const repaired = opts.repairToolArgs(call.name, args);
39545
+ if (typeof repaired === "string" && repaired !== args) {
39546
+ log(`[DevinConnect] tool call repaired: ${call.name}`);
39547
+ args = repaired;
39548
+ }
39549
+ } catch (err) {
39550
+ log(`[DevinConnect] repairToolArgs threw for ${call.name}: ${err}`);
39551
+ }
39552
+ }
39553
+ send("content_block_delta", {
39554
+ type: "content_block_delta",
39555
+ index: call.blockIndex,
39556
+ delta: { type: "input_json_delta", partial_json: args || "{}" }
39557
+ });
39558
+ } else if (!call.args) {
39559
+ send("content_block_delta", {
39560
+ type: "content_block_delta",
39561
+ index: call.blockIndex,
39562
+ delta: { type: "input_json_delta", partial_json: "{}" }
39563
+ });
39564
+ }
39565
+ send("content_block_stop", { type: "content_block_stop", index: call.blockIndex });
39566
+ call.closed = true;
39567
+ };
39568
+ const finalize = (reason, errorMessage) => {
39569
+ if (finalized2)
39570
+ return;
39571
+ finalized2 = true;
39572
+ closeCurrentTool();
39573
+ closeThinking();
39574
+ closeText();
39575
+ if (servedModel && servedModel !== opts.modelName) {
39576
+ log(`[DevinConnect] served model: ${servedModel} (requested ${opts.modelName})`);
39577
+ }
39578
+ if (sawUsage) {
39579
+ log(`[DevinConnect] usage: input=${inputTokens}, output=${outputTokens}` + (rawStopReason !== null ? `, raw stop_reason=${rawStopReason}` : ""));
39580
+ }
39581
+ opts.onTokenUpdate?.(inputTokens, outputTokens);
39582
+ if (reason === "error") {
39583
+ log(`[DevinConnect] stream error: ${errorMessage}`);
39584
+ send("error", { type: "error", error: { type: "api_error", message: errorMessage } });
39585
+ } else {
39586
+ send("message_delta", {
39587
+ type: "message_delta",
39588
+ delta: {
39589
+ stop_reason: toolBlocksEmitted > 0 ? "tool_use" : "end_turn",
39590
+ stop_sequence: null
39591
+ },
39592
+ usage: {
39593
+ ...inputTokens > 0 ? { input_tokens: inputTokens } : {},
39594
+ output_tokens: outputTokens
39595
+ }
39596
+ });
39597
+ opts.onTurnEnd?.();
39598
+ send("message_stop", { type: "message_stop" });
39599
+ }
39600
+ if (!isClosed) {
39601
+ isClosed = true;
39602
+ if (pingInterval) {
39603
+ clearInterval(pingInterval);
39604
+ pingInterval = null;
39605
+ }
39606
+ try {
39607
+ controller.close();
39608
+ } catch {}
39609
+ }
39610
+ };
39611
+ const readUsageGroup = (payload) => {
39612
+ for (const entry of parseTLV(payload)) {
39613
+ if (entry.no !== USAGE_ENTRY || entry.wire !== 2)
39614
+ continue;
39615
+ let key = "";
39616
+ let value = null;
39617
+ for (const field of parseTLV(entry.payload)) {
39618
+ if (field.no === USAGE_ENTRY_KEY && field.wire === 2) {
39619
+ key = readString(field);
39620
+ } else if (field.no === USAGE_ENTRY_STAT && field.wire === 2) {
39621
+ for (const stat2 of parseTLV(field.payload)) {
39622
+ if (stat2.no === USAGE_STAT_VALUE && stat2.wire === 5) {
39623
+ value = Math.round(readFloat32LE(stat2));
39624
+ }
39625
+ }
39626
+ }
39627
+ }
39628
+ if (key === USAGE_KEY_INPUT) {
39629
+ inputTokens = value ?? 0;
39630
+ sawUsage = true;
39631
+ } else if (key === USAGE_KEY_OUTPUT) {
39632
+ outputTokens = value ?? 0;
39633
+ sawUsage = true;
39634
+ }
39635
+ }
39636
+ };
39637
+ const readToolCall = (payload) => {
39638
+ let id = "";
39639
+ let name = "";
39640
+ let fragment = null;
39641
+ for (const field of parseTLV(payload)) {
39642
+ if (field.no === TOOL_ID && field.wire === 2)
39643
+ id = readString(field);
39644
+ else if (field.no === TOOL_NAME && field.wire === 2)
39645
+ name = readString(field);
39646
+ else if (field.no === TOOL_ARGS_FRAGMENT && field.wire === 2)
39647
+ fragment = field;
39648
+ }
39649
+ if (name) {
39650
+ closeCurrentTool();
39651
+ closeThinking();
39652
+ closeText();
39653
+ const restored = opts.toolNameMap?.get(name) ?? name;
39654
+ const blockIndex = curIdx++;
39655
+ const toolId = id || `toolu_${Date.now()}_${blockIndex}`;
39656
+ current = {
39657
+ id: toolId,
39658
+ name: restored,
39659
+ blockIndex,
39660
+ buffered: opts.shouldBufferTool?.(restored) ?? false,
39661
+ args: "",
39662
+ decoder: new TextDecoder,
39663
+ closed: false
39664
+ };
39665
+ toolBlocksEmitted++;
39666
+ opts.onToolCallObserved?.(restored);
39667
+ send("content_block_start", {
39668
+ type: "content_block_start",
39669
+ index: blockIndex,
39670
+ content_block: { type: "tool_use", id: toolId, name: restored, input: {} }
39671
+ });
39672
+ }
39673
+ if (!fragment)
39674
+ return;
39675
+ const chunk = current ? current.decoder.decode(fragment.payload, { stream: true }) : readString(fragment);
39676
+ if (!chunk)
39677
+ return;
39678
+ if (!current) {
39679
+ log("[DevinConnect] argument fragment with no open tool call, dropping");
39680
+ return;
39681
+ }
39682
+ current.args += chunk;
39683
+ if (!current.buffered) {
39684
+ send("content_block_delta", {
39685
+ type: "content_block_delta",
39686
+ index: current.blockIndex,
39687
+ delta: { type: "input_json_delta", partial_json: chunk }
39688
+ });
39689
+ }
39690
+ };
39691
+ const readMessageFrame = (payload) => {
39692
+ for (const field of parseTLV(payload)) {
39693
+ lastActivity = Date.now();
39694
+ if (field.no === FIELD_TEXT && field.wire === 2) {
39695
+ const text = textDecoder2.decode(field.payload, { stream: true });
39696
+ if (!text)
39697
+ continue;
39698
+ closeCurrentTool();
39699
+ closeThinking();
39700
+ if (!textStarted) {
39701
+ textIdx = curIdx++;
39702
+ send("content_block_start", {
39703
+ type: "content_block_start",
39704
+ index: textIdx,
39705
+ content_block: { type: "text", text: "" }
39706
+ });
39707
+ textStarted = true;
39708
+ }
39709
+ opts.onAssistantText?.(text, "text");
39710
+ send("content_block_delta", {
39711
+ type: "content_block_delta",
39712
+ index: textIdx,
39713
+ delta: { type: "text_delta", text }
39714
+ });
39715
+ } else if (field.no === FIELD_REASONING && field.wire === 2) {
39716
+ const thinking = reasoningDecoder.decode(field.payload, { stream: true });
39717
+ if (!thinking)
39718
+ continue;
39719
+ closeCurrentTool();
39720
+ if (!thinkingStarted) {
39721
+ thinkingIdx = curIdx++;
39722
+ send("content_block_start", {
39723
+ type: "content_block_start",
39724
+ index: thinkingIdx,
39725
+ content_block: { type: "thinking", thinking: "" }
39726
+ });
39727
+ thinkingStarted = true;
39728
+ }
39729
+ opts.onAssistantText?.(thinking, "reasoning");
39730
+ send("content_block_delta", {
39731
+ type: "content_block_delta",
39732
+ index: thinkingIdx,
39733
+ delta: { type: "thinking_delta", thinking }
39734
+ });
39735
+ } else if (field.no === FIELD_TOOL_CALL && field.wire === 2) {
39736
+ readToolCall(field.payload);
39737
+ } else if (field.no === FIELD_STOP_REASON && field.wire === 0) {
39738
+ rawStopReason = readVarintValue(field);
39739
+ } else if (field.no === FIELD_META && field.wire === 2) {
39740
+ for (const sub of parseTLV(field.payload)) {
39741
+ if (sub.no === META_SERVED_MODEL && sub.wire === 2) {
39742
+ const uid = readString(sub);
39743
+ if (uid && uid !== servedModel) {
39744
+ servedModel = uid;
39745
+ opts.onServedModel?.(uid);
39746
+ }
39747
+ }
39748
+ }
39749
+ } else if (field.no === FIELD_USAGE && field.wire === 2) {
39750
+ readUsageGroup(field.payload);
39751
+ }
39752
+ }
39753
+ };
39754
+ try {
39755
+ const body = response.body;
39756
+ if (!body) {
39757
+ finalize("error", "Devin returned no response body");
39758
+ return;
39759
+ }
39760
+ const reader = body.getReader();
39761
+ const nextFrames = createFrameReader();
39762
+ while (true) {
39763
+ const { done, value } = await reader.read();
39764
+ if (done)
39765
+ break;
39766
+ if (!value)
39767
+ continue;
39768
+ for (const frame of nextFrames(value)) {
39769
+ if (frame.flags === FRAME_FLAG_END_OF_STREAM) {
39770
+ const raw = new TextDecoder().decode(frame.payload).trim();
39771
+ if (!raw || raw === "{}") {
39772
+ finalize("done");
39773
+ return;
39774
+ }
39775
+ let code = "unknown";
39776
+ let message = raw;
39777
+ try {
39778
+ const parsed = JSON.parse(raw);
39779
+ code = String(parsed?.error?.code ?? parsed?.code ?? "unknown");
39780
+ message = String(parsed?.error?.message ?? parsed?.message ?? raw);
39781
+ } catch {}
39782
+ opts.onApiError?.(code, message);
39783
+ finalize("error", `${code}: ${message}`);
39784
+ return;
39785
+ }
39786
+ readMessageFrame(frame.payload);
39787
+ }
39788
+ }
39789
+ finalize("done");
39790
+ } catch (e) {
39791
+ finalize("error", String(e));
39792
+ }
39793
+ },
39794
+ cancel() {
39795
+ isClosed = true;
39796
+ if (pingInterval) {
39797
+ clearInterval(pingInterval);
39798
+ pingInterval = null;
39799
+ }
39800
+ }
39801
+ });
39802
+ return new Response(stream, {
39803
+ headers: {
39804
+ "Content-Type": "text/event-stream",
39805
+ "Cache-Control": "no-cache",
39806
+ Connection: "keep-alive"
39807
+ }
39808
+ });
39809
+ }
39810
+ var FIELD_TEXT = 3, FIELD_STOP_REASON = 5, FIELD_TOOL_CALL = 6, FIELD_META = 7, FIELD_REASONING = 9, FIELD_USAGE = 28, TOOL_ID = 1, TOOL_NAME = 2, TOOL_ARGS_FRAGMENT = 3, META_SERVED_MODEL = 9, USAGE_ENTRY = 2, USAGE_ENTRY_KEY = 5, USAGE_ENTRY_STAT = 4, USAGE_STAT_VALUE = 2, USAGE_KEY_INPUT = "input_tokens", USAGE_KEY_OUTPUT = "output_tokens";
39811
+ var init_devin_connect = __esm(() => {
39812
+ init_logger();
39813
+ init_proto_codec();
39814
+ });
39815
+
39169
39816
  // src/handlers/shared/stream-parsers/gemini-sse.ts
39170
39817
  function createGeminiSseStream(_c, response, opts) {
39171
39818
  const encoder = new TextEncoder;
@@ -39193,6 +39840,7 @@ data: ${JSON.stringify(data)}
39193
39840
  const toolCalls = new Map;
39194
39841
  let accumulatedText = "";
39195
39842
  let lastActivity = Date.now();
39843
+ let truncated = false;
39196
39844
  send("message_start", {
39197
39845
  type: "message_start",
39198
39846
  message: {
@@ -39244,9 +39892,13 @@ data: ${JSON.stringify(data)}
39244
39892
  send("error", { type: "error", error: { type: "api_error", message: err } });
39245
39893
  } else {
39246
39894
  const hasToolCalls = toolCalls.size > 0;
39895
+ const stopReason = truncated ? "max_tokens" : hasToolCalls ? "tool_use" : "end_turn";
39896
+ if (truncated) {
39897
+ log("[GeminiSSE] finishReason=MAX_TOKENS \u2192 stop_reason=max_tokens");
39898
+ }
39247
39899
  send("message_delta", {
39248
39900
  type: "message_delta",
39249
- delta: { stop_reason: hasToolCalls ? "tool_use" : "end_turn", stop_sequence: null },
39901
+ delta: { stop_reason: stopReason, stop_sequence: null },
39250
39902
  usage: {
39251
39903
  ...inputTokens > 0 ? { input_tokens: inputTokens } : {},
39252
39904
  output_tokens: outputTokens
@@ -39295,8 +39947,9 @@ data: ${JSON.stringify(data)}
39295
39947
  if (candidate?.content?.parts) {
39296
39948
  for (const part of candidate.content.parts) {
39297
39949
  lastActivity = Date.now();
39298
- if (part.thought || part.thoughtText) {
39299
- const thinkingContent = part.thought || part.thoughtText;
39950
+ const isThoughtPart = part.thought === true;
39951
+ const thinkingContent = isThoughtPart ? part.text ?? "" : part.thoughtText;
39952
+ if (thinkingContent) {
39300
39953
  if (!thinkingStarted) {
39301
39954
  thinkingIdx = curIdx++;
39302
39955
  send("content_block_start", {
@@ -39312,7 +39965,7 @@ data: ${JSON.stringify(data)}
39312
39965
  delta: { type: "thinking_delta", thinking: thinkingContent }
39313
39966
  });
39314
39967
  }
39315
- if (part.text) {
39968
+ if (part.text && !isThoughtPart) {
39316
39969
  if (thinkingStarted) {
39317
39970
  send("content_block_stop", {
39318
39971
  type: "content_block_stop",
@@ -39324,6 +39977,10 @@ data: ${JSON.stringify(data)}
39324
39977
  if (opts.adapter) {
39325
39978
  const res = opts.adapter.processTextContent(part.text, accumulatedText);
39326
39979
  cleanedText = res.cleanedText || "";
39980
+ if (!cleanedText) {
39981
+ log(`[gemini-sse] adapter emptied ${part.text.length} chars of visible text \u2014 passing the original through`);
39982
+ cleanedText = part.text;
39983
+ }
39327
39984
  accumulatedText += cleanedText;
39328
39985
  } else {
39329
39986
  accumulatedText += cleanedText;
@@ -39401,6 +40058,7 @@ data: ${JSON.stringify(data)}
39401
40058
  }
39402
40059
  if (candidate?.finishReason) {
39403
40060
  if (candidate.finishReason === "STOP" || candidate.finishReason === "MAX_TOKENS") {
40061
+ truncated = candidate.finishReason === "MAX_TOKENS";
39404
40062
  await finalize("done");
39405
40063
  return;
39406
40064
  }
@@ -39976,8 +40634,8 @@ var init_openai_responses_sse = __esm(() => {
39976
40634
 
39977
40635
  // src/handlers/shared/token-tracker.ts
39978
40636
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "fs";
39979
- import { homedir as homedir23 } from "os";
39980
- import { dirname as dirname8, join as join23 } from "path";
40637
+ import { homedir as homedir24 } from "os";
40638
+ import { dirname as dirname8, join as join24 } from "path";
39981
40639
  function stripProviderPrefix(name) {
39982
40640
  const at = name.indexOf("@");
39983
40641
  return at === -1 ? name : name.slice(at + 1);
@@ -40139,7 +40797,7 @@ class TokenTracker {
40139
40797
  };
40140
40798
  }
40141
40799
  const override = process.env.CLAUDISH_TOKEN_FILE;
40142
- const outPath = override || join23(homedir23(), ".claudish", `tokens-${this.port}.json`);
40800
+ const outPath = override || join24(homedir24(), ".claudish", `tokens-${this.port}.json`);
40143
40801
  mkdirSync10(dirname8(outPath), { recursive: true });
40144
40802
  writeFileSync9(outPath, JSON.stringify(data), "utf-8");
40145
40803
  } catch (e) {
@@ -40237,10 +40895,10 @@ class ComposedHandler {
40237
40895
  if (!this.getModelSupportsVision()) {
40238
40896
  const imageBlocks = [];
40239
40897
  for (let msgIdx = 0;msgIdx < messages.length; msgIdx++) {
40240
- const msg = messages[msgIdx];
40241
- if (Array.isArray(msg.content)) {
40242
- for (let partIdx = 0;partIdx < msg.content.length; partIdx++) {
40243
- const part = msg.content[partIdx];
40898
+ const msg2 = messages[msgIdx];
40899
+ if (Array.isArray(msg2.content)) {
40900
+ for (let partIdx = 0;partIdx < msg2.content.length; partIdx++) {
40901
+ const part = msg2.content[partIdx];
40244
40902
  if (part.type === "image_url" || part.type === "image" || part.type === "document") {
40245
40903
  imageBlocks.push({ msgIdx, partIdx, block: part });
40246
40904
  }
@@ -40264,25 +40922,25 @@ class ComposedHandler {
40264
40922
  };
40265
40923
  }
40266
40924
  log(`[ComposedHandler] Vision proxy described ${descriptions.length} image(s)`);
40267
- for (const msg of messages) {
40268
- if (Array.isArray(msg.content)) {
40269
- msg.content = msg.content.filter((part) => part.type !== "image" && part.type !== "document");
40270
- if (msg.content.length === 1 && msg.content[0].type === "text") {
40271
- msg.content = msg.content[0].text;
40272
- } else if (msg.content.length === 0) {
40273
- msg.content = "";
40925
+ for (const msg2 of messages) {
40926
+ if (Array.isArray(msg2.content)) {
40927
+ msg2.content = msg2.content.filter((part) => part.type !== "image" && part.type !== "document");
40928
+ if (msg2.content.length === 1 && msg2.content[0].type === "text") {
40929
+ msg2.content = msg2.content[0].text;
40930
+ } else if (msg2.content.length === 0) {
40931
+ msg2.content = "";
40274
40932
  }
40275
40933
  }
40276
40934
  }
40277
40935
  } else {
40278
40936
  log("[ComposedHandler] Stripping image/document blocks (vision not supported)");
40279
- for (const msg of messages) {
40280
- if (Array.isArray(msg.content)) {
40281
- msg.content = msg.content.filter((part) => part.type !== "image_url" && part.type !== "image" && part.type !== "document");
40282
- if (msg.content.length === 1 && msg.content[0].type === "text") {
40283
- msg.content = msg.content[0].text;
40284
- } else if (msg.content.length === 0) {
40285
- msg.content = "";
40937
+ for (const msg2 of messages) {
40938
+ if (Array.isArray(msg2.content)) {
40939
+ msg2.content = msg2.content.filter((part) => part.type !== "image_url" && part.type !== "image" && part.type !== "document");
40940
+ if (msg2.content.length === 1 && msg2.content[0].type === "text") {
40941
+ msg2.content = msg2.content[0].text;
40942
+ } else if (msg2.content.length === 0) {
40943
+ msg2.content = "";
40286
40944
  }
40287
40945
  }
40288
40946
  }
@@ -40320,7 +40978,7 @@ class ComposedHandler {
40320
40978
  const behaviorSession = this.behaviorEngine.startSession({
40321
40979
  modelId: this.bareModelName,
40322
40980
  providerName: this.provider.name,
40323
- isNativeAnthropic: /^claude[-.]/i.test(this.bareModelName) || this.provider.name === "anthropic"
40981
+ isNativeAnthropic: !this.options.forceForeignModel && (/^claude[-.]/i.test(this.bareModelName) || this.provider.name === "anthropic")
40324
40982
  });
40325
40983
  if (!behaviorSession.isNoop) {
40326
40984
  behaviorSession.applyRequest(claudeRequest, claudeRequest.tools ?? [], tools, messages);
@@ -40376,13 +41034,14 @@ class ComposedHandler {
40376
41034
  }
40377
41035
  const endpoint = this.provider.getEndpoint(this.targetModel);
40378
41036
  const headers = await this.provider.getHeaders();
40379
- headers["Content-Type"] = "application/json";
41037
+ const serialized = this.provider.serializeBody?.(requestPayload);
41038
+ headers["Content-Type"] = serialized?.contentType ?? "application/json";
40380
41039
  log(`[${this.provider.displayName}] Calling API: ${endpoint}`);
40381
41040
  const requestInit = this.provider.getRequestInit?.() || {};
40382
41041
  const doFetch = () => fetch(endpoint, {
40383
41042
  method: "POST",
40384
41043
  headers,
40385
- body: JSON.stringify(requestPayload),
41044
+ body: serialized?.body ?? JSON.stringify(requestPayload),
40386
41045
  ...requestInit
40387
41046
  });
40388
41047
  let response;
@@ -40391,9 +41050,9 @@ class ComposedHandler {
40391
41050
  } catch (error46) {
40392
41051
  const conn = classifyConnectionError(error46);
40393
41052
  if (conn) {
40394
- const msg = buildConnectionErrorMessage(conn.kind, this.provider.displayName, endpoint);
40395
- log(`[${this.provider.displayName}] ${msg} (code=${conn.code})`);
40396
- logStderr(`Error: ${msg}`);
41053
+ const msg2 = buildConnectionErrorMessage(conn.kind, this.provider.displayName, endpoint);
41054
+ log(`[${this.provider.displayName}] ${msg2} (code=${conn.code})`);
41055
+ logStderr(`Error: ${msg2}`);
40397
41056
  reportError({
40398
41057
  error: error46,
40399
41058
  providerName: this.provider.name,
@@ -40425,7 +41084,7 @@ class ComposedHandler {
40425
41084
  invocation_mode: this.options.invocationMode ?? "auto-route"
40426
41085
  });
40427
41086
  } catch {}
40428
- return c.json(wrapAnthropicError(400, msg, "connection_error"), 400);
41087
+ return c.json(wrapAnthropicError(400, msg2, "connection_error"), 400);
40429
41088
  }
40430
41089
  throw error46;
40431
41090
  }
@@ -40442,12 +41101,12 @@ class ComposedHandler {
40442
41101
  try {
40443
41102
  await this.provider.forceRefreshAuth();
40444
41103
  const retryHeaders = await this.provider.getHeaders();
40445
- retryHeaders["Content-Type"] = "application/json";
41104
+ retryHeaders["Content-Type"] = serialized?.contentType ?? "application/json";
40446
41105
  const retryInit = this.provider.getRequestInit?.() || {};
40447
41106
  const retryResp = await fetch(endpoint, {
40448
41107
  method: "POST",
40449
41108
  headers: retryHeaders,
40450
- body: JSON.stringify(requestPayload),
41109
+ body: serialized?.body ?? JSON.stringify(requestPayload),
40451
41110
  ...retryInit
40452
41111
  });
40453
41112
  if (retryResp.ok) {
@@ -40627,6 +41286,48 @@ class ComposedHandler {
40627
41286
  }
40628
41287
  response = settled.response;
40629
41288
  }
41289
+ if (this.resolveStreamFormat() === "connect-proto") {
41290
+ const settled = await this.settleDevinStreamHead(response, () => this.provider.enqueueRequest ? this.provider.enqueueRequest(doFetch) : doFetch());
41291
+ if (settled.kind !== "ok") {
41292
+ const isTerminal2 = settled.kind === "terminal";
41293
+ const httpStatus2 = isTerminal2 ? 400 : 503;
41294
+ const surfaced = isTerminal2 ? `${this.provider.displayName} rejected the request (${settled.code}): ${settled.message}` : `${this.provider.displayName} is overloaded upstream (${settled.code}): ${settled.message} ` + `claudish retried ${settled.attempts}\xD7 over ` + `${Math.round(STREAM_RETRY_DELAYS_MS.slice(0, settled.attempts).reduce((sum, ms) => sum + ms, 0) / 1000)}s without success.`;
41295
+ logStderr(`Error: ${surfaced}`);
41296
+ reportError({
41297
+ error: new Error(settled.message),
41298
+ providerName: this.provider.name,
41299
+ providerDisplayName: this.provider.displayName,
41300
+ streamFormat: this.provider.streamFormat,
41301
+ modelId: this.targetModel,
41302
+ httpStatus: httpStatus2,
41303
+ isStreaming: true,
41304
+ retryAttempted: !isTerminal2,
41305
+ isInteractive: this.isInteractive,
41306
+ providerErrorType: settled.code
41307
+ });
41308
+ try {
41309
+ recordStats({
41310
+ model_id: this.targetModel,
41311
+ provider_name: this.provider.name,
41312
+ stream_format: this.provider.streamFormat,
41313
+ latency_ms: Math.round(performance.now() - startTime),
41314
+ success: false,
41315
+ http_status: httpStatus2,
41316
+ error_class: isTerminal2 ? "client_error" : "server_error",
41317
+ error_code: settled.code,
41318
+ token_strategy: this.options.tokenStrategy ?? "standard",
41319
+ adapter_name: this.getActiveAdapterName(),
41320
+ middleware_names: this.middlewareManager.getActiveNames(this.bareModelName),
41321
+ fallback_used: fallbackMeta !== undefined,
41322
+ fallback_chain: fallbackMeta?.chain,
41323
+ fallback_attempts: fallbackMeta?.attempts,
41324
+ invocation_mode: this.options.invocationMode ?? "auto-route"
41325
+ });
41326
+ } catch {}
41327
+ return isTerminal2 ? c.json(wrapAnthropicError(400, surfaced, "invalid_request_error"), 400) : c.json(wrapAnthropicError(503, surfaced, "overloaded_error"), 503);
41328
+ }
41329
+ response = settled.response;
41330
+ }
40630
41331
  latencyMs = Math.round(performance.now() - startTime);
40631
41332
  const httpStatus = response.status;
40632
41333
  this.capturePlanUsage(response);
@@ -40705,6 +41406,55 @@ class ComposedHandler {
40705
41406
  response = next;
40706
41407
  }
40707
41408
  }
41409
+ async settleDevinStreamHead(initial, reissue) {
41410
+ const rewrite = this.provider.rewriteInStreamError?.bind(this.provider);
41411
+ let response = initial;
41412
+ for (let attempt = 0;; attempt++) {
41413
+ const verdict = await sniffDevinStreamHead(response, { log });
41414
+ if (verdict.kind === "clean")
41415
+ return { kind: "ok", response: verdict.response };
41416
+ if (verdict.kind === "terminal") {
41417
+ const message = rewrite?.(verdict.code, verdict.message) ?? verdict.message;
41418
+ log(`[${this.provider.displayName}] terminal in-stream error ${verdict.code}`);
41419
+ return { kind: "terminal", code: verdict.code, message };
41420
+ }
41421
+ const delayMs = STREAM_RETRY_DELAYS_MS[attempt];
41422
+ if (delayMs === undefined) {
41423
+ log(`[${this.provider.displayName}] in-stream ${verdict.code} persisted after ` + `${attempt} retries \u2014 surfacing 503 so the client can retry`);
41424
+ return {
41425
+ kind: "exhausted",
41426
+ code: verdict.code,
41427
+ message: verdict.message,
41428
+ attempts: attempt
41429
+ };
41430
+ }
41431
+ log(`[${this.provider.displayName}] in-stream ${verdict.code} before any output \u2014 ` + `retry ${attempt + 1}/${STREAM_RETRY_DELAYS_MS.length} in ${delayMs / 1000}s`);
41432
+ await new Promise((resolve2) => setTimeout(resolve2, delayMs));
41433
+ let next;
41434
+ try {
41435
+ next = await reissue();
41436
+ } catch (error46) {
41437
+ log(`[${this.provider.displayName}] retry fetch failed: ${error46}`);
41438
+ return {
41439
+ kind: "exhausted",
41440
+ code: verdict.code,
41441
+ message: `${verdict.message} (retry could not reach the provider: ${error46})`,
41442
+ attempts: attempt + 1
41443
+ };
41444
+ }
41445
+ if (!next.ok) {
41446
+ const body = await next.text().catch(() => "");
41447
+ log(`[${this.provider.displayName}] retry returned HTTP ${next.status}`);
41448
+ return {
41449
+ kind: "exhausted",
41450
+ code: `http_${next.status}`,
41451
+ message: body.slice(0, 500) || `HTTP ${next.status}`,
41452
+ attempts: attempt + 1
41453
+ };
41454
+ }
41455
+ response = next;
41456
+ }
41457
+ }
40708
41458
  resolveStreamFormat() {
40709
41459
  return this.provider.overrideStreamFormat?.() ?? this.explicitAdapter?.getStreamFormat() ?? this.modelAdapter?.getStreamFormat() ?? this.getAdapter().getStreamFormat();
40710
41460
  }
@@ -40790,6 +41540,23 @@ class ComposedHandler {
40790
41540
  priorInputTokens
40791
41541
  });
40792
41542
  }
41543
+ case "connect-proto":
41544
+ return createDevinConnectStream(c, response, {
41545
+ modelName: this.bareModelName,
41546
+ onTokenUpdate,
41547
+ priorInputTokens,
41548
+ onApiError,
41549
+ toolNameMap,
41550
+ onServedModel: (uid) => {
41551
+ if (uid !== this.bareModelName)
41552
+ this.tokenTracker.setActiveModelName(uid);
41553
+ },
41554
+ repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null,
41555
+ shouldBufferTool: (name) => behaviorSession?.interceptsTool(name) ?? false,
41556
+ onAssistantText: (text, kind) => behaviorSession?.observeText(text, kind),
41557
+ onToolCallObserved: (name) => behaviorSession?.observeToolCall(name),
41558
+ onTurnEnd: () => behaviorSession?.finishTurn()
41559
+ });
40793
41560
  case "ollama-jsonl":
40794
41561
  return createOllamaJsonlStream(c, response, {
40795
41562
  modelName: this.bareModelName,
@@ -40894,10 +41661,12 @@ var init_composed_handler = __esm(() => {
40894
41661
  init_anthropic_error();
40895
41662
  init_connection_error();
40896
41663
  init_context_window_fallback();
41664
+ init_devin_stream_head_sniffer();
40897
41665
  init_openai_compat();
40898
41666
  init_quota_exhaustion();
40899
41667
  init_stream_head_sniffer();
40900
41668
  init_anthropic_sse();
41669
+ init_devin_connect();
40901
41670
  init_gemini_sse();
40902
41671
  init_ollama_jsonl();
40903
41672
  init_openai_responses_sse();
@@ -40906,6 +41675,209 @@ var init_composed_handler = __esm(() => {
40906
41675
  STREAM_RETRY_DELAYS_MS = [3000, 15000, 30000];
40907
41676
  });
40908
41677
 
41678
+ // src/providers/devin/devin-request.ts
41679
+ import { randomUUID as randomUUID4 } from "crypto";
41680
+ function encodeChatMetadata(meta3) {
41681
+ const version2 = meta3.clientVersion ?? DEVIN_CLI_VERSION;
41682
+ return msg(bytes(1, "devin-cli"), bytes(2, version2), bytes(3, meta3.apiKey), bytes(4, "en"), bytes(5, meta3.platform ?? process.platform), bytes(7, version2), bytes(12, "chisel"), bytes(28, "chisel"));
41683
+ }
41684
+ function encodeMessage(message) {
41685
+ const parts = [
41686
+ bytes(1, message.id ?? randomUUID4()),
41687
+ vint(2, DEVIN_ROLE[message.role])
41688
+ ];
41689
+ if (message.text)
41690
+ parts.push(bytes(3, message.text));
41691
+ if (message.toolCall) {
41692
+ parts.push(bytes(6, msg(bytes(1, message.toolCall.id), bytes(2, message.toolCall.name), bytes(3, message.toolCall.argumentsJson))));
41693
+ }
41694
+ if (message.toolCallId)
41695
+ parts.push(bytes(7, message.toolCallId));
41696
+ return msg(...parts);
41697
+ }
41698
+ function encodeTool(tool) {
41699
+ return msg(bytes(1, tool.name), bytes(2, tool.description ?? ""), bytes(3, tool.parametersJson));
41700
+ }
41701
+ function encodeRequestBodyParts(req) {
41702
+ const parts = [];
41703
+ if (req.system)
41704
+ parts.push(bytes(2, req.system));
41705
+ for (const message of req.messages)
41706
+ parts.push(bytes(3, encodeMessage(message)));
41707
+ parts.push(vint(7, req.modelEnum ?? DEFAULT_MODEL_ENUM));
41708
+ for (const tool of req.tools ?? [])
41709
+ parts.push(bytes(10, encodeTool(tool)));
41710
+ parts.push(bytes(21, req.modelUid));
41711
+ return parts;
41712
+ }
41713
+ function encodeDevinRequest(req, meta3) {
41714
+ const body = msg(bytes(1, encodeChatMetadata(meta3)), ...encodeRequestBodyParts(req));
41715
+ return envelope(body);
41716
+ }
41717
+ function describeDevinRequestForLog(req) {
41718
+ const roles = { user: 0, assistant: 0, tool_result: 0 };
41719
+ let toolCalls = 0;
41720
+ for (const message of req.messages) {
41721
+ roles[message.role]++;
41722
+ if (message.toolCall)
41723
+ toolCalls++;
41724
+ }
41725
+ const size = encodeRequestBodyParts(req).reduce((total, part) => total + part.length, 0);
41726
+ const fields = [
41727
+ `uid=${req.modelUid}`,
41728
+ `enum=${req.modelEnum ?? DEFAULT_MODEL_ENUM}`,
41729
+ `messages=${req.messages.length}`,
41730
+ `(user ${roles.user}/assistant ${roles.assistant}/tool_result ${roles.tool_result}`,
41731
+ `calls ${toolCalls})`,
41732
+ `tools=${req.tools?.length ?? 0}`,
41733
+ `system=${req.system?.length ?? 0}ch`
41734
+ ];
41735
+ fields.push(`body=${size}B (excl. metadata)`);
41736
+ return fields.join(" ");
41737
+ }
41738
+ var DEVIN_CLI_VERSION = "3000.3.27", DEFAULT_MODEL_ENUM = 5, DEVIN_ROLE;
41739
+ var init_devin_request = __esm(() => {
41740
+ init_proto_codec();
41741
+ DEVIN_ROLE = {
41742
+ user: 1,
41743
+ assistant: 2,
41744
+ tool_result: 4
41745
+ };
41746
+ });
41747
+
41748
+ // src/providers/devin/devin-models.ts
41749
+ var exports_devin_models = {};
41750
+ __export(exports_devin_models, {
41751
+ getServedDevinModels: () => getServedDevinModels,
41752
+ fetchDevinModelConfigs: () => fetchDevinModelConfigs,
41753
+ fetchDevinAllowedUids: () => fetchDevinAllowedUids,
41754
+ _resetDevinModelCache: () => _resetDevinModelCache
41755
+ });
41756
+ function unaryMetadata(apiKey) {
41757
+ return msg(bytes(1, "chisel"), bytes(2, DEVIN_CLI_VERSION), bytes(3, apiKey), bytes(4, "en"), bytes(5, process.platform), bytes(7, DEVIN_CLI_VERSION));
41758
+ }
41759
+ async function postUnary(path, apiKey) {
41760
+ const url2 = `${readDevinServerUrl()}${path}`;
41761
+ try {
41762
+ const response = await fetch(url2, {
41763
+ method: "POST",
41764
+ headers: {
41765
+ authorization: `Basic ${apiKey}-${apiKey}`,
41766
+ "content-type": "application/proto",
41767
+ "connect-protocol-version": "1"
41768
+ },
41769
+ body: msg(bytes(1, unaryMetadata(apiKey))),
41770
+ signal: AbortSignal.timeout(UNARY_TIMEOUT_MS)
41771
+ });
41772
+ if (!response.ok) {
41773
+ log(`[Devin] ${path} failed: HTTP ${response.status}`);
41774
+ return null;
41775
+ }
41776
+ return new Uint8Array(await response.arrayBuffer());
41777
+ } catch (err) {
41778
+ log(`[Devin] ${path} error: ${err}`);
41779
+ return null;
41780
+ }
41781
+ }
41782
+ function decodeModelDetails(payload) {
41783
+ let maxOutput = 0;
41784
+ let family = "";
41785
+ for (const sub of parseTLV(payload)) {
41786
+ if (sub.no === 13 && sub.wire === 0)
41787
+ maxOutput = readVarintValue(sub);
41788
+ else if (sub.no === 23 && sub.wire === 2)
41789
+ family = readString(sub);
41790
+ }
41791
+ return { maxOutput, family };
41792
+ }
41793
+ function decodeModelConfig(payload) {
41794
+ let uid = "";
41795
+ let displayName = "";
41796
+ let contextWindow = 0;
41797
+ let details = { maxOutput: 0, family: "" };
41798
+ for (const field of parseTLV(payload)) {
41799
+ if (field.no === 22 && field.wire === 2)
41800
+ uid = readString(field);
41801
+ else if (field.no === 1 && field.wire === 2)
41802
+ displayName = readString(field);
41803
+ else if (field.no === 18 && field.wire === 0)
41804
+ contextWindow = readVarintValue(field);
41805
+ else if (field.no === 23 && field.wire === 2)
41806
+ details = decodeModelDetails(field.payload);
41807
+ }
41808
+ if (!uid)
41809
+ return null;
41810
+ return { uid, displayName: displayName || uid, contextWindow, ...details };
41811
+ }
41812
+ function topLevelDelimited(body, fieldNumber) {
41813
+ return parseTLV(body).filter((field) => field.no === fieldNumber && field.wire === 2);
41814
+ }
41815
+ async function fetchDevinModelConfigs(apiKey) {
41816
+ const body = await postUnary(MODEL_CONFIGS_PATH, apiKey);
41817
+ if (!body)
41818
+ return [];
41819
+ const configs = [];
41820
+ for (const field of topLevelDelimited(body, 1)) {
41821
+ const config2 = decodeModelConfig(field.payload);
41822
+ if (config2)
41823
+ configs.push(config2);
41824
+ }
41825
+ log(`[Devin] GetCliModelConfigs: ${configs.length} configs`);
41826
+ return configs;
41827
+ }
41828
+ async function fetchDevinAllowedUids(apiKey) {
41829
+ const body = await postUnary(TEAM_SETTINGS_PATH, apiKey);
41830
+ if (!body)
41831
+ return [];
41832
+ const uids = [];
41833
+ for (const field of topLevelDelimited(body, 7)) {
41834
+ const uid = readString(field).trim();
41835
+ if (uid)
41836
+ uids.push(uid);
41837
+ }
41838
+ log(`[Devin] GetCliTeamSettings: ${uids.length} allowed uids`);
41839
+ return uids;
41840
+ }
41841
+ async function getServedDevinModels(opts) {
41842
+ const now = Date.now();
41843
+ if (!opts?.force && rosterCache && now - rosterCacheAt < ROSTER_TTL_MS)
41844
+ return rosterCache;
41845
+ const apiKey = opts?.apiKey ?? readDevinApiKey();
41846
+ if (!apiKey)
41847
+ return rosterCache ?? [];
41848
+ try {
41849
+ const [configs, allowed] = await Promise.all([
41850
+ fetchDevinModelConfigs(apiKey),
41851
+ fetchDevinAllowedUids(apiKey)
41852
+ ]);
41853
+ if (configs.length === 0)
41854
+ return rosterCache ?? [];
41855
+ const entitled = new Set(allowed);
41856
+ const served = configs.filter((config2) => config2.contextWindow > 0 && (entitled.size === 0 || entitled.has(config2.uid)));
41857
+ if (entitled.size === 0) {
41858
+ log("[Devin] entitlement unknown \u2014 using the full config list (superset)");
41859
+ }
41860
+ rosterCache = served;
41861
+ rosterCacheAt = now;
41862
+ return served;
41863
+ } catch (err) {
41864
+ log(`[Devin] served-model discovery error: ${err}`);
41865
+ return rosterCache ?? [];
41866
+ }
41867
+ }
41868
+ function _resetDevinModelCache() {
41869
+ rosterCache = null;
41870
+ rosterCacheAt = 0;
41871
+ }
41872
+ var MODEL_CONFIGS_PATH = "/exa.api_server_pb.ApiServerService/GetCliModelConfigs", TEAM_SETTINGS_PATH = "/exa.seat_management_pb.SeatManagementService/GetCliTeamSettings", ROSTER_TTL_MS, UNARY_TIMEOUT_MS = 1e4, rosterCache = null, rosterCacheAt = 0;
41873
+ var init_devin_models = __esm(() => {
41874
+ init_logger();
41875
+ init_devin_credentials();
41876
+ init_devin_request();
41877
+ init_proto_codec();
41878
+ ROSTER_TTL_MS = 5 * 60 * 1000;
41879
+ });
41880
+
40909
41881
  // src/providers/model-discovery.ts
40910
41882
  function resolveBaseUrl(catalogName) {
40911
41883
  const def = getProviderByName(catalogName);
@@ -40966,6 +41938,22 @@ async function discoverProviderModels(providerName) {
40966
41938
  const descriptor = def?.modelDiscovery;
40967
41939
  if (!def || !descriptor)
40968
41940
  return [];
41941
+ if (descriptor.format === "devin-connect") {
41942
+ const { getServedDevinModels: getServedDevinModels2 } = await Promise.resolve().then(() => (init_devin_models(), exports_devin_models));
41943
+ const served = await getServedDevinModels2();
41944
+ if (served.length === 0) {
41945
+ log(`[model-discovery:${providerName}] no models for this subscription`);
41946
+ return [];
41947
+ }
41948
+ const models2 = served.map((model) => ({
41949
+ id: model.uid,
41950
+ displayName: model.displayName,
41951
+ contextWindow: model.contextWindow
41952
+ }));
41953
+ log(`[model-discovery:${providerName}] discovered ${models2.length} models`);
41954
+ _cache.set(providerName, { models: models2, expiresAt: Date.now() + CACHE_TTL_MS });
41955
+ return models2;
41956
+ }
40969
41957
  const baseUrl = resolveBaseUrl(providerName);
40970
41958
  if (!baseUrl)
40971
41959
  return [];
@@ -41140,24 +42128,24 @@ async function discoverViaOpenAIModels(endpoint, headers, cacheKey) {
41140
42128
  function classifyFetchError(e, endpoint) {
41141
42129
  const name = e?.name ?? "";
41142
42130
  const code = e?.cause?.code ?? "";
41143
- const msg = e instanceof Error ? e.message : String(e);
42131
+ const msg2 = e instanceof Error ? e.message : String(e);
41144
42132
  const url2 = tryParseUrl(endpoint);
41145
42133
  const host = url2?.host ?? endpoint;
41146
42134
  const isLocal = !!url2 && /^(localhost|127\.0\.0\.1|0\.0\.0\.0|::1)$/i.test(url2.hostname);
41147
- if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg)) {
42135
+ if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg2)) {
41148
42136
  return `${host} unresponsive (>${FETCH_TIMEOUT_MS2 / 1000}s) \u2014 check if the server is overloaded`;
41149
42137
  }
41150
42138
  if (code === "ENOTFOUND" || code === "EAI_AGAIN") {
41151
42139
  return `cannot resolve host ${url2?.hostname ?? endpoint} \u2014 check the URL`;
41152
42140
  }
41153
- const isConnRefused = code === "ECONNREFUSED" || code === "ECONNRESET" || /unable to connect|connection refused|fetch failed/i.test(msg);
42141
+ const isConnRefused = code === "ECONNREFUSED" || code === "ECONNRESET" || /unable to connect|connection refused|fetch failed/i.test(msg2);
41154
42142
  if (isConnRefused) {
41155
42143
  if (isLocal) {
41156
42144
  return `${host} not reachable \u2014 is the server running? Press u to change URL.`;
41157
42145
  }
41158
42146
  return `${host} not reachable \u2014 check the URL or network. Press u to change.`;
41159
42147
  }
41160
- return `${host}: ${msg}`;
42148
+ return `${host}: ${msg2}`;
41161
42149
  }
41162
42150
  function tryParseUrl(s) {
41163
42151
  try {
@@ -42184,6 +43172,10 @@ function buildCredentialHint(modelName, providers) {
42184
43172
  lines.push(` Run: claudish ${hint.loginFlag} (authenticate via OAuth)`);
42185
43173
  hasOption = true;
42186
43174
  }
43175
+ if (hint.note) {
43176
+ lines.push(` ${hint.note}`);
43177
+ hasOption = true;
43178
+ }
42187
43179
  if (hint.apiKeyEnvVar) {
42188
43180
  lines.push(` Set: export ${hint.apiKeyEnvVar}=your-key (for ${provider})`);
42189
43181
  hasOption = true;
@@ -42206,6 +43198,10 @@ var init_routing_hints = __esm(() => {
42206
43198
  google: { loginFlag: "login gemini", apiKeyEnvVar: "GEMINI_API_KEY" },
42207
43199
  "gemini-codeassist": { loginFlag: "login gemini", apiKeyEnvVar: "GEMINI_API_KEY" },
42208
43200
  antigravity: { loginFlag: "login antigravity" },
43201
+ devin: {
43202
+ note: "Sign in with the Devin CLI (`devin login`) \u2014 claudish reads ~/.local/share/devin/credentials.toml",
43203
+ apiKeyEnvVar: "WINDSURF_API_KEY"
43204
+ },
42209
43205
  openai: { apiKeyEnvVar: "OPENAI_API_KEY" },
42210
43206
  "openai-codex": { loginFlag: "login codex", apiKeyEnvVar: "OPENAI_CODEX_API_KEY" },
42211
43207
  minimax: { apiKeyEnvVar: "MINIMAX_API_KEY" },
@@ -43108,10 +44104,10 @@ var init_signal_watcher = __esm(() => {
43108
44104
 
43109
44105
  // src/channel/session-manager.ts
43110
44106
  import { spawn } from "child_process";
43111
- import { randomUUID as randomUUID4 } from "crypto";
44107
+ import { randomUUID as randomUUID5 } from "crypto";
43112
44108
  import { createWriteStream, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "fs";
43113
- import { homedir as homedir24 } from "os";
43114
- import { join as join24 } from "path";
44109
+ import { homedir as homedir25 } from "os";
44110
+ import { join as join25 } from "path";
43115
44111
 
43116
44112
  class SessionManager {
43117
44113
  sessions = new Map;
@@ -43123,20 +44119,20 @@ class SessionManager {
43123
44119
  constructor(options) {
43124
44120
  this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
43125
44121
  this.scrollbackCapacity = options?.scrollbackCapacity ?? DEFAULT_SCROLLBACK;
43126
- this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join24(homedir24(), ".claudish", "sessions");
44122
+ this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join25(homedir25(), ".claudish", "sessions");
43127
44123
  this.onStateChange = options?.onStateChange;
43128
44124
  }
43129
44125
  createSession(opts) {
43130
44126
  if (this.activeSessions >= this.maxSessions) {
43131
44127
  throw new Error(`Max sessions (${this.maxSessions}) reached`);
43132
44128
  }
43133
- const sessionId2 = randomUUID4().slice(0, 8);
44129
+ const sessionId2 = randomUUID5().slice(0, 8);
43134
44130
  const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
43135
44131
  const startedAt = new Date().toISOString();
43136
- const sessionDir = join24(this.sessionsDir, sessionId2);
44132
+ const sessionDir = join25(this.sessionsDir, sessionId2);
43137
44133
  mkdirSync11(sessionDir, { recursive: true });
43138
44134
  if (opts.prompt) {
43139
- writeFileSync10(join24(sessionDir, "prompt.md"), opts.prompt, "utf-8");
44135
+ writeFileSync10(join25(sessionDir, "prompt.md"), opts.prompt, "utf-8");
43140
44136
  }
43141
44137
  const args = [
43142
44138
  "--model",
@@ -43170,7 +44166,7 @@ class SessionManager {
43170
44166
  });
43171
44167
  }
43172
44168
  });
43173
- const outputLogStream = createWriteStream(join24(sessionDir, "output.log"));
44169
+ const outputLogStream = createWriteStream(join25(sessionDir, "output.log"));
43174
44170
  const entry = {
43175
44171
  info: {
43176
44172
  sessionId: sessionId2,
@@ -43217,9 +44213,9 @@ class SessionManager {
43217
44213
  watcher.processExited(code);
43218
44214
  outputLogStream.end();
43219
44215
  if (entry.stderr) {
43220
- writeFileSync10(join24(sessionDir, "stderr.log"), entry.stderr, "utf-8");
44216
+ writeFileSync10(join25(sessionDir, "stderr.log"), entry.stderr, "utf-8");
43221
44217
  }
43222
- writeFileSync10(join24(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
44218
+ writeFileSync10(join25(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
43223
44219
  this.cleanupSigint();
43224
44220
  });
43225
44221
  proc.on("error", (err) => {
@@ -45295,8 +46291,8 @@ var init_openrouter_api_format = __esm(() => {
45295
46291
  convertMessages(claudeRequest, filterIdentityFn) {
45296
46292
  const messages = super.convertMessages(claudeRequest, filterIdentityFn);
45297
46293
  if (this.modelId.includes("grok") || this.modelId.includes("x-ai")) {
45298
- const msg = "IMPORTANT: When calling tools, you MUST use the OpenAI tool_calls format with JSON. NEVER use XML format like <xai:function_call>.";
45299
- this.appendToSystemPrompt(messages, msg);
46294
+ const msg2 = "IMPORTANT: When calling tools, you MUST use the OpenAI tool_calls format with JSON. NEVER use XML format like <xai:function_call>.";
46295
+ this.appendToSystemPrompt(messages, msg2);
45300
46296
  }
45301
46297
  if (this.modelId.includes("gemini") || this.modelId.includes("google/")) {
45302
46298
  const geminiMsg = `CRITICAL INSTRUCTION FOR OUTPUT FORMAT:
@@ -45616,12 +46612,12 @@ function rewriteAdvisorToolResults(payload, getAdviceFor) {
45616
46612
  if (!Array.isArray(messages))
45617
46613
  return [];
45618
46614
  const rewritten = [];
45619
- for (const msg of messages) {
45620
- if (!msg || typeof msg !== "object")
46615
+ for (const msg2 of messages) {
46616
+ if (!msg2 || typeof msg2 !== "object")
45621
46617
  continue;
45622
- if (msg.role !== "user")
46618
+ if (msg2.role !== "user")
45623
46619
  continue;
45624
- const content = msg.content;
46620
+ const content = msg2.content;
45625
46621
  if (!Array.isArray(content))
45626
46622
  continue;
45627
46623
  for (const block of content) {
@@ -45651,12 +46647,12 @@ function findPendingAdvisorToolResults(payload) {
45651
46647
  if (!Array.isArray(messages))
45652
46648
  return [];
45653
46649
  const found = [];
45654
- for (const msg of messages) {
45655
- if (!msg || typeof msg !== "object")
46650
+ for (const msg2 of messages) {
46651
+ if (!msg2 || typeof msg2 !== "object")
45656
46652
  continue;
45657
- if (msg.role !== "user")
46653
+ if (msg2.role !== "user")
45658
46654
  continue;
45659
- const content = msg.content;
46655
+ const content = msg2.content;
45660
46656
  if (!Array.isArray(content))
45661
46657
  continue;
45662
46658
  for (const block of content) {
@@ -46161,6 +47157,270 @@ var init_api_key_map = __esm(() => {
46161
47157
  };
46162
47158
  });
46163
47159
 
47160
+ // src/providers/devin/tool-descriptions.ts
47161
+ function currentMonthAndYear(now = new Date) {
47162
+ return `${MONTHS[now.getMonth()]} ${now.getFullYear()}`;
47163
+ }
47164
+ function buildWebSearchDescription(monthAndYear) {
47165
+ return `Runs a web search and lets you fold the results into your answer.
47166
+
47167
+ - Reaches live sources, so it covers current events and material recent enough to post-date your
47168
+ training data. This is the tool for any question that runs past your knowledge cutoff.
47169
+ - Results arrive as search-result blocks; links inside them are already written as markdown
47170
+ hyperlinks.
47171
+ - The entire search happens within a single API call \u2014 there is nothing extra to orchestrate.
47172
+
47173
+ NON-NEGOTIABLE OUTPUT REQUIREMENT \u2014 this is MANDATORY, and you must never skip it:
47174
+ - Once you have answered the user's question, the very end of your response MUST carry a section
47175
+ headed \`Sources:\`.
47176
+ - Beneath that heading, list every URL from the search results that is relevant to the answer,
47177
+ each written as a markdown hyperlink in the form [Title](URL).
47178
+ - Leaving the sources section out is not an option, however short or obvious the answer looks.
47179
+ - Shape of the finished response:
47180
+
47181
+ [your answer goes here]
47182
+
47183
+ Sources:
47184
+ - [First page title](https://first.example/page)
47185
+ - [Second page title](https://second.example/page)
47186
+
47187
+ Other things worth knowing:
47188
+ - Results can be confined by domain: \`allowed_domains\` restricts the search to specific sites,
47189
+ \`blocked_domains\` keeps named sites out.
47190
+ - Web search is served only within the United States.
47191
+
47192
+ Dates in queries \u2014 get the year right:
47193
+ - The present month is ${monthAndYear}. Any query about recent material, current documentation or
47194
+ ongoing events MUST be qualified with that year.
47195
+ - For example, asked for "latest React docs", search for React documentation carrying the current
47196
+ year, not the one before it.`;
47197
+ }
47198
+ function buildDevinToolDescriptions(now = new Date) {
47199
+ return new Map([
47200
+ ["Read", READ_DESCRIPTION],
47201
+ ["TaskOutput", TASK_OUTPUT_DESCRIPTION],
47202
+ ["WebSearch", buildWebSearchDescription(currentMonthAndYear(now))]
47203
+ ]);
47204
+ }
47205
+ function toolName(tool) {
47206
+ if (!tool || typeof tool !== "object")
47207
+ return;
47208
+ const record4 = tool;
47209
+ const nested = record4.function?.name;
47210
+ if (typeof nested === "string")
47211
+ return nested;
47212
+ return typeof record4.name === "string" ? record4.name : undefined;
47213
+ }
47214
+ function applyDevinToolDescriptions(tools, descriptions = DEVIN_TOOL_DESCRIPTIONS) {
47215
+ return tools.map((tool) => {
47216
+ const name = toolName(tool);
47217
+ const replacement = name === undefined ? undefined : descriptions.get(name);
47218
+ if (replacement === undefined)
47219
+ return tool;
47220
+ const record4 = tool;
47221
+ if (record4.function && typeof record4.function === "object") {
47222
+ return {
47223
+ ...record4,
47224
+ function: { ...record4.function, description: replacement }
47225
+ };
47226
+ }
47227
+ return { ...record4, description: replacement };
47228
+ });
47229
+ }
47230
+ var MONTHS, READ_DESCRIPTION = `Retrieves the contents of a single file from the machine's local disk.
47231
+
47232
+ Nothing on the host is out of bounds \u2014 assume you can open whatever you need. When the user hands
47233
+ you a path, take it at face value and try it; aiming at a file that turns out not to exist is
47234
+ harmless, the call simply comes back as an error.
47235
+
47236
+ Calling conventions:
47237
+ - \`file_path\` has to be a fully-qualified absolute path. A relative path will not be accepted.
47238
+ - Left unbounded, the call hands back at most the first 2000 lines, counted from the top of the file.
47239
+ - If you already know which region of the file matters, ask for that region alone. On large files
47240
+ this is the difference between a cheap call and an expensive one.
47241
+ - Output is formatted the way \`cat -n\` formats it: each line prefixed with its number, and the
47242
+ numbering begins at 1.
47243
+ - Image files work (PNG, JPG and the rest). The picture itself is handed over for you to look at,
47244
+ since the model behind this session takes visual input as well as text.
47245
+ - PDF documents work. Once a document runs past ten pages the \`pages\` argument becomes REQUIRED \u2014
47246
+ give it the span you want, for instance \`pages: "1-5"\`. Leaving \`pages\` off a long PDF makes the
47247
+ call fail outright. One request may cover twenty pages at most.
47248
+ - Jupyter notebooks (\`.ipynb\`) come back fully expanded: every cell together with the output that
47249
+ cell produced, so source, prose and rendered figures all arrive in one piece.
47250
+ - Files only, never directories. To find out what a folder holds, reach for the shell tool
47251
+ registered for this session.
47252
+ - Screenshots are a routine case. Whenever a path to a screenshot is supplied, view it through this
47253
+ tool rather than by any other route; paths inside temporary directories are fine.
47254
+ - Opening a file that exists but holds nothing gives you a system-reminder notice standing in for
47255
+ the file body.
47256
+ - Do not re-open a file just to confirm an edit you have already made. Had that Edit or Write
47257
+ failed it would have raised an error at the time, and the harness keeps track of each file's
47258
+ current state on your behalf.`, TASK_OUTPUT_DESCRIPTION = `DEPRECATED \u2014 in almost every case reach for Read instead.
47259
+
47260
+ The reason it is deprecated: a task launched in the background already reports the path of its
47261
+ output file as part of the tool result, and a <task-notification> quoting that same path arrives
47262
+ once the task finishes. The path is in front of you either way, so routing back through this tool
47263
+ buys nothing.
47264
+
47265
+ Which route to take, by task kind:
47266
+ - bash tasks \u2014 open the reported output path with Read. Both stdout and stderr are captured there.
47267
+ - local_agent tasks \u2014 take the answer straight from what the Agent tool returned. NEVER open the
47268
+ \`.output\` file with Read. That entry is a symlink pointing at the subagent's ENTIRE conversation
47269
+ transcript in JSONL form, and pulling it in WILL overflow your context window.
47270
+ - remote_agent tasks \u2014 open the reported output path with Read, exactly as for bash; it holds the
47271
+ remote session's streamed output.
47272
+
47273
+ If you call it anyway, this is what it does:
47274
+ - Fetches the output of a task that is either still running or already finished \u2014 a backgrounded
47275
+ shell, an agent, or a remote session.
47276
+ - Identifies which task through the \`task_id\` parameter.
47277
+ - Replies with the task's output alongside its status.
47278
+ - \`block=true\` is the default and makes the call wait until the task has completed.
47279
+ - \`block=false\` returns straight away with whatever the status is at that moment.
47280
+ - The \`/tasks\` command lists the ids you can pass.
47281
+ - Every task flavour is supported: backgrounded shells, asynchronous agents, and remote sessions.`, DEVIN_TOOL_DESCRIPTIONS;
47282
+ var init_tool_descriptions = __esm(() => {
47283
+ MONTHS = [
47284
+ "January",
47285
+ "February",
47286
+ "March",
47287
+ "April",
47288
+ "May",
47289
+ "June",
47290
+ "July",
47291
+ "August",
47292
+ "September",
47293
+ "October",
47294
+ "November",
47295
+ "December"
47296
+ ];
47297
+ DEVIN_TOOL_DESCRIPTIONS = buildDevinToolDescriptions();
47298
+ });
47299
+
47300
+ // src/adapters/devin-api-format.ts
47301
+ function contentToText(content) {
47302
+ if (typeof content === "string")
47303
+ return content;
47304
+ if (!Array.isArray(content))
47305
+ return "";
47306
+ const parts = [];
47307
+ for (const part of content) {
47308
+ if (typeof part === "string") {
47309
+ parts.push(part);
47310
+ continue;
47311
+ }
47312
+ if (part && typeof part === "object" && "text" in part) {
47313
+ const { text } = part;
47314
+ if (typeof text === "string")
47315
+ parts.push(text);
47316
+ }
47317
+ }
47318
+ return parts.join(`
47319
+ `);
47320
+ }
47321
+ var DEVIN_RELOCATION_NOTE, DEVIN_MINIMAL_SYSTEM = "You are a coding agent.", DevinAPIFormat;
47322
+ var init_devin_api_format = __esm(() => {
47323
+ init_tool_descriptions();
47324
+ init_base_api_format();
47325
+ DEVIN_RELOCATION_NOTE = "You are a coding agent. Your complete operating instructions for this session are supplied " + "in the first user message, inside <system_instructions> tags. Treat everything inside those " + "tags as your system prompt and follow it exactly.";
47326
+ DevinAPIFormat = class DevinAPIFormat extends BaseAPIFormat {
47327
+ processTextContent(textContent, _accumulatedText) {
47328
+ return {
47329
+ cleanedText: textContent,
47330
+ extractedToolCalls: [],
47331
+ wasTransformed: false
47332
+ };
47333
+ }
47334
+ shouldHandle(_modelId) {
47335
+ return false;
47336
+ }
47337
+ getName() {
47338
+ return "DevinAPIFormat";
47339
+ }
47340
+ getStreamFormat() {
47341
+ return "connect-proto";
47342
+ }
47343
+ getContextWindow() {
47344
+ return 0;
47345
+ }
47346
+ supportsVision() {
47347
+ return false;
47348
+ }
47349
+ applyNativeReasoning(request, originalRequest) {
47350
+ const effort = this.resolveEffortLevel(originalRequest);
47351
+ if (effort)
47352
+ request.effort = effort;
47353
+ return request;
47354
+ }
47355
+ buildPayload(_claudeRequest, messages, tools) {
47356
+ const systemParts = [];
47357
+ const devinMessages = [];
47358
+ for (const message of messages) {
47359
+ const role = message?.role;
47360
+ if (role === "system") {
47361
+ const text = contentToText(message.content);
47362
+ if (text)
47363
+ systemParts.push(text);
47364
+ continue;
47365
+ }
47366
+ if (role === "tool") {
47367
+ devinMessages.push({
47368
+ role: "tool_result",
47369
+ text: contentToText(message.content),
47370
+ toolCallId: message.tool_call_id
47371
+ });
47372
+ continue;
47373
+ }
47374
+ if (role === "assistant") {
47375
+ const text = contentToText(message.content);
47376
+ if (text)
47377
+ devinMessages.push({ role: "assistant", text });
47378
+ for (const call of message.tool_calls ?? []) {
47379
+ devinMessages.push({
47380
+ role: "assistant",
47381
+ toolCall: {
47382
+ id: call?.id ?? "",
47383
+ name: call?.function?.name ?? "",
47384
+ argumentsJson: call?.function?.arguments || "{}"
47385
+ }
47386
+ });
47387
+ }
47388
+ continue;
47389
+ }
47390
+ devinMessages.push({ role: "user", text: contentToText(message.content) });
47391
+ }
47392
+ const devinTools = applyDevinToolDescriptions(tools).map((tool) => ({
47393
+ name: tool?.function?.name ?? tool?.name ?? "",
47394
+ description: tool?.function?.description ?? tool?.description ?? "",
47395
+ parametersJson: JSON.stringify(tool?.function?.parameters ?? tool?.parameters ?? { type: "object", properties: {} })
47396
+ }));
47397
+ let system;
47398
+ if (systemParts.length > 0) {
47399
+ devinMessages.unshift({
47400
+ role: "user",
47401
+ text: `<system_instructions>
47402
+ ${systemParts.join(`
47403
+
47404
+ `)}
47405
+ </system_instructions>`
47406
+ });
47407
+ system = DEVIN_RELOCATION_NOTE;
47408
+ } else if (devinTools.length > 0) {
47409
+ system = DEVIN_MINIMAL_SYSTEM;
47410
+ }
47411
+ const payload = {
47412
+ modelUid: this.modelId,
47413
+ messages: devinMessages
47414
+ };
47415
+ if (system)
47416
+ payload.system = system;
47417
+ if (devinTools.length > 0)
47418
+ payload.tools = devinTools;
47419
+ return payload;
47420
+ }
47421
+ };
47422
+ });
47423
+
46164
47424
  // src/adapters/ollama-api-format.ts
46165
47425
  var OllamaAPIFormat;
46166
47426
  var init_ollama_api_format = __esm(() => {
@@ -46188,11 +47448,11 @@ var init_ollama_api_format = __esm(() => {
46188
47448
  messages.push({ role: "system", content });
46189
47449
  }
46190
47450
  if (claudeRequest.messages) {
46191
- for (const msg of claudeRequest.messages) {
46192
- if (msg.role === "user") {
46193
- messages.push(this.processUserMessage(msg));
46194
- } else if (msg.role === "assistant") {
46195
- messages.push(this.processAssistantMessage(msg));
47451
+ for (const msg2 of claudeRequest.messages) {
47452
+ if (msg2.role === "user") {
47453
+ messages.push(this.processUserMessage(msg2));
47454
+ } else if (msg2.role === "assistant") {
47455
+ messages.push(this.processAssistantMessage(msg2));
46196
47456
  }
46197
47457
  }
46198
47458
  }
@@ -46217,10 +47477,10 @@ var init_ollama_api_format = __esm(() => {
46217
47477
  supportsVision() {
46218
47478
  return false;
46219
47479
  }
46220
- processUserMessage(msg) {
46221
- if (Array.isArray(msg.content)) {
47480
+ processUserMessage(msg2) {
47481
+ if (Array.isArray(msg2.content)) {
46222
47482
  const textParts = [];
46223
- for (const block of msg.content) {
47483
+ for (const block of msg2.content) {
46224
47484
  if (block.type === "text") {
46225
47485
  textParts.push(block.text);
46226
47486
  } else if (block.type === "tool_result") {
@@ -46232,12 +47492,12 @@ var init_ollama_api_format = __esm(() => {
46232
47492
 
46233
47493
  `) };
46234
47494
  }
46235
- return { role: "user", content: msg.content };
47495
+ return { role: "user", content: msg2.content };
46236
47496
  }
46237
- processAssistantMessage(msg) {
46238
- if (Array.isArray(msg.content)) {
47497
+ processAssistantMessage(msg2) {
47498
+ if (Array.isArray(msg2.content)) {
46239
47499
  const strings = [];
46240
- for (const block of msg.content) {
47500
+ for (const block of msg2.content) {
46241
47501
  if (block.type === "text") {
46242
47502
  strings.push(block.text);
46243
47503
  } else if (block.type === "tool_use") {
@@ -46247,17 +47507,17 @@ var init_ollama_api_format = __esm(() => {
46247
47507
  return { role: "assistant", content: strings.join(`
46248
47508
  `) };
46249
47509
  }
46250
- return { role: "assistant", content: msg.content };
47510
+ return { role: "assistant", content: msg2.content };
46251
47511
  }
46252
47512
  };
46253
47513
  });
46254
47514
 
46255
47515
  // src/providers/api-key-provenance.ts
46256
- import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
46257
- import { homedir as homedir25 } from "os";
46258
- import { join as join25, resolve as resolve2 } from "path";
47516
+ import { existsSync as existsSync17, readFileSync as readFileSync16 } from "fs";
47517
+ import { homedir as homedir26 } from "os";
47518
+ import { join as join26, resolve as resolve2 } from "path";
46259
47519
  function activeConfigPath() {
46260
- return activeGlobalConfigFile(join25(homedir25(), ".claudish", "config.json"));
47520
+ return activeGlobalConfigFile(join26(homedir26(), ".claudish", "config.json"));
46261
47521
  }
46262
47522
  function configLayerLabel() {
46263
47523
  return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
@@ -46336,7 +47596,7 @@ function readDotenvKey(envVars) {
46336
47596
  const dotenvPath = resolve2(".env");
46337
47597
  if (!existsSync17(dotenvPath))
46338
47598
  return null;
46339
- const parsed = import_dotenv.parse(readFileSync15(dotenvPath, "utf-8"));
47599
+ const parsed = import_dotenv.parse(readFileSync16(dotenvPath, "utf-8"));
46340
47600
  for (const v of envVars) {
46341
47601
  if (parsed[v])
46342
47602
  return parsed[v];
@@ -46351,7 +47611,7 @@ function readConfigKey(envVar) {
46351
47611
  const configPath = activeConfigPath();
46352
47612
  if (!existsSync17(configPath))
46353
47613
  return null;
46354
- const cfg = JSON.parse(readFileSync15(configPath, "utf-8"));
47614
+ const cfg = JSON.parse(readFileSync16(configPath, "utf-8"));
46355
47615
  return cfg.apiKeys?.[envVar] || null;
46356
47616
  } catch {
46357
47617
  return null;
@@ -46363,6 +47623,161 @@ var init_api_key_provenance = __esm(() => {
46363
47623
  import_dotenv = __toESM(require_main(), 1);
46364
47624
  });
46365
47625
 
47626
+ // src/providers/devin/model-id-resolver.ts
47627
+ function parseDevinUidTier(uid) {
47628
+ let base = uid.trim();
47629
+ let fast = false;
47630
+ if (base.toLowerCase().endsWith(FAST_SUFFIX)) {
47631
+ fast = true;
47632
+ base = base.slice(0, -FAST_SUFFIX.length);
47633
+ }
47634
+ const match2 = base.match(TIER_SUFFIX_RE);
47635
+ const candidate = match2?.[1]?.toLowerCase();
47636
+ return { tier: isEffortLevel(candidate) ? candidate : null, fast };
47637
+ }
47638
+ function effortIndex(level) {
47639
+ return EFFORT_LEVELS.indexOf(level);
47640
+ }
47641
+ function resolveDevinModelUid(requested, effort, served) {
47642
+ const req = requested.trim();
47643
+ if (!req || served.length === 0)
47644
+ return req || requested;
47645
+ const lower = req.toLowerCase();
47646
+ const exact = served.find((model) => model.uid.toLowerCase() === lower);
47647
+ if (exact)
47648
+ return exact.uid;
47649
+ const prefix = `${lower}-`;
47650
+ const candidates = served.filter((model) => model.family.toLowerCase() === lower || model.uid.toLowerCase().startsWith(prefix));
47651
+ if (candidates.length === 0)
47652
+ return req;
47653
+ const nonFast = candidates.filter((model) => !parseDevinUidTier(model.uid).fast);
47654
+ const pool = nonFast.length > 0 ? nonFast : candidates;
47655
+ if (pool.length === 1)
47656
+ return pool[0].uid;
47657
+ const tiered = pool.map((model) => ({ model, tier: parseDevinUidTier(model.uid).tier })).filter((entry) => entry.tier !== null);
47658
+ if (tiered.length === 0)
47659
+ return pool[0].uid;
47660
+ const target = effort ? effortIndex(effort) : EFFORT_LEVELS.length - 1;
47661
+ let best = tiered[0];
47662
+ let bestDistance = Number.POSITIVE_INFINITY;
47663
+ for (const entry of tiered) {
47664
+ const distance = Math.abs(effortIndex(entry.tier) - target);
47665
+ if (distance < bestDistance || distance === bestDistance && effortIndex(entry.tier) > effortIndex(best.tier)) {
47666
+ best = entry;
47667
+ bestDistance = distance;
47668
+ }
47669
+ }
47670
+ return best.model.uid;
47671
+ }
47672
+ var FAST_SUFFIX = "-fast", TIER_SUFFIX_RE;
47673
+ var init_model_id_resolver = __esm(() => {
47674
+ init_base_api_format();
47675
+ TIER_SUFFIX_RE = new RegExp(`-(${[...EFFORT_LEVELS].sort((a, b) => b.length - a.length).join("|")})$`, "i");
47676
+ });
47677
+
47678
+ // src/providers/transport/devin.ts
47679
+ class DevinProviderTransport {
47680
+ name = "devin";
47681
+ displayName = "Devin";
47682
+ streamFormat = "connect-proto";
47683
+ modelName;
47684
+ cachedAuth = null;
47685
+ served = [];
47686
+ resolvedUid;
47687
+ constructor(modelName) {
47688
+ this.modelName = modelName;
47689
+ this.resolvedUid = modelName;
47690
+ }
47691
+ getEndpoint() {
47692
+ return `${readDevinServerUrl()}${CHAT_PATH}`;
47693
+ }
47694
+ async getHeaders() {
47695
+ if (this.cachedAuth)
47696
+ return { ...this.cachedAuth.headers };
47697
+ const apiKey = readDevinApiKey();
47698
+ return apiKey ? devinAuthHeaders(apiKey) : {};
47699
+ }
47700
+ async refreshAuth() {
47701
+ this.cachedAuth = await credentials.getRequestAuth("devin", { model: this.modelName });
47702
+ this.served = await getServedDevinModels();
47703
+ log(`[Devin] auth refreshed, model: ${this.modelName}, served roster: ${this.served.length} models`);
47704
+ }
47705
+ serializeBody(payload) {
47706
+ const apiKey = readDevinApiKey();
47707
+ if (!apiKey) {
47708
+ const err = new Error("No Devin credential available when encoding the request.");
47709
+ err.terminal = true;
47710
+ throw err;
47711
+ }
47712
+ const request = payload;
47713
+ this.resolvedUid = resolveDevinModelUid(request.modelUid || this.modelName, request.effort, this.served);
47714
+ const resolved = { ...request, modelUid: this.resolvedUid };
47715
+ if (this.resolvedUid !== this.modelName) {
47716
+ log(`[Devin] model resolved: ${this.modelName} -> ${this.resolvedUid}`);
47717
+ }
47718
+ log(`[Devin] request ${describeDevinRequestForLog(resolved)}`);
47719
+ return {
47720
+ body: encodeDevinRequest(resolved, { apiKey }),
47721
+ contentType: CHAT_CONTENT_TYPE
47722
+ };
47723
+ }
47724
+ getContextWindow() {
47725
+ if (this.served.length === 0)
47726
+ return 0;
47727
+ const uid = resolveDevinModelUid(this.modelName, undefined, this.served);
47728
+ return this.served.find((model) => model.uid === uid)?.contextWindow ?? 0;
47729
+ }
47730
+ getActiveModelName() {
47731
+ return this.resolvedUid !== this.modelName ? this.resolvedUid : undefined;
47732
+ }
47733
+ async discoverProbeModel(exclude) {
47734
+ if (!readDevinApiKey()) {
47735
+ return {
47736
+ model: null,
47737
+ reason: "no Devin credential \u2014 sign in with the Devin CLI (`devin login`), or set WINDSURF_API_KEY"
47738
+ };
47739
+ }
47740
+ const served = await getServedDevinModels();
47741
+ if (served.length === 0) {
47742
+ return { model: null, reason: "Devin reported no models for this subscription" };
47743
+ }
47744
+ const ranked = [...served].sort((a, b) => {
47745
+ const diff = b.contextWindow - a.contextWindow;
47746
+ return diff !== 0 ? diff : a.uid.localeCompare(b.uid);
47747
+ });
47748
+ const candidate = ranked.find((model) => !exclude?.has(model.uid));
47749
+ if (!candidate) {
47750
+ return { model: null, reason: "every Devin model was already tried in this probe round" };
47751
+ }
47752
+ return { model: candidate.uid };
47753
+ }
47754
+ rewriteInStreamError(_code, message) {
47755
+ if (this.served.length === 0)
47756
+ return message;
47757
+ if (this.served.some((model) => model.uid === this.resolvedUid))
47758
+ return message;
47759
+ const families = [...new Set(this.served.map((model) => model.family).filter(Boolean))].sort();
47760
+ const stem = this.resolvedUid.split("-")[0]?.toLowerCase() ?? "";
47761
+ const related = families.filter((f) => f.toLowerCase().startsWith(stem));
47762
+ const ordered = [...related, ...families.filter((f) => !related.includes(f))];
47763
+ const SHOWN = 12;
47764
+ const shown = ordered.slice(0, SHOWN);
47765
+ const more = ordered.length - shown.length;
47766
+ const familyClause = shown.length > 0 ? ` Available families: ${shown.join(", ")}${more > 0 ? `, +${more} more` : ""}.` : "";
47767
+ return `\`${this.resolvedUid}\` is not served by your Devin subscription.${familyClause} ` + "Run `claudish models dv@` to list the uids this subscription can call. " + `(Upstream said: ${message})`;
47768
+ }
47769
+ }
47770
+ var CHAT_PATH = "/exa.api_server_pb.ApiServerService/GetChatMessage", CHAT_CONTENT_TYPE = "application/connect+proto";
47771
+ var init_devin = __esm(() => {
47772
+ init_authority();
47773
+ init_devin_credential();
47774
+ init_logger();
47775
+ init_devin_credentials();
47776
+ init_devin_models();
47777
+ init_devin_request();
47778
+ init_model_id_resolver();
47779
+ });
47780
+
46366
47781
  // src/providers/transport/gemini-apikey.ts
46367
47782
  class GeminiProviderTransport {
46368
47783
  name = "gemini";
@@ -46395,7 +47810,7 @@ var init_gemini_apikey = __esm(() => {
46395
47810
  });
46396
47811
 
46397
47812
  // src/providers/transport/gemini-codeassist.ts
46398
- import { randomUUID as randomUUID5 } from "crypto";
47813
+ import { randomUUID as randomUUID6 } from "crypto";
46399
47814
  function createActivityRequestId4() {
46400
47815
  return Math.random().toString(36).substring(7);
46401
47816
  }
@@ -46504,21 +47919,21 @@ class GeminiCodeAssistProviderTransport {
46504
47919
  log(`[GeminiCodeAssist] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}, served: ${this.servedModels.join(",") || "(none)"}`);
46505
47920
  }
46506
47921
  transformPayload(payload) {
46507
- const envelope = this.cachedAuth?.transformPayload ? this.cachedAuth.transformPayload(payload) : this.buildEnvelope(payload, this.modelName);
46508
- this.lastEnvelope = envelope;
46509
- return envelope;
47922
+ const envelope2 = this.cachedAuth?.transformPayload ? this.cachedAuth.transformPayload(payload) : this.buildEnvelope(payload, this.modelName);
47923
+ this.lastEnvelope = envelope2;
47924
+ return envelope2;
46510
47925
  }
46511
47926
  buildEnvelope(innerPayload, model) {
46512
- const envelope = {
47927
+ const envelope2 = {
46513
47928
  model,
46514
47929
  project: this.projectId,
46515
- user_prompt_id: randomUUID5(),
47930
+ user_prompt_id: randomUUID6(),
46516
47931
  request: innerPayload
46517
47932
  };
46518
47933
  if (this.tierId && this.tierId !== "free-tier") {
46519
- envelope.enabled_credit_types = ["GOOGLE_ONE_AI"];
47934
+ envelope2.enabled_credit_types = ["GOOGLE_ONE_AI"];
46520
47935
  }
46521
- return envelope;
47936
+ return envelope2;
46522
47937
  }
46523
47938
  async enqueueRequest(fetchFn) {
46524
47939
  const queue = GeminiRequestQueue.getInstance();
@@ -46845,11 +48260,12 @@ function createHandlerForProvider(ctx) {
46845
48260
  log(`[Proxy] Handler: provider=${ctx.provider.name}, model=${ctx.modelName}`);
46846
48261
  return profile.createHandler(ctx);
46847
48262
  }
46848
- var geminiProfile, geminiCodeAssistProfile, antigravityProfile, openaiProfile, openaiCodexProfile, anthropicCompatProfile, glmProfile, openCodeZenProfile, ollamaCloudProfile, litellmProfile, vertexProfile, PROVIDER_PROFILES;
48263
+ var geminiProfile, geminiCodeAssistProfile, antigravityProfile, devinProfile, openaiProfile, openaiCodexProfile, anthropicCompatProfile, glmProfile, openCodeZenProfile, ollamaCloudProfile, litellmProfile, vertexProfile, PROVIDER_PROFILES;
46849
48264
  var init_provider_profiles = __esm(() => {
46850
48265
  init_anthropic_api_format();
46851
48266
  init_base_api_format();
46852
48267
  init_codex_api_format();
48268
+ init_devin_api_format();
46853
48269
  init_gemini_api_format();
46854
48270
  init_litellm_api_format();
46855
48271
  init_ollama_api_format();
@@ -46862,6 +48278,7 @@ var init_provider_profiles = __esm(() => {
46862
48278
  init_runtime_providers();
46863
48279
  init_anthropic_compat();
46864
48280
  init_antigravity();
48281
+ init_devin();
46865
48282
  init_gemini_apikey();
46866
48283
  init_gemini_codeassist();
46867
48284
  init_litellm();
@@ -46907,6 +48324,19 @@ var init_provider_profiles = __esm(() => {
46907
48324
  return handler;
46908
48325
  }
46909
48326
  };
48327
+ devinProfile = {
48328
+ createHandler(ctx) {
48329
+ const transport = new DevinProviderTransport(ctx.modelName);
48330
+ const adapter = new DevinAPIFormat(ctx.modelName);
48331
+ const handler = new ComposedHandler(transport, ctx.targetModel, ctx.modelName, ctx.port, {
48332
+ adapter,
48333
+ forceForeignModel: true,
48334
+ ...ctx.sharedOpts
48335
+ });
48336
+ log(`[Proxy] Created Devin handler (composed): ${ctx.modelName}`);
48337
+ return handler;
48338
+ }
48339
+ };
46910
48340
  openaiProfile = {
46911
48341
  createHandler(ctx) {
46912
48342
  if (requiresResponsesApi(ctx.modelName)) {
@@ -47087,6 +48517,7 @@ var init_provider_profiles = __esm(() => {
47087
48517
  gemini: geminiProfile,
47088
48518
  "gemini-codeassist": geminiCodeAssistProfile,
47089
48519
  antigravity: antigravityProfile,
48520
+ devin: devinProfile,
47090
48521
  openai: openaiProfile,
47091
48522
  "openai-codex": openaiCodexProfile,
47092
48523
  "x-ai": openaiProfile,
@@ -47825,9 +49256,9 @@ var init_poe = __esm(() => {
47825
49256
  });
47826
49257
 
47827
49258
  // src/services/pricing-cache.ts
47828
- import { existsSync as existsSync18, readFileSync as readFileSync16, statSync as statSync4 } from "fs";
47829
- import { homedir as homedir26 } from "os";
47830
- import { join as join26 } from "path";
49259
+ import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync4 } from "fs";
49260
+ import { homedir as homedir27 } from "os";
49261
+ import { join as join27 } from "path";
47831
49262
  function prefixMatch(modelName) {
47832
49263
  for (const [key, pricing] of pricingMap) {
47833
49264
  if (modelName.startsWith(key))
@@ -47870,7 +49301,7 @@ function loadDiskCache() {
47870
49301
  const stat2 = statSync4(CACHE_FILE);
47871
49302
  const age = Date.now() - stat2.mtimeMs;
47872
49303
  const isFresh = age < CACHE_TTL_MS3;
47873
- const raw2 = readFileSync16(CACHE_FILE, "utf-8");
49304
+ const raw2 = readFileSync17(CACHE_FILE, "utf-8");
47874
49305
  const data = JSON.parse(raw2);
47875
49306
  for (const [key, pricing] of Object.entries(data)) {
47876
49307
  pricingMap.set(key, pricing);
@@ -47886,8 +49317,8 @@ var init_pricing_cache = __esm(() => {
47886
49317
  init_logger();
47887
49318
  init_catalog_query();
47888
49319
  pricingMap = new Map;
47889
- CACHE_DIR = join26(homedir26(), ".claudish");
47890
- CACHE_FILE = join26(CACHE_DIR, "pricing-cache.json");
49320
+ CACHE_DIR = join27(homedir27(), ".claudish");
49321
+ CACHE_FILE = join27(CACHE_DIR, "pricing-cache.json");
47891
49322
  CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
47892
49323
  });
47893
49324
 
@@ -48382,20 +49813,20 @@ var init_redact = __esm(() => {
48382
49813
  });
48383
49814
 
48384
49815
  // src/team-stats.ts
48385
- import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync11 } from "fs";
48386
- import { join as join27 } from "path";
49816
+ import { existsSync as existsSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync11 } from "fs";
49817
+ import { join as join28 } from "path";
48387
49818
  function statsDir(sessionPath) {
48388
- return join27(sessionPath, "stats");
49819
+ return join28(sessionPath, "stats");
48389
49820
  }
48390
49821
  function tokenFileFor(sessionPath, anonId) {
48391
- return join27(statsDir(sessionPath), `${anonId}.json`);
49822
+ return join28(statsDir(sessionPath), `${anonId}.json`);
48392
49823
  }
48393
49824
  function readTokenStats(sessionPath, anonId) {
48394
49825
  const path = tokenFileFor(sessionPath, anonId);
48395
49826
  if (!existsSync19(path))
48396
49827
  return null;
48397
49828
  try {
48398
- return JSON.parse(readFileSync17(path, "utf-8"));
49829
+ return JSON.parse(readFileSync18(path, "utf-8"));
48399
49830
  } catch {
48400
49831
  return null;
48401
49832
  }
@@ -48472,10 +49903,10 @@ function renderTeamStats(sessionPath, manifest, status, opts) {
48472
49903
  if (stats?.is_free)
48473
49904
  anyFree = true;
48474
49905
  const name = model.length > nameWidth ? `${model.slice(0, nameWidth - 1)}\u2026` : model;
48475
- const bytes = m.outputSize > 0 ? fmtBytes(m.outputSize) : "";
49906
+ const bytes2 = m.outputSize > 0 ? fmtBytes(m.outputSize) : "";
48476
49907
  const tokens = stats ? `${fmtTokens(inTok)}/${outTok > 0 ? fmtTokens(outTok) : "-"}` : "";
48477
49908
  const cost = stats ? fmtCost(stats.total_cost, stats.is_free) : "";
48478
- rows.push(` ${id} ${name.padEnd(nameWidth)} ${fmtState(m.state)} ` + `${bytes.padStart(7)} ${tokens.padStart(12)} ${cost.padStart(7)}`.trimEnd());
49909
+ rows.push(` ${id} ${name.padEnd(nameWidth)} ${fmtState(m.state)} ` + `${bytes2.padStart(7)} ${tokens.padStart(12)} ${cost.padStart(7)}`.trimEnd());
48479
49910
  }
48480
49911
  const parts = [`${ids.length} models`];
48481
49912
  if (done)
@@ -48543,7 +49974,7 @@ ${segs.join(" \xB7 ")}`;
48543
49974
  }
48544
49975
  function writeStatusFile(sessionPath, manifest, status, opts) {
48545
49976
  try {
48546
- writeFileSync11(join27(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
49977
+ writeFileSync11(join28(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
48547
49978
  `, "utf-8");
48548
49979
  } catch {}
48549
49980
  }
@@ -48571,11 +50002,11 @@ import {
48571
50002
  createWriteStream as createWriteStream2,
48572
50003
  existsSync as existsSync20,
48573
50004
  mkdirSync as mkdirSync12,
48574
- readFileSync as readFileSync18,
50005
+ readFileSync as readFileSync19,
48575
50006
  readdirSync as readdirSync3,
48576
50007
  writeFileSync as writeFileSync12
48577
50008
  } from "fs";
48578
- import { join as join28, resolve as resolve3 } from "path";
50009
+ import { join as join29, resolve as resolve3 } from "path";
48579
50010
  function classifyRunOutput(opts) {
48580
50011
  const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
48581
50012
  const apiError = API_ERROR_RE.exec(stdoutTail);
@@ -48636,18 +50067,18 @@ function setupSession(sessionPath, models, input) {
48636
50067
  if (models.length === 0) {
48637
50068
  throw new Error("At least one model is required");
48638
50069
  }
48639
- if (existsSync20(join28(sessionPath, "manifest.json"))) {
50070
+ if (existsSync20(join29(sessionPath, "manifest.json"))) {
48640
50071
  throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
48641
50072
  }
48642
50073
  const sentinels = models.filter(isSentinelModel);
48643
50074
  if (sentinels.length > 0) {
48644
50075
  throw new Error(`Invalid model(s) for team run: ${sentinels.join(", ")}. These are Claude Code agent selectors, not external model IDs. Use real external models (e.g., "gemini-2.0-flash", "gpt-4o", "or@deepseek/deepseek-r1"). For Claude models, use a Task agent instead of the team tool.`);
48645
50076
  }
48646
- mkdirSync12(join28(sessionPath, "work"), { recursive: true });
48647
- mkdirSync12(join28(sessionPath, "errors"), { recursive: true });
50077
+ mkdirSync12(join29(sessionPath, "work"), { recursive: true });
50078
+ mkdirSync12(join29(sessionPath, "errors"), { recursive: true });
48648
50079
  if (input !== undefined) {
48649
- writeFileSync12(join28(sessionPath, "input.md"), input, "utf-8");
48650
- } else if (!existsSync20(join28(sessionPath, "input.md"))) {
50080
+ writeFileSync12(join29(sessionPath, "input.md"), input, "utf-8");
50081
+ } else if (!existsSync20(join29(sessionPath, "input.md"))) {
48651
50082
  throw new Error(`No input.md found at ${sessionPath} and no input provided`);
48652
50083
  }
48653
50084
  const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
@@ -48664,9 +50095,9 @@ function setupSession(sessionPath, models, input) {
48664
50095
  model: models[i],
48665
50096
  assignedAt: now
48666
50097
  };
48667
- mkdirSync12(join28(sessionPath, "work", anonId), { recursive: true });
50098
+ mkdirSync12(join29(sessionPath, "work", anonId), { recursive: true });
48668
50099
  }
48669
- writeFileSync12(join28(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
50100
+ writeFileSync12(join29(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
48670
50101
  const status = {
48671
50102
  startedAt: now,
48672
50103
  models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
@@ -48680,17 +50111,17 @@ function setupSession(sessionPath, models, input) {
48680
50111
  }
48681
50112
  ]))
48682
50113
  };
48683
- writeFileSync12(join28(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
50114
+ writeFileSync12(join29(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
48684
50115
  return manifest;
48685
50116
  }
48686
50117
  async function runModels(sessionPath, opts = {}) {
48687
50118
  const timeoutMs = (opts.timeout ?? 300) * 1000;
48688
- const manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
48689
- const statusPath = join28(sessionPath, "status.json");
48690
- const inputPath = join28(sessionPath, "input.md");
48691
- const inputContent = readFileSync18(inputPath, "utf-8");
50119
+ const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
50120
+ const statusPath = join29(sessionPath, "status.json");
50121
+ const inputPath = join29(sessionPath, "input.md");
50122
+ const inputContent = readFileSync19(inputPath, "utf-8");
48692
50123
  const spawnPlan = await (opts.spawnPlanner ?? prehydrateCredentialsForSpawn)(Object.values(manifest.models).map((m) => m.model));
48693
- const statusCache = JSON.parse(readFileSync18(statusPath, "utf-8"));
50124
+ const statusCache = JSON.parse(readFileSync19(statusPath, "utf-8"));
48694
50125
  function updateModelStatus(id, update) {
48695
50126
  statusCache.models[id] = { ...statusCache.models[id], ...update };
48696
50127
  writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
@@ -48709,8 +50140,8 @@ async function runModels(sessionPath, opts = {}) {
48709
50140
  process.on("SIGINT", sigintHandler);
48710
50141
  const completionPromises = [];
48711
50142
  for (const [anonId, entry] of Object.entries(manifest.models)) {
48712
- const outputPath = join28(sessionPath, `response-${anonId}.md`);
48713
- const errorLogPath = join28(sessionPath, "errors", `${anonId}.log`);
50143
+ const outputPath = join29(sessionPath, `response-${anonId}.md`);
50144
+ const errorLogPath = join29(sessionPath, "errors", `${anonId}.log`);
48714
50145
  const spawnModel = spawnPlan.pinned.get(entry.model) ?? entry.model;
48715
50146
  const args = ["--model", spawnModel, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
48716
50147
  updateModelStatus(anonId, {
@@ -48859,14 +50290,14 @@ async function runModels(sessionPath, opts = {}) {
48859
50290
  const rt = runtimes.get(id);
48860
50291
  const stderr = rt?.getStderr() ?? "";
48861
50292
  const stdoutTail = rt?.getStdoutTail() ?? "";
48862
- const bytes = rt?.getByteCount() ?? 0;
48863
- const detail = `Killed by the orchestrator after ${timeoutMs / 1000}s with ${bytes} B of stdout. ` + "In --quiet print mode the child emits its answer only at the end, so 0 B means " + `"did not finish", not "produced nothing".`;
50293
+ const bytes2 = rt?.getByteCount() ?? 0;
50294
+ const detail = `Killed by the orchestrator after ${timeoutMs / 1000}s with ${bytes2} B of stdout. ` + "In --quiet print mode the child emits its answer only at the end, so 0 B means " + `"did not finish", not "produced nothing".`;
48864
50295
  if (rt)
48865
50296
  persistErrorLog(rt.errorLogPath, `TIMEOUT: ${detail}`, stderr, stdoutTail);
48866
50297
  updateModelStatus(id, {
48867
50298
  state: "TIMEOUT",
48868
50299
  completedAt: new Date().toISOString(),
48869
- outputSize: bytes,
50300
+ outputSize: bytes2,
48870
50301
  error: rt ? {
48871
50302
  model: id,
48872
50303
  command: rt.command,
@@ -48900,23 +50331,23 @@ async function judgeResponses(sessionPath, opts = {}) {
48900
50331
  const responses = {};
48901
50332
  for (const file2 of responseFiles) {
48902
50333
  const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
48903
- responses[id] = readFileSync18(join28(sessionPath, file2), "utf-8");
50334
+ responses[id] = readFileSync19(join29(sessionPath, file2), "utf-8");
48904
50335
  }
48905
- const input = readFileSync18(join28(sessionPath, "input.md"), "utf-8");
50336
+ const input = readFileSync19(join29(sessionPath, "input.md"), "utf-8");
48906
50337
  const judgePrompt = buildJudgePrompt(input, responses);
48907
- writeFileSync12(join28(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
50338
+ writeFileSync12(join29(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
48908
50339
  const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
48909
- const judgePath = join28(sessionPath, "judging");
50340
+ const judgePath = join29(sessionPath, "judging");
48910
50341
  mkdirSync12(judgePath, { recursive: true });
48911
50342
  setupSession(judgePath, judgeModels, judgePrompt);
48912
50343
  await runModels(judgePath, { claudeFlags: opts.claudeFlags });
48913
50344
  const votes = parseJudgeVotes(judgePath, Object.keys(responses));
48914
50345
  const verdict = aggregateVerdict(votes, Object.keys(responses));
48915
- writeFileSync12(join28(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
50346
+ writeFileSync12(join29(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
48916
50347
  return verdict;
48917
50348
  }
48918
50349
  function getStatus(sessionPath) {
48919
- return JSON.parse(readFileSync18(join28(sessionPath, "status.json"), "utf-8"));
50350
+ return JSON.parse(readFileSync19(join29(sessionPath, "status.json"), "utf-8"));
48920
50351
  }
48921
50352
  function fisherYatesShuffle(arr) {
48922
50353
  for (let i = arr.length - 1;i > 0; i--) {
@@ -48926,7 +50357,7 @@ function fisherYatesShuffle(arr) {
48926
50357
  return arr;
48927
50358
  }
48928
50359
  function getDefaultJudgeModels(sessionPath) {
48929
- const manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
50360
+ const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
48930
50361
  return Object.values(manifest.models).map((e) => e.model);
48931
50362
  }
48932
50363
  function buildJudgePrompt(input, responses) {
@@ -48989,7 +50420,7 @@ function parseJudgeVotes(judgePath, responseIds) {
48989
50420
  const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
48990
50421
  let content;
48991
50422
  try {
48992
- content = readFileSync18(join28(judgePath, file2), "utf-8");
50423
+ content = readFileSync19(join29(judgePath, file2), "utf-8");
48993
50424
  } catch {
48994
50425
  continue;
48995
50426
  }
@@ -49041,7 +50472,7 @@ function aggregateVerdict(votes, responseIds) {
49041
50472
  function formatVerdict(verdict, sessionPath) {
49042
50473
  let manifest = null;
49043
50474
  try {
49044
- manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
50475
+ manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
49045
50476
  } catch {}
49046
50477
  let output = `# Team Verdict
49047
50478
 
@@ -49096,14 +50527,14 @@ __export(exports_mcp_server, {
49096
50527
  parseAnthropicSse: () => parseAnthropicSse,
49097
50528
  formatTeamResult: () => formatTeamResult
49098
50529
  });
49099
- import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync19, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
49100
- import { homedir as homedir27 } from "os";
49101
- import { dirname as dirname9, join as join29, resolve as resolve4 } from "path";
50530
+ import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync20, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
50531
+ import { homedir as homedir28 } from "os";
50532
+ import { dirname as dirname9, join as join30, resolve as resolve4 } from "path";
49102
50533
  import { fileURLToPath } from "url";
49103
50534
  async function loadAllModels(forceRefresh = false) {
49104
50535
  if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH2)) {
49105
50536
  try {
49106
- const cacheData = JSON.parse(readFileSync19(ALL_MODELS_CACHE_PATH2, "utf-8"));
50537
+ const cacheData = JSON.parse(readFileSync20(ALL_MODELS_CACHE_PATH2, "utf-8"));
49107
50538
  const lastUpdated = new Date(cacheData.lastUpdated);
49108
50539
  const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
49109
50540
  if (ageInDays <= CACHE_MAX_AGE_DAYS) {
@@ -49122,7 +50553,7 @@ async function loadAllModels(forceRefresh = false) {
49122
50553
  return models;
49123
50554
  } catch {
49124
50555
  if (existsSync21(ALL_MODELS_CACHE_PATH2)) {
49125
- const cacheData = JSON.parse(readFileSync19(ALL_MODELS_CACHE_PATH2, "utf-8"));
50556
+ const cacheData = JSON.parse(readFileSync20(ALL_MODELS_CACHE_PATH2, "utf-8"));
49126
50557
  return cacheData.models || [];
49127
50558
  }
49128
50559
  return [];
@@ -49704,7 +51135,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49704
51135
  let stderrFull = stderr_snippet || "";
49705
51136
  if (error_log_path) {
49706
51137
  try {
49707
- stderrFull = readFileSync19(error_log_path, "utf-8");
51138
+ stderrFull = readFileSync20(error_log_path, "utf-8");
49708
51139
  } catch {}
49709
51140
  }
49710
51141
  const sessionData = {};
@@ -49712,16 +51143,16 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49712
51143
  const sp = session_path;
49713
51144
  for (const file2 of ["status.json", "manifest.json", "input.md"]) {
49714
51145
  try {
49715
- sessionData[file2] = readFileSync19(join29(sp, file2), "utf-8");
51146
+ sessionData[file2] = readFileSync20(join30(sp, file2), "utf-8");
49716
51147
  } catch {}
49717
51148
  }
49718
51149
  try {
49719
- const errorDir = join29(sp, "errors");
51150
+ const errorDir = join30(sp, "errors");
49720
51151
  if (existsSync21(errorDir)) {
49721
51152
  for (const f of readdirSync4(errorDir)) {
49722
51153
  if (f.endsWith(".log")) {
49723
51154
  try {
49724
- sessionData[`errors/${f}`] = readFileSync19(join29(errorDir, f), "utf-8");
51155
+ sessionData[`errors/${f}`] = readFileSync20(join30(errorDir, f), "utf-8");
49725
51156
  } catch {}
49726
51157
  }
49727
51158
  }
@@ -49731,7 +51162,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49731
51162
  for (const f of readdirSync4(sp)) {
49732
51163
  if (f.startsWith("response-") && f.endsWith(".md")) {
49733
51164
  try {
49734
- const content = readFileSync19(join29(sp, f), "utf-8");
51165
+ const content = readFileSync20(join30(sp, f), "utf-8");
49735
51166
  sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
49736
51167
  } catch {}
49737
51168
  }
@@ -49740,9 +51171,9 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49740
51171
  }
49741
51172
  let version2 = "unknown";
49742
51173
  try {
49743
- const pkgPath = join29(__dirname2, "../package.json");
51174
+ const pkgPath = join30(__dirname2, "../package.json");
49744
51175
  if (existsSync21(pkgPath)) {
49745
- version2 = JSON.parse(readFileSync19(pkgPath, "utf-8")).version;
51176
+ version2 = JSON.parse(readFileSync20(pkgPath, "utf-8")).version;
49746
51177
  }
49747
51178
  } catch {}
49748
51179
  const report = {
@@ -50146,8 +51577,8 @@ var init_mcp_server = __esm(() => {
50146
51577
  import_dotenv2.config({ quiet: true });
50147
51578
  __filename2 = fileURLToPath(import.meta.url);
50148
51579
  __dirname2 = dirname9(__filename2);
50149
- CLAUDISH_CACHE_DIR = join29(homedir27(), ".claudish");
50150
- ALL_MODELS_CACHE_PATH2 = join29(CLAUDISH_CACHE_DIR, "all-models.json");
51580
+ CLAUDISH_CACHE_DIR = join30(homedir28(), ".claudish");
51581
+ ALL_MODELS_CACHE_PATH2 = join30(CLAUDISH_CACHE_DIR, "all-models.json");
50151
51582
  NEXT_STEP = {
50152
51583
  nonzero_exit: "read the evidence log, then retry or drop the model",
50153
51584
  timeout: "raise `timeout`, or pick a faster model",
@@ -50172,7 +51603,7 @@ var exports_serve_command = {};
50172
51603
  __export(exports_serve_command, {
50173
51604
  serveCommand: () => serveCommand
50174
51605
  });
50175
- import { existsSync as existsSync22, readFileSync as readFileSync20 } from "fs";
51606
+ import { existsSync as existsSync22, readFileSync as readFileSync21 } from "fs";
50176
51607
  function parseServeArgs(args) {
50177
51608
  const out = {};
50178
51609
  for (let i = 0;i < args.length; i++) {
@@ -50196,7 +51627,7 @@ function loadModelMap(path) {
50196
51627
  }
50197
51628
  let raw2;
50198
51629
  try {
50199
- raw2 = readFileSync20(path, "utf-8");
51630
+ raw2 = readFileSync21(path, "utf-8");
50200
51631
  } catch (e) {
50201
51632
  throw new Error(`failed to read --models file ${path}: ${e instanceof Error ? e.message : String(e)}`);
50202
51633
  }
@@ -50273,7 +51704,7 @@ var exports_behavior_command = {};
50273
51704
  __export(exports_behavior_command, {
50274
51705
  behaviorCommand: () => behaviorCommand
50275
51706
  });
50276
- import { existsSync as existsSync23, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
51707
+ import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "fs";
50277
51708
  function severityColor(sev) {
50278
51709
  if (sev === "fix")
50279
51710
  return green(sev);
@@ -50372,7 +51803,7 @@ function setTelemetryEnabled(value) {
50372
51803
  let cfg = {};
50373
51804
  try {
50374
51805
  if (existsSync23(path)) {
50375
- const parsed = JSON.parse(readFileSync21(path, "utf-8"));
51806
+ const parsed = JSON.parse(readFileSync22(path, "utf-8"));
50376
51807
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
50377
51808
  cfg = parsed;
50378
51809
  }
@@ -50394,7 +51825,7 @@ function showTelemetry(action, json2) {
50394
51825
  try {
50395
51826
  const path = outboxPath();
50396
51827
  if (existsSync23(path)) {
50397
- pending = readFileSync21(path, "utf8").split(`
51828
+ pending = readFileSync22(path, "utf8").split(`
50398
51829
  `).filter(Boolean).length;
50399
51830
  }
50400
51831
  } catch {}
@@ -50467,6 +51898,12 @@ function describeSourceSync(p, config3) {
50467
51898
  return "oauth";
50468
51899
  if (p.catalogName === "antigravity" && hasSharedAntigravityToken())
50469
51900
  return "oauth";
51901
+ if (p.catalogName === "devin") {
51902
+ if (realValue(process.env.WINDSURF_API_KEY))
51903
+ return "env";
51904
+ if (hasDevinCredentials())
51905
+ return "oauth";
51906
+ }
50470
51907
  const hasCfg = !!p.apiKeyEnvVar && !!realValue(config3.apiKeys?.[p.apiKeyEnvVar]);
50471
51908
  const hasEnv = !!p.apiKeyEnvVar && !!realValue(process.env[p.apiKeyEnvVar]);
50472
51909
  if (hasEnv && hasCfg)
@@ -50487,6 +51924,7 @@ async function describeSource(p, config3) {
50487
51924
  }
50488
51925
  var init_source = __esm(() => {
50489
51926
  init_profile_config();
51927
+ init_devin_credentials();
50490
51928
  init_antigravity_token();
50491
51929
  init_oauth_registry();
50492
51930
  init_api_key_credential();
@@ -50534,8 +51972,8 @@ function providerIsReadyForDisplay(p, config3, localLiveness) {
50534
51972
  function providerAuthCapabilities(p, config3) {
50535
51973
  const apiKeySupported = !!p.apiKeyEnvVar;
50536
51974
  const apiKeySet = apiKeySupported && (!!process.env[p.apiKeyEnvVar] || !!config3.apiKeys?.[p.apiKeyEnvVar]);
50537
- const oauthSupported = !!p.oauthSlug;
50538
- const oauthSet = oauthSupported && (hasOAuthCredentials(p.catalogName) || p.catalogName === "antigravity" && hasSharedAntigravityToken());
51975
+ const oauthSupported = !!p.oauthSlug || p.catalogName === "devin";
51976
+ const oauthSet = oauthSupported && (hasOAuthCredentials(p.catalogName) || p.catalogName === "antigravity" && hasSharedAntigravityToken() || p.catalogName === "devin" && hasDevinCredentials());
50539
51977
  return {
50540
51978
  apiKey: { supported: apiKeySupported, set: apiKeySet },
50541
51979
  oauth: { supported: oauthSupported, set: oauthSet }
@@ -50553,6 +51991,7 @@ var init_providers = __esm(() => {
50553
51991
  init_antigravity_token();
50554
51992
  init_source();
50555
51993
  init_oauth_registry();
51994
+ init_devin_credentials();
50556
51995
  init_provider_definitions();
50557
51996
  SKIP = new Set(["qwen", "native-anthropic"]);
50558
51997
  PROVIDERS = getAllProviders().filter((d) => !SKIP.has(d.name)).map(toProviderDef);
@@ -59801,18 +61240,18 @@ var require_dbcs_codec = __commonJS((exports) => {
59801
61240
  DBCSCodec.prototype.encoder = DBCSEncoder;
59802
61241
  DBCSCodec.prototype.decoder = DBCSDecoder;
59803
61242
  DBCSCodec.prototype._getDecodeTrieNode = function(addr) {
59804
- var bytes = [];
61243
+ var bytes2 = [];
59805
61244
  for (;addr > 0; addr >>>= 8) {
59806
- bytes.push(addr & 255);
61245
+ bytes2.push(addr & 255);
59807
61246
  }
59808
- if (bytes.length == 0) {
59809
- bytes.push(0);
61247
+ if (bytes2.length == 0) {
61248
+ bytes2.push(0);
59810
61249
  }
59811
61250
  var node = this.decodeTables[0];
59812
- for (var i2 = bytes.length - 1;i2 > 0; i2--) {
59813
- var val = node[bytes[i2]];
61251
+ for (var i2 = bytes2.length - 1;i2 > 0; i2--) {
61252
+ var val = node[bytes2[i2]];
59814
61253
  if (val == UNASSIGNED) {
59815
- node[bytes[i2]] = NODE_START - this.decodeTables.length;
61254
+ node[bytes2[i2]] = NODE_START - this.decodeTables.length;
59816
61255
  this.decodeTables.push(node = UNASSIGNED_NODE.slice(0));
59817
61256
  } else if (val <= NODE_START) {
59818
61257
  node = this.decodeTables[NODE_START - val];
@@ -61863,10 +63302,10 @@ var init_RemoveFileError = __esm(() => {
61863
63302
 
61864
63303
  // ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
61865
63304
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
61866
- import { readFileSync as readFileSync22, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
63305
+ import { readFileSync as readFileSync23, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
61867
63306
  import path from "path";
61868
63307
  import os from "os";
61869
- import { randomUUID as randomUUID6 } from "crypto";
63308
+ import { randomUUID as randomUUID7 } from "crypto";
61870
63309
  function editAsync(text = "", callback, fileOptions) {
61871
63310
  const editor = new ExternalEditor(text, fileOptions);
61872
63311
  editor.runAsync((err, result) => {
@@ -61958,7 +63397,7 @@ class ExternalEditor {
61958
63397
  createTemporaryFile() {
61959
63398
  try {
61960
63399
  const baseDir = this.fileOptions.dir ?? os.tmpdir();
61961
- const id = randomUUID6();
63400
+ const id = randomUUID7();
61962
63401
  const prefix = sanitizeAffix(this.fileOptions.prefix);
61963
63402
  const postfix = sanitizeAffix(this.fileOptions.postfix);
61964
63403
  const filename = `${prefix}${id}${postfix}`;
@@ -61979,7 +63418,7 @@ class ExternalEditor {
61979
63418
  }
61980
63419
  readTemporaryFile() {
61981
63420
  try {
61982
- const tempFileBuffer = readFileSync22(this.tempFile);
63421
+ const tempFileBuffer = readFileSync23(this.tempFile);
61983
63422
  if (tempFileBuffer.length === 0) {
61984
63423
  this.text = "";
61985
63424
  } else {
@@ -62961,8 +64400,8 @@ var init_dist16 = __esm(() => {
62961
64400
  // src/auth/antigravity-oauth.ts
62962
64401
  import { spawnSync as spawnSync3 } from "child_process";
62963
64402
  import { existsSync as existsSync24, unlinkSync as unlinkSync7 } from "fs";
62964
- import { homedir as homedir28 } from "os";
62965
- import { join as join30 } from "path";
64403
+ import { homedir as homedir29 } from "os";
64404
+ import { join as join31 } from "path";
62966
64405
  async function defaultSuggestModel() {
62967
64406
  try {
62968
64407
  const tok = readSharedAntigravityToken();
@@ -63083,7 +64522,7 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
63083
64522
  async logout(deps) {
63084
64523
  deleteSharedAntigravityToken(deps);
63085
64524
  try {
63086
- const tokenFile = join30(homedir28(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
64525
+ const tokenFile = join31(homedir29(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
63087
64526
  if (existsSync24(tokenFile))
63088
64527
  unlinkSync7(tokenFile);
63089
64528
  } catch {}
@@ -64535,11 +65974,11 @@ async function probeLink(proxyUrl, link, timeoutMs) {
64535
65974
  } catch (e) {
64536
65975
  const latencyMs = Date.now() - startedAt;
64537
65976
  const name = e?.name || "";
64538
- const msg = String(e?.message || e);
64539
- if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg)) {
64540
- return { state: "timeout", latencyMs, errorMessage: msg };
65977
+ const msg2 = String(e?.message || e);
65978
+ if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg2)) {
65979
+ return { state: "timeout", latencyMs, errorMessage: msg2 };
64541
65980
  }
64542
- return { state: "network-error", latencyMs, errorMessage: msg };
65981
+ return { state: "network-error", latencyMs, errorMessage: msg2 };
64543
65982
  }
64544
65983
  const ttfbMs = Date.now() - startedAt;
64545
65984
  if (!response.ok) {
@@ -64568,7 +66007,7 @@ function annotateOAuthHint(result, provider, isOAuth) {
64568
66007
  return result;
64569
66008
  if (result.state === "live")
64570
66009
  return result;
64571
- const loginCommand2 = provider === "gemini-codeassist" ? "claudish login gemini" : provider === "antigravity" ? "claudish login antigravity" : provider === "vertex" ? "gcloud auth application-default login" : undefined;
66010
+ const loginCommand2 = provider === "gemini-codeassist" ? "claudish login gemini" : provider === "antigravity" ? "claudish login antigravity" : provider === "vertex" ? "gcloud auth application-default login" : provider === "devin" ? "devin login" : undefined;
64572
66011
  if (!loginCommand2)
64573
66012
  return result;
64574
66013
  if (result.httpStatus === 403)
@@ -64676,9 +66115,9 @@ function extractErrorMessage(body) {
64676
66115
  return;
64677
66116
  try {
64678
66117
  const parsed = JSON.parse(body);
64679
- const msg = parsed?.error?.message || parsed?.error?.error?.message || parsed?.message || parsed?.detail;
64680
- if (typeof msg === "string" && msg.length > 0) {
64681
- return msg.length > 160 ? `${msg.slice(0, 157)}...` : msg;
66118
+ const msg2 = parsed?.error?.message || parsed?.error?.error?.message || parsed?.message || parsed?.detail;
66119
+ if (typeof msg2 === "string" && msg2.length > 0) {
66120
+ return msg2.length > 160 ? `${msg2.slice(0, 157)}...` : msg2;
64682
66121
  }
64683
66122
  } catch {}
64684
66123
  const trimmed2 = body.trim();
@@ -64894,7 +66333,7 @@ function isFailureState(state) {
64894
66333
  }
64895
66334
  var STREAM_MS_FLOOR = 50, OAUTH_PROVIDERS2, PROBE_PROMPT = "Count from one to twenty in words, one per line.", PROBE_MAX_TOKENS = 512;
64896
66335
  var init_probe_live = __esm(() => {
64897
- OAUTH_PROVIDERS2 = new Set(["vertex", "gemini-codeassist"]);
66336
+ OAUTH_PROVIDERS2 = new Set(["vertex", "gemini-codeassist", "devin"]);
64898
66337
  });
64899
66338
 
64900
66339
  // src/tui/theme.ts
@@ -67172,19 +68611,19 @@ import {
67172
68611
  copyFileSync as copyFileSync2,
67173
68612
  existsSync as existsSync25,
67174
68613
  mkdirSync as mkdirSync14,
67175
- readFileSync as readFileSync23,
68614
+ readFileSync as readFileSync24,
67176
68615
  readdirSync as readdirSync5,
67177
68616
  unlinkSync as unlinkSync8,
67178
68617
  writeFileSync as writeFileSync16
67179
68618
  } from "fs";
67180
- import { homedir as homedir29 } from "os";
67181
- import { dirname as dirname10, join as join31 } from "path";
68619
+ import { homedir as homedir30 } from "os";
68620
+ import { dirname as dirname10, join as join32 } from "path";
67182
68621
  import { fileURLToPath as fileURLToPath2 } from "url";
67183
68622
  function getVersion3() {
67184
68623
  return VERSION;
67185
68624
  }
67186
68625
  function clearAllModelCaches() {
67187
- const cacheDir = join31(homedir29(), ".claudish");
68626
+ const cacheDir = join32(homedir30(), ".claudish");
67188
68627
  if (!existsSync25(cacheDir))
67189
68628
  return;
67190
68629
  const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
@@ -67193,7 +68632,7 @@ function clearAllModelCaches() {
67193
68632
  const files = readdirSync5(cacheDir);
67194
68633
  for (const file2 of files) {
67195
68634
  if (cachePatterns.includes(file2)) {
67196
- unlinkSync8(join31(cacheDir, file2));
68635
+ unlinkSync8(join32(cacheDir, file2));
67197
68636
  cleared++;
67198
68637
  }
67199
68638
  }
@@ -67603,7 +69042,7 @@ Usage: claudish --models --provider <slug>`);
67603
69042
  });
67604
69043
  config3.resolvedDefaultProvider = resolved;
67605
69044
  if (resolved.legacyAutoPromoted && !config3.quiet) {
67606
- const markerFile = join31(homedir29(), ".claudish", ".legacy-litellm-hint-shown");
69045
+ const markerFile = join32(homedir30(), ".claudish", ".legacy-litellm-hint-shown");
67607
69046
  if (!existsSync25(markerFile)) {
67608
69047
  const hint = buildLegacyHint(resolved);
67609
69048
  if (hint) {
@@ -68074,6 +69513,9 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
68074
69513
  } else if (providerName === "litellm") {
68075
69514
  formatAdapterName = "LiteLLMAPIFormat";
68076
69515
  declaredStreamFormat = "openai-sse";
69516
+ } else if (providerName === "devin") {
69517
+ formatAdapterName = "DevinAPIFormat";
69518
+ declaredStreamFormat = "connect-proto";
68077
69519
  } else {
68078
69520
  formatAdapterName = "OpenAIAPIFormat";
68079
69521
  declaredStreamFormat = "openai-sse";
@@ -68112,8 +69554,8 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
68112
69554
  console.error(`${DIM}Probing providers via live requests (may incur small cost, use --no-probe to skip)...${RESET}`);
68113
69555
  liveProxy2 = await createProxyServer2(probePort, process.env.OPENROUTER_API_KEY, undefined, false, process.env.ANTHROPIC_API_KEY, undefined, { quiet: true });
68114
69556
  } catch (e) {
68115
- const msg = e instanceof Error ? e.message : String(e);
68116
- console.error(`${YELLOW}Failed to start probe proxy (${msg}). Falling back to static probe.${RESET}`);
69557
+ const msg2 = e instanceof Error ? e.message : String(e);
69558
+ console.error(`${YELLOW}Failed to start probe proxy (${msg2}). Falling back to static probe.${RESET}`);
68117
69559
  liveProxy2 = null;
68118
69560
  }
68119
69561
  }
@@ -68678,8 +70120,8 @@ ${h("MORE INFO")}
68678
70120
  }
68679
70121
  function printAIAgentGuide() {
68680
70122
  try {
68681
- const guidePath = join31(__dirname3, "../AI_AGENT_GUIDE.md");
68682
- const guideContent = readFileSync23(guidePath, "utf-8");
70123
+ const guidePath = join32(__dirname3, "../AI_AGENT_GUIDE.md");
70124
+ const guideContent = readFileSync24(guidePath, "utf-8");
68683
70125
  console.log(guideContent);
68684
70126
  } catch (error46) {
68685
70127
  console.error("Error reading AI Agent Guide:");
@@ -68695,10 +70137,10 @@ async function initializeClaudishSkill() {
68695
70137
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
68696
70138
  `);
68697
70139
  const cwd = process.cwd();
68698
- const claudeDir = join31(cwd, ".claude");
68699
- const skillsDir = join31(claudeDir, "skills");
68700
- const claudishSkillDir = join31(skillsDir, "claudish-usage");
68701
- const skillFile = join31(claudishSkillDir, "SKILL.md");
70140
+ const claudeDir = join32(cwd, ".claude");
70141
+ const skillsDir = join32(claudeDir, "skills");
70142
+ const claudishSkillDir = join32(skillsDir, "claudish-usage");
70143
+ const skillFile = join32(claudishSkillDir, "SKILL.md");
68702
70144
  if (existsSync25(skillFile)) {
68703
70145
  console.log("\u2705 Claudish skill already installed at:");
68704
70146
  console.log(` ${skillFile}
@@ -68706,7 +70148,7 @@ async function initializeClaudishSkill() {
68706
70148
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
68707
70149
  return;
68708
70150
  }
68709
- const sourceSkillPath = join31(__dirname3, "../skills/claudish-usage/SKILL.md");
70151
+ const sourceSkillPath = join32(__dirname3, "../skills/claudish-usage/SKILL.md");
68710
70152
  if (!existsSync25(sourceSkillPath)) {
68711
70153
  console.error("\u274C Error: Claudish skill file not found in installation.");
68712
70154
  console.error(` Expected at: ${sourceSkillPath}`);
@@ -68809,24 +70251,24 @@ __export(exports_update_checker, {
68809
70251
  clearCache: () => clearCache,
68810
70252
  checkForUpdates: () => checkForUpdates
68811
70253
  });
68812
- import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync9, writeFileSync as writeFileSync17 } from "fs";
68813
- import { homedir as homedir30, platform as platform2, tmpdir } from "os";
68814
- import { join as join32 } from "path";
70254
+ import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as readFileSync25, unlinkSync as unlinkSync9, writeFileSync as writeFileSync17 } from "fs";
70255
+ import { homedir as homedir31, platform as platform2, tmpdir } from "os";
70256
+ import { join as join33 } from "path";
68815
70257
  function getCacheFilePath() {
68816
70258
  let cacheDir;
68817
70259
  if (isWindows) {
68818
- const localAppData = process.env.LOCALAPPDATA || join32(homedir30(), "AppData", "Local");
68819
- cacheDir = join32(localAppData, "claudish");
70260
+ const localAppData = process.env.LOCALAPPDATA || join33(homedir31(), "AppData", "Local");
70261
+ cacheDir = join33(localAppData, "claudish");
68820
70262
  } else {
68821
- cacheDir = join32(homedir30(), ".cache", "claudish");
70263
+ cacheDir = join33(homedir31(), ".cache", "claudish");
68822
70264
  }
68823
70265
  try {
68824
70266
  if (!existsSync26(cacheDir)) {
68825
70267
  mkdirSync15(cacheDir, { recursive: true });
68826
70268
  }
68827
- return join32(cacheDir, "update-check.json");
70269
+ return join33(cacheDir, "update-check.json");
68828
70270
  } catch {
68829
- return join32(tmpdir(), "claudish-update-check.json");
70271
+ return join33(tmpdir(), "claudish-update-check.json");
68830
70272
  }
68831
70273
  }
68832
70274
  function readCache() {
@@ -68835,7 +70277,7 @@ function readCache() {
68835
70277
  if (!existsSync26(cachePath)) {
68836
70278
  return null;
68837
70279
  }
68838
- const data = JSON.parse(readFileSync24(cachePath, "utf-8"));
70280
+ const data = JSON.parse(readFileSync25(cachePath, "utf-8"));
68839
70281
  return data;
68840
70282
  } catch {
68841
70283
  return null;
@@ -69743,15 +71185,15 @@ var init_local_liveness = __esm(() => {
69743
71185
  });
69744
71186
 
69745
71187
  // src/providers/probe-catalog.ts
69746
- import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync25, writeFileSync as writeFileSync18 } from "fs";
69747
- import { homedir as homedir31 } from "os";
69748
- import { dirname as dirname11, join as join33 } from "path";
71188
+ import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync26, writeFileSync as writeFileSync18 } from "fs";
71189
+ import { homedir as homedir32 } from "os";
71190
+ import { dirname as dirname11, join as join34 } from "path";
69749
71191
  function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
69750
71192
  if (!existsSync27(path2))
69751
71193
  return null;
69752
71194
  let raw2;
69753
71195
  try {
69754
- raw2 = JSON.parse(readFileSync25(path2, "utf-8"));
71196
+ raw2 = JSON.parse(readFileSync26(path2, "utf-8"));
69755
71197
  } catch {
69756
71198
  return null;
69757
71199
  }
@@ -69880,7 +71322,7 @@ function isValidResponse(raw2) {
69880
71322
  var PROBE_MODELS_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/probeModels", CACHE_TTL_MS4, FETCH_TIMEOUT_MS3 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null;
69881
71323
  var init_probe_catalog = __esm(() => {
69882
71324
  CACHE_TTL_MS4 = 60 * 60 * 1000;
69883
- PROBE_MODELS_CACHE_PATH = join33(homedir31(), ".claudish", "probe-models.json");
71325
+ PROBE_MODELS_CACHE_PATH = join34(homedir32(), ".claudish", "probe-models.json");
69884
71326
  });
69885
71327
 
69886
71328
  // src/tui/constants.ts
@@ -74327,8 +75769,8 @@ function useRouteProbe(config3) {
74327
75769
  try {
74328
75770
  proxyUrl = await ensureProbeProxy();
74329
75771
  } catch (err) {
74330
- const msg = err instanceof Error ? err.message : String(err);
74331
- setProbeResults((prev) => prev.map((e) => ({ ...e, status: "failed", error: `probe proxy: ${msg}` })));
75772
+ const msg2 = err instanceof Error ? err.message : String(err);
75773
+ setProbeResults((prev) => prev.map((e) => ({ ...e, status: "failed", error: `probe proxy: ${msg2}` })));
74332
75774
  setProbeMode("done");
74333
75775
  return;
74334
75776
  }
@@ -74682,12 +76124,12 @@ function App({ requestLogin } = {}) {
74682
76124
  }));
74683
76125
  setStatusMsg(`1Password test ok \u2192 ${note}`);
74684
76126
  } catch (err) {
74685
- const msg = err instanceof Error ? err.message : String(err);
76127
+ const msg2 = err instanceof Error ? err.message : String(err);
74686
76128
  setOpTestResults((prev) => ({
74687
76129
  ...prev,
74688
- [key]: { status: "failed", error: msg }
76130
+ [key]: { status: "failed", error: msg2 }
74689
76131
  }));
74690
- setStatusMsg(msg);
76132
+ setStatusMsg(msg2);
74691
76133
  } finally {
74692
76134
  setOpBusy(false);
74693
76135
  }
@@ -74762,14 +76204,14 @@ function App({ requestLogin } = {}) {
74762
76204
  invalidateProbeProxyHandlers();
74763
76205
  refreshConfig();
74764
76206
  } catch (testErr) {
74765
- const msg = testErr instanceof Error ? testErr.message : String(testErr);
74766
- console.error(`[claudish] 1Password add: saved but live resolve failed: ${msg}`);
74767
- setStatusMsg(`1Password ${kindWord} saved (${scope}) \u2014 live resolve failed: ${msg}`);
76207
+ const msg2 = testErr instanceof Error ? testErr.message : String(testErr);
76208
+ console.error(`[claudish] 1Password add: saved but live resolve failed: ${msg2}`);
76209
+ setStatusMsg(`1Password ${kindWord} saved (${scope}) \u2014 live resolve failed: ${msg2}`);
74768
76210
  }
74769
76211
  } catch (err) {
74770
- const msg = err instanceof Error ? err.message : String(err);
74771
- console.error(`[claudish] 1Password add failed to persist: ${msg}`);
74772
- setStatusMsg(`1Password add failed: ${msg}`);
76212
+ const msg2 = err instanceof Error ? err.message : String(err);
76213
+ console.error(`[claudish] 1Password add failed to persist: ${msg2}`);
76214
+ setStatusMsg(`1Password add failed: ${msg2}`);
74773
76215
  setMode("browse");
74774
76216
  resetOpWizard();
74775
76217
  } finally {
@@ -74789,8 +76231,8 @@ function App({ requestLogin } = {}) {
74789
76231
  setOpVaults(vaults);
74790
76232
  setStatusMsg(`1Password: ${vaults.length} vault${vaults.length === 1 ? "" : "s"}.`);
74791
76233
  } catch (err) {
74792
- const msg = err instanceof Error ? err.message : String(err);
74793
- setStatusMsg(msg);
76234
+ const msg2 = err instanceof Error ? err.message : String(err);
76235
+ setStatusMsg(msg2);
74794
76236
  setMode("browse");
74795
76237
  } finally {
74796
76238
  setOpBusy(false);
@@ -74811,8 +76253,8 @@ function App({ requestLogin } = {}) {
74811
76253
  setOpItems(items);
74812
76254
  setStatusMsg(`1Password: ${items.length} item${items.length === 1 ? "" : "s"}.`);
74813
76255
  } catch (err) {
74814
- const msg = err instanceof Error ? err.message : String(err);
74815
- setStatusMsg(msg);
76256
+ const msg2 = err instanceof Error ? err.message : String(err);
76257
+ setStatusMsg(msg2);
74816
76258
  setMode("browse");
74817
76259
  } finally {
74818
76260
  setOpBusy(false);
@@ -74840,8 +76282,8 @@ function App({ requestLogin } = {}) {
74840
76282
  setOpFields(fields);
74841
76283
  setStatusMsg(`1Password: ${fields.length} field${fields.length === 1 ? "" : "s"}.`);
74842
76284
  } catch (err) {
74843
- const msg = err instanceof Error ? err.message : String(err);
74844
- setStatusMsg(msg);
76285
+ const msg2 = err instanceof Error ? err.message : String(err);
76286
+ setStatusMsg(msg2);
74845
76287
  setMode("browse");
74846
76288
  } finally {
74847
76289
  setOpBusy(false);
@@ -74857,9 +76299,9 @@ function App({ requestLogin } = {}) {
74857
76299
  setOpEnvPreview(names);
74858
76300
  setStatusMsg(`1Password environment \u2192 ${names.length} var${names.length === 1 ? "" : "s"}. Enter to save.`);
74859
76301
  } catch (err) {
74860
- const msg = err instanceof Error ? err.message : String(err);
76302
+ const msg2 = err instanceof Error ? err.message : String(err);
74861
76303
  setOpEnvPreview(null);
74862
- setStatusMsg(msg);
76304
+ setStatusMsg(msg2);
74863
76305
  } finally {
74864
76306
  setOpBusy(false);
74865
76307
  }
@@ -74967,10 +76409,10 @@ function App({ requestLogin } = {}) {
74967
76409
  }
74968
76410
  } catch (err) {
74969
76411
  const ms = Date.now() - startMs;
74970
- const msg = err instanceof Error ? err.message : String(err);
76412
+ const msg2 = err instanceof Error ? err.message : String(err);
74971
76413
  setTestResults((prev) => ({
74972
76414
  ...prev,
74973
- [provName]: { status: "failed", error: `proxy: ${msg}`, ms }
76415
+ [provName]: { status: "failed", error: `proxy: ${msg2}`, ms }
74974
76416
  }));
74975
76417
  }
74976
76418
  }, []);
@@ -76237,14 +77679,14 @@ import {
76237
77679
  existsSync as existsSync28,
76238
77680
  mkdirSync as mkdirSync17,
76239
77681
  openSync as openSync5,
76240
- readFileSync as readFileSync26,
77682
+ readFileSync as readFileSync27,
76241
77683
  readdirSync as readdirSync6,
76242
77684
  statSync as statSync5,
76243
77685
  unlinkSync as unlinkSync10,
76244
77686
  writeFileSync as writeFileSync19
76245
77687
  } from "fs";
76246
- import { homedir as homedir32, tmpdir as tmpdir2 } from "os";
76247
- import { dirname as dirname12, join as join34 } from "path";
77688
+ import { homedir as homedir33, tmpdir as tmpdir2 } from "os";
77689
+ import { dirname as dirname12, join as join35 } from "path";
76248
77690
  import { isatty } from "tty";
76249
77691
  function releaseTerminalIsolation() {
76250
77692
  if (!restoreTerminal)
@@ -76279,14 +77721,14 @@ function isProxyAuthMode(config3) {
76279
77721
  }
76280
77722
  function managedSettingsPath() {
76281
77723
  if (isWindows2()) {
76282
- return join34(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
77724
+ return join35(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
76283
77725
  }
76284
77726
  if (process.platform === "darwin") {
76285
77727
  return "/Library/Application Support/ClaudeCode/managed-settings.json";
76286
77728
  }
76287
77729
  return "/etc/claude-code/managed-settings.json";
76288
77730
  }
76289
- function managedSettingsForcesClaudeAi(readFile3 = readFileSync26) {
77731
+ function managedSettingsForcesClaudeAi(readFile3 = readFileSync27) {
76290
77732
  try {
76291
77733
  const raw2 = readFile3(managedSettingsPath(), "utf-8");
76292
77734
  const parsed = JSON.parse(raw2);
@@ -76300,9 +77742,9 @@ function isWindows2() {
76300
77742
  }
76301
77743
  function createStatusLineScript(tokenFilePath) {
76302
77744
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
76303
- const claudishDir = join34(homeDir, ".claudish");
77745
+ const claudishDir = join35(homeDir, ".claudish");
76304
77746
  const timestamp = Date.now();
76305
- const scriptPath = join34(claudishDir, `status-${timestamp}.js`);
77747
+ const scriptPath = join35(claudishDir, `status-${timestamp}.js`);
76306
77748
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
76307
77749
  const script = `
76308
77750
  const fs = require('fs');
@@ -76466,7 +77908,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
76466
77908
  if (!name.startsWith("tokens-") || !name.endsWith(".json"))
76467
77909
  continue;
76468
77910
  scanned++;
76469
- const full = join34(dir, name);
77911
+ const full = join35(dir, name);
76470
77912
  try {
76471
77913
  if (statSync5(full).mtimeMs >= cutoff)
76472
77914
  continue;
@@ -76483,7 +77925,7 @@ function parseSettingsArg(value) {
76483
77925
  if (value.trimStart().startsWith("{")) {
76484
77926
  return JSON.parse(value);
76485
77927
  }
76486
- return JSON.parse(readFileSync26(value, "utf-8"));
77928
+ return JSON.parse(readFileSync27(value, "utf-8"));
76487
77929
  }
76488
77930
  function parseSettingsArgSafe(value) {
76489
77931
  try {
@@ -76495,9 +77937,9 @@ function parseSettingsArgSafe(value) {
76495
77937
  }
76496
77938
  function userSettingsFileCandidates(cwd) {
76497
77939
  return [
76498
- join34(homedir32(), ".claude", "settings.json"),
76499
- join34(cwd, ".claude", "settings.json"),
76500
- join34(cwd, ".claude", "settings.local.json")
77940
+ join35(homedir33(), ".claude", "settings.json"),
77941
+ join35(cwd, ".claude", "settings.json"),
77942
+ join35(cwd, ".claude", "settings.local.json")
76501
77943
  ];
76502
77944
  }
76503
77945
  function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
@@ -76538,13 +77980,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
76538
77980
  }
76539
77981
  function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
76540
77982
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
76541
- const claudishDir = join34(homeDir, ".claudish");
77983
+ const claudishDir = join35(homeDir, ".claudish");
76542
77984
  try {
76543
77985
  mkdirSync17(claudishDir, { recursive: true });
76544
77986
  } catch {}
76545
77987
  const timestamp = Date.now();
76546
- const tempPath = join34(claudishDir, `settings-${timestamp}.json`);
76547
- const tokenFilePath = join34(claudishDir, `tokens-${port}.json`);
77988
+ const tempPath = join35(claudishDir, `settings-${timestamp}.json`);
77989
+ const tokenFilePath = join35(claudishDir, `tokens-${port}.json`);
76548
77990
  cleanupStaleTokenFiles(claudishDir);
76549
77991
  initializeTokenFile(tokenFilePath);
76550
77992
  let statusCommand;
@@ -76817,8 +78259,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
76817
78259
  console.error("Install it from: https://claude.com/claude-code");
76818
78260
  console.error(`
76819
78261
  Or set CLAUDE_PATH to your custom installation:`);
76820
- const home = homedir32();
76821
- const localPath = isWindows2() ? join34(home, ".claude", "local", "claude.exe") : join34(home, ".claude", "local", "claude");
78262
+ const home = homedir33();
78263
+ const localPath = isWindows2() ? join35(home, ".claude", "local", "claude.exe") : join35(home, ".claude", "local", "claude");
76822
78264
  console.error(` export CLAUDE_PATH=${localPath}`);
76823
78265
  process.exit(1);
76824
78266
  }
@@ -76902,16 +78344,16 @@ async function findClaudeBinary() {
76902
78344
  return process.env.CLAUDE_PATH;
76903
78345
  }
76904
78346
  }
76905
- const home = homedir32();
76906
- const localPath = isWindows3 ? join34(home, ".claude", "local", "claude.exe") : join34(home, ".claude", "local", "claude");
78347
+ const home = homedir33();
78348
+ const localPath = isWindows3 ? join35(home, ".claude", "local", "claude.exe") : join35(home, ".claude", "local", "claude");
76907
78349
  if (existsSync28(localPath)) {
76908
78350
  return localPath;
76909
78351
  }
76910
78352
  if (isWindows3) {
76911
78353
  const windowsPaths = [
76912
- join34(home, "AppData", "Roaming", "npm", "claude.cmd"),
76913
- join34(home, ".npm-global", "claude.cmd"),
76914
- join34(home, "node_modules", ".bin", "claude.cmd")
78354
+ join35(home, "AppData", "Roaming", "npm", "claude.cmd"),
78355
+ join35(home, ".npm-global", "claude.cmd"),
78356
+ join35(home, "node_modules", ".bin", "claude.cmd")
76915
78357
  ];
76916
78358
  for (const path2 of windowsPaths) {
76917
78359
  if (existsSync28(path2)) {
@@ -76922,11 +78364,11 @@ async function findClaudeBinary() {
76922
78364
  const commonPaths = [
76923
78365
  "/usr/local/bin/claude",
76924
78366
  "/opt/homebrew/bin/claude",
76925
- join34(home, ".npm-global/bin/claude"),
76926
- join34(home, ".local/bin/claude"),
76927
- join34(home, "node_modules/.bin/claude"),
78367
+ join35(home, ".npm-global/bin/claude"),
78368
+ join35(home, ".local/bin/claude"),
78369
+ join35(home, "node_modules/.bin/claude"),
76928
78370
  "/data/data/com.termux/files/usr/bin/claude",
76929
- join34(home, "../usr/bin/claude")
78371
+ join35(home, "../usr/bin/claude")
76930
78372
  ];
76931
78373
  for (const path2 of commonPaths) {
76932
78374
  if (existsSync28(path2)) {
@@ -76990,17 +78432,17 @@ __export(exports_diag_output, {
76990
78432
  LogFileDiagOutput: () => LogFileDiagOutput
76991
78433
  });
76992
78434
  import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync18, unlinkSync as unlinkSync11, writeFileSync as writeFileSync20 } from "fs";
76993
- import { homedir as homedir33 } from "os";
76994
- import { join as join35 } from "path";
78435
+ import { homedir as homedir34 } from "os";
78436
+ import { join as join36 } from "path";
76995
78437
  function getClaudishDir() {
76996
- const dir = join35(homedir33(), ".claudish");
78438
+ const dir = join36(homedir34(), ".claudish");
76997
78439
  try {
76998
78440
  mkdirSync18(dir, { recursive: true });
76999
78441
  } catch {}
77000
78442
  return dir;
77001
78443
  }
77002
78444
  function getDiagLogPath() {
77003
- return join35(getClaudishDir(), `diag-${process.pid}.log`);
78445
+ return join36(getClaudishDir(), `diag-${process.pid}.log`);
77004
78446
  }
77005
78447
 
77006
78448
  class LogFileDiagOutput {
@@ -77015,9 +78457,9 @@ class LogFileDiagOutput {
77015
78457
  this.stream = createWriteStream3(this.logPath, { flags: "a" });
77016
78458
  this.stream.on("error", () => {});
77017
78459
  }
77018
- write(msg) {
78460
+ write(msg2) {
77019
78461
  const timestamp = new Date().toISOString();
77020
- const line = `[${timestamp}] ${msg}
78462
+ const line = `[${timestamp}] ${msg2}
77021
78463
  `;
77022
78464
  try {
77023
78465
  this.stream.write(line);
@@ -77211,9 +78653,9 @@ __export(exports_team_grid, {
77211
78653
  });
77212
78654
  import { spawn as spawn5 } from "child_process";
77213
78655
  import { execSync as execSync2 } from "child_process";
77214
- import { existsSync as existsSync29, readFileSync as readFileSync27, writeFileSync as writeFileSync21 } from "fs";
78656
+ import { existsSync as existsSync29, readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "fs";
77215
78657
  import { connect as netConnect } from "net";
77216
- import { dirname as dirname13, join as join36 } from "path";
78658
+ import { dirname as dirname13, join as join37 } from "path";
77217
78659
  import { setTimeout as wait } from "timers/promises";
77218
78660
  import { fileURLToPath as fileURLToPath3 } from "url";
77219
78661
  function resolveRouteInfo(modelId) {
@@ -77307,17 +78749,17 @@ function buildPaneHeader(model, prompt, bg) {
77307
78749
  function findMagmuxBinary() {
77308
78750
  const thisFile = fileURLToPath3(import.meta.url);
77309
78751
  const thisDir = dirname13(thisFile);
77310
- const pkgRoot = join36(thisDir, "..");
78752
+ const pkgRoot = join37(thisDir, "..");
77311
78753
  const platform3 = process.platform;
77312
78754
  const arch = process.arch;
77313
- const bundledMagmux = join36(pkgRoot, "native", `magmux-${platform3}-${arch}`);
78755
+ const bundledMagmux = join37(pkgRoot, "native", `magmux-${platform3}-${arch}`);
77314
78756
  if (existsSync29(bundledMagmux))
77315
78757
  return bundledMagmux;
77316
78758
  try {
77317
78759
  const pkgName = `@claudish/magmux-${platform3}-${arch}`;
77318
78760
  let searchDir = pkgRoot;
77319
78761
  for (let i = 0;i < 5; i++) {
77320
- const candidate = join36(searchDir, "node_modules", pkgName, "bin", "magmux");
78762
+ const candidate = join37(searchDir, "node_modules", pkgName, "bin", "magmux");
77321
78763
  if (existsSync29(candidate))
77322
78764
  return candidate;
77323
78765
  const parent = dirname13(searchDir);
@@ -77424,9 +78866,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
77424
78866
  const keep = opts?.keep ?? false;
77425
78867
  const manifest = setupSession(sessionPath, models, input);
77426
78868
  const startedAt = new Date().toISOString();
77427
- const gridfilePath = join36(sessionPath, "gridfile.txt");
77428
- const prompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
77429
- const rawPrompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8");
78869
+ const gridfilePath = join37(sessionPath, "gridfile.txt");
78870
+ const prompt = readFileSync28(join37(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
78871
+ const rawPrompt = readFileSync28(join37(sessionPath, "input.md"), "utf-8");
77430
78872
  const usedBannerColors = new Set;
77431
78873
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
77432
78874
  const model = manifest.models[anonId].model;
@@ -77457,7 +78899,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
77457
78899
  });
77458
78900
  const [{ results: results2 }] = await Promise.all([subscription, procExit]);
77459
78901
  const status = buildTeamStatus(manifest, startedAt, results2?.panes ?? null);
77460
- const statusPath = join36(sessionPath, "status.json");
78902
+ const statusPath = join37(sessionPath, "status.json");
77461
78903
  writeFileSync21(statusPath, JSON.stringify(status, null, 2), "utf-8");
77462
78904
  return status;
77463
78905
  }
@@ -77481,8 +78923,8 @@ var init_team_grid = __esm(() => {
77481
78923
  init_op_source();
77482
78924
  init_startup_trace();
77483
78925
  var import_dotenv3 = __toESM(require_main(), 1);
77484
- import { existsSync as existsSync30, readFileSync as readFileSync28 } from "fs";
77485
- import { join as join37, resolve as resolve5 } from "path";
78926
+ import { existsSync as existsSync30, readFileSync as readFileSync29 } from "fs";
78927
+ import { join as join38, resolve as resolve5 } from "path";
77486
78928
  import_dotenv3.config({ quiet: true });
77487
78929
  function classifyStartupKind() {
77488
78930
  const argv = process.argv.slice(2);
@@ -77729,14 +79171,14 @@ async function runCli() {
77729
79171
  if (cliConfig.team && cliConfig.team.length > 0) {
77730
79172
  let prompt = cliConfig.claudeArgs.join(" ");
77731
79173
  if (cliConfig.inputFile) {
77732
- prompt = readFileSync28(cliConfig.inputFile, "utf-8");
79174
+ prompt = readFileSync29(cliConfig.inputFile, "utf-8");
77733
79175
  }
77734
79176
  if (!prompt.trim()) {
77735
79177
  console.error("Error: --team requires a prompt (positional args or -f <file>)");
77736
79178
  process.exit(1);
77737
79179
  }
77738
79180
  const mode = cliConfig.teamMode ?? "default";
77739
- const sessionPath = join37(process.cwd(), `.claudish-team-${Date.now()}`);
79181
+ const sessionPath = join38(process.cwd(), `.claudish-team-${Date.now()}`);
77740
79182
  if (mode === "json") {
77741
79183
  const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
77742
79184
  setupSession2(sessionPath, cliConfig.team, prompt);
@@ -77746,9 +79188,9 @@ async function runCli() {
77746
79188
  });
77747
79189
  const result = { ...status2, responses: {} };
77748
79190
  for (const anonId of Object.keys(status2.models)) {
77749
- const responsePath = join37(sessionPath, `response-${anonId}.md`);
79191
+ const responsePath = join38(sessionPath, `response-${anonId}.md`);
77750
79192
  try {
77751
- const raw2 = readFileSync28(responsePath, "utf-8").trim();
79193
+ const raw2 = readFileSync29(responsePath, "utf-8").trim();
77752
79194
  try {
77753
79195
  result.responses[anonId] = JSON.parse(raw2);
77754
79196
  } catch {