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.
- package/dist/index.js +1866 -424
- 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.
|
|
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/
|
|
31555
|
-
import {
|
|
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 =
|
|
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(
|
|
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
|
|
31672
|
-
import { homedir as
|
|
31673
|
-
import { join as
|
|
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 =
|
|
31702
|
-
return
|
|
31805
|
+
const claudishDir = join15(homedir15(), ".claudish");
|
|
31806
|
+
return join15(claudishDir, "kimi-oauth.json");
|
|
31703
31807
|
}
|
|
31704
31808
|
getDeviceIdPath() {
|
|
31705
|
-
const claudishDir =
|
|
31706
|
-
return
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
32168
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
33519
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
|
34694
|
-
import { homedir as
|
|
34695
|
-
import { join as
|
|
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
|
|
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 =
|
|
34791
|
+
const cachePath = join17(homedir17(), ".codex", "models_cache.json");
|
|
34762
34792
|
if (!existsSync14(cachePath))
|
|
34763
34793
|
return;
|
|
34764
|
-
const cache2 = JSON.parse(
|
|
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(
|
|
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
|
|
35191
|
-
import { dirname as dirname6, join as
|
|
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
|
|
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
|
|
35265
|
-
import { dirname as dirname7, join as
|
|
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
|
|
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
|
|
35607
|
-
import { join as
|
|
35636
|
+
import { homedir as homedir20 } from "os";
|
|
35637
|
+
import { join as join20 } from "path";
|
|
35608
35638
|
function defaultPath() {
|
|
35609
|
-
return
|
|
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
|
|
36267
|
-
import { homedir as
|
|
36268
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 ??
|
|
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 ??
|
|
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
|
|
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
|
|
37137
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
37246
|
-
BUFFER_FILE =
|
|
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
|
|
38361
|
-
import { homedir as
|
|
38362
|
-
import { join as
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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:
|
|
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
|
-
|
|
39299
|
-
|
|
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
|
|
39980
|
-
import { dirname as dirname8, join as
|
|
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 ||
|
|
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
|
|
40241
|
-
if (Array.isArray(
|
|
40242
|
-
for (let partIdx = 0;partIdx <
|
|
40243
|
-
const part =
|
|
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
|
|
40268
|
-
if (Array.isArray(
|
|
40269
|
-
|
|
40270
|
-
if (
|
|
40271
|
-
|
|
40272
|
-
} else if (
|
|
40273
|
-
|
|
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
|
|
40280
|
-
if (Array.isArray(
|
|
40281
|
-
|
|
40282
|
-
if (
|
|
40283
|
-
|
|
40284
|
-
} else if (
|
|
40285
|
-
|
|
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
|
-
|
|
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
|
|
40395
|
-
log(`[${this.provider.displayName}] ${
|
|
40396
|
-
logStderr(`Error: ${
|
|
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,
|
|
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
|
|
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(
|
|
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(
|
|
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}: ${
|
|
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
|
|
44107
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
43112
44108
|
import { createWriteStream, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "fs";
|
|
43113
|
-
import { homedir as
|
|
43114
|
-
import { join as
|
|
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 ??
|
|
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 =
|
|
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 =
|
|
44132
|
+
const sessionDir = join25(this.sessionsDir, sessionId2);
|
|
43137
44133
|
mkdirSync11(sessionDir, { recursive: true });
|
|
43138
44134
|
if (opts.prompt) {
|
|
43139
|
-
writeFileSync10(
|
|
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(
|
|
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(
|
|
44216
|
+
writeFileSync10(join25(sessionDir, "stderr.log"), entry.stderr, "utf-8");
|
|
43221
44217
|
}
|
|
43222
|
-
writeFileSync10(
|
|
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
|
|
45299
|
-
this.appendToSystemPrompt(messages,
|
|
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
|
|
45620
|
-
if (!
|
|
46615
|
+
for (const msg2 of messages) {
|
|
46616
|
+
if (!msg2 || typeof msg2 !== "object")
|
|
45621
46617
|
continue;
|
|
45622
|
-
if (
|
|
46618
|
+
if (msg2.role !== "user")
|
|
45623
46619
|
continue;
|
|
45624
|
-
const 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
|
|
45655
|
-
if (!
|
|
46650
|
+
for (const msg2 of messages) {
|
|
46651
|
+
if (!msg2 || typeof msg2 !== "object")
|
|
45656
46652
|
continue;
|
|
45657
|
-
if (
|
|
46653
|
+
if (msg2.role !== "user")
|
|
45658
46654
|
continue;
|
|
45659
|
-
const 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
|
|
46192
|
-
if (
|
|
46193
|
-
messages.push(this.processUserMessage(
|
|
46194
|
-
} else if (
|
|
46195
|
-
messages.push(this.processAssistantMessage(
|
|
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(
|
|
46221
|
-
if (Array.isArray(
|
|
47480
|
+
processUserMessage(msg2) {
|
|
47481
|
+
if (Array.isArray(msg2.content)) {
|
|
46222
47482
|
const textParts = [];
|
|
46223
|
-
for (const block of
|
|
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:
|
|
47495
|
+
return { role: "user", content: msg2.content };
|
|
46236
47496
|
}
|
|
46237
|
-
processAssistantMessage(
|
|
46238
|
-
if (Array.isArray(
|
|
47497
|
+
processAssistantMessage(msg2) {
|
|
47498
|
+
if (Array.isArray(msg2.content)) {
|
|
46239
47499
|
const strings = [];
|
|
46240
|
-
for (const block of
|
|
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:
|
|
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
|
|
46257
|
-
import { homedir as
|
|
46258
|
-
import { join as
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
46508
|
-
this.lastEnvelope =
|
|
46509
|
-
return
|
|
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
|
|
47927
|
+
const envelope2 = {
|
|
46513
47928
|
model,
|
|
46514
47929
|
project: this.projectId,
|
|
46515
|
-
user_prompt_id:
|
|
47930
|
+
user_prompt_id: randomUUID6(),
|
|
46516
47931
|
request: innerPayload
|
|
46517
47932
|
};
|
|
46518
47933
|
if (this.tierId && this.tierId !== "free-tier") {
|
|
46519
|
-
|
|
47934
|
+
envelope2.enabled_credit_types = ["GOOGLE_ONE_AI"];
|
|
46520
47935
|
}
|
|
46521
|
-
return
|
|
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
|
|
47829
|
-
import { homedir as
|
|
47830
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
47890
|
-
CACHE_FILE =
|
|
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
|
|
48386
|
-
import { join as
|
|
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
|
|
49819
|
+
return join28(sessionPath, "stats");
|
|
48389
49820
|
}
|
|
48390
49821
|
function tokenFileFor(sessionPath, anonId) {
|
|
48391
|
-
return
|
|
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(
|
|
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
|
|
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)} ` + `${
|
|
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(
|
|
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
|
|
50005
|
+
readFileSync as readFileSync19,
|
|
48575
50006
|
readdirSync as readdirSync3,
|
|
48576
50007
|
writeFileSync as writeFileSync12
|
|
48577
50008
|
} from "fs";
|
|
48578
|
-
import { join as
|
|
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(
|
|
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(
|
|
48647
|
-
mkdirSync12(
|
|
50077
|
+
mkdirSync12(join29(sessionPath, "work"), { recursive: true });
|
|
50078
|
+
mkdirSync12(join29(sessionPath, "errors"), { recursive: true });
|
|
48648
50079
|
if (input !== undefined) {
|
|
48649
|
-
writeFileSync12(
|
|
48650
|
-
} else if (!existsSync20(
|
|
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(
|
|
50098
|
+
mkdirSync12(join29(sessionPath, "work", anonId), { recursive: true });
|
|
48668
50099
|
}
|
|
48669
|
-
writeFileSync12(
|
|
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(
|
|
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(
|
|
48689
|
-
const statusPath =
|
|
48690
|
-
const inputPath =
|
|
48691
|
-
const inputContent =
|
|
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(
|
|
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 =
|
|
48713
|
-
const errorLogPath =
|
|
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
|
|
48863
|
-
const detail = `Killed by the orchestrator after ${timeoutMs / 1000}s with ${
|
|
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:
|
|
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] =
|
|
50334
|
+
responses[id] = readFileSync19(join29(sessionPath, file2), "utf-8");
|
|
48904
50335
|
}
|
|
48905
|
-
const input =
|
|
50336
|
+
const input = readFileSync19(join29(sessionPath, "input.md"), "utf-8");
|
|
48906
50337
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
48907
|
-
writeFileSync12(
|
|
50338
|
+
writeFileSync12(join29(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
48908
50339
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
48909
|
-
const judgePath =
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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
|
|
49100
|
-
import { homedir as
|
|
49101
|
-
import { dirname as dirname9, join as
|
|
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(
|
|
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(
|
|
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 =
|
|
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] =
|
|
51146
|
+
sessionData[file2] = readFileSync20(join30(sp, file2), "utf-8");
|
|
49716
51147
|
} catch {}
|
|
49717
51148
|
}
|
|
49718
51149
|
try {
|
|
49719
|
-
const errorDir =
|
|
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}`] =
|
|
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 =
|
|
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 =
|
|
51174
|
+
const pkgPath = join30(__dirname2, "../package.json");
|
|
49744
51175
|
if (existsSync21(pkgPath)) {
|
|
49745
|
-
version2 = JSON.parse(
|
|
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 =
|
|
50150
|
-
ALL_MODELS_CACHE_PATH2 =
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
61243
|
+
var bytes2 = [];
|
|
59805
61244
|
for (;addr > 0; addr >>>= 8) {
|
|
59806
|
-
|
|
61245
|
+
bytes2.push(addr & 255);
|
|
59807
61246
|
}
|
|
59808
|
-
if (
|
|
59809
|
-
|
|
61247
|
+
if (bytes2.length == 0) {
|
|
61248
|
+
bytes2.push(0);
|
|
59810
61249
|
}
|
|
59811
61250
|
var node = this.decodeTables[0];
|
|
59812
|
-
for (var i2 =
|
|
59813
|
-
var val = node[
|
|
61251
|
+
for (var i2 = bytes2.length - 1;i2 > 0; i2--) {
|
|
61252
|
+
var val = node[bytes2[i2]];
|
|
59814
61253
|
if (val == UNASSIGNED) {
|
|
59815
|
-
node[
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
62965
|
-
import { join as
|
|
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 =
|
|
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
|
|
64539
|
-
if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(
|
|
64540
|
-
return { state: "timeout", latencyMs, errorMessage:
|
|
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:
|
|
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
|
|
64680
|
-
if (typeof
|
|
64681
|
-
return
|
|
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
|
|
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
|
|
67181
|
-
import { dirname as dirname10, join as
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
|
68116
|
-
console.error(`${YELLOW}Failed to start probe proxy (${
|
|
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 =
|
|
68682
|
-
const guideContent =
|
|
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 =
|
|
68699
|
-
const skillsDir =
|
|
68700
|
-
const claudishSkillDir =
|
|
68701
|
-
const skillFile =
|
|
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 =
|
|
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
|
|
68813
|
-
import { homedir as
|
|
68814
|
-
import { join as
|
|
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 ||
|
|
68819
|
-
cacheDir =
|
|
70260
|
+
const localAppData = process.env.LOCALAPPDATA || join33(homedir31(), "AppData", "Local");
|
|
70261
|
+
cacheDir = join33(localAppData, "claudish");
|
|
68820
70262
|
} else {
|
|
68821
|
-
cacheDir =
|
|
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
|
|
70269
|
+
return join33(cacheDir, "update-check.json");
|
|
68828
70270
|
} catch {
|
|
68829
|
-
return
|
|
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(
|
|
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
|
|
69747
|
-
import { homedir as
|
|
69748
|
-
import { dirname as dirname11, join as
|
|
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(
|
|
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 =
|
|
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
|
|
74331
|
-
setProbeResults((prev) => prev.map((e) => ({ ...e, status: "failed", error: `probe proxy: ${
|
|
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
|
|
76127
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74686
76128
|
setOpTestResults((prev) => ({
|
|
74687
76129
|
...prev,
|
|
74688
|
-
[key]: { status: "failed", error:
|
|
76130
|
+
[key]: { status: "failed", error: msg2 }
|
|
74689
76131
|
}));
|
|
74690
|
-
setStatusMsg(
|
|
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
|
|
74766
|
-
console.error(`[claudish] 1Password add: saved but live resolve failed: ${
|
|
74767
|
-
setStatusMsg(`1Password ${kindWord} saved (${scope}) \u2014 live resolve failed: ${
|
|
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
|
|
74771
|
-
console.error(`[claudish] 1Password add failed to persist: ${
|
|
74772
|
-
setStatusMsg(`1Password add failed: ${
|
|
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
|
|
74793
|
-
setStatusMsg(
|
|
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
|
|
74815
|
-
setStatusMsg(
|
|
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
|
|
74844
|
-
setStatusMsg(
|
|
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
|
|
76302
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74861
76303
|
setOpEnvPreview(null);
|
|
74862
|
-
setStatusMsg(
|
|
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
|
|
76412
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74971
76413
|
setTestResults((prev) => ({
|
|
74972
76414
|
...prev,
|
|
74973
|
-
[provName]: { status: "failed", error: `proxy: ${
|
|
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
|
|
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
|
|
76247
|
-
import { dirname as dirname12, join as
|
|
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
|
|
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 =
|
|
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 =
|
|
77745
|
+
const claudishDir = join35(homeDir, ".claudish");
|
|
76304
77746
|
const timestamp = Date.now();
|
|
76305
|
-
const scriptPath =
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
76499
|
-
|
|
76500
|
-
|
|
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 =
|
|
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 =
|
|
76547
|
-
const tokenFilePath =
|
|
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 =
|
|
76821
|
-
const localPath = isWindows2() ?
|
|
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 =
|
|
76906
|
-
const localPath = isWindows3 ?
|
|
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
|
-
|
|
76913
|
-
|
|
76914
|
-
|
|
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
|
-
|
|
76926
|
-
|
|
76927
|
-
|
|
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
|
-
|
|
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
|
|
76994
|
-
import { join as
|
|
78435
|
+
import { homedir as homedir34 } from "os";
|
|
78436
|
+
import { join as join36 } from "path";
|
|
76995
78437
|
function getClaudishDir() {
|
|
76996
|
-
const dir =
|
|
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
|
|
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(
|
|
78460
|
+
write(msg2) {
|
|
77019
78461
|
const timestamp = new Date().toISOString();
|
|
77020
|
-
const line = `[${timestamp}] ${
|
|
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
|
|
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
|
|
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 =
|
|
78752
|
+
const pkgRoot = join37(thisDir, "..");
|
|
77311
78753
|
const platform3 = process.platform;
|
|
77312
78754
|
const arch = process.arch;
|
|
77313
|
-
const bundledMagmux =
|
|
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 =
|
|
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 =
|
|
77428
|
-
const prompt =
|
|
77429
|
-
const rawPrompt =
|
|
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 =
|
|
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
|
|
77485
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
79191
|
+
const responsePath = join38(sessionPath, `response-${anonId}.md`);
|
|
77750
79192
|
try {
|
|
77751
|
-
const raw2 =
|
|
79193
|
+
const raw2 = readFileSync29(responsePath, "utf-8").trim();
|
|
77752
79194
|
try {
|
|
77753
79195
|
result.responses[anonId] = JSON.parse(raw2);
|
|
77754
79196
|
} catch {
|