claudish 7.39.0 → 7.41.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 +1888 -360
- 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.41.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();
|
|
@@ -34690,9 +34797,9 @@ var init_antigravity2 = __esm(() => {
|
|
|
34690
34797
|
});
|
|
34691
34798
|
|
|
34692
34799
|
// src/auth/quota/sources/codex.ts
|
|
34693
|
-
import { existsSync as existsSync14, readFileSync as
|
|
34694
|
-
import { homedir as
|
|
34695
|
-
import { join as
|
|
34800
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
|
|
34801
|
+
import { homedir as homedir17 } from "os";
|
|
34802
|
+
import { join as join17 } from "path";
|
|
34696
34803
|
function formatWindowMinutes(minutes) {
|
|
34697
34804
|
if (!Number.isFinite(minutes) || minutes <= 0)
|
|
34698
34805
|
return "";
|
|
@@ -34706,7 +34813,7 @@ function formatWindowMinutes(minutes) {
|
|
|
34706
34813
|
return `${hours}h${minutes % 60}m`;
|
|
34707
34814
|
}
|
|
34708
34815
|
function credentialsPath() {
|
|
34709
|
-
return
|
|
34816
|
+
return join17(homedir17(), ".claudish", "codex-oauth.json");
|
|
34710
34817
|
}
|
|
34711
34818
|
function planLabel(planType) {
|
|
34712
34819
|
if (!planType)
|
|
@@ -34758,10 +34865,10 @@ function scrapeCodexHeaders(headers) {
|
|
|
34758
34865
|
}
|
|
34759
34866
|
function resolveProbeModel() {
|
|
34760
34867
|
try {
|
|
34761
|
-
const cachePath =
|
|
34868
|
+
const cachePath = join17(homedir17(), ".codex", "models_cache.json");
|
|
34762
34869
|
if (!existsSync14(cachePath))
|
|
34763
34870
|
return;
|
|
34764
|
-
const cache2 = JSON.parse(
|
|
34871
|
+
const cache2 = JSON.parse(readFileSync12(cachePath, "utf-8"));
|
|
34765
34872
|
for (const m of cache2.models ?? []) {
|
|
34766
34873
|
const slug = m?.slug ?? m?.id;
|
|
34767
34874
|
if (typeof slug === "string" && slug.length > 0)
|
|
@@ -34775,7 +34882,7 @@ function readCodexCredentials() {
|
|
|
34775
34882
|
const path = credentialsPath();
|
|
34776
34883
|
if (!existsSync14(path))
|
|
34777
34884
|
return;
|
|
34778
|
-
return JSON.parse(
|
|
34885
|
+
return JSON.parse(readFileSync12(path, "utf-8"));
|
|
34779
34886
|
} catch {
|
|
34780
34887
|
return;
|
|
34781
34888
|
}
|
|
@@ -35187,8 +35294,8 @@ var init_harness = __esm(() => {
|
|
|
35187
35294
|
|
|
35188
35295
|
// src/behavior/journal.ts
|
|
35189
35296
|
import { appendFile as appendFile2, mkdir, readFile, rename, stat, writeFile } from "fs/promises";
|
|
35190
|
-
import { homedir as
|
|
35191
|
-
import { dirname as dirname6, join as
|
|
35297
|
+
import { homedir as homedir18 } from "os";
|
|
35298
|
+
import { dirname as dirname6, join as join18 } from "path";
|
|
35192
35299
|
function classifyPath(observed, expected) {
|
|
35193
35300
|
if (!observed)
|
|
35194
35301
|
return "not_applicable";
|
|
@@ -35200,7 +35307,7 @@ function classifyPath(observed, expected) {
|
|
|
35200
35307
|
return dirOf(observed) === dirOf(expected) ? "same_dir_wrong_name" : "outside_expected_dir";
|
|
35201
35308
|
}
|
|
35202
35309
|
function journalPath() {
|
|
35203
|
-
return
|
|
35310
|
+
return join18(homedir18(), ".claudish", "behavior-journal.jsonl");
|
|
35204
35311
|
}
|
|
35205
35312
|
async function prune(path) {
|
|
35206
35313
|
const content = await readFile(path, "utf8");
|
|
@@ -35261,8 +35368,8 @@ __export(exports_aggregate, {
|
|
|
35261
35368
|
});
|
|
35262
35369
|
import { createHash as createHash4, randomBytes as randomBytes4 } from "crypto";
|
|
35263
35370
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7 } from "fs";
|
|
35264
|
-
import { homedir as
|
|
35265
|
-
import { dirname as dirname7, join as
|
|
35371
|
+
import { homedir as homedir19 } from "os";
|
|
35372
|
+
import { dirname as dirname7, join as join19 } from "path";
|
|
35266
35373
|
function contextBucket(inputTokens) {
|
|
35267
35374
|
if (inputTokens < 50000)
|
|
35268
35375
|
return "0-50k";
|
|
@@ -35380,7 +35487,7 @@ function pendingReports() {
|
|
|
35380
35487
|
return [...sessions.values()].map(toReport);
|
|
35381
35488
|
}
|
|
35382
35489
|
function outboxPath() {
|
|
35383
|
-
return
|
|
35490
|
+
return join19(homedir19(), ".claudish", "behavior-outbox.jsonl");
|
|
35384
35491
|
}
|
|
35385
35492
|
function spoolPendingSync(path = outboxPath()) {
|
|
35386
35493
|
if (sessions.size === 0)
|
|
@@ -35603,10 +35710,10 @@ __export(exports_live_log, {
|
|
|
35603
35710
|
recordLiveDivergence: () => recordLiveDivergence
|
|
35604
35711
|
});
|
|
35605
35712
|
import { appendFile as appendFile3 } from "fs/promises";
|
|
35606
|
-
import { homedir as
|
|
35607
|
-
import { join as
|
|
35713
|
+
import { homedir as homedir20 } from "os";
|
|
35714
|
+
import { join as join20 } from "path";
|
|
35608
35715
|
function defaultPath() {
|
|
35609
|
-
return
|
|
35716
|
+
return join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
|
|
35610
35717
|
}
|
|
35611
35718
|
async function recordLiveDivergence(entry, path = defaultPath()) {
|
|
35612
35719
|
try {
|
|
@@ -36263,9 +36370,9 @@ var init_hooks = __esm(() => {
|
|
|
36263
36370
|
});
|
|
36264
36371
|
|
|
36265
36372
|
// src/behavior/observer/corpus.ts
|
|
36266
|
-
import { appendFileSync as appendFileSync3, readFileSync as
|
|
36267
|
-
import { homedir as
|
|
36268
|
-
import { join as
|
|
36373
|
+
import { appendFileSync as appendFileSync3, readFileSync as readFileSync13, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
36374
|
+
import { homedir as homedir21 } from "os";
|
|
36375
|
+
import { join as join21 } from "path";
|
|
36269
36376
|
function directoryOf2(filePath) {
|
|
36270
36377
|
const slash = filePath.lastIndexOf("/");
|
|
36271
36378
|
return slash > 0 ? filePath.slice(0, slash) : undefined;
|
|
@@ -36287,7 +36394,7 @@ function writeTargetsOf(row) {
|
|
|
36287
36394
|
function replayTranscript(file2) {
|
|
36288
36395
|
let text;
|
|
36289
36396
|
try {
|
|
36290
|
-
text =
|
|
36397
|
+
text = readFileSync13(file2, "utf8");
|
|
36291
36398
|
} catch {
|
|
36292
36399
|
return [];
|
|
36293
36400
|
}
|
|
@@ -36344,26 +36451,26 @@ function listTranscripts(root) {
|
|
|
36344
36451
|
return files;
|
|
36345
36452
|
}
|
|
36346
36453
|
for (const project of projects) {
|
|
36347
|
-
const dir =
|
|
36454
|
+
const dir = join21(root, project);
|
|
36348
36455
|
try {
|
|
36349
36456
|
if (!statSync2(dir).isDirectory())
|
|
36350
36457
|
continue;
|
|
36351
36458
|
for (const f of readdirSync2(dir)) {
|
|
36352
36459
|
if (f.endsWith(".jsonl"))
|
|
36353
|
-
files.push(
|
|
36460
|
+
files.push(join21(dir, f));
|
|
36354
36461
|
}
|
|
36355
36462
|
} catch {}
|
|
36356
36463
|
}
|
|
36357
36464
|
return files;
|
|
36358
36465
|
}
|
|
36359
36466
|
function buildCorpus(options = {}) {
|
|
36360
|
-
const root = options.projectsRoot ??
|
|
36467
|
+
const root = options.projectsRoot ?? join21(homedir21(), ".claude", "projects");
|
|
36361
36468
|
const files = listTranscripts(root);
|
|
36362
36469
|
const records = [];
|
|
36363
36470
|
for (const f of files)
|
|
36364
36471
|
records.push(...replayTranscript(f));
|
|
36365
36472
|
if (options.write && records.length > 0) {
|
|
36366
|
-
const outputPath = options.outputPath ??
|
|
36473
|
+
const outputPath = options.outputPath ?? join21(homedir21(), ".claudish", "behavior-divergences.jsonl");
|
|
36367
36474
|
try {
|
|
36368
36475
|
appendFileSync3(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
|
|
36369
36476
|
`)}
|
|
@@ -36683,6 +36790,33 @@ var init_middleware = __esm(() => {
|
|
|
36683
36790
|
init_gemini_thought_signature();
|
|
36684
36791
|
});
|
|
36685
36792
|
|
|
36793
|
+
// src/handlers/shared/quota-exhaustion.ts
|
|
36794
|
+
function hasQuotaExhaustionWording(errorBody) {
|
|
36795
|
+
const lower = (errorBody || "").toLowerCase();
|
|
36796
|
+
return EXHAUSTION_PHRASES.some((phrase) => lower.includes(phrase));
|
|
36797
|
+
}
|
|
36798
|
+
function isQuotaExhaustionError(status, errorBody) {
|
|
36799
|
+
if (status !== 401 && status !== 403 && status !== 429)
|
|
36800
|
+
return false;
|
|
36801
|
+
return hasQuotaExhaustionWording(errorBody);
|
|
36802
|
+
}
|
|
36803
|
+
var EXHAUSTION_PHRASES;
|
|
36804
|
+
var init_quota_exhaustion = __esm(() => {
|
|
36805
|
+
EXHAUSTION_PHRASES = [
|
|
36806
|
+
"usage limit",
|
|
36807
|
+
"billing cycle",
|
|
36808
|
+
"quota",
|
|
36809
|
+
"insufficient balance",
|
|
36810
|
+
"insufficient_quota",
|
|
36811
|
+
"upgrade your plan",
|
|
36812
|
+
"exceeded your current",
|
|
36813
|
+
"out of credits",
|
|
36814
|
+
"credit balance",
|
|
36815
|
+
"daily limit",
|
|
36816
|
+
"plan limit"
|
|
36817
|
+
];
|
|
36818
|
+
});
|
|
36819
|
+
|
|
36686
36820
|
// src/providers/transport/openai.ts
|
|
36687
36821
|
class OpenAIProviderTransport {
|
|
36688
36822
|
name;
|
|
@@ -36768,11 +36902,14 @@ class OpenAIProviderTransport {
|
|
|
36768
36902
|
function isTerminal429(body) {
|
|
36769
36903
|
if (!body)
|
|
36770
36904
|
return false;
|
|
36905
|
+
if (isQuotaExhaustionError(429, body))
|
|
36906
|
+
return true;
|
|
36771
36907
|
const lower = body.toLowerCase();
|
|
36772
36908
|
return lower.includes("insufficient balance") || lower.includes("insufficient_balance") || lower.includes("insufficient_quota") || lower.includes("insufficient quota") || lower.includes("billing_not_active") || lower.includes("billing not active") || lower.includes("quota_exceeded") || lower.includes("exceeded your current quota") || lower.includes("out of credits") || lower.includes('"code":"1113"') || lower.includes('"code":1113');
|
|
36773
36909
|
}
|
|
36774
36910
|
var OpenAITimeoutError, OpenAIConnectionError;
|
|
36775
36911
|
var init_openai = __esm(() => {
|
|
36912
|
+
init_quota_exhaustion();
|
|
36776
36913
|
init_logger();
|
|
36777
36914
|
OpenAITimeoutError = class OpenAITimeoutError extends Error {
|
|
36778
36915
|
constructor(baseUrl) {
|
|
@@ -37098,13 +37235,13 @@ var init_model_parser = __esm(() => {
|
|
|
37098
37235
|
import {
|
|
37099
37236
|
existsSync as existsSync15,
|
|
37100
37237
|
mkdirSync as mkdirSync8,
|
|
37101
|
-
readFileSync as
|
|
37238
|
+
readFileSync as readFileSync14,
|
|
37102
37239
|
renameSync,
|
|
37103
37240
|
unlinkSync as unlinkSync5,
|
|
37104
37241
|
writeFileSync as writeFileSync7
|
|
37105
37242
|
} from "fs";
|
|
37106
|
-
import { homedir as
|
|
37107
|
-
import { join as
|
|
37243
|
+
import { homedir as homedir22 } from "os";
|
|
37244
|
+
import { join as join22 } from "path";
|
|
37108
37245
|
function ensureDir() {
|
|
37109
37246
|
if (!existsSync15(CLAUDISH_DIR)) {
|
|
37110
37247
|
mkdirSync8(CLAUDISH_DIR, { recursive: true });
|
|
@@ -37114,7 +37251,7 @@ function readFromDisk() {
|
|
|
37114
37251
|
try {
|
|
37115
37252
|
if (!existsSync15(BUFFER_FILE))
|
|
37116
37253
|
return [];
|
|
37117
|
-
const raw =
|
|
37254
|
+
const raw = readFileSync14(BUFFER_FILE, "utf-8");
|
|
37118
37255
|
const parsed = JSON.parse(raw);
|
|
37119
37256
|
if (!Array.isArray(parsed.events))
|
|
37120
37257
|
return [];
|
|
@@ -37139,7 +37276,7 @@ function writeToDisk(events) {
|
|
|
37139
37276
|
ensureDir();
|
|
37140
37277
|
const trimmed2 = enforceSizeCap([...events]);
|
|
37141
37278
|
const payload = { version: 1, events: trimmed2 };
|
|
37142
|
-
const tmpFile =
|
|
37279
|
+
const tmpFile = join22(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
|
|
37143
37280
|
writeFileSync7(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
|
|
37144
37281
|
renameSync(tmpFile, BUFFER_FILE);
|
|
37145
37282
|
memoryCache = trimmed2;
|
|
@@ -37212,8 +37349,8 @@ function syncFlushOnExit() {
|
|
|
37212
37349
|
var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
|
|
37213
37350
|
var init_stats_buffer = __esm(() => {
|
|
37214
37351
|
BUFFER_MAX_BYTES = 64 * 1024;
|
|
37215
|
-
CLAUDISH_DIR =
|
|
37216
|
-
BUFFER_FILE =
|
|
37352
|
+
CLAUDISH_DIR = join22(homedir22(), ".claudish");
|
|
37353
|
+
BUFFER_FILE = join22(CLAUDISH_DIR, "stats-buffer.json");
|
|
37217
37354
|
process.on("exit", syncFlushOnExit);
|
|
37218
37355
|
process.on("SIGTERM", () => {
|
|
37219
37356
|
try {
|
|
@@ -38327,9 +38464,9 @@ function compareByReleaseDateDesc(a, b) {
|
|
|
38327
38464
|
}
|
|
38328
38465
|
|
|
38329
38466
|
// src/model-loader.ts
|
|
38330
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as
|
|
38331
|
-
import { homedir as
|
|
38332
|
-
import { join as
|
|
38467
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "fs";
|
|
38468
|
+
import { homedir as homedir23 } from "os";
|
|
38469
|
+
import { join as join23 } from "path";
|
|
38333
38470
|
function groupRecommendedModels(entries) {
|
|
38334
38471
|
const byId = new Map;
|
|
38335
38472
|
const categoryOrder = new Map;
|
|
@@ -38441,7 +38578,7 @@ async function getRecommendedModels(opts = {}) {
|
|
|
38441
38578
|
}
|
|
38442
38579
|
if (!forceRefresh && existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
38443
38580
|
try {
|
|
38444
|
-
const cacheData = JSON.parse(
|
|
38581
|
+
const cacheData = JSON.parse(readFileSync15(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
38445
38582
|
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
38446
38583
|
_cachedRecommendedModels = cacheData;
|
|
38447
38584
|
return cacheData;
|
|
@@ -38457,7 +38594,7 @@ async function getRecommendedModels(opts = {}) {
|
|
|
38457
38594
|
if (data.models && data.models.length > 0) {
|
|
38458
38595
|
_cachedRecommendedModels = data;
|
|
38459
38596
|
try {
|
|
38460
|
-
const cacheDir =
|
|
38597
|
+
const cacheDir = join23(homedir23(), ".claudish");
|
|
38461
38598
|
mkdirSync9(cacheDir, { recursive: true });
|
|
38462
38599
|
writeFileSync8(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
|
|
38463
38600
|
} catch {}
|
|
@@ -38472,7 +38609,7 @@ function getRecommendedModelsSync() {
|
|
|
38472
38609
|
return _cachedRecommendedModels;
|
|
38473
38610
|
if (existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
38474
38611
|
try {
|
|
38475
|
-
const cacheData = JSON.parse(
|
|
38612
|
+
const cacheData = JSON.parse(readFileSync15(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
38476
38613
|
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
38477
38614
|
_cachedRecommendedModels = cacheData;
|
|
38478
38615
|
return cacheData;
|
|
@@ -38596,7 +38733,7 @@ var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels =
|
|
|
38596
38733
|
var init_model_loader = __esm(() => {
|
|
38597
38734
|
init_cache_ttl();
|
|
38598
38735
|
FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
|
|
38599
|
-
RECOMMENDED_MODELS_CACHE_PATH =
|
|
38736
|
+
RECOMMENDED_MODELS_CACHE_PATH = join23(homedir23(), ".claudish", "recommended-models-cache.json");
|
|
38600
38737
|
FIREBASE_SLUG_TO_PROVIDER_NAME = {
|
|
38601
38738
|
openai: "openai",
|
|
38602
38739
|
google: "google",
|
|
@@ -38664,26 +38801,277 @@ var init_context_window_fallback = __esm(() => {
|
|
|
38664
38801
|
inFlight2 = new Map;
|
|
38665
38802
|
});
|
|
38666
38803
|
|
|
38667
|
-
// src/
|
|
38668
|
-
function
|
|
38669
|
-
|
|
38670
|
-
|
|
38671
|
-
|
|
38672
|
-
|
|
38804
|
+
// src/providers/devin/proto-codec.ts
|
|
38805
|
+
function cat(parts) {
|
|
38806
|
+
let total = 0;
|
|
38807
|
+
for (const part of parts)
|
|
38808
|
+
total += part.length;
|
|
38809
|
+
const out = new Uint8Array(total);
|
|
38810
|
+
let offset = 0;
|
|
38811
|
+
for (const part of parts) {
|
|
38812
|
+
out.set(part, offset);
|
|
38813
|
+
offset += part.length;
|
|
38814
|
+
}
|
|
38815
|
+
return out;
|
|
38673
38816
|
}
|
|
38674
|
-
|
|
38675
|
-
|
|
38676
|
-
|
|
38677
|
-
|
|
38678
|
-
|
|
38679
|
-
|
|
38680
|
-
|
|
38681
|
-
|
|
38682
|
-
|
|
38683
|
-
|
|
38684
|
-
|
|
38685
|
-
|
|
38686
|
-
|
|
38817
|
+
function varint(n) {
|
|
38818
|
+
let value = BigInt(n);
|
|
38819
|
+
const out = [];
|
|
38820
|
+
do {
|
|
38821
|
+
let byte = Number(value & 0x7fn);
|
|
38822
|
+
value >>= 7n;
|
|
38823
|
+
if (value > 0n)
|
|
38824
|
+
byte |= 128;
|
|
38825
|
+
out.push(byte);
|
|
38826
|
+
} while (value > 0n);
|
|
38827
|
+
return new Uint8Array(out);
|
|
38828
|
+
}
|
|
38829
|
+
function tag(fieldNumber, wireType) {
|
|
38830
|
+
return varint(fieldNumber << 3 | wireType);
|
|
38831
|
+
}
|
|
38832
|
+
function bytes(fieldNumber, value) {
|
|
38833
|
+
const body = typeof value === "string" ? textEncoder.encode(value) : value;
|
|
38834
|
+
return cat([tag(fieldNumber, 2), varint(body.length), body]);
|
|
38835
|
+
}
|
|
38836
|
+
function vint(fieldNumber, value) {
|
|
38837
|
+
return cat([tag(fieldNumber, 0), varint(value)]);
|
|
38838
|
+
}
|
|
38839
|
+
function msg(...parts) {
|
|
38840
|
+
return cat(parts);
|
|
38841
|
+
}
|
|
38842
|
+
function writeUint32BE(target, offset, value) {
|
|
38843
|
+
target[offset] = value >>> 24 & 255;
|
|
38844
|
+
target[offset + 1] = value >>> 16 & 255;
|
|
38845
|
+
target[offset + 2] = value >>> 8 & 255;
|
|
38846
|
+
target[offset + 3] = value & 255;
|
|
38847
|
+
}
|
|
38848
|
+
function readUint32BE(source, offset) {
|
|
38849
|
+
return (source[offset] << 24 | source[offset + 1] << 16 | source[offset + 2] << 8 | source[offset + 3]) >>> 0;
|
|
38850
|
+
}
|
|
38851
|
+
function envelope(payload, flags = 0) {
|
|
38852
|
+
const out = new Uint8Array(FRAME_HEADER_BYTES + payload.length);
|
|
38853
|
+
out[0] = flags;
|
|
38854
|
+
writeUint32BE(out, 1, payload.length);
|
|
38855
|
+
out.set(payload, FRAME_HEADER_BYTES);
|
|
38856
|
+
return out;
|
|
38857
|
+
}
|
|
38858
|
+
function readVarintAt(buf, p) {
|
|
38859
|
+
let value = 0n;
|
|
38860
|
+
let shift = 0n;
|
|
38861
|
+
let offset = p;
|
|
38862
|
+
while (offset < buf.length) {
|
|
38863
|
+
const byte = buf[offset++];
|
|
38864
|
+
value |= BigInt(byte & 127) << shift;
|
|
38865
|
+
if ((byte & 128) === 0)
|
|
38866
|
+
break;
|
|
38867
|
+
shift += 7n;
|
|
38868
|
+
}
|
|
38869
|
+
return [value, offset];
|
|
38870
|
+
}
|
|
38871
|
+
function parseTLV(buf) {
|
|
38872
|
+
const out = [];
|
|
38873
|
+
let p = 0;
|
|
38874
|
+
while (p < buf.length) {
|
|
38875
|
+
const start = p;
|
|
38876
|
+
let rawTag;
|
|
38877
|
+
[rawTag, p] = readVarintAt(buf, p);
|
|
38878
|
+
const no = Number(rawTag >> 3n);
|
|
38879
|
+
const wire = Number(rawTag & 7n);
|
|
38880
|
+
if (no === 0)
|
|
38881
|
+
break;
|
|
38882
|
+
let payloadStart = p;
|
|
38883
|
+
if (wire === 0) {
|
|
38884
|
+
[, p] = readVarintAt(buf, p);
|
|
38885
|
+
} else if (wire === 1) {
|
|
38886
|
+
p += 8;
|
|
38887
|
+
} else if (wire === 5) {
|
|
38888
|
+
p += 4;
|
|
38889
|
+
} else if (wire === 2) {
|
|
38890
|
+
let len;
|
|
38891
|
+
[len, p] = readVarintAt(buf, p);
|
|
38892
|
+
payloadStart = p;
|
|
38893
|
+
p += Number(len);
|
|
38894
|
+
} else {
|
|
38895
|
+
break;
|
|
38896
|
+
}
|
|
38897
|
+
if (p > buf.length)
|
|
38898
|
+
break;
|
|
38899
|
+
out.push({ no, wire, raw: buf.subarray(start, p), payload: buf.subarray(payloadStart, p) });
|
|
38900
|
+
}
|
|
38901
|
+
return out;
|
|
38902
|
+
}
|
|
38903
|
+
function readVarintValue(tlv) {
|
|
38904
|
+
if (tlv.wire !== 0)
|
|
38905
|
+
return 0;
|
|
38906
|
+
const [value] = readVarintAt(tlv.payload, 0);
|
|
38907
|
+
return Number(value);
|
|
38908
|
+
}
|
|
38909
|
+
function readFloat32LE(tlv) {
|
|
38910
|
+
if (tlv.wire !== 5 || tlv.payload.length < 4)
|
|
38911
|
+
return 0;
|
|
38912
|
+
const view = new DataView(tlv.payload.buffer, tlv.payload.byteOffset, tlv.payload.byteLength);
|
|
38913
|
+
return view.getFloat32(0, true);
|
|
38914
|
+
}
|
|
38915
|
+
function readString(tlv) {
|
|
38916
|
+
return textDecoder.decode(tlv.payload);
|
|
38917
|
+
}
|
|
38918
|
+
function createFrameReader() {
|
|
38919
|
+
let pending = new Uint8Array(0);
|
|
38920
|
+
return (chunk) => {
|
|
38921
|
+
if (chunk.length > 0) {
|
|
38922
|
+
if (pending.length === 0) {
|
|
38923
|
+
pending = chunk;
|
|
38924
|
+
} else {
|
|
38925
|
+
const merged = new Uint8Array(pending.length + chunk.length);
|
|
38926
|
+
merged.set(pending, 0);
|
|
38927
|
+
merged.set(chunk, pending.length);
|
|
38928
|
+
pending = merged;
|
|
38929
|
+
}
|
|
38930
|
+
}
|
|
38931
|
+
const frames = [];
|
|
38932
|
+
let offset = 0;
|
|
38933
|
+
while (offset + FRAME_HEADER_BYTES <= pending.length) {
|
|
38934
|
+
const flags = pending[offset];
|
|
38935
|
+
const length = readUint32BE(pending, offset + 1);
|
|
38936
|
+
const end = offset + FRAME_HEADER_BYTES + length;
|
|
38937
|
+
if (end > pending.length)
|
|
38938
|
+
break;
|
|
38939
|
+
frames.push({ flags, payload: pending.slice(offset + FRAME_HEADER_BYTES, end) });
|
|
38940
|
+
offset = end;
|
|
38941
|
+
}
|
|
38942
|
+
if (offset > 0)
|
|
38943
|
+
pending = pending.slice(offset);
|
|
38944
|
+
return frames;
|
|
38945
|
+
};
|
|
38946
|
+
}
|
|
38947
|
+
var FRAME_HEADER_BYTES = 5, FRAME_FLAG_END_OF_STREAM = 2, textEncoder, textDecoder;
|
|
38948
|
+
var init_proto_codec = __esm(() => {
|
|
38949
|
+
textEncoder = new TextEncoder;
|
|
38950
|
+
textDecoder = new TextDecoder;
|
|
38951
|
+
});
|
|
38952
|
+
|
|
38953
|
+
// src/handlers/shared/devin-stream-head-sniffer.ts
|
|
38954
|
+
function classifyDevinStreamError(code, message) {
|
|
38955
|
+
const lowerCode = code.toLowerCase();
|
|
38956
|
+
if (RETRYABLE_CODES.has(lowerCode))
|
|
38957
|
+
return "retryable";
|
|
38958
|
+
if (TERMINAL_CODES.has(lowerCode))
|
|
38959
|
+
return "terminal";
|
|
38960
|
+
if (lowerCode === "resource_exhausted") {
|
|
38961
|
+
return QUOTA_MESSAGE_RE.test(message) ? "terminal" : "retryable";
|
|
38962
|
+
}
|
|
38963
|
+
if (RETRYABLE_MESSAGE_RE.test(message))
|
|
38964
|
+
return "retryable";
|
|
38965
|
+
return "terminal";
|
|
38966
|
+
}
|
|
38967
|
+
async function sniffDevinStreamHead(response, opts = {}) {
|
|
38968
|
+
const budgetMs = opts.budgetMs ?? DEVIN_SNIFF_BUDGET_MS;
|
|
38969
|
+
const logMsg = opts.log ?? (() => {});
|
|
38970
|
+
if (!response.body)
|
|
38971
|
+
return { kind: "clean", response };
|
|
38972
|
+
const reader = response.body.getReader();
|
|
38973
|
+
const consumed = [];
|
|
38974
|
+
const nextFrames = createFrameReader();
|
|
38975
|
+
const decoder = new TextDecoder;
|
|
38976
|
+
const deadline = Date.now() + budgetMs;
|
|
38977
|
+
const replayResponse = () => {
|
|
38978
|
+
const buffered = consumed.slice();
|
|
38979
|
+
const body = new ReadableStream({
|
|
38980
|
+
start: async (controller) => {
|
|
38981
|
+
try {
|
|
38982
|
+
for (const chunk of buffered)
|
|
38983
|
+
controller.enqueue(chunk);
|
|
38984
|
+
while (true) {
|
|
38985
|
+
const { done, value } = await reader.read();
|
|
38986
|
+
if (done)
|
|
38987
|
+
break;
|
|
38988
|
+
if (value)
|
|
38989
|
+
controller.enqueue(value);
|
|
38990
|
+
}
|
|
38991
|
+
controller.close();
|
|
38992
|
+
} catch (error46) {
|
|
38993
|
+
try {
|
|
38994
|
+
controller.error(error46);
|
|
38995
|
+
} catch {}
|
|
38996
|
+
}
|
|
38997
|
+
},
|
|
38998
|
+
cancel: () => {
|
|
38999
|
+
reader.cancel().catch(() => {});
|
|
39000
|
+
}
|
|
39001
|
+
});
|
|
39002
|
+
return new Response(body, {
|
|
39003
|
+
status: response.status,
|
|
39004
|
+
statusText: response.statusText,
|
|
39005
|
+
headers: response.headers
|
|
39006
|
+
});
|
|
39007
|
+
};
|
|
39008
|
+
try {
|
|
39009
|
+
while (true) {
|
|
39010
|
+
const remaining = deadline - Date.now();
|
|
39011
|
+
if (remaining <= 0) {
|
|
39012
|
+
logMsg(`[DevinSniff] budget ${budgetMs}ms elapsed with no verdict \u2014 streaming through`);
|
|
39013
|
+
return { kind: "clean", response: replayResponse() };
|
|
39014
|
+
}
|
|
39015
|
+
let timer;
|
|
39016
|
+
const timeout = new Promise((resolve2) => {
|
|
39017
|
+
timer = setTimeout(() => resolve2("timeout"), remaining);
|
|
39018
|
+
});
|
|
39019
|
+
let result;
|
|
39020
|
+
try {
|
|
39021
|
+
result = await Promise.race([reader.read(), timeout]);
|
|
39022
|
+
} finally {
|
|
39023
|
+
if (timer)
|
|
39024
|
+
clearTimeout(timer);
|
|
39025
|
+
}
|
|
39026
|
+
if (result === "timeout") {
|
|
39027
|
+
logMsg(`[DevinSniff] budget ${budgetMs}ms elapsed mid-read \u2014 streaming through`);
|
|
39028
|
+
return { kind: "clean", response: replayResponse() };
|
|
39029
|
+
}
|
|
39030
|
+
if (result.done)
|
|
39031
|
+
return { kind: "clean", response: replayResponse() };
|
|
39032
|
+
if (!result.value)
|
|
39033
|
+
continue;
|
|
39034
|
+
consumed.push(result.value);
|
|
39035
|
+
for (const frame of nextFrames(result.value)) {
|
|
39036
|
+
if (frame.flags !== FRAME_FLAG_END_OF_STREAM) {
|
|
39037
|
+
return { kind: "clean", response: replayResponse() };
|
|
39038
|
+
}
|
|
39039
|
+
const raw = decoder.decode(frame.payload).trim();
|
|
39040
|
+
if (!raw || raw === "{}") {
|
|
39041
|
+
return { kind: "clean", response: replayResponse() };
|
|
39042
|
+
}
|
|
39043
|
+
let code = "unknown";
|
|
39044
|
+
let message = raw;
|
|
39045
|
+
try {
|
|
39046
|
+
const parsed = JSON.parse(raw);
|
|
39047
|
+
code = String(parsed?.error?.code ?? parsed?.code ?? "unknown");
|
|
39048
|
+
message = String(parsed?.error?.message ?? parsed?.message ?? raw);
|
|
39049
|
+
} catch {}
|
|
39050
|
+
const kind = classifyDevinStreamError(code, message);
|
|
39051
|
+
logMsg(`[DevinSniff] in-stream error ${code} classified ${kind}: ${message.slice(0, 200)}`);
|
|
39052
|
+
reader.cancel().catch(() => {});
|
|
39053
|
+
return { kind, code, message };
|
|
39054
|
+
}
|
|
39055
|
+
}
|
|
39056
|
+
} catch (error46) {
|
|
39057
|
+
logMsg(`[DevinSniff] read failed (${error46}) \u2014 handing stream to parser`);
|
|
39058
|
+
return { kind: "clean", response: replayResponse() };
|
|
39059
|
+
}
|
|
39060
|
+
}
|
|
39061
|
+
var DEVIN_SNIFF_BUDGET_MS = 12000, RETRYABLE_CODES, TERMINAL_CODES, RETRYABLE_MESSAGE_RE, QUOTA_MESSAGE_RE;
|
|
39062
|
+
var init_devin_stream_head_sniffer = __esm(() => {
|
|
39063
|
+
init_proto_codec();
|
|
39064
|
+
RETRYABLE_CODES = new Set(["unavailable", "internal", "deadline_exceeded", "aborted"]);
|
|
39065
|
+
TERMINAL_CODES = new Set([
|
|
39066
|
+
"permission_denied",
|
|
39067
|
+
"unauthenticated",
|
|
39068
|
+
"invalid_argument",
|
|
39069
|
+
"not_found",
|
|
39070
|
+
"failed_precondition",
|
|
39071
|
+
"unimplemented"
|
|
39072
|
+
]);
|
|
39073
|
+
RETRYABLE_MESSAGE_RE = /third-party model provider is experiencing issues|overloaded|temporarily unavailable|try again|please retry/i;
|
|
39074
|
+
QUOTA_MESSAGE_RE = /quota|out of credits|credit balance|billing|plan limit|exceeded your/i;
|
|
38687
39075
|
});
|
|
38688
39076
|
|
|
38689
39077
|
// src/handlers/shared/stream-head-sniffer.ts
|
|
@@ -39158,6 +39546,350 @@ var init_anthropic_sse = __esm(() => {
|
|
|
39158
39546
|
init_logger();
|
|
39159
39547
|
});
|
|
39160
39548
|
|
|
39549
|
+
// src/handlers/shared/stream-parsers/devin-connect.ts
|
|
39550
|
+
function createDevinConnectStream(_c, response, opts) {
|
|
39551
|
+
const encoder = new TextEncoder;
|
|
39552
|
+
let isClosed = false;
|
|
39553
|
+
let pingInterval = null;
|
|
39554
|
+
const stream = new ReadableStream({
|
|
39555
|
+
async start(controller) {
|
|
39556
|
+
const send = (event, data) => {
|
|
39557
|
+
if (!isClosed) {
|
|
39558
|
+
controller.enqueue(encoder.encode(`event: ${event}
|
|
39559
|
+
data: ${JSON.stringify(data)}
|
|
39560
|
+
|
|
39561
|
+
`));
|
|
39562
|
+
}
|
|
39563
|
+
};
|
|
39564
|
+
const msgId = `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
39565
|
+
let finalized2 = false;
|
|
39566
|
+
let curIdx = 0;
|
|
39567
|
+
let textIdx = -1;
|
|
39568
|
+
let textStarted = false;
|
|
39569
|
+
let thinkingIdx = -1;
|
|
39570
|
+
let thinkingStarted = false;
|
|
39571
|
+
let inputTokens = 0;
|
|
39572
|
+
let outputTokens = 0;
|
|
39573
|
+
let sawUsage = false;
|
|
39574
|
+
let rawStopReason = null;
|
|
39575
|
+
let servedModel = "";
|
|
39576
|
+
let toolBlocksEmitted = 0;
|
|
39577
|
+
let current = null;
|
|
39578
|
+
let lastActivity = Date.now();
|
|
39579
|
+
const textDecoder2 = new TextDecoder;
|
|
39580
|
+
const reasoningDecoder = new TextDecoder;
|
|
39581
|
+
send("message_start", {
|
|
39582
|
+
type: "message_start",
|
|
39583
|
+
message: {
|
|
39584
|
+
id: msgId,
|
|
39585
|
+
type: "message",
|
|
39586
|
+
role: "assistant",
|
|
39587
|
+
content: [],
|
|
39588
|
+
model: opts.modelName,
|
|
39589
|
+
stop_reason: null,
|
|
39590
|
+
stop_sequence: null,
|
|
39591
|
+
usage: messageStartUsage(opts.priorInputTokens)
|
|
39592
|
+
}
|
|
39593
|
+
});
|
|
39594
|
+
send("ping", { type: "ping" });
|
|
39595
|
+
pingInterval = setInterval(() => {
|
|
39596
|
+
if (!isClosed && Date.now() - lastActivity > 1000) {
|
|
39597
|
+
send("ping", { type: "ping" });
|
|
39598
|
+
}
|
|
39599
|
+
}, 1000);
|
|
39600
|
+
const closeThinking = () => {
|
|
39601
|
+
if (!thinkingStarted)
|
|
39602
|
+
return;
|
|
39603
|
+
send("content_block_stop", { type: "content_block_stop", index: thinkingIdx });
|
|
39604
|
+
thinkingStarted = false;
|
|
39605
|
+
};
|
|
39606
|
+
const closeText = () => {
|
|
39607
|
+
if (!textStarted)
|
|
39608
|
+
return;
|
|
39609
|
+
send("content_block_stop", { type: "content_block_stop", index: textIdx });
|
|
39610
|
+
textStarted = false;
|
|
39611
|
+
};
|
|
39612
|
+
const closeCurrentTool = () => {
|
|
39613
|
+
if (!current || current.closed)
|
|
39614
|
+
return;
|
|
39615
|
+
const call = current;
|
|
39616
|
+
current = null;
|
|
39617
|
+
if (call.buffered) {
|
|
39618
|
+
let args = call.args;
|
|
39619
|
+
if (opts.repairToolArgs) {
|
|
39620
|
+
try {
|
|
39621
|
+
const repaired = opts.repairToolArgs(call.name, args);
|
|
39622
|
+
if (typeof repaired === "string" && repaired !== args) {
|
|
39623
|
+
log(`[DevinConnect] tool call repaired: ${call.name}`);
|
|
39624
|
+
args = repaired;
|
|
39625
|
+
}
|
|
39626
|
+
} catch (err) {
|
|
39627
|
+
log(`[DevinConnect] repairToolArgs threw for ${call.name}: ${err}`);
|
|
39628
|
+
}
|
|
39629
|
+
}
|
|
39630
|
+
send("content_block_delta", {
|
|
39631
|
+
type: "content_block_delta",
|
|
39632
|
+
index: call.blockIndex,
|
|
39633
|
+
delta: { type: "input_json_delta", partial_json: args || "{}" }
|
|
39634
|
+
});
|
|
39635
|
+
} else if (!call.args) {
|
|
39636
|
+
send("content_block_delta", {
|
|
39637
|
+
type: "content_block_delta",
|
|
39638
|
+
index: call.blockIndex,
|
|
39639
|
+
delta: { type: "input_json_delta", partial_json: "{}" }
|
|
39640
|
+
});
|
|
39641
|
+
}
|
|
39642
|
+
send("content_block_stop", { type: "content_block_stop", index: call.blockIndex });
|
|
39643
|
+
call.closed = true;
|
|
39644
|
+
};
|
|
39645
|
+
const finalize = (reason, errorMessage) => {
|
|
39646
|
+
if (finalized2)
|
|
39647
|
+
return;
|
|
39648
|
+
finalized2 = true;
|
|
39649
|
+
closeCurrentTool();
|
|
39650
|
+
closeThinking();
|
|
39651
|
+
closeText();
|
|
39652
|
+
if (servedModel && servedModel !== opts.modelName) {
|
|
39653
|
+
log(`[DevinConnect] served model: ${servedModel} (requested ${opts.modelName})`);
|
|
39654
|
+
}
|
|
39655
|
+
if (sawUsage) {
|
|
39656
|
+
log(`[DevinConnect] usage: input=${inputTokens}, output=${outputTokens}` + (rawStopReason !== null ? `, raw stop_reason=${rawStopReason}` : ""));
|
|
39657
|
+
}
|
|
39658
|
+
opts.onTokenUpdate?.(inputTokens, outputTokens);
|
|
39659
|
+
if (reason === "error") {
|
|
39660
|
+
log(`[DevinConnect] stream error: ${errorMessage}`);
|
|
39661
|
+
send("error", { type: "error", error: { type: "api_error", message: errorMessage } });
|
|
39662
|
+
} else {
|
|
39663
|
+
send("message_delta", {
|
|
39664
|
+
type: "message_delta",
|
|
39665
|
+
delta: {
|
|
39666
|
+
stop_reason: toolBlocksEmitted > 0 ? "tool_use" : "end_turn",
|
|
39667
|
+
stop_sequence: null
|
|
39668
|
+
},
|
|
39669
|
+
usage: {
|
|
39670
|
+
...inputTokens > 0 ? { input_tokens: inputTokens } : {},
|
|
39671
|
+
output_tokens: outputTokens
|
|
39672
|
+
}
|
|
39673
|
+
});
|
|
39674
|
+
opts.onTurnEnd?.();
|
|
39675
|
+
send("message_stop", { type: "message_stop" });
|
|
39676
|
+
}
|
|
39677
|
+
if (!isClosed) {
|
|
39678
|
+
isClosed = true;
|
|
39679
|
+
if (pingInterval) {
|
|
39680
|
+
clearInterval(pingInterval);
|
|
39681
|
+
pingInterval = null;
|
|
39682
|
+
}
|
|
39683
|
+
try {
|
|
39684
|
+
controller.close();
|
|
39685
|
+
} catch {}
|
|
39686
|
+
}
|
|
39687
|
+
};
|
|
39688
|
+
const readUsageGroup = (payload) => {
|
|
39689
|
+
for (const entry of parseTLV(payload)) {
|
|
39690
|
+
if (entry.no !== USAGE_ENTRY || entry.wire !== 2)
|
|
39691
|
+
continue;
|
|
39692
|
+
let key = "";
|
|
39693
|
+
let value = null;
|
|
39694
|
+
for (const field of parseTLV(entry.payload)) {
|
|
39695
|
+
if (field.no === USAGE_ENTRY_KEY && field.wire === 2) {
|
|
39696
|
+
key = readString(field);
|
|
39697
|
+
} else if (field.no === USAGE_ENTRY_STAT && field.wire === 2) {
|
|
39698
|
+
for (const stat2 of parseTLV(field.payload)) {
|
|
39699
|
+
if (stat2.no === USAGE_STAT_VALUE && stat2.wire === 5) {
|
|
39700
|
+
value = Math.round(readFloat32LE(stat2));
|
|
39701
|
+
}
|
|
39702
|
+
}
|
|
39703
|
+
}
|
|
39704
|
+
}
|
|
39705
|
+
if (key === USAGE_KEY_INPUT) {
|
|
39706
|
+
inputTokens = value ?? 0;
|
|
39707
|
+
sawUsage = true;
|
|
39708
|
+
} else if (key === USAGE_KEY_OUTPUT) {
|
|
39709
|
+
outputTokens = value ?? 0;
|
|
39710
|
+
sawUsage = true;
|
|
39711
|
+
}
|
|
39712
|
+
}
|
|
39713
|
+
};
|
|
39714
|
+
const readToolCall = (payload) => {
|
|
39715
|
+
let id = "";
|
|
39716
|
+
let name = "";
|
|
39717
|
+
let fragment = null;
|
|
39718
|
+
for (const field of parseTLV(payload)) {
|
|
39719
|
+
if (field.no === TOOL_ID && field.wire === 2)
|
|
39720
|
+
id = readString(field);
|
|
39721
|
+
else if (field.no === TOOL_NAME && field.wire === 2)
|
|
39722
|
+
name = readString(field);
|
|
39723
|
+
else if (field.no === TOOL_ARGS_FRAGMENT && field.wire === 2)
|
|
39724
|
+
fragment = field;
|
|
39725
|
+
}
|
|
39726
|
+
if (name) {
|
|
39727
|
+
closeCurrentTool();
|
|
39728
|
+
closeThinking();
|
|
39729
|
+
closeText();
|
|
39730
|
+
const restored = opts.toolNameMap?.get(name) ?? name;
|
|
39731
|
+
const blockIndex = curIdx++;
|
|
39732
|
+
const toolId = id || `toolu_${Date.now()}_${blockIndex}`;
|
|
39733
|
+
current = {
|
|
39734
|
+
id: toolId,
|
|
39735
|
+
name: restored,
|
|
39736
|
+
blockIndex,
|
|
39737
|
+
buffered: opts.shouldBufferTool?.(restored) ?? false,
|
|
39738
|
+
args: "",
|
|
39739
|
+
decoder: new TextDecoder,
|
|
39740
|
+
closed: false
|
|
39741
|
+
};
|
|
39742
|
+
toolBlocksEmitted++;
|
|
39743
|
+
opts.onToolCallObserved?.(restored);
|
|
39744
|
+
send("content_block_start", {
|
|
39745
|
+
type: "content_block_start",
|
|
39746
|
+
index: blockIndex,
|
|
39747
|
+
content_block: { type: "tool_use", id: toolId, name: restored, input: {} }
|
|
39748
|
+
});
|
|
39749
|
+
}
|
|
39750
|
+
if (!fragment)
|
|
39751
|
+
return;
|
|
39752
|
+
const chunk = current ? current.decoder.decode(fragment.payload, { stream: true }) : readString(fragment);
|
|
39753
|
+
if (!chunk)
|
|
39754
|
+
return;
|
|
39755
|
+
if (!current) {
|
|
39756
|
+
log("[DevinConnect] argument fragment with no open tool call, dropping");
|
|
39757
|
+
return;
|
|
39758
|
+
}
|
|
39759
|
+
current.args += chunk;
|
|
39760
|
+
if (!current.buffered) {
|
|
39761
|
+
send("content_block_delta", {
|
|
39762
|
+
type: "content_block_delta",
|
|
39763
|
+
index: current.blockIndex,
|
|
39764
|
+
delta: { type: "input_json_delta", partial_json: chunk }
|
|
39765
|
+
});
|
|
39766
|
+
}
|
|
39767
|
+
};
|
|
39768
|
+
const readMessageFrame = (payload) => {
|
|
39769
|
+
for (const field of parseTLV(payload)) {
|
|
39770
|
+
lastActivity = Date.now();
|
|
39771
|
+
if (field.no === FIELD_TEXT && field.wire === 2) {
|
|
39772
|
+
const text = textDecoder2.decode(field.payload, { stream: true });
|
|
39773
|
+
if (!text)
|
|
39774
|
+
continue;
|
|
39775
|
+
closeCurrentTool();
|
|
39776
|
+
closeThinking();
|
|
39777
|
+
if (!textStarted) {
|
|
39778
|
+
textIdx = curIdx++;
|
|
39779
|
+
send("content_block_start", {
|
|
39780
|
+
type: "content_block_start",
|
|
39781
|
+
index: textIdx,
|
|
39782
|
+
content_block: { type: "text", text: "" }
|
|
39783
|
+
});
|
|
39784
|
+
textStarted = true;
|
|
39785
|
+
}
|
|
39786
|
+
opts.onAssistantText?.(text, "text");
|
|
39787
|
+
send("content_block_delta", {
|
|
39788
|
+
type: "content_block_delta",
|
|
39789
|
+
index: textIdx,
|
|
39790
|
+
delta: { type: "text_delta", text }
|
|
39791
|
+
});
|
|
39792
|
+
} else if (field.no === FIELD_REASONING && field.wire === 2) {
|
|
39793
|
+
const thinking = reasoningDecoder.decode(field.payload, { stream: true });
|
|
39794
|
+
if (!thinking)
|
|
39795
|
+
continue;
|
|
39796
|
+
closeCurrentTool();
|
|
39797
|
+
if (!thinkingStarted) {
|
|
39798
|
+
thinkingIdx = curIdx++;
|
|
39799
|
+
send("content_block_start", {
|
|
39800
|
+
type: "content_block_start",
|
|
39801
|
+
index: thinkingIdx,
|
|
39802
|
+
content_block: { type: "thinking", thinking: "" }
|
|
39803
|
+
});
|
|
39804
|
+
thinkingStarted = true;
|
|
39805
|
+
}
|
|
39806
|
+
opts.onAssistantText?.(thinking, "reasoning");
|
|
39807
|
+
send("content_block_delta", {
|
|
39808
|
+
type: "content_block_delta",
|
|
39809
|
+
index: thinkingIdx,
|
|
39810
|
+
delta: { type: "thinking_delta", thinking }
|
|
39811
|
+
});
|
|
39812
|
+
} else if (field.no === FIELD_TOOL_CALL && field.wire === 2) {
|
|
39813
|
+
readToolCall(field.payload);
|
|
39814
|
+
} else if (field.no === FIELD_STOP_REASON && field.wire === 0) {
|
|
39815
|
+
rawStopReason = readVarintValue(field);
|
|
39816
|
+
} else if (field.no === FIELD_META && field.wire === 2) {
|
|
39817
|
+
for (const sub of parseTLV(field.payload)) {
|
|
39818
|
+
if (sub.no === META_SERVED_MODEL && sub.wire === 2) {
|
|
39819
|
+
const uid = readString(sub);
|
|
39820
|
+
if (uid && uid !== servedModel) {
|
|
39821
|
+
servedModel = uid;
|
|
39822
|
+
opts.onServedModel?.(uid);
|
|
39823
|
+
}
|
|
39824
|
+
}
|
|
39825
|
+
}
|
|
39826
|
+
} else if (field.no === FIELD_USAGE && field.wire === 2) {
|
|
39827
|
+
readUsageGroup(field.payload);
|
|
39828
|
+
}
|
|
39829
|
+
}
|
|
39830
|
+
};
|
|
39831
|
+
try {
|
|
39832
|
+
const body = response.body;
|
|
39833
|
+
if (!body) {
|
|
39834
|
+
finalize("error", "Devin returned no response body");
|
|
39835
|
+
return;
|
|
39836
|
+
}
|
|
39837
|
+
const reader = body.getReader();
|
|
39838
|
+
const nextFrames = createFrameReader();
|
|
39839
|
+
while (true) {
|
|
39840
|
+
const { done, value } = await reader.read();
|
|
39841
|
+
if (done)
|
|
39842
|
+
break;
|
|
39843
|
+
if (!value)
|
|
39844
|
+
continue;
|
|
39845
|
+
for (const frame of nextFrames(value)) {
|
|
39846
|
+
if (frame.flags === FRAME_FLAG_END_OF_STREAM) {
|
|
39847
|
+
const raw = new TextDecoder().decode(frame.payload).trim();
|
|
39848
|
+
if (!raw || raw === "{}") {
|
|
39849
|
+
finalize("done");
|
|
39850
|
+
return;
|
|
39851
|
+
}
|
|
39852
|
+
let code = "unknown";
|
|
39853
|
+
let message = raw;
|
|
39854
|
+
try {
|
|
39855
|
+
const parsed = JSON.parse(raw);
|
|
39856
|
+
code = String(parsed?.error?.code ?? parsed?.code ?? "unknown");
|
|
39857
|
+
message = String(parsed?.error?.message ?? parsed?.message ?? raw);
|
|
39858
|
+
} catch {}
|
|
39859
|
+
opts.onApiError?.(code, message);
|
|
39860
|
+
finalize("error", `${code}: ${message}`);
|
|
39861
|
+
return;
|
|
39862
|
+
}
|
|
39863
|
+
readMessageFrame(frame.payload);
|
|
39864
|
+
}
|
|
39865
|
+
}
|
|
39866
|
+
finalize("done");
|
|
39867
|
+
} catch (e) {
|
|
39868
|
+
finalize("error", String(e));
|
|
39869
|
+
}
|
|
39870
|
+
},
|
|
39871
|
+
cancel() {
|
|
39872
|
+
isClosed = true;
|
|
39873
|
+
if (pingInterval) {
|
|
39874
|
+
clearInterval(pingInterval);
|
|
39875
|
+
pingInterval = null;
|
|
39876
|
+
}
|
|
39877
|
+
}
|
|
39878
|
+
});
|
|
39879
|
+
return new Response(stream, {
|
|
39880
|
+
headers: {
|
|
39881
|
+
"Content-Type": "text/event-stream",
|
|
39882
|
+
"Cache-Control": "no-cache",
|
|
39883
|
+
Connection: "keep-alive"
|
|
39884
|
+
}
|
|
39885
|
+
});
|
|
39886
|
+
}
|
|
39887
|
+
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";
|
|
39888
|
+
var init_devin_connect = __esm(() => {
|
|
39889
|
+
init_logger();
|
|
39890
|
+
init_proto_codec();
|
|
39891
|
+
});
|
|
39892
|
+
|
|
39161
39893
|
// src/handlers/shared/stream-parsers/gemini-sse.ts
|
|
39162
39894
|
function createGeminiSseStream(_c, response, opts) {
|
|
39163
39895
|
const encoder = new TextEncoder;
|
|
@@ -39968,8 +40700,8 @@ var init_openai_responses_sse = __esm(() => {
|
|
|
39968
40700
|
|
|
39969
40701
|
// src/handlers/shared/token-tracker.ts
|
|
39970
40702
|
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
39971
|
-
import { homedir as
|
|
39972
|
-
import { dirname as dirname8, join as
|
|
40703
|
+
import { homedir as homedir24 } from "os";
|
|
40704
|
+
import { dirname as dirname8, join as join24 } from "path";
|
|
39973
40705
|
function stripProviderPrefix(name) {
|
|
39974
40706
|
const at = name.indexOf("@");
|
|
39975
40707
|
return at === -1 ? name : name.slice(at + 1);
|
|
@@ -40131,7 +40863,7 @@ class TokenTracker {
|
|
|
40131
40863
|
};
|
|
40132
40864
|
}
|
|
40133
40865
|
const override = process.env.CLAUDISH_TOKEN_FILE;
|
|
40134
|
-
const outPath = override ||
|
|
40866
|
+
const outPath = override || join24(homedir24(), ".claudish", `tokens-${this.port}.json`);
|
|
40135
40867
|
mkdirSync10(dirname8(outPath), { recursive: true });
|
|
40136
40868
|
writeFileSync9(outPath, JSON.stringify(data), "utf-8");
|
|
40137
40869
|
} catch (e) {
|
|
@@ -40229,10 +40961,10 @@ class ComposedHandler {
|
|
|
40229
40961
|
if (!this.getModelSupportsVision()) {
|
|
40230
40962
|
const imageBlocks = [];
|
|
40231
40963
|
for (let msgIdx = 0;msgIdx < messages.length; msgIdx++) {
|
|
40232
|
-
const
|
|
40233
|
-
if (Array.isArray(
|
|
40234
|
-
for (let partIdx = 0;partIdx <
|
|
40235
|
-
const part =
|
|
40964
|
+
const msg2 = messages[msgIdx];
|
|
40965
|
+
if (Array.isArray(msg2.content)) {
|
|
40966
|
+
for (let partIdx = 0;partIdx < msg2.content.length; partIdx++) {
|
|
40967
|
+
const part = msg2.content[partIdx];
|
|
40236
40968
|
if (part.type === "image_url" || part.type === "image" || part.type === "document") {
|
|
40237
40969
|
imageBlocks.push({ msgIdx, partIdx, block: part });
|
|
40238
40970
|
}
|
|
@@ -40256,25 +40988,25 @@ class ComposedHandler {
|
|
|
40256
40988
|
};
|
|
40257
40989
|
}
|
|
40258
40990
|
log(`[ComposedHandler] Vision proxy described ${descriptions.length} image(s)`);
|
|
40259
|
-
for (const
|
|
40260
|
-
if (Array.isArray(
|
|
40261
|
-
|
|
40262
|
-
if (
|
|
40263
|
-
|
|
40264
|
-
} else if (
|
|
40265
|
-
|
|
40991
|
+
for (const msg2 of messages) {
|
|
40992
|
+
if (Array.isArray(msg2.content)) {
|
|
40993
|
+
msg2.content = msg2.content.filter((part) => part.type !== "image" && part.type !== "document");
|
|
40994
|
+
if (msg2.content.length === 1 && msg2.content[0].type === "text") {
|
|
40995
|
+
msg2.content = msg2.content[0].text;
|
|
40996
|
+
} else if (msg2.content.length === 0) {
|
|
40997
|
+
msg2.content = "";
|
|
40266
40998
|
}
|
|
40267
40999
|
}
|
|
40268
41000
|
}
|
|
40269
41001
|
} else {
|
|
40270
41002
|
log("[ComposedHandler] Stripping image/document blocks (vision not supported)");
|
|
40271
|
-
for (const
|
|
40272
|
-
if (Array.isArray(
|
|
40273
|
-
|
|
40274
|
-
if (
|
|
40275
|
-
|
|
40276
|
-
} else if (
|
|
40277
|
-
|
|
41003
|
+
for (const msg2 of messages) {
|
|
41004
|
+
if (Array.isArray(msg2.content)) {
|
|
41005
|
+
msg2.content = msg2.content.filter((part) => part.type !== "image_url" && part.type !== "image" && part.type !== "document");
|
|
41006
|
+
if (msg2.content.length === 1 && msg2.content[0].type === "text") {
|
|
41007
|
+
msg2.content = msg2.content[0].text;
|
|
41008
|
+
} else if (msg2.content.length === 0) {
|
|
41009
|
+
msg2.content = "";
|
|
40278
41010
|
}
|
|
40279
41011
|
}
|
|
40280
41012
|
}
|
|
@@ -40312,7 +41044,7 @@ class ComposedHandler {
|
|
|
40312
41044
|
const behaviorSession = this.behaviorEngine.startSession({
|
|
40313
41045
|
modelId: this.bareModelName,
|
|
40314
41046
|
providerName: this.provider.name,
|
|
40315
|
-
isNativeAnthropic: /^claude[-.]/i.test(this.bareModelName) || this.provider.name === "anthropic"
|
|
41047
|
+
isNativeAnthropic: !this.options.forceForeignModel && (/^claude[-.]/i.test(this.bareModelName) || this.provider.name === "anthropic")
|
|
40316
41048
|
});
|
|
40317
41049
|
if (!behaviorSession.isNoop) {
|
|
40318
41050
|
behaviorSession.applyRequest(claudeRequest, claudeRequest.tools ?? [], tools, messages);
|
|
@@ -40368,13 +41100,14 @@ class ComposedHandler {
|
|
|
40368
41100
|
}
|
|
40369
41101
|
const endpoint = this.provider.getEndpoint(this.targetModel);
|
|
40370
41102
|
const headers = await this.provider.getHeaders();
|
|
40371
|
-
|
|
41103
|
+
const serialized = this.provider.serializeBody?.(requestPayload);
|
|
41104
|
+
headers["Content-Type"] = serialized?.contentType ?? "application/json";
|
|
40372
41105
|
log(`[${this.provider.displayName}] Calling API: ${endpoint}`);
|
|
40373
41106
|
const requestInit = this.provider.getRequestInit?.() || {};
|
|
40374
41107
|
const doFetch = () => fetch(endpoint, {
|
|
40375
41108
|
method: "POST",
|
|
40376
41109
|
headers,
|
|
40377
|
-
body: JSON.stringify(requestPayload),
|
|
41110
|
+
body: serialized?.body ?? JSON.stringify(requestPayload),
|
|
40378
41111
|
...requestInit
|
|
40379
41112
|
});
|
|
40380
41113
|
let response;
|
|
@@ -40383,9 +41116,9 @@ class ComposedHandler {
|
|
|
40383
41116
|
} catch (error46) {
|
|
40384
41117
|
const conn = classifyConnectionError(error46);
|
|
40385
41118
|
if (conn) {
|
|
40386
|
-
const
|
|
40387
|
-
log(`[${this.provider.displayName}] ${
|
|
40388
|
-
logStderr(`Error: ${
|
|
41119
|
+
const msg2 = buildConnectionErrorMessage(conn.kind, this.provider.displayName, endpoint);
|
|
41120
|
+
log(`[${this.provider.displayName}] ${msg2} (code=${conn.code})`);
|
|
41121
|
+
logStderr(`Error: ${msg2}`);
|
|
40389
41122
|
reportError({
|
|
40390
41123
|
error: error46,
|
|
40391
41124
|
providerName: this.provider.name,
|
|
@@ -40417,7 +41150,7 @@ class ComposedHandler {
|
|
|
40417
41150
|
invocation_mode: this.options.invocationMode ?? "auto-route"
|
|
40418
41151
|
});
|
|
40419
41152
|
} catch {}
|
|
40420
|
-
return c.json(wrapAnthropicError(400,
|
|
41153
|
+
return c.json(wrapAnthropicError(400, msg2, "connection_error"), 400);
|
|
40421
41154
|
}
|
|
40422
41155
|
throw error46;
|
|
40423
41156
|
}
|
|
@@ -40434,12 +41167,12 @@ class ComposedHandler {
|
|
|
40434
41167
|
try {
|
|
40435
41168
|
await this.provider.forceRefreshAuth();
|
|
40436
41169
|
const retryHeaders = await this.provider.getHeaders();
|
|
40437
|
-
retryHeaders["Content-Type"] = "application/json";
|
|
41170
|
+
retryHeaders["Content-Type"] = serialized?.contentType ?? "application/json";
|
|
40438
41171
|
const retryInit = this.provider.getRequestInit?.() || {};
|
|
40439
41172
|
const retryResp = await fetch(endpoint, {
|
|
40440
41173
|
method: "POST",
|
|
40441
41174
|
headers: retryHeaders,
|
|
40442
|
-
body: JSON.stringify(requestPayload),
|
|
41175
|
+
body: serialized?.body ?? JSON.stringify(requestPayload),
|
|
40443
41176
|
...retryInit
|
|
40444
41177
|
});
|
|
40445
41178
|
if (retryResp.ok) {
|
|
@@ -40619,6 +41352,48 @@ class ComposedHandler {
|
|
|
40619
41352
|
}
|
|
40620
41353
|
response = settled.response;
|
|
40621
41354
|
}
|
|
41355
|
+
if (this.resolveStreamFormat() === "connect-proto") {
|
|
41356
|
+
const settled = await this.settleDevinStreamHead(response, () => this.provider.enqueueRequest ? this.provider.enqueueRequest(doFetch) : doFetch());
|
|
41357
|
+
if (settled.kind !== "ok") {
|
|
41358
|
+
const isTerminal2 = settled.kind === "terminal";
|
|
41359
|
+
const httpStatus2 = isTerminal2 ? 400 : 503;
|
|
41360
|
+
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.`;
|
|
41361
|
+
logStderr(`Error: ${surfaced}`);
|
|
41362
|
+
reportError({
|
|
41363
|
+
error: new Error(settled.message),
|
|
41364
|
+
providerName: this.provider.name,
|
|
41365
|
+
providerDisplayName: this.provider.displayName,
|
|
41366
|
+
streamFormat: this.provider.streamFormat,
|
|
41367
|
+
modelId: this.targetModel,
|
|
41368
|
+
httpStatus: httpStatus2,
|
|
41369
|
+
isStreaming: true,
|
|
41370
|
+
retryAttempted: !isTerminal2,
|
|
41371
|
+
isInteractive: this.isInteractive,
|
|
41372
|
+
providerErrorType: settled.code
|
|
41373
|
+
});
|
|
41374
|
+
try {
|
|
41375
|
+
recordStats({
|
|
41376
|
+
model_id: this.targetModel,
|
|
41377
|
+
provider_name: this.provider.name,
|
|
41378
|
+
stream_format: this.provider.streamFormat,
|
|
41379
|
+
latency_ms: Math.round(performance.now() - startTime),
|
|
41380
|
+
success: false,
|
|
41381
|
+
http_status: httpStatus2,
|
|
41382
|
+
error_class: isTerminal2 ? "client_error" : "server_error",
|
|
41383
|
+
error_code: settled.code,
|
|
41384
|
+
token_strategy: this.options.tokenStrategy ?? "standard",
|
|
41385
|
+
adapter_name: this.getActiveAdapterName(),
|
|
41386
|
+
middleware_names: this.middlewareManager.getActiveNames(this.bareModelName),
|
|
41387
|
+
fallback_used: fallbackMeta !== undefined,
|
|
41388
|
+
fallback_chain: fallbackMeta?.chain,
|
|
41389
|
+
fallback_attempts: fallbackMeta?.attempts,
|
|
41390
|
+
invocation_mode: this.options.invocationMode ?? "auto-route"
|
|
41391
|
+
});
|
|
41392
|
+
} catch {}
|
|
41393
|
+
return isTerminal2 ? c.json(wrapAnthropicError(400, surfaced, "invalid_request_error"), 400) : c.json(wrapAnthropicError(503, surfaced, "overloaded_error"), 503);
|
|
41394
|
+
}
|
|
41395
|
+
response = settled.response;
|
|
41396
|
+
}
|
|
40622
41397
|
latencyMs = Math.round(performance.now() - startTime);
|
|
40623
41398
|
const httpStatus = response.status;
|
|
40624
41399
|
this.capturePlanUsage(response);
|
|
@@ -40697,6 +41472,55 @@ class ComposedHandler {
|
|
|
40697
41472
|
response = next;
|
|
40698
41473
|
}
|
|
40699
41474
|
}
|
|
41475
|
+
async settleDevinStreamHead(initial, reissue) {
|
|
41476
|
+
const rewrite = this.provider.rewriteInStreamError?.bind(this.provider);
|
|
41477
|
+
let response = initial;
|
|
41478
|
+
for (let attempt = 0;; attempt++) {
|
|
41479
|
+
const verdict = await sniffDevinStreamHead(response, { log });
|
|
41480
|
+
if (verdict.kind === "clean")
|
|
41481
|
+
return { kind: "ok", response: verdict.response };
|
|
41482
|
+
if (verdict.kind === "terminal") {
|
|
41483
|
+
const message = rewrite?.(verdict.code, verdict.message) ?? verdict.message;
|
|
41484
|
+
log(`[${this.provider.displayName}] terminal in-stream error ${verdict.code}`);
|
|
41485
|
+
return { kind: "terminal", code: verdict.code, message };
|
|
41486
|
+
}
|
|
41487
|
+
const delayMs = STREAM_RETRY_DELAYS_MS[attempt];
|
|
41488
|
+
if (delayMs === undefined) {
|
|
41489
|
+
log(`[${this.provider.displayName}] in-stream ${verdict.code} persisted after ` + `${attempt} retries \u2014 surfacing 503 so the client can retry`);
|
|
41490
|
+
return {
|
|
41491
|
+
kind: "exhausted",
|
|
41492
|
+
code: verdict.code,
|
|
41493
|
+
message: verdict.message,
|
|
41494
|
+
attempts: attempt
|
|
41495
|
+
};
|
|
41496
|
+
}
|
|
41497
|
+
log(`[${this.provider.displayName}] in-stream ${verdict.code} before any output \u2014 ` + `retry ${attempt + 1}/${STREAM_RETRY_DELAYS_MS.length} in ${delayMs / 1000}s`);
|
|
41498
|
+
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
41499
|
+
let next;
|
|
41500
|
+
try {
|
|
41501
|
+
next = await reissue();
|
|
41502
|
+
} catch (error46) {
|
|
41503
|
+
log(`[${this.provider.displayName}] retry fetch failed: ${error46}`);
|
|
41504
|
+
return {
|
|
41505
|
+
kind: "exhausted",
|
|
41506
|
+
code: verdict.code,
|
|
41507
|
+
message: `${verdict.message} (retry could not reach the provider: ${error46})`,
|
|
41508
|
+
attempts: attempt + 1
|
|
41509
|
+
};
|
|
41510
|
+
}
|
|
41511
|
+
if (!next.ok) {
|
|
41512
|
+
const body = await next.text().catch(() => "");
|
|
41513
|
+
log(`[${this.provider.displayName}] retry returned HTTP ${next.status}`);
|
|
41514
|
+
return {
|
|
41515
|
+
kind: "exhausted",
|
|
41516
|
+
code: `http_${next.status}`,
|
|
41517
|
+
message: body.slice(0, 500) || `HTTP ${next.status}`,
|
|
41518
|
+
attempts: attempt + 1
|
|
41519
|
+
};
|
|
41520
|
+
}
|
|
41521
|
+
response = next;
|
|
41522
|
+
}
|
|
41523
|
+
}
|
|
40700
41524
|
resolveStreamFormat() {
|
|
40701
41525
|
return this.provider.overrideStreamFormat?.() ?? this.explicitAdapter?.getStreamFormat() ?? this.modelAdapter?.getStreamFormat() ?? this.getAdapter().getStreamFormat();
|
|
40702
41526
|
}
|
|
@@ -40782,6 +41606,23 @@ class ComposedHandler {
|
|
|
40782
41606
|
priorInputTokens
|
|
40783
41607
|
});
|
|
40784
41608
|
}
|
|
41609
|
+
case "connect-proto":
|
|
41610
|
+
return createDevinConnectStream(c, response, {
|
|
41611
|
+
modelName: this.bareModelName,
|
|
41612
|
+
onTokenUpdate,
|
|
41613
|
+
priorInputTokens,
|
|
41614
|
+
onApiError,
|
|
41615
|
+
toolNameMap,
|
|
41616
|
+
onServedModel: (uid) => {
|
|
41617
|
+
if (uid !== this.bareModelName)
|
|
41618
|
+
this.tokenTracker.setActiveModelName(uid);
|
|
41619
|
+
},
|
|
41620
|
+
repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null,
|
|
41621
|
+
shouldBufferTool: (name) => behaviorSession?.interceptsTool(name) ?? false,
|
|
41622
|
+
onAssistantText: (text, kind) => behaviorSession?.observeText(text, kind),
|
|
41623
|
+
onToolCallObserved: (name) => behaviorSession?.observeToolCall(name),
|
|
41624
|
+
onTurnEnd: () => behaviorSession?.finishTurn()
|
|
41625
|
+
});
|
|
40785
41626
|
case "ollama-jsonl":
|
|
40786
41627
|
return createOllamaJsonlStream(c, response, {
|
|
40787
41628
|
modelName: this.bareModelName,
|
|
@@ -40837,6 +41678,9 @@ function getRecoveryHint(status, errorText, providerName) {
|
|
|
40837
41678
|
if (status === 429 && isTerminal429(errorText)) {
|
|
40838
41679
|
return "Out of quota \u2014 check your plan & billing details. This won't recover on retry.";
|
|
40839
41680
|
}
|
|
41681
|
+
if (isQuotaExhaustionError(status, errorText)) {
|
|
41682
|
+
return "Subscription allowance spent \u2014 this refills on the provider's own schedule (see the message below). Reducing concurrency won't help; switch model/provider or wait.";
|
|
41683
|
+
}
|
|
40840
41684
|
if (status === 429 || lower.includes("rate limit")) {
|
|
40841
41685
|
return "Rate limited. Wait, reduce concurrency, or check plan limits.";
|
|
40842
41686
|
}
|
|
@@ -40883,10 +41727,12 @@ var init_composed_handler = __esm(() => {
|
|
|
40883
41727
|
init_anthropic_error();
|
|
40884
41728
|
init_connection_error();
|
|
40885
41729
|
init_context_window_fallback();
|
|
41730
|
+
init_devin_stream_head_sniffer();
|
|
40886
41731
|
init_openai_compat();
|
|
40887
41732
|
init_quota_exhaustion();
|
|
40888
41733
|
init_stream_head_sniffer();
|
|
40889
41734
|
init_anthropic_sse();
|
|
41735
|
+
init_devin_connect();
|
|
40890
41736
|
init_gemini_sse();
|
|
40891
41737
|
init_ollama_jsonl();
|
|
40892
41738
|
init_openai_responses_sse();
|
|
@@ -40895,6 +41741,209 @@ var init_composed_handler = __esm(() => {
|
|
|
40895
41741
|
STREAM_RETRY_DELAYS_MS = [3000, 15000, 30000];
|
|
40896
41742
|
});
|
|
40897
41743
|
|
|
41744
|
+
// src/providers/devin/devin-request.ts
|
|
41745
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
41746
|
+
function encodeChatMetadata(meta3) {
|
|
41747
|
+
const version2 = meta3.clientVersion ?? DEVIN_CLI_VERSION;
|
|
41748
|
+
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"));
|
|
41749
|
+
}
|
|
41750
|
+
function encodeMessage(message) {
|
|
41751
|
+
const parts = [
|
|
41752
|
+
bytes(1, message.id ?? randomUUID4()),
|
|
41753
|
+
vint(2, DEVIN_ROLE[message.role])
|
|
41754
|
+
];
|
|
41755
|
+
if (message.text)
|
|
41756
|
+
parts.push(bytes(3, message.text));
|
|
41757
|
+
if (message.toolCall) {
|
|
41758
|
+
parts.push(bytes(6, msg(bytes(1, message.toolCall.id), bytes(2, message.toolCall.name), bytes(3, message.toolCall.argumentsJson))));
|
|
41759
|
+
}
|
|
41760
|
+
if (message.toolCallId)
|
|
41761
|
+
parts.push(bytes(7, message.toolCallId));
|
|
41762
|
+
return msg(...parts);
|
|
41763
|
+
}
|
|
41764
|
+
function encodeTool(tool) {
|
|
41765
|
+
return msg(bytes(1, tool.name), bytes(2, tool.description ?? ""), bytes(3, tool.parametersJson));
|
|
41766
|
+
}
|
|
41767
|
+
function encodeRequestBodyParts(req) {
|
|
41768
|
+
const parts = [];
|
|
41769
|
+
if (req.system)
|
|
41770
|
+
parts.push(bytes(2, req.system));
|
|
41771
|
+
for (const message of req.messages)
|
|
41772
|
+
parts.push(bytes(3, encodeMessage(message)));
|
|
41773
|
+
parts.push(vint(7, req.modelEnum ?? DEFAULT_MODEL_ENUM));
|
|
41774
|
+
for (const tool of req.tools ?? [])
|
|
41775
|
+
parts.push(bytes(10, encodeTool(tool)));
|
|
41776
|
+
parts.push(bytes(21, req.modelUid));
|
|
41777
|
+
return parts;
|
|
41778
|
+
}
|
|
41779
|
+
function encodeDevinRequest(req, meta3) {
|
|
41780
|
+
const body = msg(bytes(1, encodeChatMetadata(meta3)), ...encodeRequestBodyParts(req));
|
|
41781
|
+
return envelope(body);
|
|
41782
|
+
}
|
|
41783
|
+
function describeDevinRequestForLog(req) {
|
|
41784
|
+
const roles = { user: 0, assistant: 0, tool_result: 0 };
|
|
41785
|
+
let toolCalls = 0;
|
|
41786
|
+
for (const message of req.messages) {
|
|
41787
|
+
roles[message.role]++;
|
|
41788
|
+
if (message.toolCall)
|
|
41789
|
+
toolCalls++;
|
|
41790
|
+
}
|
|
41791
|
+
const size = encodeRequestBodyParts(req).reduce((total, part) => total + part.length, 0);
|
|
41792
|
+
const fields = [
|
|
41793
|
+
`uid=${req.modelUid}`,
|
|
41794
|
+
`enum=${req.modelEnum ?? DEFAULT_MODEL_ENUM}`,
|
|
41795
|
+
`messages=${req.messages.length}`,
|
|
41796
|
+
`(user ${roles.user}/assistant ${roles.assistant}/tool_result ${roles.tool_result}`,
|
|
41797
|
+
`calls ${toolCalls})`,
|
|
41798
|
+
`tools=${req.tools?.length ?? 0}`,
|
|
41799
|
+
`system=${req.system?.length ?? 0}ch`
|
|
41800
|
+
];
|
|
41801
|
+
fields.push(`body=${size}B (excl. metadata)`);
|
|
41802
|
+
return fields.join(" ");
|
|
41803
|
+
}
|
|
41804
|
+
var DEVIN_CLI_VERSION = "3000.3.27", DEFAULT_MODEL_ENUM = 5, DEVIN_ROLE;
|
|
41805
|
+
var init_devin_request = __esm(() => {
|
|
41806
|
+
init_proto_codec();
|
|
41807
|
+
DEVIN_ROLE = {
|
|
41808
|
+
user: 1,
|
|
41809
|
+
assistant: 2,
|
|
41810
|
+
tool_result: 4
|
|
41811
|
+
};
|
|
41812
|
+
});
|
|
41813
|
+
|
|
41814
|
+
// src/providers/devin/devin-models.ts
|
|
41815
|
+
var exports_devin_models = {};
|
|
41816
|
+
__export(exports_devin_models, {
|
|
41817
|
+
getServedDevinModels: () => getServedDevinModels,
|
|
41818
|
+
fetchDevinModelConfigs: () => fetchDevinModelConfigs,
|
|
41819
|
+
fetchDevinAllowedUids: () => fetchDevinAllowedUids,
|
|
41820
|
+
_resetDevinModelCache: () => _resetDevinModelCache
|
|
41821
|
+
});
|
|
41822
|
+
function unaryMetadata(apiKey) {
|
|
41823
|
+
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));
|
|
41824
|
+
}
|
|
41825
|
+
async function postUnary(path, apiKey) {
|
|
41826
|
+
const url2 = `${readDevinServerUrl()}${path}`;
|
|
41827
|
+
try {
|
|
41828
|
+
const response = await fetch(url2, {
|
|
41829
|
+
method: "POST",
|
|
41830
|
+
headers: {
|
|
41831
|
+
authorization: `Basic ${apiKey}-${apiKey}`,
|
|
41832
|
+
"content-type": "application/proto",
|
|
41833
|
+
"connect-protocol-version": "1"
|
|
41834
|
+
},
|
|
41835
|
+
body: msg(bytes(1, unaryMetadata(apiKey))),
|
|
41836
|
+
signal: AbortSignal.timeout(UNARY_TIMEOUT_MS)
|
|
41837
|
+
});
|
|
41838
|
+
if (!response.ok) {
|
|
41839
|
+
log(`[Devin] ${path} failed: HTTP ${response.status}`);
|
|
41840
|
+
return null;
|
|
41841
|
+
}
|
|
41842
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
41843
|
+
} catch (err) {
|
|
41844
|
+
log(`[Devin] ${path} error: ${err}`);
|
|
41845
|
+
return null;
|
|
41846
|
+
}
|
|
41847
|
+
}
|
|
41848
|
+
function decodeModelDetails(payload) {
|
|
41849
|
+
let maxOutput = 0;
|
|
41850
|
+
let family = "";
|
|
41851
|
+
for (const sub of parseTLV(payload)) {
|
|
41852
|
+
if (sub.no === 13 && sub.wire === 0)
|
|
41853
|
+
maxOutput = readVarintValue(sub);
|
|
41854
|
+
else if (sub.no === 23 && sub.wire === 2)
|
|
41855
|
+
family = readString(sub);
|
|
41856
|
+
}
|
|
41857
|
+
return { maxOutput, family };
|
|
41858
|
+
}
|
|
41859
|
+
function decodeModelConfig(payload) {
|
|
41860
|
+
let uid = "";
|
|
41861
|
+
let displayName = "";
|
|
41862
|
+
let contextWindow = 0;
|
|
41863
|
+
let details = { maxOutput: 0, family: "" };
|
|
41864
|
+
for (const field of parseTLV(payload)) {
|
|
41865
|
+
if (field.no === 22 && field.wire === 2)
|
|
41866
|
+
uid = readString(field);
|
|
41867
|
+
else if (field.no === 1 && field.wire === 2)
|
|
41868
|
+
displayName = readString(field);
|
|
41869
|
+
else if (field.no === 18 && field.wire === 0)
|
|
41870
|
+
contextWindow = readVarintValue(field);
|
|
41871
|
+
else if (field.no === 23 && field.wire === 2)
|
|
41872
|
+
details = decodeModelDetails(field.payload);
|
|
41873
|
+
}
|
|
41874
|
+
if (!uid)
|
|
41875
|
+
return null;
|
|
41876
|
+
return { uid, displayName: displayName || uid, contextWindow, ...details };
|
|
41877
|
+
}
|
|
41878
|
+
function topLevelDelimited(body, fieldNumber) {
|
|
41879
|
+
return parseTLV(body).filter((field) => field.no === fieldNumber && field.wire === 2);
|
|
41880
|
+
}
|
|
41881
|
+
async function fetchDevinModelConfigs(apiKey) {
|
|
41882
|
+
const body = await postUnary(MODEL_CONFIGS_PATH, apiKey);
|
|
41883
|
+
if (!body)
|
|
41884
|
+
return [];
|
|
41885
|
+
const configs = [];
|
|
41886
|
+
for (const field of topLevelDelimited(body, 1)) {
|
|
41887
|
+
const config2 = decodeModelConfig(field.payload);
|
|
41888
|
+
if (config2)
|
|
41889
|
+
configs.push(config2);
|
|
41890
|
+
}
|
|
41891
|
+
log(`[Devin] GetCliModelConfigs: ${configs.length} configs`);
|
|
41892
|
+
return configs;
|
|
41893
|
+
}
|
|
41894
|
+
async function fetchDevinAllowedUids(apiKey) {
|
|
41895
|
+
const body = await postUnary(TEAM_SETTINGS_PATH, apiKey);
|
|
41896
|
+
if (!body)
|
|
41897
|
+
return [];
|
|
41898
|
+
const uids = [];
|
|
41899
|
+
for (const field of topLevelDelimited(body, 7)) {
|
|
41900
|
+
const uid = readString(field).trim();
|
|
41901
|
+
if (uid)
|
|
41902
|
+
uids.push(uid);
|
|
41903
|
+
}
|
|
41904
|
+
log(`[Devin] GetCliTeamSettings: ${uids.length} allowed uids`);
|
|
41905
|
+
return uids;
|
|
41906
|
+
}
|
|
41907
|
+
async function getServedDevinModels(opts) {
|
|
41908
|
+
const now = Date.now();
|
|
41909
|
+
if (!opts?.force && rosterCache && now - rosterCacheAt < ROSTER_TTL_MS)
|
|
41910
|
+
return rosterCache;
|
|
41911
|
+
const apiKey = opts?.apiKey ?? readDevinApiKey();
|
|
41912
|
+
if (!apiKey)
|
|
41913
|
+
return rosterCache ?? [];
|
|
41914
|
+
try {
|
|
41915
|
+
const [configs, allowed] = await Promise.all([
|
|
41916
|
+
fetchDevinModelConfigs(apiKey),
|
|
41917
|
+
fetchDevinAllowedUids(apiKey)
|
|
41918
|
+
]);
|
|
41919
|
+
if (configs.length === 0)
|
|
41920
|
+
return rosterCache ?? [];
|
|
41921
|
+
const entitled = new Set(allowed);
|
|
41922
|
+
const served = configs.filter((config2) => config2.contextWindow > 0 && (entitled.size === 0 || entitled.has(config2.uid)));
|
|
41923
|
+
if (entitled.size === 0) {
|
|
41924
|
+
log("[Devin] entitlement unknown \u2014 using the full config list (superset)");
|
|
41925
|
+
}
|
|
41926
|
+
rosterCache = served;
|
|
41927
|
+
rosterCacheAt = now;
|
|
41928
|
+
return served;
|
|
41929
|
+
} catch (err) {
|
|
41930
|
+
log(`[Devin] served-model discovery error: ${err}`);
|
|
41931
|
+
return rosterCache ?? [];
|
|
41932
|
+
}
|
|
41933
|
+
}
|
|
41934
|
+
function _resetDevinModelCache() {
|
|
41935
|
+
rosterCache = null;
|
|
41936
|
+
rosterCacheAt = 0;
|
|
41937
|
+
}
|
|
41938
|
+
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;
|
|
41939
|
+
var init_devin_models = __esm(() => {
|
|
41940
|
+
init_logger();
|
|
41941
|
+
init_devin_credentials();
|
|
41942
|
+
init_devin_request();
|
|
41943
|
+
init_proto_codec();
|
|
41944
|
+
ROSTER_TTL_MS = 5 * 60 * 1000;
|
|
41945
|
+
});
|
|
41946
|
+
|
|
40898
41947
|
// src/providers/model-discovery.ts
|
|
40899
41948
|
function resolveBaseUrl(catalogName) {
|
|
40900
41949
|
const def = getProviderByName(catalogName);
|
|
@@ -40955,6 +42004,22 @@ async function discoverProviderModels(providerName) {
|
|
|
40955
42004
|
const descriptor = def?.modelDiscovery;
|
|
40956
42005
|
if (!def || !descriptor)
|
|
40957
42006
|
return [];
|
|
42007
|
+
if (descriptor.format === "devin-connect") {
|
|
42008
|
+
const { getServedDevinModels: getServedDevinModels2 } = await Promise.resolve().then(() => (init_devin_models(), exports_devin_models));
|
|
42009
|
+
const served = await getServedDevinModels2();
|
|
42010
|
+
if (served.length === 0) {
|
|
42011
|
+
log(`[model-discovery:${providerName}] no models for this subscription`);
|
|
42012
|
+
return [];
|
|
42013
|
+
}
|
|
42014
|
+
const models2 = served.map((model) => ({
|
|
42015
|
+
id: model.uid,
|
|
42016
|
+
displayName: model.displayName,
|
|
42017
|
+
contextWindow: model.contextWindow
|
|
42018
|
+
}));
|
|
42019
|
+
log(`[model-discovery:${providerName}] discovered ${models2.length} models`);
|
|
42020
|
+
_cache.set(providerName, { models: models2, expiresAt: Date.now() + CACHE_TTL_MS });
|
|
42021
|
+
return models2;
|
|
42022
|
+
}
|
|
40958
42023
|
const baseUrl = resolveBaseUrl(providerName);
|
|
40959
42024
|
if (!baseUrl)
|
|
40960
42025
|
return [];
|
|
@@ -41129,24 +42194,24 @@ async function discoverViaOpenAIModels(endpoint, headers, cacheKey) {
|
|
|
41129
42194
|
function classifyFetchError(e, endpoint) {
|
|
41130
42195
|
const name = e?.name ?? "";
|
|
41131
42196
|
const code = e?.cause?.code ?? "";
|
|
41132
|
-
const
|
|
42197
|
+
const msg2 = e instanceof Error ? e.message : String(e);
|
|
41133
42198
|
const url2 = tryParseUrl(endpoint);
|
|
41134
42199
|
const host = url2?.host ?? endpoint;
|
|
41135
42200
|
const isLocal = !!url2 && /^(localhost|127\.0\.0\.1|0\.0\.0\.0|::1)$/i.test(url2.hostname);
|
|
41136
|
-
if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(
|
|
42201
|
+
if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg2)) {
|
|
41137
42202
|
return `${host} unresponsive (>${FETCH_TIMEOUT_MS2 / 1000}s) \u2014 check if the server is overloaded`;
|
|
41138
42203
|
}
|
|
41139
42204
|
if (code === "ENOTFOUND" || code === "EAI_AGAIN") {
|
|
41140
42205
|
return `cannot resolve host ${url2?.hostname ?? endpoint} \u2014 check the URL`;
|
|
41141
42206
|
}
|
|
41142
|
-
const isConnRefused = code === "ECONNREFUSED" || code === "ECONNRESET" || /unable to connect|connection refused|fetch failed/i.test(
|
|
42207
|
+
const isConnRefused = code === "ECONNREFUSED" || code === "ECONNRESET" || /unable to connect|connection refused|fetch failed/i.test(msg2);
|
|
41143
42208
|
if (isConnRefused) {
|
|
41144
42209
|
if (isLocal) {
|
|
41145
42210
|
return `${host} not reachable \u2014 is the server running? Press u to change URL.`;
|
|
41146
42211
|
}
|
|
41147
42212
|
return `${host} not reachable \u2014 check the URL or network. Press u to change.`;
|
|
41148
42213
|
}
|
|
41149
|
-
return `${host}: ${
|
|
42214
|
+
return `${host}: ${msg2}`;
|
|
41150
42215
|
}
|
|
41151
42216
|
function tryParseUrl(s) {
|
|
41152
42217
|
try {
|
|
@@ -42173,6 +43238,10 @@ function buildCredentialHint(modelName, providers) {
|
|
|
42173
43238
|
lines.push(` Run: claudish ${hint.loginFlag} (authenticate via OAuth)`);
|
|
42174
43239
|
hasOption = true;
|
|
42175
43240
|
}
|
|
43241
|
+
if (hint.note) {
|
|
43242
|
+
lines.push(` ${hint.note}`);
|
|
43243
|
+
hasOption = true;
|
|
43244
|
+
}
|
|
42176
43245
|
if (hint.apiKeyEnvVar) {
|
|
42177
43246
|
lines.push(` Set: export ${hint.apiKeyEnvVar}=your-key (for ${provider})`);
|
|
42178
43247
|
hasOption = true;
|
|
@@ -42195,6 +43264,10 @@ var init_routing_hints = __esm(() => {
|
|
|
42195
43264
|
google: { loginFlag: "login gemini", apiKeyEnvVar: "GEMINI_API_KEY" },
|
|
42196
43265
|
"gemini-codeassist": { loginFlag: "login gemini", apiKeyEnvVar: "GEMINI_API_KEY" },
|
|
42197
43266
|
antigravity: { loginFlag: "login antigravity" },
|
|
43267
|
+
devin: {
|
|
43268
|
+
note: "Sign in with the Devin CLI (`devin login`) \u2014 claudish reads ~/.local/share/devin/credentials.toml",
|
|
43269
|
+
apiKeyEnvVar: "WINDSURF_API_KEY"
|
|
43270
|
+
},
|
|
42198
43271
|
openai: { apiKeyEnvVar: "OPENAI_API_KEY" },
|
|
42199
43272
|
"openai-codex": { loginFlag: "login codex", apiKeyEnvVar: "OPENAI_CODEX_API_KEY" },
|
|
42200
43273
|
minimax: { apiKeyEnvVar: "MINIMAX_API_KEY" },
|
|
@@ -42249,13 +43322,15 @@ var init_default_routing_rules = __esm(() => {
|
|
|
42249
43322
|
"o3-*": ["openai-codex", "openai", "openrouter"],
|
|
42250
43323
|
"gemini-*": ["antigravity", "google", "openrouter"],
|
|
42251
43324
|
"grok-*": ["x-ai", "openrouter"],
|
|
42252
|
-
"kimi-*": ["kimi-coding", "kimi", "openrouter"],
|
|
42253
|
-
"k3*": ["kimi-coding", "kimi", "openrouter"],
|
|
42254
|
-
"minimax-*": ["minimax-coding", "minimax", "openrouter"],
|
|
42255
|
-
"glm-*": ["glm-coding", "glm", "openrouter"],
|
|
42256
|
-
"qwen3.*": ["qwen-cloud", "openrouter"],
|
|
43325
|
+
"kimi-*": ["kimi-coding", "opencode-zen-go", "kimi", "openrouter"],
|
|
43326
|
+
"k3*": ["kimi-coding", "opencode-zen-go", "kimi", "openrouter"],
|
|
43327
|
+
"minimax-*": ["minimax-coding", "opencode-zen-go", "minimax", "openrouter"],
|
|
43328
|
+
"glm-*": ["glm-coding", "opencode-zen-go", "glm", "openrouter"],
|
|
43329
|
+
"qwen3.*": ["qwen-cloud", "opencode-zen-go", "openrouter"],
|
|
42257
43330
|
"z-ai-*": ["z-ai", "openrouter"],
|
|
42258
|
-
"deepseek-*": ["deepseek", "openrouter"],
|
|
43331
|
+
"deepseek-*": ["opencode-zen-go", "deepseek", "openrouter"],
|
|
43332
|
+
"mimo-*": ["opencode-zen-go", "openrouter"],
|
|
43333
|
+
"hy3*": ["opencode-zen-go", "openrouter"],
|
|
42259
43334
|
fugu: ["sakana-subscription", "sakana"],
|
|
42260
43335
|
"fugu-*": ["sakana-subscription", "sakana"],
|
|
42261
43336
|
"*-zen": ["opencode-zen"],
|
|
@@ -43095,10 +44170,10 @@ var init_signal_watcher = __esm(() => {
|
|
|
43095
44170
|
|
|
43096
44171
|
// src/channel/session-manager.ts
|
|
43097
44172
|
import { spawn } from "child_process";
|
|
43098
|
-
import { randomUUID as
|
|
44173
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
43099
44174
|
import { createWriteStream, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "fs";
|
|
43100
|
-
import { homedir as
|
|
43101
|
-
import { join as
|
|
44175
|
+
import { homedir as homedir25 } from "os";
|
|
44176
|
+
import { join as join25 } from "path";
|
|
43102
44177
|
|
|
43103
44178
|
class SessionManager {
|
|
43104
44179
|
sessions = new Map;
|
|
@@ -43110,20 +44185,20 @@ class SessionManager {
|
|
|
43110
44185
|
constructor(options) {
|
|
43111
44186
|
this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
|
|
43112
44187
|
this.scrollbackCapacity = options?.scrollbackCapacity ?? DEFAULT_SCROLLBACK;
|
|
43113
|
-
this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ??
|
|
44188
|
+
this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join25(homedir25(), ".claudish", "sessions");
|
|
43114
44189
|
this.onStateChange = options?.onStateChange;
|
|
43115
44190
|
}
|
|
43116
44191
|
createSession(opts) {
|
|
43117
44192
|
if (this.activeSessions >= this.maxSessions) {
|
|
43118
44193
|
throw new Error(`Max sessions (${this.maxSessions}) reached`);
|
|
43119
44194
|
}
|
|
43120
|
-
const sessionId2 =
|
|
44195
|
+
const sessionId2 = randomUUID5().slice(0, 8);
|
|
43121
44196
|
const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
|
|
43122
44197
|
const startedAt = new Date().toISOString();
|
|
43123
|
-
const sessionDir =
|
|
44198
|
+
const sessionDir = join25(this.sessionsDir, sessionId2);
|
|
43124
44199
|
mkdirSync11(sessionDir, { recursive: true });
|
|
43125
44200
|
if (opts.prompt) {
|
|
43126
|
-
writeFileSync10(
|
|
44201
|
+
writeFileSync10(join25(sessionDir, "prompt.md"), opts.prompt, "utf-8");
|
|
43127
44202
|
}
|
|
43128
44203
|
const args = [
|
|
43129
44204
|
"--model",
|
|
@@ -43157,7 +44232,7 @@ class SessionManager {
|
|
|
43157
44232
|
});
|
|
43158
44233
|
}
|
|
43159
44234
|
});
|
|
43160
|
-
const outputLogStream = createWriteStream(
|
|
44235
|
+
const outputLogStream = createWriteStream(join25(sessionDir, "output.log"));
|
|
43161
44236
|
const entry = {
|
|
43162
44237
|
info: {
|
|
43163
44238
|
sessionId: sessionId2,
|
|
@@ -43204,9 +44279,9 @@ class SessionManager {
|
|
|
43204
44279
|
watcher.processExited(code);
|
|
43205
44280
|
outputLogStream.end();
|
|
43206
44281
|
if (entry.stderr) {
|
|
43207
|
-
writeFileSync10(
|
|
44282
|
+
writeFileSync10(join25(sessionDir, "stderr.log"), entry.stderr, "utf-8");
|
|
43208
44283
|
}
|
|
43209
|
-
writeFileSync10(
|
|
44284
|
+
writeFileSync10(join25(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
|
|
43210
44285
|
this.cleanupSigint();
|
|
43211
44286
|
});
|
|
43212
44287
|
proc.on("error", (err) => {
|
|
@@ -45282,8 +46357,8 @@ var init_openrouter_api_format = __esm(() => {
|
|
|
45282
46357
|
convertMessages(claudeRequest, filterIdentityFn) {
|
|
45283
46358
|
const messages = super.convertMessages(claudeRequest, filterIdentityFn);
|
|
45284
46359
|
if (this.modelId.includes("grok") || this.modelId.includes("x-ai")) {
|
|
45285
|
-
const
|
|
45286
|
-
this.appendToSystemPrompt(messages,
|
|
46360
|
+
const msg2 = "IMPORTANT: When calling tools, you MUST use the OpenAI tool_calls format with JSON. NEVER use XML format like <xai:function_call>.";
|
|
46361
|
+
this.appendToSystemPrompt(messages, msg2);
|
|
45287
46362
|
}
|
|
45288
46363
|
if (this.modelId.includes("gemini") || this.modelId.includes("google/")) {
|
|
45289
46364
|
const geminiMsg = `CRITICAL INSTRUCTION FOR OUTPUT FORMAT:
|
|
@@ -45404,7 +46479,11 @@ class FallbackHandler {
|
|
|
45404
46479
|
}
|
|
45405
46480
|
errors3.push({ provider: name, status: response.status, message: errorBody });
|
|
45406
46481
|
if (!isLast) {
|
|
45407
|
-
|
|
46482
|
+
if (hasQuotaExhaustionWording(errorBody)) {
|
|
46483
|
+
logStderr(`[Fallback] ${name} subscription allowance is spent \u2014 falling through to the next provider, which is billed PER TOKEN. Use a provider prefix (e.g. \`zgo@model\`) to fail instead of switching.`);
|
|
46484
|
+
} else {
|
|
46485
|
+
logStderr(`[Fallback] ${name} failed (HTTP ${response.status}), trying next provider...`);
|
|
46486
|
+
}
|
|
45408
46487
|
}
|
|
45409
46488
|
} catch (err) {
|
|
45410
46489
|
errors3.push({ provider: name, status: 0, message: err.message });
|
|
@@ -45441,8 +46520,8 @@ ${summary}`);
|
|
|
45441
46520
|
}
|
|
45442
46521
|
}
|
|
45443
46522
|
function isRetryableError(status, errorBody) {
|
|
45444
|
-
if (
|
|
45445
|
-
return
|
|
46523
|
+
if (hasQuotaExhaustionWording(errorBody))
|
|
46524
|
+
return true;
|
|
45446
46525
|
if (status === 401 || status === 403)
|
|
45447
46526
|
return true;
|
|
45448
46527
|
if (status === 402)
|
|
@@ -45599,12 +46678,12 @@ function rewriteAdvisorToolResults(payload, getAdviceFor) {
|
|
|
45599
46678
|
if (!Array.isArray(messages))
|
|
45600
46679
|
return [];
|
|
45601
46680
|
const rewritten = [];
|
|
45602
|
-
for (const
|
|
45603
|
-
if (!
|
|
46681
|
+
for (const msg2 of messages) {
|
|
46682
|
+
if (!msg2 || typeof msg2 !== "object")
|
|
45604
46683
|
continue;
|
|
45605
|
-
if (
|
|
46684
|
+
if (msg2.role !== "user")
|
|
45606
46685
|
continue;
|
|
45607
|
-
const content =
|
|
46686
|
+
const content = msg2.content;
|
|
45608
46687
|
if (!Array.isArray(content))
|
|
45609
46688
|
continue;
|
|
45610
46689
|
for (const block of content) {
|
|
@@ -45634,12 +46713,12 @@ function findPendingAdvisorToolResults(payload) {
|
|
|
45634
46713
|
if (!Array.isArray(messages))
|
|
45635
46714
|
return [];
|
|
45636
46715
|
const found = [];
|
|
45637
|
-
for (const
|
|
45638
|
-
if (!
|
|
46716
|
+
for (const msg2 of messages) {
|
|
46717
|
+
if (!msg2 || typeof msg2 !== "object")
|
|
45639
46718
|
continue;
|
|
45640
|
-
if (
|
|
46719
|
+
if (msg2.role !== "user")
|
|
45641
46720
|
continue;
|
|
45642
|
-
const content =
|
|
46721
|
+
const content = msg2.content;
|
|
45643
46722
|
if (!Array.isArray(content))
|
|
45644
46723
|
continue;
|
|
45645
46724
|
for (const block of content) {
|
|
@@ -46137,13 +47216,277 @@ var init_api_key_map = __esm(() => {
|
|
|
46137
47216
|
"qwen-cloud": { envVar: "QWEN_CLOUD_PLAN_API_KEY" },
|
|
46138
47217
|
ollamacloud: { envVar: "OLLAMA_API_KEY" },
|
|
46139
47218
|
"opencode-zen": { envVar: "OPENCODE_API_KEY" },
|
|
46140
|
-
"opencode-zen-go": { envVar: "OPENCODE_API_KEY" },
|
|
47219
|
+
"opencode-zen-go": { envVar: "OPENCODE_GO_API_KEY", aliases: ["OPENCODE_API_KEY"] },
|
|
46141
47220
|
"gemini-codeassist": { envVar: "GEMINI_API_KEY" },
|
|
46142
47221
|
vertex: { envVar: "VERTEX_API_KEY", aliases: ["VERTEX_PROJECT"] },
|
|
46143
47222
|
poe: { envVar: "POE_API_KEY" }
|
|
46144
47223
|
};
|
|
46145
47224
|
});
|
|
46146
47225
|
|
|
47226
|
+
// src/providers/devin/tool-descriptions.ts
|
|
47227
|
+
function currentMonthAndYear(now = new Date) {
|
|
47228
|
+
return `${MONTHS[now.getMonth()]} ${now.getFullYear()}`;
|
|
47229
|
+
}
|
|
47230
|
+
function buildWebSearchDescription(monthAndYear) {
|
|
47231
|
+
return `Runs a web search and lets you fold the results into your answer.
|
|
47232
|
+
|
|
47233
|
+
- Reaches live sources, so it covers current events and material recent enough to post-date your
|
|
47234
|
+
training data. This is the tool for any question that runs past your knowledge cutoff.
|
|
47235
|
+
- Results arrive as search-result blocks; links inside them are already written as markdown
|
|
47236
|
+
hyperlinks.
|
|
47237
|
+
- The entire search happens within a single API call \u2014 there is nothing extra to orchestrate.
|
|
47238
|
+
|
|
47239
|
+
NON-NEGOTIABLE OUTPUT REQUIREMENT \u2014 this is MANDATORY, and you must never skip it:
|
|
47240
|
+
- Once you have answered the user's question, the very end of your response MUST carry a section
|
|
47241
|
+
headed \`Sources:\`.
|
|
47242
|
+
- Beneath that heading, list every URL from the search results that is relevant to the answer,
|
|
47243
|
+
each written as a markdown hyperlink in the form [Title](URL).
|
|
47244
|
+
- Leaving the sources section out is not an option, however short or obvious the answer looks.
|
|
47245
|
+
- Shape of the finished response:
|
|
47246
|
+
|
|
47247
|
+
[your answer goes here]
|
|
47248
|
+
|
|
47249
|
+
Sources:
|
|
47250
|
+
- [First page title](https://first.example/page)
|
|
47251
|
+
- [Second page title](https://second.example/page)
|
|
47252
|
+
|
|
47253
|
+
Other things worth knowing:
|
|
47254
|
+
- Results can be confined by domain: \`allowed_domains\` restricts the search to specific sites,
|
|
47255
|
+
\`blocked_domains\` keeps named sites out.
|
|
47256
|
+
- Web search is served only within the United States.
|
|
47257
|
+
|
|
47258
|
+
Dates in queries \u2014 get the year right:
|
|
47259
|
+
- The present month is ${monthAndYear}. Any query about recent material, current documentation or
|
|
47260
|
+
ongoing events MUST be qualified with that year.
|
|
47261
|
+
- For example, asked for "latest React docs", search for React documentation carrying the current
|
|
47262
|
+
year, not the one before it.`;
|
|
47263
|
+
}
|
|
47264
|
+
function buildDevinToolDescriptions(now = new Date) {
|
|
47265
|
+
return new Map([
|
|
47266
|
+
["Read", READ_DESCRIPTION],
|
|
47267
|
+
["TaskOutput", TASK_OUTPUT_DESCRIPTION],
|
|
47268
|
+
["WebSearch", buildWebSearchDescription(currentMonthAndYear(now))]
|
|
47269
|
+
]);
|
|
47270
|
+
}
|
|
47271
|
+
function toolName(tool) {
|
|
47272
|
+
if (!tool || typeof tool !== "object")
|
|
47273
|
+
return;
|
|
47274
|
+
const record4 = tool;
|
|
47275
|
+
const nested = record4.function?.name;
|
|
47276
|
+
if (typeof nested === "string")
|
|
47277
|
+
return nested;
|
|
47278
|
+
return typeof record4.name === "string" ? record4.name : undefined;
|
|
47279
|
+
}
|
|
47280
|
+
function applyDevinToolDescriptions(tools, descriptions = DEVIN_TOOL_DESCRIPTIONS) {
|
|
47281
|
+
return tools.map((tool) => {
|
|
47282
|
+
const name = toolName(tool);
|
|
47283
|
+
const replacement = name === undefined ? undefined : descriptions.get(name);
|
|
47284
|
+
if (replacement === undefined)
|
|
47285
|
+
return tool;
|
|
47286
|
+
const record4 = tool;
|
|
47287
|
+
if (record4.function && typeof record4.function === "object") {
|
|
47288
|
+
return {
|
|
47289
|
+
...record4,
|
|
47290
|
+
function: { ...record4.function, description: replacement }
|
|
47291
|
+
};
|
|
47292
|
+
}
|
|
47293
|
+
return { ...record4, description: replacement };
|
|
47294
|
+
});
|
|
47295
|
+
}
|
|
47296
|
+
var MONTHS, READ_DESCRIPTION = `Retrieves the contents of a single file from the machine's local disk.
|
|
47297
|
+
|
|
47298
|
+
Nothing on the host is out of bounds \u2014 assume you can open whatever you need. When the user hands
|
|
47299
|
+
you a path, take it at face value and try it; aiming at a file that turns out not to exist is
|
|
47300
|
+
harmless, the call simply comes back as an error.
|
|
47301
|
+
|
|
47302
|
+
Calling conventions:
|
|
47303
|
+
- \`file_path\` has to be a fully-qualified absolute path. A relative path will not be accepted.
|
|
47304
|
+
- Left unbounded, the call hands back at most the first 2000 lines, counted from the top of the file.
|
|
47305
|
+
- If you already know which region of the file matters, ask for that region alone. On large files
|
|
47306
|
+
this is the difference between a cheap call and an expensive one.
|
|
47307
|
+
- Output is formatted the way \`cat -n\` formats it: each line prefixed with its number, and the
|
|
47308
|
+
numbering begins at 1.
|
|
47309
|
+
- Image files work (PNG, JPG and the rest). The picture itself is handed over for you to look at,
|
|
47310
|
+
since the model behind this session takes visual input as well as text.
|
|
47311
|
+
- PDF documents work. Once a document runs past ten pages the \`pages\` argument becomes REQUIRED \u2014
|
|
47312
|
+
give it the span you want, for instance \`pages: "1-5"\`. Leaving \`pages\` off a long PDF makes the
|
|
47313
|
+
call fail outright. One request may cover twenty pages at most.
|
|
47314
|
+
- Jupyter notebooks (\`.ipynb\`) come back fully expanded: every cell together with the output that
|
|
47315
|
+
cell produced, so source, prose and rendered figures all arrive in one piece.
|
|
47316
|
+
- Files only, never directories. To find out what a folder holds, reach for the shell tool
|
|
47317
|
+
registered for this session.
|
|
47318
|
+
- Screenshots are a routine case. Whenever a path to a screenshot is supplied, view it through this
|
|
47319
|
+
tool rather than by any other route; paths inside temporary directories are fine.
|
|
47320
|
+
- Opening a file that exists but holds nothing gives you a system-reminder notice standing in for
|
|
47321
|
+
the file body.
|
|
47322
|
+
- Do not re-open a file just to confirm an edit you have already made. Had that Edit or Write
|
|
47323
|
+
failed it would have raised an error at the time, and the harness keeps track of each file's
|
|
47324
|
+
current state on your behalf.`, TASK_OUTPUT_DESCRIPTION = `DEPRECATED \u2014 in almost every case reach for Read instead.
|
|
47325
|
+
|
|
47326
|
+
The reason it is deprecated: a task launched in the background already reports the path of its
|
|
47327
|
+
output file as part of the tool result, and a <task-notification> quoting that same path arrives
|
|
47328
|
+
once the task finishes. The path is in front of you either way, so routing back through this tool
|
|
47329
|
+
buys nothing.
|
|
47330
|
+
|
|
47331
|
+
Which route to take, by task kind:
|
|
47332
|
+
- bash tasks \u2014 open the reported output path with Read. Both stdout and stderr are captured there.
|
|
47333
|
+
- local_agent tasks \u2014 take the answer straight from what the Agent tool returned. NEVER open the
|
|
47334
|
+
\`.output\` file with Read. That entry is a symlink pointing at the subagent's ENTIRE conversation
|
|
47335
|
+
transcript in JSONL form, and pulling it in WILL overflow your context window.
|
|
47336
|
+
- remote_agent tasks \u2014 open the reported output path with Read, exactly as for bash; it holds the
|
|
47337
|
+
remote session's streamed output.
|
|
47338
|
+
|
|
47339
|
+
If you call it anyway, this is what it does:
|
|
47340
|
+
- Fetches the output of a task that is either still running or already finished \u2014 a backgrounded
|
|
47341
|
+
shell, an agent, or a remote session.
|
|
47342
|
+
- Identifies which task through the \`task_id\` parameter.
|
|
47343
|
+
- Replies with the task's output alongside its status.
|
|
47344
|
+
- \`block=true\` is the default and makes the call wait until the task has completed.
|
|
47345
|
+
- \`block=false\` returns straight away with whatever the status is at that moment.
|
|
47346
|
+
- The \`/tasks\` command lists the ids you can pass.
|
|
47347
|
+
- Every task flavour is supported: backgrounded shells, asynchronous agents, and remote sessions.`, DEVIN_TOOL_DESCRIPTIONS;
|
|
47348
|
+
var init_tool_descriptions = __esm(() => {
|
|
47349
|
+
MONTHS = [
|
|
47350
|
+
"January",
|
|
47351
|
+
"February",
|
|
47352
|
+
"March",
|
|
47353
|
+
"April",
|
|
47354
|
+
"May",
|
|
47355
|
+
"June",
|
|
47356
|
+
"July",
|
|
47357
|
+
"August",
|
|
47358
|
+
"September",
|
|
47359
|
+
"October",
|
|
47360
|
+
"November",
|
|
47361
|
+
"December"
|
|
47362
|
+
];
|
|
47363
|
+
DEVIN_TOOL_DESCRIPTIONS = buildDevinToolDescriptions();
|
|
47364
|
+
});
|
|
47365
|
+
|
|
47366
|
+
// src/adapters/devin-api-format.ts
|
|
47367
|
+
function contentToText(content) {
|
|
47368
|
+
if (typeof content === "string")
|
|
47369
|
+
return content;
|
|
47370
|
+
if (!Array.isArray(content))
|
|
47371
|
+
return "";
|
|
47372
|
+
const parts = [];
|
|
47373
|
+
for (const part of content) {
|
|
47374
|
+
if (typeof part === "string") {
|
|
47375
|
+
parts.push(part);
|
|
47376
|
+
continue;
|
|
47377
|
+
}
|
|
47378
|
+
if (part && typeof part === "object" && "text" in part) {
|
|
47379
|
+
const { text } = part;
|
|
47380
|
+
if (typeof text === "string")
|
|
47381
|
+
parts.push(text);
|
|
47382
|
+
}
|
|
47383
|
+
}
|
|
47384
|
+
return parts.join(`
|
|
47385
|
+
`);
|
|
47386
|
+
}
|
|
47387
|
+
var DEVIN_RELOCATION_NOTE, DEVIN_MINIMAL_SYSTEM = "You are a coding agent.", DevinAPIFormat;
|
|
47388
|
+
var init_devin_api_format = __esm(() => {
|
|
47389
|
+
init_tool_descriptions();
|
|
47390
|
+
init_base_api_format();
|
|
47391
|
+
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.";
|
|
47392
|
+
DevinAPIFormat = class DevinAPIFormat extends BaseAPIFormat {
|
|
47393
|
+
processTextContent(textContent, _accumulatedText) {
|
|
47394
|
+
return {
|
|
47395
|
+
cleanedText: textContent,
|
|
47396
|
+
extractedToolCalls: [],
|
|
47397
|
+
wasTransformed: false
|
|
47398
|
+
};
|
|
47399
|
+
}
|
|
47400
|
+
shouldHandle(_modelId) {
|
|
47401
|
+
return false;
|
|
47402
|
+
}
|
|
47403
|
+
getName() {
|
|
47404
|
+
return "DevinAPIFormat";
|
|
47405
|
+
}
|
|
47406
|
+
getStreamFormat() {
|
|
47407
|
+
return "connect-proto";
|
|
47408
|
+
}
|
|
47409
|
+
getContextWindow() {
|
|
47410
|
+
return 0;
|
|
47411
|
+
}
|
|
47412
|
+
supportsVision() {
|
|
47413
|
+
return false;
|
|
47414
|
+
}
|
|
47415
|
+
applyNativeReasoning(request, originalRequest) {
|
|
47416
|
+
const effort = this.resolveEffortLevel(originalRequest);
|
|
47417
|
+
if (effort)
|
|
47418
|
+
request.effort = effort;
|
|
47419
|
+
return request;
|
|
47420
|
+
}
|
|
47421
|
+
buildPayload(_claudeRequest, messages, tools) {
|
|
47422
|
+
const systemParts = [];
|
|
47423
|
+
const devinMessages = [];
|
|
47424
|
+
for (const message of messages) {
|
|
47425
|
+
const role = message?.role;
|
|
47426
|
+
if (role === "system") {
|
|
47427
|
+
const text = contentToText(message.content);
|
|
47428
|
+
if (text)
|
|
47429
|
+
systemParts.push(text);
|
|
47430
|
+
continue;
|
|
47431
|
+
}
|
|
47432
|
+
if (role === "tool") {
|
|
47433
|
+
devinMessages.push({
|
|
47434
|
+
role: "tool_result",
|
|
47435
|
+
text: contentToText(message.content),
|
|
47436
|
+
toolCallId: message.tool_call_id
|
|
47437
|
+
});
|
|
47438
|
+
continue;
|
|
47439
|
+
}
|
|
47440
|
+
if (role === "assistant") {
|
|
47441
|
+
const text = contentToText(message.content);
|
|
47442
|
+
if (text)
|
|
47443
|
+
devinMessages.push({ role: "assistant", text });
|
|
47444
|
+
for (const call of message.tool_calls ?? []) {
|
|
47445
|
+
devinMessages.push({
|
|
47446
|
+
role: "assistant",
|
|
47447
|
+
toolCall: {
|
|
47448
|
+
id: call?.id ?? "",
|
|
47449
|
+
name: call?.function?.name ?? "",
|
|
47450
|
+
argumentsJson: call?.function?.arguments || "{}"
|
|
47451
|
+
}
|
|
47452
|
+
});
|
|
47453
|
+
}
|
|
47454
|
+
continue;
|
|
47455
|
+
}
|
|
47456
|
+
devinMessages.push({ role: "user", text: contentToText(message.content) });
|
|
47457
|
+
}
|
|
47458
|
+
const devinTools = applyDevinToolDescriptions(tools).map((tool) => ({
|
|
47459
|
+
name: tool?.function?.name ?? tool?.name ?? "",
|
|
47460
|
+
description: tool?.function?.description ?? tool?.description ?? "",
|
|
47461
|
+
parametersJson: JSON.stringify(tool?.function?.parameters ?? tool?.parameters ?? { type: "object", properties: {} })
|
|
47462
|
+
}));
|
|
47463
|
+
let system;
|
|
47464
|
+
if (systemParts.length > 0) {
|
|
47465
|
+
devinMessages.unshift({
|
|
47466
|
+
role: "user",
|
|
47467
|
+
text: `<system_instructions>
|
|
47468
|
+
${systemParts.join(`
|
|
47469
|
+
|
|
47470
|
+
`)}
|
|
47471
|
+
</system_instructions>`
|
|
47472
|
+
});
|
|
47473
|
+
system = DEVIN_RELOCATION_NOTE;
|
|
47474
|
+
} else if (devinTools.length > 0) {
|
|
47475
|
+
system = DEVIN_MINIMAL_SYSTEM;
|
|
47476
|
+
}
|
|
47477
|
+
const payload = {
|
|
47478
|
+
modelUid: this.modelId,
|
|
47479
|
+
messages: devinMessages
|
|
47480
|
+
};
|
|
47481
|
+
if (system)
|
|
47482
|
+
payload.system = system;
|
|
47483
|
+
if (devinTools.length > 0)
|
|
47484
|
+
payload.tools = devinTools;
|
|
47485
|
+
return payload;
|
|
47486
|
+
}
|
|
47487
|
+
};
|
|
47488
|
+
});
|
|
47489
|
+
|
|
46147
47490
|
// src/adapters/ollama-api-format.ts
|
|
46148
47491
|
var OllamaAPIFormat;
|
|
46149
47492
|
var init_ollama_api_format = __esm(() => {
|
|
@@ -46171,11 +47514,11 @@ var init_ollama_api_format = __esm(() => {
|
|
|
46171
47514
|
messages.push({ role: "system", content });
|
|
46172
47515
|
}
|
|
46173
47516
|
if (claudeRequest.messages) {
|
|
46174
|
-
for (const
|
|
46175
|
-
if (
|
|
46176
|
-
messages.push(this.processUserMessage(
|
|
46177
|
-
} else if (
|
|
46178
|
-
messages.push(this.processAssistantMessage(
|
|
47517
|
+
for (const msg2 of claudeRequest.messages) {
|
|
47518
|
+
if (msg2.role === "user") {
|
|
47519
|
+
messages.push(this.processUserMessage(msg2));
|
|
47520
|
+
} else if (msg2.role === "assistant") {
|
|
47521
|
+
messages.push(this.processAssistantMessage(msg2));
|
|
46179
47522
|
}
|
|
46180
47523
|
}
|
|
46181
47524
|
}
|
|
@@ -46200,10 +47543,10 @@ var init_ollama_api_format = __esm(() => {
|
|
|
46200
47543
|
supportsVision() {
|
|
46201
47544
|
return false;
|
|
46202
47545
|
}
|
|
46203
|
-
processUserMessage(
|
|
46204
|
-
if (Array.isArray(
|
|
47546
|
+
processUserMessage(msg2) {
|
|
47547
|
+
if (Array.isArray(msg2.content)) {
|
|
46205
47548
|
const textParts = [];
|
|
46206
|
-
for (const block of
|
|
47549
|
+
for (const block of msg2.content) {
|
|
46207
47550
|
if (block.type === "text") {
|
|
46208
47551
|
textParts.push(block.text);
|
|
46209
47552
|
} else if (block.type === "tool_result") {
|
|
@@ -46215,12 +47558,12 @@ var init_ollama_api_format = __esm(() => {
|
|
|
46215
47558
|
|
|
46216
47559
|
`) };
|
|
46217
47560
|
}
|
|
46218
|
-
return { role: "user", content:
|
|
47561
|
+
return { role: "user", content: msg2.content };
|
|
46219
47562
|
}
|
|
46220
|
-
processAssistantMessage(
|
|
46221
|
-
if (Array.isArray(
|
|
47563
|
+
processAssistantMessage(msg2) {
|
|
47564
|
+
if (Array.isArray(msg2.content)) {
|
|
46222
47565
|
const strings = [];
|
|
46223
|
-
for (const block of
|
|
47566
|
+
for (const block of msg2.content) {
|
|
46224
47567
|
if (block.type === "text") {
|
|
46225
47568
|
strings.push(block.text);
|
|
46226
47569
|
} else if (block.type === "tool_use") {
|
|
@@ -46230,17 +47573,17 @@ var init_ollama_api_format = __esm(() => {
|
|
|
46230
47573
|
return { role: "assistant", content: strings.join(`
|
|
46231
47574
|
`) };
|
|
46232
47575
|
}
|
|
46233
|
-
return { role: "assistant", content:
|
|
47576
|
+
return { role: "assistant", content: msg2.content };
|
|
46234
47577
|
}
|
|
46235
47578
|
};
|
|
46236
47579
|
});
|
|
46237
47580
|
|
|
46238
47581
|
// src/providers/api-key-provenance.ts
|
|
46239
|
-
import { existsSync as existsSync17, readFileSync as
|
|
46240
|
-
import { homedir as
|
|
46241
|
-
import { join as
|
|
47582
|
+
import { existsSync as existsSync17, readFileSync as readFileSync16 } from "fs";
|
|
47583
|
+
import { homedir as homedir26 } from "os";
|
|
47584
|
+
import { join as join26, resolve as resolve2 } from "path";
|
|
46242
47585
|
function activeConfigPath() {
|
|
46243
|
-
return activeGlobalConfigFile(
|
|
47586
|
+
return activeGlobalConfigFile(join26(homedir26(), ".claudish", "config.json"));
|
|
46244
47587
|
}
|
|
46245
47588
|
function configLayerLabel() {
|
|
46246
47589
|
return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
|
|
@@ -46319,7 +47662,7 @@ function readDotenvKey(envVars) {
|
|
|
46319
47662
|
const dotenvPath = resolve2(".env");
|
|
46320
47663
|
if (!existsSync17(dotenvPath))
|
|
46321
47664
|
return null;
|
|
46322
|
-
const parsed = import_dotenv.parse(
|
|
47665
|
+
const parsed = import_dotenv.parse(readFileSync16(dotenvPath, "utf-8"));
|
|
46323
47666
|
for (const v of envVars) {
|
|
46324
47667
|
if (parsed[v])
|
|
46325
47668
|
return parsed[v];
|
|
@@ -46334,7 +47677,7 @@ function readConfigKey(envVar) {
|
|
|
46334
47677
|
const configPath = activeConfigPath();
|
|
46335
47678
|
if (!existsSync17(configPath))
|
|
46336
47679
|
return null;
|
|
46337
|
-
const cfg = JSON.parse(
|
|
47680
|
+
const cfg = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
46338
47681
|
return cfg.apiKeys?.[envVar] || null;
|
|
46339
47682
|
} catch {
|
|
46340
47683
|
return null;
|
|
@@ -46346,6 +47689,161 @@ var init_api_key_provenance = __esm(() => {
|
|
|
46346
47689
|
import_dotenv = __toESM(require_main(), 1);
|
|
46347
47690
|
});
|
|
46348
47691
|
|
|
47692
|
+
// src/providers/devin/model-id-resolver.ts
|
|
47693
|
+
function parseDevinUidTier(uid) {
|
|
47694
|
+
let base = uid.trim();
|
|
47695
|
+
let fast = false;
|
|
47696
|
+
if (base.toLowerCase().endsWith(FAST_SUFFIX)) {
|
|
47697
|
+
fast = true;
|
|
47698
|
+
base = base.slice(0, -FAST_SUFFIX.length);
|
|
47699
|
+
}
|
|
47700
|
+
const match2 = base.match(TIER_SUFFIX_RE);
|
|
47701
|
+
const candidate = match2?.[1]?.toLowerCase();
|
|
47702
|
+
return { tier: isEffortLevel(candidate) ? candidate : null, fast };
|
|
47703
|
+
}
|
|
47704
|
+
function effortIndex(level) {
|
|
47705
|
+
return EFFORT_LEVELS.indexOf(level);
|
|
47706
|
+
}
|
|
47707
|
+
function resolveDevinModelUid(requested, effort, served) {
|
|
47708
|
+
const req = requested.trim();
|
|
47709
|
+
if (!req || served.length === 0)
|
|
47710
|
+
return req || requested;
|
|
47711
|
+
const lower = req.toLowerCase();
|
|
47712
|
+
const exact = served.find((model) => model.uid.toLowerCase() === lower);
|
|
47713
|
+
if (exact)
|
|
47714
|
+
return exact.uid;
|
|
47715
|
+
const prefix = `${lower}-`;
|
|
47716
|
+
const candidates = served.filter((model) => model.family.toLowerCase() === lower || model.uid.toLowerCase().startsWith(prefix));
|
|
47717
|
+
if (candidates.length === 0)
|
|
47718
|
+
return req;
|
|
47719
|
+
const nonFast = candidates.filter((model) => !parseDevinUidTier(model.uid).fast);
|
|
47720
|
+
const pool = nonFast.length > 0 ? nonFast : candidates;
|
|
47721
|
+
if (pool.length === 1)
|
|
47722
|
+
return pool[0].uid;
|
|
47723
|
+
const tiered = pool.map((model) => ({ model, tier: parseDevinUidTier(model.uid).tier })).filter((entry) => entry.tier !== null);
|
|
47724
|
+
if (tiered.length === 0)
|
|
47725
|
+
return pool[0].uid;
|
|
47726
|
+
const target = effort ? effortIndex(effort) : EFFORT_LEVELS.length - 1;
|
|
47727
|
+
let best = tiered[0];
|
|
47728
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
47729
|
+
for (const entry of tiered) {
|
|
47730
|
+
const distance = Math.abs(effortIndex(entry.tier) - target);
|
|
47731
|
+
if (distance < bestDistance || distance === bestDistance && effortIndex(entry.tier) > effortIndex(best.tier)) {
|
|
47732
|
+
best = entry;
|
|
47733
|
+
bestDistance = distance;
|
|
47734
|
+
}
|
|
47735
|
+
}
|
|
47736
|
+
return best.model.uid;
|
|
47737
|
+
}
|
|
47738
|
+
var FAST_SUFFIX = "-fast", TIER_SUFFIX_RE;
|
|
47739
|
+
var init_model_id_resolver = __esm(() => {
|
|
47740
|
+
init_base_api_format();
|
|
47741
|
+
TIER_SUFFIX_RE = new RegExp(`-(${[...EFFORT_LEVELS].sort((a, b) => b.length - a.length).join("|")})$`, "i");
|
|
47742
|
+
});
|
|
47743
|
+
|
|
47744
|
+
// src/providers/transport/devin.ts
|
|
47745
|
+
class DevinProviderTransport {
|
|
47746
|
+
name = "devin";
|
|
47747
|
+
displayName = "Devin";
|
|
47748
|
+
streamFormat = "connect-proto";
|
|
47749
|
+
modelName;
|
|
47750
|
+
cachedAuth = null;
|
|
47751
|
+
served = [];
|
|
47752
|
+
resolvedUid;
|
|
47753
|
+
constructor(modelName) {
|
|
47754
|
+
this.modelName = modelName;
|
|
47755
|
+
this.resolvedUid = modelName;
|
|
47756
|
+
}
|
|
47757
|
+
getEndpoint() {
|
|
47758
|
+
return `${readDevinServerUrl()}${CHAT_PATH}`;
|
|
47759
|
+
}
|
|
47760
|
+
async getHeaders() {
|
|
47761
|
+
if (this.cachedAuth)
|
|
47762
|
+
return { ...this.cachedAuth.headers };
|
|
47763
|
+
const apiKey = readDevinApiKey();
|
|
47764
|
+
return apiKey ? devinAuthHeaders(apiKey) : {};
|
|
47765
|
+
}
|
|
47766
|
+
async refreshAuth() {
|
|
47767
|
+
this.cachedAuth = await credentials.getRequestAuth("devin", { model: this.modelName });
|
|
47768
|
+
this.served = await getServedDevinModels();
|
|
47769
|
+
log(`[Devin] auth refreshed, model: ${this.modelName}, served roster: ${this.served.length} models`);
|
|
47770
|
+
}
|
|
47771
|
+
serializeBody(payload) {
|
|
47772
|
+
const apiKey = readDevinApiKey();
|
|
47773
|
+
if (!apiKey) {
|
|
47774
|
+
const err = new Error("No Devin credential available when encoding the request.");
|
|
47775
|
+
err.terminal = true;
|
|
47776
|
+
throw err;
|
|
47777
|
+
}
|
|
47778
|
+
const request = payload;
|
|
47779
|
+
this.resolvedUid = resolveDevinModelUid(request.modelUid || this.modelName, request.effort, this.served);
|
|
47780
|
+
const resolved = { ...request, modelUid: this.resolvedUid };
|
|
47781
|
+
if (this.resolvedUid !== this.modelName) {
|
|
47782
|
+
log(`[Devin] model resolved: ${this.modelName} -> ${this.resolvedUid}`);
|
|
47783
|
+
}
|
|
47784
|
+
log(`[Devin] request ${describeDevinRequestForLog(resolved)}`);
|
|
47785
|
+
return {
|
|
47786
|
+
body: encodeDevinRequest(resolved, { apiKey }),
|
|
47787
|
+
contentType: CHAT_CONTENT_TYPE
|
|
47788
|
+
};
|
|
47789
|
+
}
|
|
47790
|
+
getContextWindow() {
|
|
47791
|
+
if (this.served.length === 0)
|
|
47792
|
+
return 0;
|
|
47793
|
+
const uid = resolveDevinModelUid(this.modelName, undefined, this.served);
|
|
47794
|
+
return this.served.find((model) => model.uid === uid)?.contextWindow ?? 0;
|
|
47795
|
+
}
|
|
47796
|
+
getActiveModelName() {
|
|
47797
|
+
return this.resolvedUid !== this.modelName ? this.resolvedUid : undefined;
|
|
47798
|
+
}
|
|
47799
|
+
async discoverProbeModel(exclude) {
|
|
47800
|
+
if (!readDevinApiKey()) {
|
|
47801
|
+
return {
|
|
47802
|
+
model: null,
|
|
47803
|
+
reason: "no Devin credential \u2014 sign in with the Devin CLI (`devin login`), or set WINDSURF_API_KEY"
|
|
47804
|
+
};
|
|
47805
|
+
}
|
|
47806
|
+
const served = await getServedDevinModels();
|
|
47807
|
+
if (served.length === 0) {
|
|
47808
|
+
return { model: null, reason: "Devin reported no models for this subscription" };
|
|
47809
|
+
}
|
|
47810
|
+
const ranked = [...served].sort((a, b) => {
|
|
47811
|
+
const diff = b.contextWindow - a.contextWindow;
|
|
47812
|
+
return diff !== 0 ? diff : a.uid.localeCompare(b.uid);
|
|
47813
|
+
});
|
|
47814
|
+
const candidate = ranked.find((model) => !exclude?.has(model.uid));
|
|
47815
|
+
if (!candidate) {
|
|
47816
|
+
return { model: null, reason: "every Devin model was already tried in this probe round" };
|
|
47817
|
+
}
|
|
47818
|
+
return { model: candidate.uid };
|
|
47819
|
+
}
|
|
47820
|
+
rewriteInStreamError(_code, message) {
|
|
47821
|
+
if (this.served.length === 0)
|
|
47822
|
+
return message;
|
|
47823
|
+
if (this.served.some((model) => model.uid === this.resolvedUid))
|
|
47824
|
+
return message;
|
|
47825
|
+
const families = [...new Set(this.served.map((model) => model.family).filter(Boolean))].sort();
|
|
47826
|
+
const stem = this.resolvedUid.split("-")[0]?.toLowerCase() ?? "";
|
|
47827
|
+
const related = families.filter((f) => f.toLowerCase().startsWith(stem));
|
|
47828
|
+
const ordered = [...related, ...families.filter((f) => !related.includes(f))];
|
|
47829
|
+
const SHOWN = 12;
|
|
47830
|
+
const shown = ordered.slice(0, SHOWN);
|
|
47831
|
+
const more = ordered.length - shown.length;
|
|
47832
|
+
const familyClause = shown.length > 0 ? ` Available families: ${shown.join(", ")}${more > 0 ? `, +${more} more` : ""}.` : "";
|
|
47833
|
+
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})`;
|
|
47834
|
+
}
|
|
47835
|
+
}
|
|
47836
|
+
var CHAT_PATH = "/exa.api_server_pb.ApiServerService/GetChatMessage", CHAT_CONTENT_TYPE = "application/connect+proto";
|
|
47837
|
+
var init_devin = __esm(() => {
|
|
47838
|
+
init_authority();
|
|
47839
|
+
init_devin_credential();
|
|
47840
|
+
init_logger();
|
|
47841
|
+
init_devin_credentials();
|
|
47842
|
+
init_devin_models();
|
|
47843
|
+
init_devin_request();
|
|
47844
|
+
init_model_id_resolver();
|
|
47845
|
+
});
|
|
47846
|
+
|
|
46349
47847
|
// src/providers/transport/gemini-apikey.ts
|
|
46350
47848
|
class GeminiProviderTransport {
|
|
46351
47849
|
name = "gemini";
|
|
@@ -46378,7 +47876,7 @@ var init_gemini_apikey = __esm(() => {
|
|
|
46378
47876
|
});
|
|
46379
47877
|
|
|
46380
47878
|
// src/providers/transport/gemini-codeassist.ts
|
|
46381
|
-
import { randomUUID as
|
|
47879
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
46382
47880
|
function createActivityRequestId4() {
|
|
46383
47881
|
return Math.random().toString(36).substring(7);
|
|
46384
47882
|
}
|
|
@@ -46487,21 +47985,21 @@ class GeminiCodeAssistProviderTransport {
|
|
|
46487
47985
|
log(`[GeminiCodeAssist] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}, served: ${this.servedModels.join(",") || "(none)"}`);
|
|
46488
47986
|
}
|
|
46489
47987
|
transformPayload(payload) {
|
|
46490
|
-
const
|
|
46491
|
-
this.lastEnvelope =
|
|
46492
|
-
return
|
|
47988
|
+
const envelope2 = this.cachedAuth?.transformPayload ? this.cachedAuth.transformPayload(payload) : this.buildEnvelope(payload, this.modelName);
|
|
47989
|
+
this.lastEnvelope = envelope2;
|
|
47990
|
+
return envelope2;
|
|
46493
47991
|
}
|
|
46494
47992
|
buildEnvelope(innerPayload, model) {
|
|
46495
|
-
const
|
|
47993
|
+
const envelope2 = {
|
|
46496
47994
|
model,
|
|
46497
47995
|
project: this.projectId,
|
|
46498
|
-
user_prompt_id:
|
|
47996
|
+
user_prompt_id: randomUUID6(),
|
|
46499
47997
|
request: innerPayload
|
|
46500
47998
|
};
|
|
46501
47999
|
if (this.tierId && this.tierId !== "free-tier") {
|
|
46502
|
-
|
|
48000
|
+
envelope2.enabled_credit_types = ["GOOGLE_ONE_AI"];
|
|
46503
48001
|
}
|
|
46504
|
-
return
|
|
48002
|
+
return envelope2;
|
|
46505
48003
|
}
|
|
46506
48004
|
async enqueueRequest(fetchFn) {
|
|
46507
48005
|
const queue = GeminiRequestQueue.getInstance();
|
|
@@ -46828,11 +48326,12 @@ function createHandlerForProvider(ctx) {
|
|
|
46828
48326
|
log(`[Proxy] Handler: provider=${ctx.provider.name}, model=${ctx.modelName}`);
|
|
46829
48327
|
return profile.createHandler(ctx);
|
|
46830
48328
|
}
|
|
46831
|
-
var geminiProfile, geminiCodeAssistProfile, antigravityProfile, openaiProfile, openaiCodexProfile, anthropicCompatProfile, glmProfile, openCodeZenProfile, ollamaCloudProfile, litellmProfile, vertexProfile, PROVIDER_PROFILES;
|
|
48329
|
+
var geminiProfile, geminiCodeAssistProfile, antigravityProfile, devinProfile, openaiProfile, openaiCodexProfile, anthropicCompatProfile, glmProfile, openCodeZenProfile, ollamaCloudProfile, litellmProfile, vertexProfile, PROVIDER_PROFILES;
|
|
46832
48330
|
var init_provider_profiles = __esm(() => {
|
|
46833
48331
|
init_anthropic_api_format();
|
|
46834
48332
|
init_base_api_format();
|
|
46835
48333
|
init_codex_api_format();
|
|
48334
|
+
init_devin_api_format();
|
|
46836
48335
|
init_gemini_api_format();
|
|
46837
48336
|
init_litellm_api_format();
|
|
46838
48337
|
init_ollama_api_format();
|
|
@@ -46845,6 +48344,7 @@ var init_provider_profiles = __esm(() => {
|
|
|
46845
48344
|
init_runtime_providers();
|
|
46846
48345
|
init_anthropic_compat();
|
|
46847
48346
|
init_antigravity();
|
|
48347
|
+
init_devin();
|
|
46848
48348
|
init_gemini_apikey();
|
|
46849
48349
|
init_gemini_codeassist();
|
|
46850
48350
|
init_litellm();
|
|
@@ -46890,6 +48390,19 @@ var init_provider_profiles = __esm(() => {
|
|
|
46890
48390
|
return handler;
|
|
46891
48391
|
}
|
|
46892
48392
|
};
|
|
48393
|
+
devinProfile = {
|
|
48394
|
+
createHandler(ctx) {
|
|
48395
|
+
const transport = new DevinProviderTransport(ctx.modelName);
|
|
48396
|
+
const adapter = new DevinAPIFormat(ctx.modelName);
|
|
48397
|
+
const handler = new ComposedHandler(transport, ctx.targetModel, ctx.modelName, ctx.port, {
|
|
48398
|
+
adapter,
|
|
48399
|
+
forceForeignModel: true,
|
|
48400
|
+
...ctx.sharedOpts
|
|
48401
|
+
});
|
|
48402
|
+
log(`[Proxy] Created Devin handler (composed): ${ctx.modelName}`);
|
|
48403
|
+
return handler;
|
|
48404
|
+
}
|
|
48405
|
+
};
|
|
46893
48406
|
openaiProfile = {
|
|
46894
48407
|
createHandler(ctx) {
|
|
46895
48408
|
if (requiresResponsesApi(ctx.modelName)) {
|
|
@@ -46958,7 +48471,8 @@ var init_provider_profiles = __esm(() => {
|
|
|
46958
48471
|
const zenApiKey = ctx.apiKey;
|
|
46959
48472
|
const isGoProvider = ctx.provider.name === "opencode-zen-go";
|
|
46960
48473
|
if (ctx.modelName.toLowerCase().includes("minimax")) {
|
|
46961
|
-
const
|
|
48474
|
+
const bearerProvider = { ...ctx.provider, authScheme: "bearer" };
|
|
48475
|
+
const transport2 = new AnthropicProviderTransport(bearerProvider, zenApiKey);
|
|
46962
48476
|
const adapter2 = new AnthropicAPIFormat(ctx.modelName, ctx.provider.name);
|
|
46963
48477
|
const handler2 = new ComposedHandler(transport2, ctx.targetModel, ctx.modelName, ctx.port, {
|
|
46964
48478
|
adapter: adapter2,
|
|
@@ -47069,6 +48583,7 @@ var init_provider_profiles = __esm(() => {
|
|
|
47069
48583
|
gemini: geminiProfile,
|
|
47070
48584
|
"gemini-codeassist": geminiCodeAssistProfile,
|
|
47071
48585
|
antigravity: antigravityProfile,
|
|
48586
|
+
devin: devinProfile,
|
|
47072
48587
|
openai: openaiProfile,
|
|
47073
48588
|
"openai-codex": openaiCodexProfile,
|
|
47074
48589
|
"x-ai": openaiProfile,
|
|
@@ -47807,9 +49322,9 @@ var init_poe = __esm(() => {
|
|
|
47807
49322
|
});
|
|
47808
49323
|
|
|
47809
49324
|
// src/services/pricing-cache.ts
|
|
47810
|
-
import { existsSync as existsSync18, readFileSync as
|
|
47811
|
-
import { homedir as
|
|
47812
|
-
import { join as
|
|
49325
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync4 } from "fs";
|
|
49326
|
+
import { homedir as homedir27 } from "os";
|
|
49327
|
+
import { join as join27 } from "path";
|
|
47813
49328
|
function prefixMatch(modelName) {
|
|
47814
49329
|
for (const [key, pricing] of pricingMap) {
|
|
47815
49330
|
if (modelName.startsWith(key))
|
|
@@ -47852,7 +49367,7 @@ function loadDiskCache() {
|
|
|
47852
49367
|
const stat2 = statSync4(CACHE_FILE);
|
|
47853
49368
|
const age = Date.now() - stat2.mtimeMs;
|
|
47854
49369
|
const isFresh = age < CACHE_TTL_MS3;
|
|
47855
|
-
const raw2 =
|
|
49370
|
+
const raw2 = readFileSync17(CACHE_FILE, "utf-8");
|
|
47856
49371
|
const data = JSON.parse(raw2);
|
|
47857
49372
|
for (const [key, pricing] of Object.entries(data)) {
|
|
47858
49373
|
pricingMap.set(key, pricing);
|
|
@@ -47868,8 +49383,8 @@ var init_pricing_cache = __esm(() => {
|
|
|
47868
49383
|
init_logger();
|
|
47869
49384
|
init_catalog_query();
|
|
47870
49385
|
pricingMap = new Map;
|
|
47871
|
-
CACHE_DIR =
|
|
47872
|
-
CACHE_FILE =
|
|
49386
|
+
CACHE_DIR = join27(homedir27(), ".claudish");
|
|
49387
|
+
CACHE_FILE = join27(CACHE_DIR, "pricing-cache.json");
|
|
47873
49388
|
CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
|
|
47874
49389
|
});
|
|
47875
49390
|
|
|
@@ -48364,20 +49879,20 @@ var init_redact = __esm(() => {
|
|
|
48364
49879
|
});
|
|
48365
49880
|
|
|
48366
49881
|
// src/team-stats.ts
|
|
48367
|
-
import { existsSync as existsSync19, readFileSync as
|
|
48368
|
-
import { join as
|
|
49882
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync11 } from "fs";
|
|
49883
|
+
import { join as join28 } from "path";
|
|
48369
49884
|
function statsDir(sessionPath) {
|
|
48370
|
-
return
|
|
49885
|
+
return join28(sessionPath, "stats");
|
|
48371
49886
|
}
|
|
48372
49887
|
function tokenFileFor(sessionPath, anonId) {
|
|
48373
|
-
return
|
|
49888
|
+
return join28(statsDir(sessionPath), `${anonId}.json`);
|
|
48374
49889
|
}
|
|
48375
49890
|
function readTokenStats(sessionPath, anonId) {
|
|
48376
49891
|
const path = tokenFileFor(sessionPath, anonId);
|
|
48377
49892
|
if (!existsSync19(path))
|
|
48378
49893
|
return null;
|
|
48379
49894
|
try {
|
|
48380
|
-
return JSON.parse(
|
|
49895
|
+
return JSON.parse(readFileSync18(path, "utf-8"));
|
|
48381
49896
|
} catch {
|
|
48382
49897
|
return null;
|
|
48383
49898
|
}
|
|
@@ -48454,10 +49969,10 @@ function renderTeamStats(sessionPath, manifest, status, opts) {
|
|
|
48454
49969
|
if (stats?.is_free)
|
|
48455
49970
|
anyFree = true;
|
|
48456
49971
|
const name = model.length > nameWidth ? `${model.slice(0, nameWidth - 1)}\u2026` : model;
|
|
48457
|
-
const
|
|
49972
|
+
const bytes2 = m.outputSize > 0 ? fmtBytes(m.outputSize) : "";
|
|
48458
49973
|
const tokens = stats ? `${fmtTokens(inTok)}/${outTok > 0 ? fmtTokens(outTok) : "-"}` : "";
|
|
48459
49974
|
const cost = stats ? fmtCost(stats.total_cost, stats.is_free) : "";
|
|
48460
|
-
rows.push(` ${id} ${name.padEnd(nameWidth)} ${fmtState(m.state)} ` + `${
|
|
49975
|
+
rows.push(` ${id} ${name.padEnd(nameWidth)} ${fmtState(m.state)} ` + `${bytes2.padStart(7)} ${tokens.padStart(12)} ${cost.padStart(7)}`.trimEnd());
|
|
48461
49976
|
}
|
|
48462
49977
|
const parts = [`${ids.length} models`];
|
|
48463
49978
|
if (done)
|
|
@@ -48525,7 +50040,7 @@ ${segs.join(" \xB7 ")}`;
|
|
|
48525
50040
|
}
|
|
48526
50041
|
function writeStatusFile(sessionPath, manifest, status, opts) {
|
|
48527
50042
|
try {
|
|
48528
|
-
writeFileSync11(
|
|
50043
|
+
writeFileSync11(join28(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
|
|
48529
50044
|
`, "utf-8");
|
|
48530
50045
|
} catch {}
|
|
48531
50046
|
}
|
|
@@ -48553,11 +50068,11 @@ import {
|
|
|
48553
50068
|
createWriteStream as createWriteStream2,
|
|
48554
50069
|
existsSync as existsSync20,
|
|
48555
50070
|
mkdirSync as mkdirSync12,
|
|
48556
|
-
readFileSync as
|
|
50071
|
+
readFileSync as readFileSync19,
|
|
48557
50072
|
readdirSync as readdirSync3,
|
|
48558
50073
|
writeFileSync as writeFileSync12
|
|
48559
50074
|
} from "fs";
|
|
48560
|
-
import { join as
|
|
50075
|
+
import { join as join29, resolve as resolve3 } from "path";
|
|
48561
50076
|
function classifyRunOutput(opts) {
|
|
48562
50077
|
const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
|
|
48563
50078
|
const apiError = API_ERROR_RE.exec(stdoutTail);
|
|
@@ -48618,18 +50133,18 @@ function setupSession(sessionPath, models, input) {
|
|
|
48618
50133
|
if (models.length === 0) {
|
|
48619
50134
|
throw new Error("At least one model is required");
|
|
48620
50135
|
}
|
|
48621
|
-
if (existsSync20(
|
|
50136
|
+
if (existsSync20(join29(sessionPath, "manifest.json"))) {
|
|
48622
50137
|
throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
|
|
48623
50138
|
}
|
|
48624
50139
|
const sentinels = models.filter(isSentinelModel);
|
|
48625
50140
|
if (sentinels.length > 0) {
|
|
48626
50141
|
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.`);
|
|
48627
50142
|
}
|
|
48628
|
-
mkdirSync12(
|
|
48629
|
-
mkdirSync12(
|
|
50143
|
+
mkdirSync12(join29(sessionPath, "work"), { recursive: true });
|
|
50144
|
+
mkdirSync12(join29(sessionPath, "errors"), { recursive: true });
|
|
48630
50145
|
if (input !== undefined) {
|
|
48631
|
-
writeFileSync12(
|
|
48632
|
-
} else if (!existsSync20(
|
|
50146
|
+
writeFileSync12(join29(sessionPath, "input.md"), input, "utf-8");
|
|
50147
|
+
} else if (!existsSync20(join29(sessionPath, "input.md"))) {
|
|
48633
50148
|
throw new Error(`No input.md found at ${sessionPath} and no input provided`);
|
|
48634
50149
|
}
|
|
48635
50150
|
const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
|
|
@@ -48646,9 +50161,9 @@ function setupSession(sessionPath, models, input) {
|
|
|
48646
50161
|
model: models[i],
|
|
48647
50162
|
assignedAt: now
|
|
48648
50163
|
};
|
|
48649
|
-
mkdirSync12(
|
|
50164
|
+
mkdirSync12(join29(sessionPath, "work", anonId), { recursive: true });
|
|
48650
50165
|
}
|
|
48651
|
-
writeFileSync12(
|
|
50166
|
+
writeFileSync12(join29(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
48652
50167
|
const status = {
|
|
48653
50168
|
startedAt: now,
|
|
48654
50169
|
models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
|
|
@@ -48662,17 +50177,17 @@ function setupSession(sessionPath, models, input) {
|
|
|
48662
50177
|
}
|
|
48663
50178
|
]))
|
|
48664
50179
|
};
|
|
48665
|
-
writeFileSync12(
|
|
50180
|
+
writeFileSync12(join29(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
|
|
48666
50181
|
return manifest;
|
|
48667
50182
|
}
|
|
48668
50183
|
async function runModels(sessionPath, opts = {}) {
|
|
48669
50184
|
const timeoutMs = (opts.timeout ?? 300) * 1000;
|
|
48670
|
-
const manifest = JSON.parse(
|
|
48671
|
-
const statusPath =
|
|
48672
|
-
const inputPath =
|
|
48673
|
-
const inputContent =
|
|
50185
|
+
const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
50186
|
+
const statusPath = join29(sessionPath, "status.json");
|
|
50187
|
+
const inputPath = join29(sessionPath, "input.md");
|
|
50188
|
+
const inputContent = readFileSync19(inputPath, "utf-8");
|
|
48674
50189
|
const spawnPlan = await (opts.spawnPlanner ?? prehydrateCredentialsForSpawn)(Object.values(manifest.models).map((m) => m.model));
|
|
48675
|
-
const statusCache = JSON.parse(
|
|
50190
|
+
const statusCache = JSON.parse(readFileSync19(statusPath, "utf-8"));
|
|
48676
50191
|
function updateModelStatus(id, update) {
|
|
48677
50192
|
statusCache.models[id] = { ...statusCache.models[id], ...update };
|
|
48678
50193
|
writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
|
|
@@ -48691,8 +50206,8 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
48691
50206
|
process.on("SIGINT", sigintHandler);
|
|
48692
50207
|
const completionPromises = [];
|
|
48693
50208
|
for (const [anonId, entry] of Object.entries(manifest.models)) {
|
|
48694
|
-
const outputPath =
|
|
48695
|
-
const errorLogPath =
|
|
50209
|
+
const outputPath = join29(sessionPath, `response-${anonId}.md`);
|
|
50210
|
+
const errorLogPath = join29(sessionPath, "errors", `${anonId}.log`);
|
|
48696
50211
|
const spawnModel = spawnPlan.pinned.get(entry.model) ?? entry.model;
|
|
48697
50212
|
const args = ["--model", spawnModel, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
|
|
48698
50213
|
updateModelStatus(anonId, {
|
|
@@ -48841,14 +50356,14 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
48841
50356
|
const rt = runtimes.get(id);
|
|
48842
50357
|
const stderr = rt?.getStderr() ?? "";
|
|
48843
50358
|
const stdoutTail = rt?.getStdoutTail() ?? "";
|
|
48844
|
-
const
|
|
48845
|
-
const detail = `Killed by the orchestrator after ${timeoutMs / 1000}s with ${
|
|
50359
|
+
const bytes2 = rt?.getByteCount() ?? 0;
|
|
50360
|
+
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".`;
|
|
48846
50361
|
if (rt)
|
|
48847
50362
|
persistErrorLog(rt.errorLogPath, `TIMEOUT: ${detail}`, stderr, stdoutTail);
|
|
48848
50363
|
updateModelStatus(id, {
|
|
48849
50364
|
state: "TIMEOUT",
|
|
48850
50365
|
completedAt: new Date().toISOString(),
|
|
48851
|
-
outputSize:
|
|
50366
|
+
outputSize: bytes2,
|
|
48852
50367
|
error: rt ? {
|
|
48853
50368
|
model: id,
|
|
48854
50369
|
command: rt.command,
|
|
@@ -48882,23 +50397,23 @@ async function judgeResponses(sessionPath, opts = {}) {
|
|
|
48882
50397
|
const responses = {};
|
|
48883
50398
|
for (const file2 of responseFiles) {
|
|
48884
50399
|
const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
48885
|
-
responses[id] =
|
|
50400
|
+
responses[id] = readFileSync19(join29(sessionPath, file2), "utf-8");
|
|
48886
50401
|
}
|
|
48887
|
-
const input =
|
|
50402
|
+
const input = readFileSync19(join29(sessionPath, "input.md"), "utf-8");
|
|
48888
50403
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
48889
|
-
writeFileSync12(
|
|
50404
|
+
writeFileSync12(join29(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
48890
50405
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
48891
|
-
const judgePath =
|
|
50406
|
+
const judgePath = join29(sessionPath, "judging");
|
|
48892
50407
|
mkdirSync12(judgePath, { recursive: true });
|
|
48893
50408
|
setupSession(judgePath, judgeModels, judgePrompt);
|
|
48894
50409
|
await runModels(judgePath, { claudeFlags: opts.claudeFlags });
|
|
48895
50410
|
const votes = parseJudgeVotes(judgePath, Object.keys(responses));
|
|
48896
50411
|
const verdict = aggregateVerdict(votes, Object.keys(responses));
|
|
48897
|
-
writeFileSync12(
|
|
50412
|
+
writeFileSync12(join29(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
|
|
48898
50413
|
return verdict;
|
|
48899
50414
|
}
|
|
48900
50415
|
function getStatus(sessionPath) {
|
|
48901
|
-
return JSON.parse(
|
|
50416
|
+
return JSON.parse(readFileSync19(join29(sessionPath, "status.json"), "utf-8"));
|
|
48902
50417
|
}
|
|
48903
50418
|
function fisherYatesShuffle(arr) {
|
|
48904
50419
|
for (let i = arr.length - 1;i > 0; i--) {
|
|
@@ -48908,7 +50423,7 @@ function fisherYatesShuffle(arr) {
|
|
|
48908
50423
|
return arr;
|
|
48909
50424
|
}
|
|
48910
50425
|
function getDefaultJudgeModels(sessionPath) {
|
|
48911
|
-
const manifest = JSON.parse(
|
|
50426
|
+
const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
48912
50427
|
return Object.values(manifest.models).map((e) => e.model);
|
|
48913
50428
|
}
|
|
48914
50429
|
function buildJudgePrompt(input, responses) {
|
|
@@ -48971,7 +50486,7 @@ function parseJudgeVotes(judgePath, responseIds) {
|
|
|
48971
50486
|
const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
48972
50487
|
let content;
|
|
48973
50488
|
try {
|
|
48974
|
-
content =
|
|
50489
|
+
content = readFileSync19(join29(judgePath, file2), "utf-8");
|
|
48975
50490
|
} catch {
|
|
48976
50491
|
continue;
|
|
48977
50492
|
}
|
|
@@ -49023,7 +50538,7 @@ function aggregateVerdict(votes, responseIds) {
|
|
|
49023
50538
|
function formatVerdict(verdict, sessionPath) {
|
|
49024
50539
|
let manifest = null;
|
|
49025
50540
|
try {
|
|
49026
|
-
manifest = JSON.parse(
|
|
50541
|
+
manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
49027
50542
|
} catch {}
|
|
49028
50543
|
let output = `# Team Verdict
|
|
49029
50544
|
|
|
@@ -49078,14 +50593,14 @@ __export(exports_mcp_server, {
|
|
|
49078
50593
|
parseAnthropicSse: () => parseAnthropicSse,
|
|
49079
50594
|
formatTeamResult: () => formatTeamResult
|
|
49080
50595
|
});
|
|
49081
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as
|
|
49082
|
-
import { homedir as
|
|
49083
|
-
import { dirname as dirname9, join as
|
|
50596
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync20, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
50597
|
+
import { homedir as homedir28 } from "os";
|
|
50598
|
+
import { dirname as dirname9, join as join30, resolve as resolve4 } from "path";
|
|
49084
50599
|
import { fileURLToPath } from "url";
|
|
49085
50600
|
async function loadAllModels(forceRefresh = false) {
|
|
49086
50601
|
if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH2)) {
|
|
49087
50602
|
try {
|
|
49088
|
-
const cacheData = JSON.parse(
|
|
50603
|
+
const cacheData = JSON.parse(readFileSync20(ALL_MODELS_CACHE_PATH2, "utf-8"));
|
|
49089
50604
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
49090
50605
|
const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
|
|
49091
50606
|
if (ageInDays <= CACHE_MAX_AGE_DAYS) {
|
|
@@ -49104,7 +50619,7 @@ async function loadAllModels(forceRefresh = false) {
|
|
|
49104
50619
|
return models;
|
|
49105
50620
|
} catch {
|
|
49106
50621
|
if (existsSync21(ALL_MODELS_CACHE_PATH2)) {
|
|
49107
|
-
const cacheData = JSON.parse(
|
|
50622
|
+
const cacheData = JSON.parse(readFileSync20(ALL_MODELS_CACHE_PATH2, "utf-8"));
|
|
49108
50623
|
return cacheData.models || [];
|
|
49109
50624
|
}
|
|
49110
50625
|
return [];
|
|
@@ -49686,7 +51201,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
|
|
|
49686
51201
|
let stderrFull = stderr_snippet || "";
|
|
49687
51202
|
if (error_log_path) {
|
|
49688
51203
|
try {
|
|
49689
|
-
stderrFull =
|
|
51204
|
+
stderrFull = readFileSync20(error_log_path, "utf-8");
|
|
49690
51205
|
} catch {}
|
|
49691
51206
|
}
|
|
49692
51207
|
const sessionData = {};
|
|
@@ -49694,16 +51209,16 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
|
|
|
49694
51209
|
const sp = session_path;
|
|
49695
51210
|
for (const file2 of ["status.json", "manifest.json", "input.md"]) {
|
|
49696
51211
|
try {
|
|
49697
|
-
sessionData[file2] =
|
|
51212
|
+
sessionData[file2] = readFileSync20(join30(sp, file2), "utf-8");
|
|
49698
51213
|
} catch {}
|
|
49699
51214
|
}
|
|
49700
51215
|
try {
|
|
49701
|
-
const errorDir =
|
|
51216
|
+
const errorDir = join30(sp, "errors");
|
|
49702
51217
|
if (existsSync21(errorDir)) {
|
|
49703
51218
|
for (const f of readdirSync4(errorDir)) {
|
|
49704
51219
|
if (f.endsWith(".log")) {
|
|
49705
51220
|
try {
|
|
49706
|
-
sessionData[`errors/${f}`] =
|
|
51221
|
+
sessionData[`errors/${f}`] = readFileSync20(join30(errorDir, f), "utf-8");
|
|
49707
51222
|
} catch {}
|
|
49708
51223
|
}
|
|
49709
51224
|
}
|
|
@@ -49713,7 +51228,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
|
|
|
49713
51228
|
for (const f of readdirSync4(sp)) {
|
|
49714
51229
|
if (f.startsWith("response-") && f.endsWith(".md")) {
|
|
49715
51230
|
try {
|
|
49716
|
-
const content =
|
|
51231
|
+
const content = readFileSync20(join30(sp, f), "utf-8");
|
|
49717
51232
|
sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
|
|
49718
51233
|
} catch {}
|
|
49719
51234
|
}
|
|
@@ -49722,9 +51237,9 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
|
|
|
49722
51237
|
}
|
|
49723
51238
|
let version2 = "unknown";
|
|
49724
51239
|
try {
|
|
49725
|
-
const pkgPath =
|
|
51240
|
+
const pkgPath = join30(__dirname2, "../package.json");
|
|
49726
51241
|
if (existsSync21(pkgPath)) {
|
|
49727
|
-
version2 = JSON.parse(
|
|
51242
|
+
version2 = JSON.parse(readFileSync20(pkgPath, "utf-8")).version;
|
|
49728
51243
|
}
|
|
49729
51244
|
} catch {}
|
|
49730
51245
|
const report = {
|
|
@@ -50128,8 +51643,8 @@ var init_mcp_server = __esm(() => {
|
|
|
50128
51643
|
import_dotenv2.config({ quiet: true });
|
|
50129
51644
|
__filename2 = fileURLToPath(import.meta.url);
|
|
50130
51645
|
__dirname2 = dirname9(__filename2);
|
|
50131
|
-
CLAUDISH_CACHE_DIR =
|
|
50132
|
-
ALL_MODELS_CACHE_PATH2 =
|
|
51646
|
+
CLAUDISH_CACHE_DIR = join30(homedir28(), ".claudish");
|
|
51647
|
+
ALL_MODELS_CACHE_PATH2 = join30(CLAUDISH_CACHE_DIR, "all-models.json");
|
|
50133
51648
|
NEXT_STEP = {
|
|
50134
51649
|
nonzero_exit: "read the evidence log, then retry or drop the model",
|
|
50135
51650
|
timeout: "raise `timeout`, or pick a faster model",
|
|
@@ -50154,7 +51669,7 @@ var exports_serve_command = {};
|
|
|
50154
51669
|
__export(exports_serve_command, {
|
|
50155
51670
|
serveCommand: () => serveCommand
|
|
50156
51671
|
});
|
|
50157
|
-
import { existsSync as existsSync22, readFileSync as
|
|
51672
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21 } from "fs";
|
|
50158
51673
|
function parseServeArgs(args) {
|
|
50159
51674
|
const out = {};
|
|
50160
51675
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -50178,7 +51693,7 @@ function loadModelMap(path) {
|
|
|
50178
51693
|
}
|
|
50179
51694
|
let raw2;
|
|
50180
51695
|
try {
|
|
50181
|
-
raw2 =
|
|
51696
|
+
raw2 = readFileSync21(path, "utf-8");
|
|
50182
51697
|
} catch (e) {
|
|
50183
51698
|
throw new Error(`failed to read --models file ${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
50184
51699
|
}
|
|
@@ -50255,7 +51770,7 @@ var exports_behavior_command = {};
|
|
|
50255
51770
|
__export(exports_behavior_command, {
|
|
50256
51771
|
behaviorCommand: () => behaviorCommand
|
|
50257
51772
|
});
|
|
50258
|
-
import { existsSync as existsSync23, readFileSync as
|
|
51773
|
+
import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "fs";
|
|
50259
51774
|
function severityColor(sev) {
|
|
50260
51775
|
if (sev === "fix")
|
|
50261
51776
|
return green(sev);
|
|
@@ -50354,7 +51869,7 @@ function setTelemetryEnabled(value) {
|
|
|
50354
51869
|
let cfg = {};
|
|
50355
51870
|
try {
|
|
50356
51871
|
if (existsSync23(path)) {
|
|
50357
|
-
const parsed = JSON.parse(
|
|
51872
|
+
const parsed = JSON.parse(readFileSync22(path, "utf-8"));
|
|
50358
51873
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
50359
51874
|
cfg = parsed;
|
|
50360
51875
|
}
|
|
@@ -50376,7 +51891,7 @@ function showTelemetry(action, json2) {
|
|
|
50376
51891
|
try {
|
|
50377
51892
|
const path = outboxPath();
|
|
50378
51893
|
if (existsSync23(path)) {
|
|
50379
|
-
pending =
|
|
51894
|
+
pending = readFileSync22(path, "utf8").split(`
|
|
50380
51895
|
`).filter(Boolean).length;
|
|
50381
51896
|
}
|
|
50382
51897
|
} catch {}
|
|
@@ -50449,6 +51964,12 @@ function describeSourceSync(p, config3) {
|
|
|
50449
51964
|
return "oauth";
|
|
50450
51965
|
if (p.catalogName === "antigravity" && hasSharedAntigravityToken())
|
|
50451
51966
|
return "oauth";
|
|
51967
|
+
if (p.catalogName === "devin") {
|
|
51968
|
+
if (realValue(process.env.WINDSURF_API_KEY))
|
|
51969
|
+
return "env";
|
|
51970
|
+
if (hasDevinCredentials())
|
|
51971
|
+
return "oauth";
|
|
51972
|
+
}
|
|
50452
51973
|
const hasCfg = !!p.apiKeyEnvVar && !!realValue(config3.apiKeys?.[p.apiKeyEnvVar]);
|
|
50453
51974
|
const hasEnv = !!p.apiKeyEnvVar && !!realValue(process.env[p.apiKeyEnvVar]);
|
|
50454
51975
|
if (hasEnv && hasCfg)
|
|
@@ -50469,6 +51990,7 @@ async function describeSource(p, config3) {
|
|
|
50469
51990
|
}
|
|
50470
51991
|
var init_source = __esm(() => {
|
|
50471
51992
|
init_profile_config();
|
|
51993
|
+
init_devin_credentials();
|
|
50472
51994
|
init_antigravity_token();
|
|
50473
51995
|
init_oauth_registry();
|
|
50474
51996
|
init_api_key_credential();
|
|
@@ -50516,8 +52038,8 @@ function providerIsReadyForDisplay(p, config3, localLiveness) {
|
|
|
50516
52038
|
function providerAuthCapabilities(p, config3) {
|
|
50517
52039
|
const apiKeySupported = !!p.apiKeyEnvVar;
|
|
50518
52040
|
const apiKeySet = apiKeySupported && (!!process.env[p.apiKeyEnvVar] || !!config3.apiKeys?.[p.apiKeyEnvVar]);
|
|
50519
|
-
const oauthSupported = !!p.oauthSlug;
|
|
50520
|
-
const oauthSet = oauthSupported && (hasOAuthCredentials(p.catalogName) || p.catalogName === "antigravity" && hasSharedAntigravityToken());
|
|
52041
|
+
const oauthSupported = !!p.oauthSlug || p.catalogName === "devin";
|
|
52042
|
+
const oauthSet = oauthSupported && (hasOAuthCredentials(p.catalogName) || p.catalogName === "antigravity" && hasSharedAntigravityToken() || p.catalogName === "devin" && hasDevinCredentials());
|
|
50521
52043
|
return {
|
|
50522
52044
|
apiKey: { supported: apiKeySupported, set: apiKeySet },
|
|
50523
52045
|
oauth: { supported: oauthSupported, set: oauthSet }
|
|
@@ -50535,6 +52057,7 @@ var init_providers = __esm(() => {
|
|
|
50535
52057
|
init_antigravity_token();
|
|
50536
52058
|
init_source();
|
|
50537
52059
|
init_oauth_registry();
|
|
52060
|
+
init_devin_credentials();
|
|
50538
52061
|
init_provider_definitions();
|
|
50539
52062
|
SKIP = new Set(["qwen", "native-anthropic"]);
|
|
50540
52063
|
PROVIDERS = getAllProviders().filter((d) => !SKIP.has(d.name)).map(toProviderDef);
|
|
@@ -59783,18 +61306,18 @@ var require_dbcs_codec = __commonJS((exports) => {
|
|
|
59783
61306
|
DBCSCodec.prototype.encoder = DBCSEncoder;
|
|
59784
61307
|
DBCSCodec.prototype.decoder = DBCSDecoder;
|
|
59785
61308
|
DBCSCodec.prototype._getDecodeTrieNode = function(addr) {
|
|
59786
|
-
var
|
|
61309
|
+
var bytes2 = [];
|
|
59787
61310
|
for (;addr > 0; addr >>>= 8) {
|
|
59788
|
-
|
|
61311
|
+
bytes2.push(addr & 255);
|
|
59789
61312
|
}
|
|
59790
|
-
if (
|
|
59791
|
-
|
|
61313
|
+
if (bytes2.length == 0) {
|
|
61314
|
+
bytes2.push(0);
|
|
59792
61315
|
}
|
|
59793
61316
|
var node = this.decodeTables[0];
|
|
59794
|
-
for (var i2 =
|
|
59795
|
-
var val = node[
|
|
61317
|
+
for (var i2 = bytes2.length - 1;i2 > 0; i2--) {
|
|
61318
|
+
var val = node[bytes2[i2]];
|
|
59796
61319
|
if (val == UNASSIGNED) {
|
|
59797
|
-
node[
|
|
61320
|
+
node[bytes2[i2]] = NODE_START - this.decodeTables.length;
|
|
59798
61321
|
this.decodeTables.push(node = UNASSIGNED_NODE.slice(0));
|
|
59799
61322
|
} else if (val <= NODE_START) {
|
|
59800
61323
|
node = this.decodeTables[NODE_START - val];
|
|
@@ -61845,10 +63368,10 @@ var init_RemoveFileError = __esm(() => {
|
|
|
61845
63368
|
|
|
61846
63369
|
// ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
|
|
61847
63370
|
import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
|
|
61848
|
-
import { readFileSync as
|
|
63371
|
+
import { readFileSync as readFileSync23, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
|
|
61849
63372
|
import path from "path";
|
|
61850
63373
|
import os from "os";
|
|
61851
|
-
import { randomUUID as
|
|
63374
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
61852
63375
|
function editAsync(text = "", callback, fileOptions) {
|
|
61853
63376
|
const editor = new ExternalEditor(text, fileOptions);
|
|
61854
63377
|
editor.runAsync((err, result) => {
|
|
@@ -61940,7 +63463,7 @@ class ExternalEditor {
|
|
|
61940
63463
|
createTemporaryFile() {
|
|
61941
63464
|
try {
|
|
61942
63465
|
const baseDir = this.fileOptions.dir ?? os.tmpdir();
|
|
61943
|
-
const id =
|
|
63466
|
+
const id = randomUUID7();
|
|
61944
63467
|
const prefix = sanitizeAffix(this.fileOptions.prefix);
|
|
61945
63468
|
const postfix = sanitizeAffix(this.fileOptions.postfix);
|
|
61946
63469
|
const filename = `${prefix}${id}${postfix}`;
|
|
@@ -61961,7 +63484,7 @@ class ExternalEditor {
|
|
|
61961
63484
|
}
|
|
61962
63485
|
readTemporaryFile() {
|
|
61963
63486
|
try {
|
|
61964
|
-
const tempFileBuffer =
|
|
63487
|
+
const tempFileBuffer = readFileSync23(this.tempFile);
|
|
61965
63488
|
if (tempFileBuffer.length === 0) {
|
|
61966
63489
|
this.text = "";
|
|
61967
63490
|
} else {
|
|
@@ -62943,8 +64466,8 @@ var init_dist16 = __esm(() => {
|
|
|
62943
64466
|
// src/auth/antigravity-oauth.ts
|
|
62944
64467
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
62945
64468
|
import { existsSync as existsSync24, unlinkSync as unlinkSync7 } from "fs";
|
|
62946
|
-
import { homedir as
|
|
62947
|
-
import { join as
|
|
64469
|
+
import { homedir as homedir29 } from "os";
|
|
64470
|
+
import { join as join31 } from "path";
|
|
62948
64471
|
async function defaultSuggestModel() {
|
|
62949
64472
|
try {
|
|
62950
64473
|
const tok = readSharedAntigravityToken();
|
|
@@ -63065,7 +64588,7 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
|
|
|
63065
64588
|
async logout(deps) {
|
|
63066
64589
|
deleteSharedAntigravityToken(deps);
|
|
63067
64590
|
try {
|
|
63068
|
-
const tokenFile =
|
|
64591
|
+
const tokenFile = join31(homedir29(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
|
|
63069
64592
|
if (existsSync24(tokenFile))
|
|
63070
64593
|
unlinkSync7(tokenFile);
|
|
63071
64594
|
} catch {}
|
|
@@ -64517,11 +66040,11 @@ async function probeLink(proxyUrl, link, timeoutMs) {
|
|
|
64517
66040
|
} catch (e) {
|
|
64518
66041
|
const latencyMs = Date.now() - startedAt;
|
|
64519
66042
|
const name = e?.name || "";
|
|
64520
|
-
const
|
|
64521
|
-
if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(
|
|
64522
|
-
return { state: "timeout", latencyMs, errorMessage:
|
|
66043
|
+
const msg2 = String(e?.message || e);
|
|
66044
|
+
if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg2)) {
|
|
66045
|
+
return { state: "timeout", latencyMs, errorMessage: msg2 };
|
|
64523
66046
|
}
|
|
64524
|
-
return { state: "network-error", latencyMs, errorMessage:
|
|
66047
|
+
return { state: "network-error", latencyMs, errorMessage: msg2 };
|
|
64525
66048
|
}
|
|
64526
66049
|
const ttfbMs = Date.now() - startedAt;
|
|
64527
66050
|
if (!response.ok) {
|
|
@@ -64550,7 +66073,7 @@ function annotateOAuthHint(result, provider, isOAuth) {
|
|
|
64550
66073
|
return result;
|
|
64551
66074
|
if (result.state === "live")
|
|
64552
66075
|
return result;
|
|
64553
|
-
const loginCommand2 = provider === "gemini-codeassist" ? "claudish login gemini" : provider === "antigravity" ? "claudish login antigravity" : provider === "vertex" ? "gcloud auth application-default login" : undefined;
|
|
66076
|
+
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;
|
|
64554
66077
|
if (!loginCommand2)
|
|
64555
66078
|
return result;
|
|
64556
66079
|
if (result.httpStatus === 403)
|
|
@@ -64658,9 +66181,9 @@ function extractErrorMessage(body) {
|
|
|
64658
66181
|
return;
|
|
64659
66182
|
try {
|
|
64660
66183
|
const parsed = JSON.parse(body);
|
|
64661
|
-
const
|
|
64662
|
-
if (typeof
|
|
64663
|
-
return
|
|
66184
|
+
const msg2 = parsed?.error?.message || parsed?.error?.error?.message || parsed?.message || parsed?.detail;
|
|
66185
|
+
if (typeof msg2 === "string" && msg2.length > 0) {
|
|
66186
|
+
return msg2.length > 160 ? `${msg2.slice(0, 157)}...` : msg2;
|
|
64664
66187
|
}
|
|
64665
66188
|
} catch {}
|
|
64666
66189
|
const trimmed2 = body.trim();
|
|
@@ -64876,7 +66399,7 @@ function isFailureState(state) {
|
|
|
64876
66399
|
}
|
|
64877
66400
|
var STREAM_MS_FLOOR = 50, OAUTH_PROVIDERS2, PROBE_PROMPT = "Count from one to twenty in words, one per line.", PROBE_MAX_TOKENS = 512;
|
|
64878
66401
|
var init_probe_live = __esm(() => {
|
|
64879
|
-
OAUTH_PROVIDERS2 = new Set(["vertex", "gemini-codeassist"]);
|
|
66402
|
+
OAUTH_PROVIDERS2 = new Set(["vertex", "gemini-codeassist", "devin"]);
|
|
64880
66403
|
});
|
|
64881
66404
|
|
|
64882
66405
|
// src/tui/theme.ts
|
|
@@ -67154,19 +68677,19 @@ import {
|
|
|
67154
68677
|
copyFileSync as copyFileSync2,
|
|
67155
68678
|
existsSync as existsSync25,
|
|
67156
68679
|
mkdirSync as mkdirSync14,
|
|
67157
|
-
readFileSync as
|
|
68680
|
+
readFileSync as readFileSync24,
|
|
67158
68681
|
readdirSync as readdirSync5,
|
|
67159
68682
|
unlinkSync as unlinkSync8,
|
|
67160
68683
|
writeFileSync as writeFileSync16
|
|
67161
68684
|
} from "fs";
|
|
67162
|
-
import { homedir as
|
|
67163
|
-
import { dirname as dirname10, join as
|
|
68685
|
+
import { homedir as homedir30 } from "os";
|
|
68686
|
+
import { dirname as dirname10, join as join32 } from "path";
|
|
67164
68687
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
67165
68688
|
function getVersion3() {
|
|
67166
68689
|
return VERSION;
|
|
67167
68690
|
}
|
|
67168
68691
|
function clearAllModelCaches() {
|
|
67169
|
-
const cacheDir =
|
|
68692
|
+
const cacheDir = join32(homedir30(), ".claudish");
|
|
67170
68693
|
if (!existsSync25(cacheDir))
|
|
67171
68694
|
return;
|
|
67172
68695
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
|
|
@@ -67175,7 +68698,7 @@ function clearAllModelCaches() {
|
|
|
67175
68698
|
const files = readdirSync5(cacheDir);
|
|
67176
68699
|
for (const file2 of files) {
|
|
67177
68700
|
if (cachePatterns.includes(file2)) {
|
|
67178
|
-
unlinkSync8(
|
|
68701
|
+
unlinkSync8(join32(cacheDir, file2));
|
|
67179
68702
|
cleared++;
|
|
67180
68703
|
}
|
|
67181
68704
|
}
|
|
@@ -67585,7 +69108,7 @@ Usage: claudish --models --provider <slug>`);
|
|
|
67585
69108
|
});
|
|
67586
69109
|
config3.resolvedDefaultProvider = resolved;
|
|
67587
69110
|
if (resolved.legacyAutoPromoted && !config3.quiet) {
|
|
67588
|
-
const markerFile =
|
|
69111
|
+
const markerFile = join32(homedir30(), ".claudish", ".legacy-litellm-hint-shown");
|
|
67589
69112
|
if (!existsSync25(markerFile)) {
|
|
67590
69113
|
const hint = buildLegacyHint(resolved);
|
|
67591
69114
|
if (hint) {
|
|
@@ -68056,6 +69579,9 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
68056
69579
|
} else if (providerName === "litellm") {
|
|
68057
69580
|
formatAdapterName = "LiteLLMAPIFormat";
|
|
68058
69581
|
declaredStreamFormat = "openai-sse";
|
|
69582
|
+
} else if (providerName === "devin") {
|
|
69583
|
+
formatAdapterName = "DevinAPIFormat";
|
|
69584
|
+
declaredStreamFormat = "connect-proto";
|
|
68059
69585
|
} else {
|
|
68060
69586
|
formatAdapterName = "OpenAIAPIFormat";
|
|
68061
69587
|
declaredStreamFormat = "openai-sse";
|
|
@@ -68094,8 +69620,8 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
68094
69620
|
console.error(`${DIM}Probing providers via live requests (may incur small cost, use --no-probe to skip)...${RESET}`);
|
|
68095
69621
|
liveProxy2 = await createProxyServer2(probePort, process.env.OPENROUTER_API_KEY, undefined, false, process.env.ANTHROPIC_API_KEY, undefined, { quiet: true });
|
|
68096
69622
|
} catch (e) {
|
|
68097
|
-
const
|
|
68098
|
-
console.error(`${YELLOW}Failed to start probe proxy (${
|
|
69623
|
+
const msg2 = e instanceof Error ? e.message : String(e);
|
|
69624
|
+
console.error(`${YELLOW}Failed to start probe proxy (${msg2}). Falling back to static probe.${RESET}`);
|
|
68099
69625
|
liveProxy2 = null;
|
|
68100
69626
|
}
|
|
68101
69627
|
}
|
|
@@ -68660,8 +70186,8 @@ ${h("MORE INFO")}
|
|
|
68660
70186
|
}
|
|
68661
70187
|
function printAIAgentGuide() {
|
|
68662
70188
|
try {
|
|
68663
|
-
const guidePath =
|
|
68664
|
-
const guideContent =
|
|
70189
|
+
const guidePath = join32(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
70190
|
+
const guideContent = readFileSync24(guidePath, "utf-8");
|
|
68665
70191
|
console.log(guideContent);
|
|
68666
70192
|
} catch (error46) {
|
|
68667
70193
|
console.error("Error reading AI Agent Guide:");
|
|
@@ -68677,10 +70203,10 @@ async function initializeClaudishSkill() {
|
|
|
68677
70203
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
68678
70204
|
`);
|
|
68679
70205
|
const cwd = process.cwd();
|
|
68680
|
-
const claudeDir =
|
|
68681
|
-
const skillsDir =
|
|
68682
|
-
const claudishSkillDir =
|
|
68683
|
-
const skillFile =
|
|
70206
|
+
const claudeDir = join32(cwd, ".claude");
|
|
70207
|
+
const skillsDir = join32(claudeDir, "skills");
|
|
70208
|
+
const claudishSkillDir = join32(skillsDir, "claudish-usage");
|
|
70209
|
+
const skillFile = join32(claudishSkillDir, "SKILL.md");
|
|
68684
70210
|
if (existsSync25(skillFile)) {
|
|
68685
70211
|
console.log("\u2705 Claudish skill already installed at:");
|
|
68686
70212
|
console.log(` ${skillFile}
|
|
@@ -68688,7 +70214,7 @@ async function initializeClaudishSkill() {
|
|
|
68688
70214
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
68689
70215
|
return;
|
|
68690
70216
|
}
|
|
68691
|
-
const sourceSkillPath =
|
|
70217
|
+
const sourceSkillPath = join32(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
68692
70218
|
if (!existsSync25(sourceSkillPath)) {
|
|
68693
70219
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
68694
70220
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
@@ -68791,24 +70317,24 @@ __export(exports_update_checker, {
|
|
|
68791
70317
|
clearCache: () => clearCache,
|
|
68792
70318
|
checkForUpdates: () => checkForUpdates
|
|
68793
70319
|
});
|
|
68794
|
-
import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as
|
|
68795
|
-
import { homedir as
|
|
68796
|
-
import { join as
|
|
70320
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as readFileSync25, unlinkSync as unlinkSync9, writeFileSync as writeFileSync17 } from "fs";
|
|
70321
|
+
import { homedir as homedir31, platform as platform2, tmpdir } from "os";
|
|
70322
|
+
import { join as join33 } from "path";
|
|
68797
70323
|
function getCacheFilePath() {
|
|
68798
70324
|
let cacheDir;
|
|
68799
70325
|
if (isWindows) {
|
|
68800
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
68801
|
-
cacheDir =
|
|
70326
|
+
const localAppData = process.env.LOCALAPPDATA || join33(homedir31(), "AppData", "Local");
|
|
70327
|
+
cacheDir = join33(localAppData, "claudish");
|
|
68802
70328
|
} else {
|
|
68803
|
-
cacheDir =
|
|
70329
|
+
cacheDir = join33(homedir31(), ".cache", "claudish");
|
|
68804
70330
|
}
|
|
68805
70331
|
try {
|
|
68806
70332
|
if (!existsSync26(cacheDir)) {
|
|
68807
70333
|
mkdirSync15(cacheDir, { recursive: true });
|
|
68808
70334
|
}
|
|
68809
|
-
return
|
|
70335
|
+
return join33(cacheDir, "update-check.json");
|
|
68810
70336
|
} catch {
|
|
68811
|
-
return
|
|
70337
|
+
return join33(tmpdir(), "claudish-update-check.json");
|
|
68812
70338
|
}
|
|
68813
70339
|
}
|
|
68814
70340
|
function readCache() {
|
|
@@ -68817,7 +70343,7 @@ function readCache() {
|
|
|
68817
70343
|
if (!existsSync26(cachePath)) {
|
|
68818
70344
|
return null;
|
|
68819
70345
|
}
|
|
68820
|
-
const data = JSON.parse(
|
|
70346
|
+
const data = JSON.parse(readFileSync25(cachePath, "utf-8"));
|
|
68821
70347
|
return data;
|
|
68822
70348
|
} catch {
|
|
68823
70349
|
return null;
|
|
@@ -69725,15 +71251,15 @@ var init_local_liveness = __esm(() => {
|
|
|
69725
71251
|
});
|
|
69726
71252
|
|
|
69727
71253
|
// src/providers/probe-catalog.ts
|
|
69728
|
-
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as
|
|
69729
|
-
import { homedir as
|
|
69730
|
-
import { dirname as dirname11, join as
|
|
71254
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync26, writeFileSync as writeFileSync18 } from "fs";
|
|
71255
|
+
import { homedir as homedir32 } from "os";
|
|
71256
|
+
import { dirname as dirname11, join as join34 } from "path";
|
|
69731
71257
|
function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
69732
71258
|
if (!existsSync27(path2))
|
|
69733
71259
|
return null;
|
|
69734
71260
|
let raw2;
|
|
69735
71261
|
try {
|
|
69736
|
-
raw2 = JSON.parse(
|
|
71262
|
+
raw2 = JSON.parse(readFileSync26(path2, "utf-8"));
|
|
69737
71263
|
} catch {
|
|
69738
71264
|
return null;
|
|
69739
71265
|
}
|
|
@@ -69862,7 +71388,7 @@ function isValidResponse(raw2) {
|
|
|
69862
71388
|
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;
|
|
69863
71389
|
var init_probe_catalog = __esm(() => {
|
|
69864
71390
|
CACHE_TTL_MS4 = 60 * 60 * 1000;
|
|
69865
|
-
PROBE_MODELS_CACHE_PATH =
|
|
71391
|
+
PROBE_MODELS_CACHE_PATH = join34(homedir32(), ".claudish", "probe-models.json");
|
|
69866
71392
|
});
|
|
69867
71393
|
|
|
69868
71394
|
// src/tui/constants.ts
|
|
@@ -74309,8 +75835,8 @@ function useRouteProbe(config3) {
|
|
|
74309
75835
|
try {
|
|
74310
75836
|
proxyUrl = await ensureProbeProxy();
|
|
74311
75837
|
} catch (err) {
|
|
74312
|
-
const
|
|
74313
|
-
setProbeResults((prev) => prev.map((e) => ({ ...e, status: "failed", error: `probe proxy: ${
|
|
75838
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
75839
|
+
setProbeResults((prev) => prev.map((e) => ({ ...e, status: "failed", error: `probe proxy: ${msg2}` })));
|
|
74314
75840
|
setProbeMode("done");
|
|
74315
75841
|
return;
|
|
74316
75842
|
}
|
|
@@ -74664,12 +76190,12 @@ function App({ requestLogin } = {}) {
|
|
|
74664
76190
|
}));
|
|
74665
76191
|
setStatusMsg(`1Password test ok \u2192 ${note}`);
|
|
74666
76192
|
} catch (err) {
|
|
74667
|
-
const
|
|
76193
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74668
76194
|
setOpTestResults((prev) => ({
|
|
74669
76195
|
...prev,
|
|
74670
|
-
[key]: { status: "failed", error:
|
|
76196
|
+
[key]: { status: "failed", error: msg2 }
|
|
74671
76197
|
}));
|
|
74672
|
-
setStatusMsg(
|
|
76198
|
+
setStatusMsg(msg2);
|
|
74673
76199
|
} finally {
|
|
74674
76200
|
setOpBusy(false);
|
|
74675
76201
|
}
|
|
@@ -74744,14 +76270,14 @@ function App({ requestLogin } = {}) {
|
|
|
74744
76270
|
invalidateProbeProxyHandlers();
|
|
74745
76271
|
refreshConfig();
|
|
74746
76272
|
} catch (testErr) {
|
|
74747
|
-
const
|
|
74748
|
-
console.error(`[claudish] 1Password add: saved but live resolve failed: ${
|
|
74749
|
-
setStatusMsg(`1Password ${kindWord} saved (${scope}) \u2014 live resolve failed: ${
|
|
76273
|
+
const msg2 = testErr instanceof Error ? testErr.message : String(testErr);
|
|
76274
|
+
console.error(`[claudish] 1Password add: saved but live resolve failed: ${msg2}`);
|
|
76275
|
+
setStatusMsg(`1Password ${kindWord} saved (${scope}) \u2014 live resolve failed: ${msg2}`);
|
|
74750
76276
|
}
|
|
74751
76277
|
} catch (err) {
|
|
74752
|
-
const
|
|
74753
|
-
console.error(`[claudish] 1Password add failed to persist: ${
|
|
74754
|
-
setStatusMsg(`1Password add failed: ${
|
|
76278
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
76279
|
+
console.error(`[claudish] 1Password add failed to persist: ${msg2}`);
|
|
76280
|
+
setStatusMsg(`1Password add failed: ${msg2}`);
|
|
74755
76281
|
setMode("browse");
|
|
74756
76282
|
resetOpWizard();
|
|
74757
76283
|
} finally {
|
|
@@ -74771,8 +76297,8 @@ function App({ requestLogin } = {}) {
|
|
|
74771
76297
|
setOpVaults(vaults);
|
|
74772
76298
|
setStatusMsg(`1Password: ${vaults.length} vault${vaults.length === 1 ? "" : "s"}.`);
|
|
74773
76299
|
} catch (err) {
|
|
74774
|
-
const
|
|
74775
|
-
setStatusMsg(
|
|
76300
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
76301
|
+
setStatusMsg(msg2);
|
|
74776
76302
|
setMode("browse");
|
|
74777
76303
|
} finally {
|
|
74778
76304
|
setOpBusy(false);
|
|
@@ -74793,8 +76319,8 @@ function App({ requestLogin } = {}) {
|
|
|
74793
76319
|
setOpItems(items);
|
|
74794
76320
|
setStatusMsg(`1Password: ${items.length} item${items.length === 1 ? "" : "s"}.`);
|
|
74795
76321
|
} catch (err) {
|
|
74796
|
-
const
|
|
74797
|
-
setStatusMsg(
|
|
76322
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
76323
|
+
setStatusMsg(msg2);
|
|
74798
76324
|
setMode("browse");
|
|
74799
76325
|
} finally {
|
|
74800
76326
|
setOpBusy(false);
|
|
@@ -74822,8 +76348,8 @@ function App({ requestLogin } = {}) {
|
|
|
74822
76348
|
setOpFields(fields);
|
|
74823
76349
|
setStatusMsg(`1Password: ${fields.length} field${fields.length === 1 ? "" : "s"}.`);
|
|
74824
76350
|
} catch (err) {
|
|
74825
|
-
const
|
|
74826
|
-
setStatusMsg(
|
|
76351
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
76352
|
+
setStatusMsg(msg2);
|
|
74827
76353
|
setMode("browse");
|
|
74828
76354
|
} finally {
|
|
74829
76355
|
setOpBusy(false);
|
|
@@ -74839,9 +76365,9 @@ function App({ requestLogin } = {}) {
|
|
|
74839
76365
|
setOpEnvPreview(names);
|
|
74840
76366
|
setStatusMsg(`1Password environment \u2192 ${names.length} var${names.length === 1 ? "" : "s"}. Enter to save.`);
|
|
74841
76367
|
} catch (err) {
|
|
74842
|
-
const
|
|
76368
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74843
76369
|
setOpEnvPreview(null);
|
|
74844
|
-
setStatusMsg(
|
|
76370
|
+
setStatusMsg(msg2);
|
|
74845
76371
|
} finally {
|
|
74846
76372
|
setOpBusy(false);
|
|
74847
76373
|
}
|
|
@@ -74949,10 +76475,10 @@ function App({ requestLogin } = {}) {
|
|
|
74949
76475
|
}
|
|
74950
76476
|
} catch (err) {
|
|
74951
76477
|
const ms = Date.now() - startMs;
|
|
74952
|
-
const
|
|
76478
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74953
76479
|
setTestResults((prev) => ({
|
|
74954
76480
|
...prev,
|
|
74955
|
-
[provName]: { status: "failed", error: `proxy: ${
|
|
76481
|
+
[provName]: { status: "failed", error: `proxy: ${msg2}`, ms }
|
|
74956
76482
|
}));
|
|
74957
76483
|
}
|
|
74958
76484
|
}, []);
|
|
@@ -76219,14 +77745,14 @@ import {
|
|
|
76219
77745
|
existsSync as existsSync28,
|
|
76220
77746
|
mkdirSync as mkdirSync17,
|
|
76221
77747
|
openSync as openSync5,
|
|
76222
|
-
readFileSync as
|
|
77748
|
+
readFileSync as readFileSync27,
|
|
76223
77749
|
readdirSync as readdirSync6,
|
|
76224
77750
|
statSync as statSync5,
|
|
76225
77751
|
unlinkSync as unlinkSync10,
|
|
76226
77752
|
writeFileSync as writeFileSync19
|
|
76227
77753
|
} from "fs";
|
|
76228
|
-
import { homedir as
|
|
76229
|
-
import { dirname as dirname12, join as
|
|
77754
|
+
import { homedir as homedir33, tmpdir as tmpdir2 } from "os";
|
|
77755
|
+
import { dirname as dirname12, join as join35 } from "path";
|
|
76230
77756
|
import { isatty } from "tty";
|
|
76231
77757
|
function releaseTerminalIsolation() {
|
|
76232
77758
|
if (!restoreTerminal)
|
|
@@ -76261,14 +77787,14 @@ function isProxyAuthMode(config3) {
|
|
|
76261
77787
|
}
|
|
76262
77788
|
function managedSettingsPath() {
|
|
76263
77789
|
if (isWindows2()) {
|
|
76264
|
-
return
|
|
77790
|
+
return join35(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
|
|
76265
77791
|
}
|
|
76266
77792
|
if (process.platform === "darwin") {
|
|
76267
77793
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
76268
77794
|
}
|
|
76269
77795
|
return "/etc/claude-code/managed-settings.json";
|
|
76270
77796
|
}
|
|
76271
|
-
function managedSettingsForcesClaudeAi(readFile3 =
|
|
77797
|
+
function managedSettingsForcesClaudeAi(readFile3 = readFileSync27) {
|
|
76272
77798
|
try {
|
|
76273
77799
|
const raw2 = readFile3(managedSettingsPath(), "utf-8");
|
|
76274
77800
|
const parsed = JSON.parse(raw2);
|
|
@@ -76282,9 +77808,9 @@ function isWindows2() {
|
|
|
76282
77808
|
}
|
|
76283
77809
|
function createStatusLineScript(tokenFilePath) {
|
|
76284
77810
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
76285
|
-
const claudishDir =
|
|
77811
|
+
const claudishDir = join35(homeDir, ".claudish");
|
|
76286
77812
|
const timestamp = Date.now();
|
|
76287
|
-
const scriptPath =
|
|
77813
|
+
const scriptPath = join35(claudishDir, `status-${timestamp}.js`);
|
|
76288
77814
|
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
76289
77815
|
const script = `
|
|
76290
77816
|
const fs = require('fs');
|
|
@@ -76448,7 +77974,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
|
|
|
76448
77974
|
if (!name.startsWith("tokens-") || !name.endsWith(".json"))
|
|
76449
77975
|
continue;
|
|
76450
77976
|
scanned++;
|
|
76451
|
-
const full =
|
|
77977
|
+
const full = join35(dir, name);
|
|
76452
77978
|
try {
|
|
76453
77979
|
if (statSync5(full).mtimeMs >= cutoff)
|
|
76454
77980
|
continue;
|
|
@@ -76465,7 +77991,7 @@ function parseSettingsArg(value) {
|
|
|
76465
77991
|
if (value.trimStart().startsWith("{")) {
|
|
76466
77992
|
return JSON.parse(value);
|
|
76467
77993
|
}
|
|
76468
|
-
return JSON.parse(
|
|
77994
|
+
return JSON.parse(readFileSync27(value, "utf-8"));
|
|
76469
77995
|
}
|
|
76470
77996
|
function parseSettingsArgSafe(value) {
|
|
76471
77997
|
try {
|
|
@@ -76477,9 +78003,9 @@ function parseSettingsArgSafe(value) {
|
|
|
76477
78003
|
}
|
|
76478
78004
|
function userSettingsFileCandidates(cwd) {
|
|
76479
78005
|
return [
|
|
76480
|
-
|
|
76481
|
-
|
|
76482
|
-
|
|
78006
|
+
join35(homedir33(), ".claude", "settings.json"),
|
|
78007
|
+
join35(cwd, ".claude", "settings.json"),
|
|
78008
|
+
join35(cwd, ".claude", "settings.local.json")
|
|
76483
78009
|
];
|
|
76484
78010
|
}
|
|
76485
78011
|
function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
|
|
@@ -76520,13 +78046,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
|
|
|
76520
78046
|
}
|
|
76521
78047
|
function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
|
|
76522
78048
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
76523
|
-
const claudishDir =
|
|
78049
|
+
const claudishDir = join35(homeDir, ".claudish");
|
|
76524
78050
|
try {
|
|
76525
78051
|
mkdirSync17(claudishDir, { recursive: true });
|
|
76526
78052
|
} catch {}
|
|
76527
78053
|
const timestamp = Date.now();
|
|
76528
|
-
const tempPath =
|
|
76529
|
-
const tokenFilePath =
|
|
78054
|
+
const tempPath = join35(claudishDir, `settings-${timestamp}.json`);
|
|
78055
|
+
const tokenFilePath = join35(claudishDir, `tokens-${port}.json`);
|
|
76530
78056
|
cleanupStaleTokenFiles(claudishDir);
|
|
76531
78057
|
initializeTokenFile(tokenFilePath);
|
|
76532
78058
|
let statusCommand;
|
|
@@ -76541,13 +78067,15 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
|
|
|
76541
78067
|
const DIM4 = "\\033[2m";
|
|
76542
78068
|
const RESET4 = "\\033[0m";
|
|
76543
78069
|
const BOLD4 = "\\033[1m";
|
|
78070
|
+
const readPlanBash = `PLAN_PAIR=$(echo "$TOKENS" | grep -o '"id": *"[^"]*", *"used_pct": *[0-9]*' | sed 's/"id": *"\\([^"]*\\)", *"used_pct": *\\([0-9]*\\)/\\2 \\1/' | sort -rn | head -1); if [ -n "$PLAN_PAIR" ]; then PLAN_PCT="\${PLAN_PAIR%% *}"; PLAN_ID="\${PLAN_PAIR#* }"; case "$PLAN_PCT" in ''|*[!0-9]*) PLAN_PCT="" ;; esac; [ -n "$PLAN_PCT" ] && PLAN_DISPLAY="$PLAN_ID:$PLAN_PCT%"; fi;`;
|
|
76544
78071
|
const formatTokensBash = `fmt_tok() { local n=\${1:-0}; if [ "$n" -ge 1000000 ]; then echo "$((n/1000000))M"; elif [ "$n" -ge 1000 ]; then echo "$((n/1000))k"; else echo "$n"; fi; }`;
|
|
76545
78072
|
const effWinBash = `eff_win() { local w=\${1:-0}; local m=\${CLAUDE_CODE_MAX_CONTEXT_TOKENS:-}; local a=\${CLAUDE_CODE_AUTO_COMPACT_WINDOW:-}; case "$m" in ''|*[!0-9]*) m=${CLAUDE_CODE_DEFAULT_MAX_CONTEXT};; esac; case "$a" in ''|*[!0-9]*) a=0;; esac; case "$w" in ''|*[!0-9]*) w=0;; esac; if [ "$w" -gt 0 ]; then if [ "$m" -gt 0 ] && [ "$m" -lt "$w" ]; then w=$m; fi; if [ "$a" -gt 0 ] && [ "$a" -lt "$w" ]; then w=$a; fi; fi; echo "$w"; }`;
|
|
76546
78073
|
const dirPrelude = `DIR=$(basename "$(pwd)"); [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true; `;
|
|
76547
|
-
const readState = `CTX=-1; COST="0"; IS_FREE="false"; IS_EST="false"; PROVIDER=""; TOKEN_MODEL=""; IN_TOK=0; CTX_WIN=0; ${formatTokensBash}; ${effWinBash}; if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d '\\n\\r'); V=$(echo "$TOKENS" | grep -o '"context_left_percent": *-\\?[0-9]*' | grep -o '\\-\\?[0-9]*'); [ -n "$V" ] && CTX="$V"; V=$(echo "$TOKENS" | grep -o '"total_cost": *[0-9.]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && COST="$V"; V=$(echo "$TOKENS" | grep -o '"input_tokens": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && IN_TOK="$V"; V=$(echo "$TOKENS" | grep -o '"context_window": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && CTX_WIN="$V"; V=$(echo "$TOKENS" | grep -o '"is_free": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_FREE="$V"; V=$(echo "$TOKENS" | grep -o '"is_estimated": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_EST="$V"; V=$(echo "$TOKENS" | grep -o '"provider_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && PROVIDER="$V"; V=$(echo "$TOKENS" | grep -o '"model_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && TOKEN_MODEL="$V"; fi; if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi; MODEL_DISPLAY="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}"; if [ -n "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi; EFF_WIN=$(eff_win $CTX_WIN); if [ "$EFF_WIN" -gt 0 ] 2>/dev/null && [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX=$(( ((EFF_WIN - IN_TOK) * 200 / EFF_WIN + 1) / 2 )); if [ "$CTX" -lt 0 ]; then CTX=0; fi; fi; if [ "$CTX" -lt 0 ] 2>/dev/null || [ "$EFF_WIN" -le 0 ] 2>/dev/null; then if [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$(fmt_tok $IN_TOK) tokens"; else CTX_DISPLAY="N/A"; fi; elif [ "$IN_TOK" -gt 0 ] 2>/dev/null; then if [ "$EFF_WIN" -lt "$CTX_WIN" ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN) of $(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN))"; fi; else CTX_DISPLAY="$CTX%"; fi`;
|
|
76548
|
-
const
|
|
76549
|
-
const
|
|
76550
|
-
const
|
|
78074
|
+
const readState = `CTX=-1; COST="0"; IS_FREE="false"; IS_EST="false"; PROVIDER=""; TOKEN_MODEL=""; IN_TOK=0; CTX_WIN=0; PLAN_DISPLAY=""; ${formatTokensBash}; ${effWinBash}; if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d '\\n\\r'); V=$(echo "$TOKENS" | grep -o '"context_left_percent": *-\\?[0-9]*' | grep -o '\\-\\?[0-9]*'); [ -n "$V" ] && CTX="$V"; V=$(echo "$TOKENS" | grep -o '"total_cost": *[0-9.]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && COST="$V"; V=$(echo "$TOKENS" | grep -o '"input_tokens": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && IN_TOK="$V"; V=$(echo "$TOKENS" | grep -o '"context_window": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && CTX_WIN="$V"; V=$(echo "$TOKENS" | grep -o '"is_free": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_FREE="$V"; V=$(echo "$TOKENS" | grep -o '"is_estimated": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_EST="$V"; V=$(echo "$TOKENS" | grep -o '"provider_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && PROVIDER="$V"; V=$(echo "$TOKENS" | grep -o '"model_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && TOKEN_MODEL="$V"; ${readPlanBash} fi; if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi; MODEL_DISPLAY="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}"; if [ -n "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi; EFF_WIN=$(eff_win $CTX_WIN); if [ "$EFF_WIN" -gt 0 ] 2>/dev/null && [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX=$(( ((EFF_WIN - IN_TOK) * 200 / EFF_WIN + 1) / 2 )); if [ "$CTX" -lt 0 ]; then CTX=0; fi; fi; if [ "$CTX" -lt 0 ] 2>/dev/null || [ "$EFF_WIN" -le 0 ] 2>/dev/null; then if [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$(fmt_tok $IN_TOK) tokens"; else CTX_DISPLAY="N/A"; fi; elif [ "$IN_TOK" -gt 0 ] 2>/dev/null; then if [ "$EFF_WIN" -lt "$CTX_WIN" ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN) of $(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN))"; fi; else CTX_DISPLAY="$CTX%"; fi`;
|
|
78075
|
+
const planSuffix = `if [ -n "$PLAN_DISPLAY" ]; then printf " ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4}" "$PLAN_DISPLAY"; fi`;
|
|
78076
|
+
const segmentWithDir = `printf "${CYAN4}${BOLD4}%s${RESET4} ${DIM4}\u2022${RESET4} ${YELLOW3}%s${RESET4} ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"; ${planSuffix}; printf "\\n"`;
|
|
78077
|
+
const segmentNoDirWithProvider = `printf "${YELLOW3}%s${RESET4} ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}" "$PROVIDER" "$COST_DISPLAY" "$CTX_DISPLAY"; ${planSuffix}; printf "\\n"`;
|
|
78078
|
+
const segmentNoDirNoProvider = `printf "${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}" "$COST_DISPLAY" "$CTX_DISPLAY"; ${planSuffix}; printf "\\n"`;
|
|
76551
78079
|
const segmentNoDir = `if [ -n "$PROVIDER" ]; then ${segmentNoDirWithProvider}; else ${segmentNoDirNoProvider}; fi`;
|
|
76552
78080
|
statusCommand = userStatusLineCommand ? buildChainedStatusCommand(userStatusLineCommand, readState, segmentNoDir) : `JSON=$(cat); ${dirPrelude}${readState}; ${segmentWithDir}`;
|
|
76553
78081
|
}
|
|
@@ -76797,8 +78325,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
76797
78325
|
console.error("Install it from: https://claude.com/claude-code");
|
|
76798
78326
|
console.error(`
|
|
76799
78327
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
76800
|
-
const home =
|
|
76801
|
-
const localPath = isWindows2() ?
|
|
78328
|
+
const home = homedir33();
|
|
78329
|
+
const localPath = isWindows2() ? join35(home, ".claude", "local", "claude.exe") : join35(home, ".claude", "local", "claude");
|
|
76802
78330
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
76803
78331
|
process.exit(1);
|
|
76804
78332
|
}
|
|
@@ -76882,16 +78410,16 @@ async function findClaudeBinary() {
|
|
|
76882
78410
|
return process.env.CLAUDE_PATH;
|
|
76883
78411
|
}
|
|
76884
78412
|
}
|
|
76885
|
-
const home =
|
|
76886
|
-
const localPath = isWindows3 ?
|
|
78413
|
+
const home = homedir33();
|
|
78414
|
+
const localPath = isWindows3 ? join35(home, ".claude", "local", "claude.exe") : join35(home, ".claude", "local", "claude");
|
|
76887
78415
|
if (existsSync28(localPath)) {
|
|
76888
78416
|
return localPath;
|
|
76889
78417
|
}
|
|
76890
78418
|
if (isWindows3) {
|
|
76891
78419
|
const windowsPaths = [
|
|
76892
|
-
|
|
76893
|
-
|
|
76894
|
-
|
|
78420
|
+
join35(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
78421
|
+
join35(home, ".npm-global", "claude.cmd"),
|
|
78422
|
+
join35(home, "node_modules", ".bin", "claude.cmd")
|
|
76895
78423
|
];
|
|
76896
78424
|
for (const path2 of windowsPaths) {
|
|
76897
78425
|
if (existsSync28(path2)) {
|
|
@@ -76902,11 +78430,11 @@ async function findClaudeBinary() {
|
|
|
76902
78430
|
const commonPaths = [
|
|
76903
78431
|
"/usr/local/bin/claude",
|
|
76904
78432
|
"/opt/homebrew/bin/claude",
|
|
76905
|
-
|
|
76906
|
-
|
|
76907
|
-
|
|
78433
|
+
join35(home, ".npm-global/bin/claude"),
|
|
78434
|
+
join35(home, ".local/bin/claude"),
|
|
78435
|
+
join35(home, "node_modules/.bin/claude"),
|
|
76908
78436
|
"/data/data/com.termux/files/usr/bin/claude",
|
|
76909
|
-
|
|
78437
|
+
join35(home, "../usr/bin/claude")
|
|
76910
78438
|
];
|
|
76911
78439
|
for (const path2 of commonPaths) {
|
|
76912
78440
|
if (existsSync28(path2)) {
|
|
@@ -76970,17 +78498,17 @@ __export(exports_diag_output, {
|
|
|
76970
78498
|
LogFileDiagOutput: () => LogFileDiagOutput
|
|
76971
78499
|
});
|
|
76972
78500
|
import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync18, unlinkSync as unlinkSync11, writeFileSync as writeFileSync20 } from "fs";
|
|
76973
|
-
import { homedir as
|
|
76974
|
-
import { join as
|
|
78501
|
+
import { homedir as homedir34 } from "os";
|
|
78502
|
+
import { join as join36 } from "path";
|
|
76975
78503
|
function getClaudishDir() {
|
|
76976
|
-
const dir =
|
|
78504
|
+
const dir = join36(homedir34(), ".claudish");
|
|
76977
78505
|
try {
|
|
76978
78506
|
mkdirSync18(dir, { recursive: true });
|
|
76979
78507
|
} catch {}
|
|
76980
78508
|
return dir;
|
|
76981
78509
|
}
|
|
76982
78510
|
function getDiagLogPath() {
|
|
76983
|
-
return
|
|
78511
|
+
return join36(getClaudishDir(), `diag-${process.pid}.log`);
|
|
76984
78512
|
}
|
|
76985
78513
|
|
|
76986
78514
|
class LogFileDiagOutput {
|
|
@@ -76995,9 +78523,9 @@ class LogFileDiagOutput {
|
|
|
76995
78523
|
this.stream = createWriteStream3(this.logPath, { flags: "a" });
|
|
76996
78524
|
this.stream.on("error", () => {});
|
|
76997
78525
|
}
|
|
76998
|
-
write(
|
|
78526
|
+
write(msg2) {
|
|
76999
78527
|
const timestamp = new Date().toISOString();
|
|
77000
|
-
const line = `[${timestamp}] ${
|
|
78528
|
+
const line = `[${timestamp}] ${msg2}
|
|
77001
78529
|
`;
|
|
77002
78530
|
try {
|
|
77003
78531
|
this.stream.write(line);
|
|
@@ -77191,9 +78719,9 @@ __export(exports_team_grid, {
|
|
|
77191
78719
|
});
|
|
77192
78720
|
import { spawn as spawn5 } from "child_process";
|
|
77193
78721
|
import { execSync as execSync2 } from "child_process";
|
|
77194
|
-
import { existsSync as existsSync29, readFileSync as
|
|
78722
|
+
import { existsSync as existsSync29, readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "fs";
|
|
77195
78723
|
import { connect as netConnect } from "net";
|
|
77196
|
-
import { dirname as dirname13, join as
|
|
78724
|
+
import { dirname as dirname13, join as join37 } from "path";
|
|
77197
78725
|
import { setTimeout as wait } from "timers/promises";
|
|
77198
78726
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
77199
78727
|
function resolveRouteInfo(modelId) {
|
|
@@ -77287,17 +78815,17 @@ function buildPaneHeader(model, prompt, bg) {
|
|
|
77287
78815
|
function findMagmuxBinary() {
|
|
77288
78816
|
const thisFile = fileURLToPath3(import.meta.url);
|
|
77289
78817
|
const thisDir = dirname13(thisFile);
|
|
77290
|
-
const pkgRoot =
|
|
78818
|
+
const pkgRoot = join37(thisDir, "..");
|
|
77291
78819
|
const platform3 = process.platform;
|
|
77292
78820
|
const arch = process.arch;
|
|
77293
|
-
const bundledMagmux =
|
|
78821
|
+
const bundledMagmux = join37(pkgRoot, "native", `magmux-${platform3}-${arch}`);
|
|
77294
78822
|
if (existsSync29(bundledMagmux))
|
|
77295
78823
|
return bundledMagmux;
|
|
77296
78824
|
try {
|
|
77297
78825
|
const pkgName = `@claudish/magmux-${platform3}-${arch}`;
|
|
77298
78826
|
let searchDir = pkgRoot;
|
|
77299
78827
|
for (let i = 0;i < 5; i++) {
|
|
77300
|
-
const candidate =
|
|
78828
|
+
const candidate = join37(searchDir, "node_modules", pkgName, "bin", "magmux");
|
|
77301
78829
|
if (existsSync29(candidate))
|
|
77302
78830
|
return candidate;
|
|
77303
78831
|
const parent = dirname13(searchDir);
|
|
@@ -77404,9 +78932,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
77404
78932
|
const keep = opts?.keep ?? false;
|
|
77405
78933
|
const manifest = setupSession(sessionPath, models, input);
|
|
77406
78934
|
const startedAt = new Date().toISOString();
|
|
77407
|
-
const gridfilePath =
|
|
77408
|
-
const prompt =
|
|
77409
|
-
const rawPrompt =
|
|
78935
|
+
const gridfilePath = join37(sessionPath, "gridfile.txt");
|
|
78936
|
+
const prompt = readFileSync28(join37(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
78937
|
+
const rawPrompt = readFileSync28(join37(sessionPath, "input.md"), "utf-8");
|
|
77410
78938
|
const usedBannerColors = new Set;
|
|
77411
78939
|
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
77412
78940
|
const model = manifest.models[anonId].model;
|
|
@@ -77437,7 +78965,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
77437
78965
|
});
|
|
77438
78966
|
const [{ results: results2 }] = await Promise.all([subscription, procExit]);
|
|
77439
78967
|
const status = buildTeamStatus(manifest, startedAt, results2?.panes ?? null);
|
|
77440
|
-
const statusPath =
|
|
78968
|
+
const statusPath = join37(sessionPath, "status.json");
|
|
77441
78969
|
writeFileSync21(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
77442
78970
|
return status;
|
|
77443
78971
|
}
|
|
@@ -77461,8 +78989,8 @@ var init_team_grid = __esm(() => {
|
|
|
77461
78989
|
init_op_source();
|
|
77462
78990
|
init_startup_trace();
|
|
77463
78991
|
var import_dotenv3 = __toESM(require_main(), 1);
|
|
77464
|
-
import { existsSync as existsSync30, readFileSync as
|
|
77465
|
-
import { join as
|
|
78992
|
+
import { existsSync as existsSync30, readFileSync as readFileSync29 } from "fs";
|
|
78993
|
+
import { join as join38, resolve as resolve5 } from "path";
|
|
77466
78994
|
import_dotenv3.config({ quiet: true });
|
|
77467
78995
|
function classifyStartupKind() {
|
|
77468
78996
|
const argv = process.argv.slice(2);
|
|
@@ -77709,14 +79237,14 @@ async function runCli() {
|
|
|
77709
79237
|
if (cliConfig.team && cliConfig.team.length > 0) {
|
|
77710
79238
|
let prompt = cliConfig.claudeArgs.join(" ");
|
|
77711
79239
|
if (cliConfig.inputFile) {
|
|
77712
|
-
prompt =
|
|
79240
|
+
prompt = readFileSync29(cliConfig.inputFile, "utf-8");
|
|
77713
79241
|
}
|
|
77714
79242
|
if (!prompt.trim()) {
|
|
77715
79243
|
console.error("Error: --team requires a prompt (positional args or -f <file>)");
|
|
77716
79244
|
process.exit(1);
|
|
77717
79245
|
}
|
|
77718
79246
|
const mode = cliConfig.teamMode ?? "default";
|
|
77719
|
-
const sessionPath =
|
|
79247
|
+
const sessionPath = join38(process.cwd(), `.claudish-team-${Date.now()}`);
|
|
77720
79248
|
if (mode === "json") {
|
|
77721
79249
|
const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
|
|
77722
79250
|
setupSession2(sessionPath, cliConfig.team, prompt);
|
|
@@ -77726,9 +79254,9 @@ async function runCli() {
|
|
|
77726
79254
|
});
|
|
77727
79255
|
const result = { ...status2, responses: {} };
|
|
77728
79256
|
for (const anonId of Object.keys(status2.models)) {
|
|
77729
|
-
const responsePath =
|
|
79257
|
+
const responsePath = join38(sessionPath, `response-${anonId}.md`);
|
|
77730
79258
|
try {
|
|
77731
|
-
const raw2 =
|
|
79259
|
+
const raw2 = readFileSync29(responsePath, "utf-8").trim();
|
|
77732
79260
|
try {
|
|
77733
79261
|
result.responses[anonId] = JSON.parse(raw2);
|
|
77734
79262
|
} catch {
|