claudish 7.40.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 +1834 -326
- 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
|
`)}
|
|
@@ -37128,13 +37235,13 @@ var init_model_parser = __esm(() => {
|
|
|
37128
37235
|
import {
|
|
37129
37236
|
existsSync as existsSync15,
|
|
37130
37237
|
mkdirSync as mkdirSync8,
|
|
37131
|
-
readFileSync as
|
|
37238
|
+
readFileSync as readFileSync14,
|
|
37132
37239
|
renameSync,
|
|
37133
37240
|
unlinkSync as unlinkSync5,
|
|
37134
37241
|
writeFileSync as writeFileSync7
|
|
37135
37242
|
} from "fs";
|
|
37136
|
-
import { homedir as
|
|
37137
|
-
import { join as
|
|
37243
|
+
import { homedir as homedir22 } from "os";
|
|
37244
|
+
import { join as join22 } from "path";
|
|
37138
37245
|
function ensureDir() {
|
|
37139
37246
|
if (!existsSync15(CLAUDISH_DIR)) {
|
|
37140
37247
|
mkdirSync8(CLAUDISH_DIR, { recursive: true });
|
|
@@ -37144,7 +37251,7 @@ function readFromDisk() {
|
|
|
37144
37251
|
try {
|
|
37145
37252
|
if (!existsSync15(BUFFER_FILE))
|
|
37146
37253
|
return [];
|
|
37147
|
-
const raw =
|
|
37254
|
+
const raw = readFileSync14(BUFFER_FILE, "utf-8");
|
|
37148
37255
|
const parsed = JSON.parse(raw);
|
|
37149
37256
|
if (!Array.isArray(parsed.events))
|
|
37150
37257
|
return [];
|
|
@@ -37169,7 +37276,7 @@ function writeToDisk(events) {
|
|
|
37169
37276
|
ensureDir();
|
|
37170
37277
|
const trimmed2 = enforceSizeCap([...events]);
|
|
37171
37278
|
const payload = { version: 1, events: trimmed2 };
|
|
37172
|
-
const tmpFile =
|
|
37279
|
+
const tmpFile = join22(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
|
|
37173
37280
|
writeFileSync7(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
|
|
37174
37281
|
renameSync(tmpFile, BUFFER_FILE);
|
|
37175
37282
|
memoryCache = trimmed2;
|
|
@@ -37242,8 +37349,8 @@ function syncFlushOnExit() {
|
|
|
37242
37349
|
var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
|
|
37243
37350
|
var init_stats_buffer = __esm(() => {
|
|
37244
37351
|
BUFFER_MAX_BYTES = 64 * 1024;
|
|
37245
|
-
CLAUDISH_DIR =
|
|
37246
|
-
BUFFER_FILE =
|
|
37352
|
+
CLAUDISH_DIR = join22(homedir22(), ".claudish");
|
|
37353
|
+
BUFFER_FILE = join22(CLAUDISH_DIR, "stats-buffer.json");
|
|
37247
37354
|
process.on("exit", syncFlushOnExit);
|
|
37248
37355
|
process.on("SIGTERM", () => {
|
|
37249
37356
|
try {
|
|
@@ -38357,9 +38464,9 @@ function compareByReleaseDateDesc(a, b) {
|
|
|
38357
38464
|
}
|
|
38358
38465
|
|
|
38359
38466
|
// src/model-loader.ts
|
|
38360
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as
|
|
38361
|
-
import { homedir as
|
|
38362
|
-
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";
|
|
38363
38470
|
function groupRecommendedModels(entries) {
|
|
38364
38471
|
const byId = new Map;
|
|
38365
38472
|
const categoryOrder = new Map;
|
|
@@ -38471,7 +38578,7 @@ async function getRecommendedModels(opts = {}) {
|
|
|
38471
38578
|
}
|
|
38472
38579
|
if (!forceRefresh && existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
38473
38580
|
try {
|
|
38474
|
-
const cacheData = JSON.parse(
|
|
38581
|
+
const cacheData = JSON.parse(readFileSync15(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
38475
38582
|
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
38476
38583
|
_cachedRecommendedModels = cacheData;
|
|
38477
38584
|
return cacheData;
|
|
@@ -38487,7 +38594,7 @@ async function getRecommendedModels(opts = {}) {
|
|
|
38487
38594
|
if (data.models && data.models.length > 0) {
|
|
38488
38595
|
_cachedRecommendedModels = data;
|
|
38489
38596
|
try {
|
|
38490
|
-
const cacheDir =
|
|
38597
|
+
const cacheDir = join23(homedir23(), ".claudish");
|
|
38491
38598
|
mkdirSync9(cacheDir, { recursive: true });
|
|
38492
38599
|
writeFileSync8(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
|
|
38493
38600
|
} catch {}
|
|
@@ -38502,7 +38609,7 @@ function getRecommendedModelsSync() {
|
|
|
38502
38609
|
return _cachedRecommendedModels;
|
|
38503
38610
|
if (existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
38504
38611
|
try {
|
|
38505
|
-
const cacheData = JSON.parse(
|
|
38612
|
+
const cacheData = JSON.parse(readFileSync15(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
38506
38613
|
if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
|
|
38507
38614
|
_cachedRecommendedModels = cacheData;
|
|
38508
38615
|
return cacheData;
|
|
@@ -38626,7 +38733,7 @@ var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels =
|
|
|
38626
38733
|
var init_model_loader = __esm(() => {
|
|
38627
38734
|
init_cache_ttl();
|
|
38628
38735
|
FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
|
|
38629
|
-
RECOMMENDED_MODELS_CACHE_PATH =
|
|
38736
|
+
RECOMMENDED_MODELS_CACHE_PATH = join23(homedir23(), ".claudish", "recommended-models-cache.json");
|
|
38630
38737
|
FIREBASE_SLUG_TO_PROVIDER_NAME = {
|
|
38631
38738
|
openai: "openai",
|
|
38632
38739
|
google: "google",
|
|
@@ -38694,6 +38801,279 @@ var init_context_window_fallback = __esm(() => {
|
|
|
38694
38801
|
inFlight2 = new Map;
|
|
38695
38802
|
});
|
|
38696
38803
|
|
|
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;
|
|
38816
|
+
}
|
|
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;
|
|
39075
|
+
});
|
|
39076
|
+
|
|
38697
39077
|
// src/handlers/shared/stream-head-sniffer.ts
|
|
38698
39078
|
function isRetryableStreamError(code, type, message) {
|
|
38699
39079
|
if (RETRYABLE_ERROR_CODES.has(code))
|
|
@@ -39166,6 +39546,350 @@ var init_anthropic_sse = __esm(() => {
|
|
|
39166
39546
|
init_logger();
|
|
39167
39547
|
});
|
|
39168
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
|
+
|
|
39169
39893
|
// src/handlers/shared/stream-parsers/gemini-sse.ts
|
|
39170
39894
|
function createGeminiSseStream(_c, response, opts) {
|
|
39171
39895
|
const encoder = new TextEncoder;
|
|
@@ -39976,8 +40700,8 @@ var init_openai_responses_sse = __esm(() => {
|
|
|
39976
40700
|
|
|
39977
40701
|
// src/handlers/shared/token-tracker.ts
|
|
39978
40702
|
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
39979
|
-
import { homedir as
|
|
39980
|
-
import { dirname as dirname8, join as
|
|
40703
|
+
import { homedir as homedir24 } from "os";
|
|
40704
|
+
import { dirname as dirname8, join as join24 } from "path";
|
|
39981
40705
|
function stripProviderPrefix(name) {
|
|
39982
40706
|
const at = name.indexOf("@");
|
|
39983
40707
|
return at === -1 ? name : name.slice(at + 1);
|
|
@@ -40139,7 +40863,7 @@ class TokenTracker {
|
|
|
40139
40863
|
};
|
|
40140
40864
|
}
|
|
40141
40865
|
const override = process.env.CLAUDISH_TOKEN_FILE;
|
|
40142
|
-
const outPath = override ||
|
|
40866
|
+
const outPath = override || join24(homedir24(), ".claudish", `tokens-${this.port}.json`);
|
|
40143
40867
|
mkdirSync10(dirname8(outPath), { recursive: true });
|
|
40144
40868
|
writeFileSync9(outPath, JSON.stringify(data), "utf-8");
|
|
40145
40869
|
} catch (e) {
|
|
@@ -40237,10 +40961,10 @@ class ComposedHandler {
|
|
|
40237
40961
|
if (!this.getModelSupportsVision()) {
|
|
40238
40962
|
const imageBlocks = [];
|
|
40239
40963
|
for (let msgIdx = 0;msgIdx < messages.length; msgIdx++) {
|
|
40240
|
-
const
|
|
40241
|
-
if (Array.isArray(
|
|
40242
|
-
for (let partIdx = 0;partIdx <
|
|
40243
|
-
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];
|
|
40244
40968
|
if (part.type === "image_url" || part.type === "image" || part.type === "document") {
|
|
40245
40969
|
imageBlocks.push({ msgIdx, partIdx, block: part });
|
|
40246
40970
|
}
|
|
@@ -40264,25 +40988,25 @@ class ComposedHandler {
|
|
|
40264
40988
|
};
|
|
40265
40989
|
}
|
|
40266
40990
|
log(`[ComposedHandler] Vision proxy described ${descriptions.length} image(s)`);
|
|
40267
|
-
for (const
|
|
40268
|
-
if (Array.isArray(
|
|
40269
|
-
|
|
40270
|
-
if (
|
|
40271
|
-
|
|
40272
|
-
} else if (
|
|
40273
|
-
|
|
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 = "";
|
|
40274
40998
|
}
|
|
40275
40999
|
}
|
|
40276
41000
|
}
|
|
40277
41001
|
} else {
|
|
40278
41002
|
log("[ComposedHandler] Stripping image/document blocks (vision not supported)");
|
|
40279
|
-
for (const
|
|
40280
|
-
if (Array.isArray(
|
|
40281
|
-
|
|
40282
|
-
if (
|
|
40283
|
-
|
|
40284
|
-
} else if (
|
|
40285
|
-
|
|
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 = "";
|
|
40286
41010
|
}
|
|
40287
41011
|
}
|
|
40288
41012
|
}
|
|
@@ -40320,7 +41044,7 @@ class ComposedHandler {
|
|
|
40320
41044
|
const behaviorSession = this.behaviorEngine.startSession({
|
|
40321
41045
|
modelId: this.bareModelName,
|
|
40322
41046
|
providerName: this.provider.name,
|
|
40323
|
-
isNativeAnthropic: /^claude[-.]/i.test(this.bareModelName) || this.provider.name === "anthropic"
|
|
41047
|
+
isNativeAnthropic: !this.options.forceForeignModel && (/^claude[-.]/i.test(this.bareModelName) || this.provider.name === "anthropic")
|
|
40324
41048
|
});
|
|
40325
41049
|
if (!behaviorSession.isNoop) {
|
|
40326
41050
|
behaviorSession.applyRequest(claudeRequest, claudeRequest.tools ?? [], tools, messages);
|
|
@@ -40376,13 +41100,14 @@ class ComposedHandler {
|
|
|
40376
41100
|
}
|
|
40377
41101
|
const endpoint = this.provider.getEndpoint(this.targetModel);
|
|
40378
41102
|
const headers = await this.provider.getHeaders();
|
|
40379
|
-
|
|
41103
|
+
const serialized = this.provider.serializeBody?.(requestPayload);
|
|
41104
|
+
headers["Content-Type"] = serialized?.contentType ?? "application/json";
|
|
40380
41105
|
log(`[${this.provider.displayName}] Calling API: ${endpoint}`);
|
|
40381
41106
|
const requestInit = this.provider.getRequestInit?.() || {};
|
|
40382
41107
|
const doFetch = () => fetch(endpoint, {
|
|
40383
41108
|
method: "POST",
|
|
40384
41109
|
headers,
|
|
40385
|
-
body: JSON.stringify(requestPayload),
|
|
41110
|
+
body: serialized?.body ?? JSON.stringify(requestPayload),
|
|
40386
41111
|
...requestInit
|
|
40387
41112
|
});
|
|
40388
41113
|
let response;
|
|
@@ -40391,9 +41116,9 @@ class ComposedHandler {
|
|
|
40391
41116
|
} catch (error46) {
|
|
40392
41117
|
const conn = classifyConnectionError(error46);
|
|
40393
41118
|
if (conn) {
|
|
40394
|
-
const
|
|
40395
|
-
log(`[${this.provider.displayName}] ${
|
|
40396
|
-
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}`);
|
|
40397
41122
|
reportError({
|
|
40398
41123
|
error: error46,
|
|
40399
41124
|
providerName: this.provider.name,
|
|
@@ -40425,7 +41150,7 @@ class ComposedHandler {
|
|
|
40425
41150
|
invocation_mode: this.options.invocationMode ?? "auto-route"
|
|
40426
41151
|
});
|
|
40427
41152
|
} catch {}
|
|
40428
|
-
return c.json(wrapAnthropicError(400,
|
|
41153
|
+
return c.json(wrapAnthropicError(400, msg2, "connection_error"), 400);
|
|
40429
41154
|
}
|
|
40430
41155
|
throw error46;
|
|
40431
41156
|
}
|
|
@@ -40442,12 +41167,12 @@ class ComposedHandler {
|
|
|
40442
41167
|
try {
|
|
40443
41168
|
await this.provider.forceRefreshAuth();
|
|
40444
41169
|
const retryHeaders = await this.provider.getHeaders();
|
|
40445
|
-
retryHeaders["Content-Type"] = "application/json";
|
|
41170
|
+
retryHeaders["Content-Type"] = serialized?.contentType ?? "application/json";
|
|
40446
41171
|
const retryInit = this.provider.getRequestInit?.() || {};
|
|
40447
41172
|
const retryResp = await fetch(endpoint, {
|
|
40448
41173
|
method: "POST",
|
|
40449
41174
|
headers: retryHeaders,
|
|
40450
|
-
body: JSON.stringify(requestPayload),
|
|
41175
|
+
body: serialized?.body ?? JSON.stringify(requestPayload),
|
|
40451
41176
|
...retryInit
|
|
40452
41177
|
});
|
|
40453
41178
|
if (retryResp.ok) {
|
|
@@ -40627,6 +41352,48 @@ class ComposedHandler {
|
|
|
40627
41352
|
}
|
|
40628
41353
|
response = settled.response;
|
|
40629
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
|
+
}
|
|
40630
41397
|
latencyMs = Math.round(performance.now() - startTime);
|
|
40631
41398
|
const httpStatus = response.status;
|
|
40632
41399
|
this.capturePlanUsage(response);
|
|
@@ -40705,6 +41472,55 @@ class ComposedHandler {
|
|
|
40705
41472
|
response = next;
|
|
40706
41473
|
}
|
|
40707
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
|
+
}
|
|
40708
41524
|
resolveStreamFormat() {
|
|
40709
41525
|
return this.provider.overrideStreamFormat?.() ?? this.explicitAdapter?.getStreamFormat() ?? this.modelAdapter?.getStreamFormat() ?? this.getAdapter().getStreamFormat();
|
|
40710
41526
|
}
|
|
@@ -40790,6 +41606,23 @@ class ComposedHandler {
|
|
|
40790
41606
|
priorInputTokens
|
|
40791
41607
|
});
|
|
40792
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
|
+
});
|
|
40793
41626
|
case "ollama-jsonl":
|
|
40794
41627
|
return createOllamaJsonlStream(c, response, {
|
|
40795
41628
|
modelName: this.bareModelName,
|
|
@@ -40894,10 +41727,12 @@ var init_composed_handler = __esm(() => {
|
|
|
40894
41727
|
init_anthropic_error();
|
|
40895
41728
|
init_connection_error();
|
|
40896
41729
|
init_context_window_fallback();
|
|
41730
|
+
init_devin_stream_head_sniffer();
|
|
40897
41731
|
init_openai_compat();
|
|
40898
41732
|
init_quota_exhaustion();
|
|
40899
41733
|
init_stream_head_sniffer();
|
|
40900
41734
|
init_anthropic_sse();
|
|
41735
|
+
init_devin_connect();
|
|
40901
41736
|
init_gemini_sse();
|
|
40902
41737
|
init_ollama_jsonl();
|
|
40903
41738
|
init_openai_responses_sse();
|
|
@@ -40906,6 +41741,209 @@ var init_composed_handler = __esm(() => {
|
|
|
40906
41741
|
STREAM_RETRY_DELAYS_MS = [3000, 15000, 30000];
|
|
40907
41742
|
});
|
|
40908
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
|
+
|
|
40909
41947
|
// src/providers/model-discovery.ts
|
|
40910
41948
|
function resolveBaseUrl(catalogName) {
|
|
40911
41949
|
const def = getProviderByName(catalogName);
|
|
@@ -40966,6 +42004,22 @@ async function discoverProviderModels(providerName) {
|
|
|
40966
42004
|
const descriptor = def?.modelDiscovery;
|
|
40967
42005
|
if (!def || !descriptor)
|
|
40968
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
|
+
}
|
|
40969
42023
|
const baseUrl = resolveBaseUrl(providerName);
|
|
40970
42024
|
if (!baseUrl)
|
|
40971
42025
|
return [];
|
|
@@ -41140,24 +42194,24 @@ async function discoverViaOpenAIModels(endpoint, headers, cacheKey) {
|
|
|
41140
42194
|
function classifyFetchError(e, endpoint) {
|
|
41141
42195
|
const name = e?.name ?? "";
|
|
41142
42196
|
const code = e?.cause?.code ?? "";
|
|
41143
|
-
const
|
|
42197
|
+
const msg2 = e instanceof Error ? e.message : String(e);
|
|
41144
42198
|
const url2 = tryParseUrl(endpoint);
|
|
41145
42199
|
const host = url2?.host ?? endpoint;
|
|
41146
42200
|
const isLocal = !!url2 && /^(localhost|127\.0\.0\.1|0\.0\.0\.0|::1)$/i.test(url2.hostname);
|
|
41147
|
-
if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(
|
|
42201
|
+
if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(msg2)) {
|
|
41148
42202
|
return `${host} unresponsive (>${FETCH_TIMEOUT_MS2 / 1000}s) \u2014 check if the server is overloaded`;
|
|
41149
42203
|
}
|
|
41150
42204
|
if (code === "ENOTFOUND" || code === "EAI_AGAIN") {
|
|
41151
42205
|
return `cannot resolve host ${url2?.hostname ?? endpoint} \u2014 check the URL`;
|
|
41152
42206
|
}
|
|
41153
|
-
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);
|
|
41154
42208
|
if (isConnRefused) {
|
|
41155
42209
|
if (isLocal) {
|
|
41156
42210
|
return `${host} not reachable \u2014 is the server running? Press u to change URL.`;
|
|
41157
42211
|
}
|
|
41158
42212
|
return `${host} not reachable \u2014 check the URL or network. Press u to change.`;
|
|
41159
42213
|
}
|
|
41160
|
-
return `${host}: ${
|
|
42214
|
+
return `${host}: ${msg2}`;
|
|
41161
42215
|
}
|
|
41162
42216
|
function tryParseUrl(s) {
|
|
41163
42217
|
try {
|
|
@@ -42184,6 +43238,10 @@ function buildCredentialHint(modelName, providers) {
|
|
|
42184
43238
|
lines.push(` Run: claudish ${hint.loginFlag} (authenticate via OAuth)`);
|
|
42185
43239
|
hasOption = true;
|
|
42186
43240
|
}
|
|
43241
|
+
if (hint.note) {
|
|
43242
|
+
lines.push(` ${hint.note}`);
|
|
43243
|
+
hasOption = true;
|
|
43244
|
+
}
|
|
42187
43245
|
if (hint.apiKeyEnvVar) {
|
|
42188
43246
|
lines.push(` Set: export ${hint.apiKeyEnvVar}=your-key (for ${provider})`);
|
|
42189
43247
|
hasOption = true;
|
|
@@ -42206,6 +43264,10 @@ var init_routing_hints = __esm(() => {
|
|
|
42206
43264
|
google: { loginFlag: "login gemini", apiKeyEnvVar: "GEMINI_API_KEY" },
|
|
42207
43265
|
"gemini-codeassist": { loginFlag: "login gemini", apiKeyEnvVar: "GEMINI_API_KEY" },
|
|
42208
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
|
+
},
|
|
42209
43271
|
openai: { apiKeyEnvVar: "OPENAI_API_KEY" },
|
|
42210
43272
|
"openai-codex": { loginFlag: "login codex", apiKeyEnvVar: "OPENAI_CODEX_API_KEY" },
|
|
42211
43273
|
minimax: { apiKeyEnvVar: "MINIMAX_API_KEY" },
|
|
@@ -43108,10 +44170,10 @@ var init_signal_watcher = __esm(() => {
|
|
|
43108
44170
|
|
|
43109
44171
|
// src/channel/session-manager.ts
|
|
43110
44172
|
import { spawn } from "child_process";
|
|
43111
|
-
import { randomUUID as
|
|
44173
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
43112
44174
|
import { createWriteStream, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "fs";
|
|
43113
|
-
import { homedir as
|
|
43114
|
-
import { join as
|
|
44175
|
+
import { homedir as homedir25 } from "os";
|
|
44176
|
+
import { join as join25 } from "path";
|
|
43115
44177
|
|
|
43116
44178
|
class SessionManager {
|
|
43117
44179
|
sessions = new Map;
|
|
@@ -43123,20 +44185,20 @@ class SessionManager {
|
|
|
43123
44185
|
constructor(options) {
|
|
43124
44186
|
this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
|
|
43125
44187
|
this.scrollbackCapacity = options?.scrollbackCapacity ?? DEFAULT_SCROLLBACK;
|
|
43126
|
-
this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ??
|
|
44188
|
+
this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join25(homedir25(), ".claudish", "sessions");
|
|
43127
44189
|
this.onStateChange = options?.onStateChange;
|
|
43128
44190
|
}
|
|
43129
44191
|
createSession(opts) {
|
|
43130
44192
|
if (this.activeSessions >= this.maxSessions) {
|
|
43131
44193
|
throw new Error(`Max sessions (${this.maxSessions}) reached`);
|
|
43132
44194
|
}
|
|
43133
|
-
const sessionId2 =
|
|
44195
|
+
const sessionId2 = randomUUID5().slice(0, 8);
|
|
43134
44196
|
const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
|
|
43135
44197
|
const startedAt = new Date().toISOString();
|
|
43136
|
-
const sessionDir =
|
|
44198
|
+
const sessionDir = join25(this.sessionsDir, sessionId2);
|
|
43137
44199
|
mkdirSync11(sessionDir, { recursive: true });
|
|
43138
44200
|
if (opts.prompt) {
|
|
43139
|
-
writeFileSync10(
|
|
44201
|
+
writeFileSync10(join25(sessionDir, "prompt.md"), opts.prompt, "utf-8");
|
|
43140
44202
|
}
|
|
43141
44203
|
const args = [
|
|
43142
44204
|
"--model",
|
|
@@ -43170,7 +44232,7 @@ class SessionManager {
|
|
|
43170
44232
|
});
|
|
43171
44233
|
}
|
|
43172
44234
|
});
|
|
43173
|
-
const outputLogStream = createWriteStream(
|
|
44235
|
+
const outputLogStream = createWriteStream(join25(sessionDir, "output.log"));
|
|
43174
44236
|
const entry = {
|
|
43175
44237
|
info: {
|
|
43176
44238
|
sessionId: sessionId2,
|
|
@@ -43217,9 +44279,9 @@ class SessionManager {
|
|
|
43217
44279
|
watcher.processExited(code);
|
|
43218
44280
|
outputLogStream.end();
|
|
43219
44281
|
if (entry.stderr) {
|
|
43220
|
-
writeFileSync10(
|
|
44282
|
+
writeFileSync10(join25(sessionDir, "stderr.log"), entry.stderr, "utf-8");
|
|
43221
44283
|
}
|
|
43222
|
-
writeFileSync10(
|
|
44284
|
+
writeFileSync10(join25(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
|
|
43223
44285
|
this.cleanupSigint();
|
|
43224
44286
|
});
|
|
43225
44287
|
proc.on("error", (err) => {
|
|
@@ -45295,8 +46357,8 @@ var init_openrouter_api_format = __esm(() => {
|
|
|
45295
46357
|
convertMessages(claudeRequest, filterIdentityFn) {
|
|
45296
46358
|
const messages = super.convertMessages(claudeRequest, filterIdentityFn);
|
|
45297
46359
|
if (this.modelId.includes("grok") || this.modelId.includes("x-ai")) {
|
|
45298
|
-
const
|
|
45299
|
-
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);
|
|
45300
46362
|
}
|
|
45301
46363
|
if (this.modelId.includes("gemini") || this.modelId.includes("google/")) {
|
|
45302
46364
|
const geminiMsg = `CRITICAL INSTRUCTION FOR OUTPUT FORMAT:
|
|
@@ -45616,12 +46678,12 @@ function rewriteAdvisorToolResults(payload, getAdviceFor) {
|
|
|
45616
46678
|
if (!Array.isArray(messages))
|
|
45617
46679
|
return [];
|
|
45618
46680
|
const rewritten = [];
|
|
45619
|
-
for (const
|
|
45620
|
-
if (!
|
|
46681
|
+
for (const msg2 of messages) {
|
|
46682
|
+
if (!msg2 || typeof msg2 !== "object")
|
|
45621
46683
|
continue;
|
|
45622
|
-
if (
|
|
46684
|
+
if (msg2.role !== "user")
|
|
45623
46685
|
continue;
|
|
45624
|
-
const content =
|
|
46686
|
+
const content = msg2.content;
|
|
45625
46687
|
if (!Array.isArray(content))
|
|
45626
46688
|
continue;
|
|
45627
46689
|
for (const block of content) {
|
|
@@ -45651,12 +46713,12 @@ function findPendingAdvisorToolResults(payload) {
|
|
|
45651
46713
|
if (!Array.isArray(messages))
|
|
45652
46714
|
return [];
|
|
45653
46715
|
const found = [];
|
|
45654
|
-
for (const
|
|
45655
|
-
if (!
|
|
46716
|
+
for (const msg2 of messages) {
|
|
46717
|
+
if (!msg2 || typeof msg2 !== "object")
|
|
45656
46718
|
continue;
|
|
45657
|
-
if (
|
|
46719
|
+
if (msg2.role !== "user")
|
|
45658
46720
|
continue;
|
|
45659
|
-
const content =
|
|
46721
|
+
const content = msg2.content;
|
|
45660
46722
|
if (!Array.isArray(content))
|
|
45661
46723
|
continue;
|
|
45662
46724
|
for (const block of content) {
|
|
@@ -46161,6 +47223,270 @@ var init_api_key_map = __esm(() => {
|
|
|
46161
47223
|
};
|
|
46162
47224
|
});
|
|
46163
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
|
+
|
|
46164
47490
|
// src/adapters/ollama-api-format.ts
|
|
46165
47491
|
var OllamaAPIFormat;
|
|
46166
47492
|
var init_ollama_api_format = __esm(() => {
|
|
@@ -46188,11 +47514,11 @@ var init_ollama_api_format = __esm(() => {
|
|
|
46188
47514
|
messages.push({ role: "system", content });
|
|
46189
47515
|
}
|
|
46190
47516
|
if (claudeRequest.messages) {
|
|
46191
|
-
for (const
|
|
46192
|
-
if (
|
|
46193
|
-
messages.push(this.processUserMessage(
|
|
46194
|
-
} else if (
|
|
46195
|
-
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));
|
|
46196
47522
|
}
|
|
46197
47523
|
}
|
|
46198
47524
|
}
|
|
@@ -46217,10 +47543,10 @@ var init_ollama_api_format = __esm(() => {
|
|
|
46217
47543
|
supportsVision() {
|
|
46218
47544
|
return false;
|
|
46219
47545
|
}
|
|
46220
|
-
processUserMessage(
|
|
46221
|
-
if (Array.isArray(
|
|
47546
|
+
processUserMessage(msg2) {
|
|
47547
|
+
if (Array.isArray(msg2.content)) {
|
|
46222
47548
|
const textParts = [];
|
|
46223
|
-
for (const block of
|
|
47549
|
+
for (const block of msg2.content) {
|
|
46224
47550
|
if (block.type === "text") {
|
|
46225
47551
|
textParts.push(block.text);
|
|
46226
47552
|
} else if (block.type === "tool_result") {
|
|
@@ -46232,12 +47558,12 @@ var init_ollama_api_format = __esm(() => {
|
|
|
46232
47558
|
|
|
46233
47559
|
`) };
|
|
46234
47560
|
}
|
|
46235
|
-
return { role: "user", content:
|
|
47561
|
+
return { role: "user", content: msg2.content };
|
|
46236
47562
|
}
|
|
46237
|
-
processAssistantMessage(
|
|
46238
|
-
if (Array.isArray(
|
|
47563
|
+
processAssistantMessage(msg2) {
|
|
47564
|
+
if (Array.isArray(msg2.content)) {
|
|
46239
47565
|
const strings = [];
|
|
46240
|
-
for (const block of
|
|
47566
|
+
for (const block of msg2.content) {
|
|
46241
47567
|
if (block.type === "text") {
|
|
46242
47568
|
strings.push(block.text);
|
|
46243
47569
|
} else if (block.type === "tool_use") {
|
|
@@ -46247,17 +47573,17 @@ var init_ollama_api_format = __esm(() => {
|
|
|
46247
47573
|
return { role: "assistant", content: strings.join(`
|
|
46248
47574
|
`) };
|
|
46249
47575
|
}
|
|
46250
|
-
return { role: "assistant", content:
|
|
47576
|
+
return { role: "assistant", content: msg2.content };
|
|
46251
47577
|
}
|
|
46252
47578
|
};
|
|
46253
47579
|
});
|
|
46254
47580
|
|
|
46255
47581
|
// src/providers/api-key-provenance.ts
|
|
46256
|
-
import { existsSync as existsSync17, readFileSync as
|
|
46257
|
-
import { homedir as
|
|
46258
|
-
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";
|
|
46259
47585
|
function activeConfigPath() {
|
|
46260
|
-
return activeGlobalConfigFile(
|
|
47586
|
+
return activeGlobalConfigFile(join26(homedir26(), ".claudish", "config.json"));
|
|
46261
47587
|
}
|
|
46262
47588
|
function configLayerLabel() {
|
|
46263
47589
|
return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
|
|
@@ -46336,7 +47662,7 @@ function readDotenvKey(envVars) {
|
|
|
46336
47662
|
const dotenvPath = resolve2(".env");
|
|
46337
47663
|
if (!existsSync17(dotenvPath))
|
|
46338
47664
|
return null;
|
|
46339
|
-
const parsed = import_dotenv.parse(
|
|
47665
|
+
const parsed = import_dotenv.parse(readFileSync16(dotenvPath, "utf-8"));
|
|
46340
47666
|
for (const v of envVars) {
|
|
46341
47667
|
if (parsed[v])
|
|
46342
47668
|
return parsed[v];
|
|
@@ -46351,7 +47677,7 @@ function readConfigKey(envVar) {
|
|
|
46351
47677
|
const configPath = activeConfigPath();
|
|
46352
47678
|
if (!existsSync17(configPath))
|
|
46353
47679
|
return null;
|
|
46354
|
-
const cfg = JSON.parse(
|
|
47680
|
+
const cfg = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
46355
47681
|
return cfg.apiKeys?.[envVar] || null;
|
|
46356
47682
|
} catch {
|
|
46357
47683
|
return null;
|
|
@@ -46363,6 +47689,161 @@ var init_api_key_provenance = __esm(() => {
|
|
|
46363
47689
|
import_dotenv = __toESM(require_main(), 1);
|
|
46364
47690
|
});
|
|
46365
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
|
+
|
|
46366
47847
|
// src/providers/transport/gemini-apikey.ts
|
|
46367
47848
|
class GeminiProviderTransport {
|
|
46368
47849
|
name = "gemini";
|
|
@@ -46395,7 +47876,7 @@ var init_gemini_apikey = __esm(() => {
|
|
|
46395
47876
|
});
|
|
46396
47877
|
|
|
46397
47878
|
// src/providers/transport/gemini-codeassist.ts
|
|
46398
|
-
import { randomUUID as
|
|
47879
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
46399
47880
|
function createActivityRequestId4() {
|
|
46400
47881
|
return Math.random().toString(36).substring(7);
|
|
46401
47882
|
}
|
|
@@ -46504,21 +47985,21 @@ class GeminiCodeAssistProviderTransport {
|
|
|
46504
47985
|
log(`[GeminiCodeAssist] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}, served: ${this.servedModels.join(",") || "(none)"}`);
|
|
46505
47986
|
}
|
|
46506
47987
|
transformPayload(payload) {
|
|
46507
|
-
const
|
|
46508
|
-
this.lastEnvelope =
|
|
46509
|
-
return
|
|
47988
|
+
const envelope2 = this.cachedAuth?.transformPayload ? this.cachedAuth.transformPayload(payload) : this.buildEnvelope(payload, this.modelName);
|
|
47989
|
+
this.lastEnvelope = envelope2;
|
|
47990
|
+
return envelope2;
|
|
46510
47991
|
}
|
|
46511
47992
|
buildEnvelope(innerPayload, model) {
|
|
46512
|
-
const
|
|
47993
|
+
const envelope2 = {
|
|
46513
47994
|
model,
|
|
46514
47995
|
project: this.projectId,
|
|
46515
|
-
user_prompt_id:
|
|
47996
|
+
user_prompt_id: randomUUID6(),
|
|
46516
47997
|
request: innerPayload
|
|
46517
47998
|
};
|
|
46518
47999
|
if (this.tierId && this.tierId !== "free-tier") {
|
|
46519
|
-
|
|
48000
|
+
envelope2.enabled_credit_types = ["GOOGLE_ONE_AI"];
|
|
46520
48001
|
}
|
|
46521
|
-
return
|
|
48002
|
+
return envelope2;
|
|
46522
48003
|
}
|
|
46523
48004
|
async enqueueRequest(fetchFn) {
|
|
46524
48005
|
const queue = GeminiRequestQueue.getInstance();
|
|
@@ -46845,11 +48326,12 @@ function createHandlerForProvider(ctx) {
|
|
|
46845
48326
|
log(`[Proxy] Handler: provider=${ctx.provider.name}, model=${ctx.modelName}`);
|
|
46846
48327
|
return profile.createHandler(ctx);
|
|
46847
48328
|
}
|
|
46848
|
-
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;
|
|
46849
48330
|
var init_provider_profiles = __esm(() => {
|
|
46850
48331
|
init_anthropic_api_format();
|
|
46851
48332
|
init_base_api_format();
|
|
46852
48333
|
init_codex_api_format();
|
|
48334
|
+
init_devin_api_format();
|
|
46853
48335
|
init_gemini_api_format();
|
|
46854
48336
|
init_litellm_api_format();
|
|
46855
48337
|
init_ollama_api_format();
|
|
@@ -46862,6 +48344,7 @@ var init_provider_profiles = __esm(() => {
|
|
|
46862
48344
|
init_runtime_providers();
|
|
46863
48345
|
init_anthropic_compat();
|
|
46864
48346
|
init_antigravity();
|
|
48347
|
+
init_devin();
|
|
46865
48348
|
init_gemini_apikey();
|
|
46866
48349
|
init_gemini_codeassist();
|
|
46867
48350
|
init_litellm();
|
|
@@ -46907,6 +48390,19 @@ var init_provider_profiles = __esm(() => {
|
|
|
46907
48390
|
return handler;
|
|
46908
48391
|
}
|
|
46909
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
|
+
};
|
|
46910
48406
|
openaiProfile = {
|
|
46911
48407
|
createHandler(ctx) {
|
|
46912
48408
|
if (requiresResponsesApi(ctx.modelName)) {
|
|
@@ -47087,6 +48583,7 @@ var init_provider_profiles = __esm(() => {
|
|
|
47087
48583
|
gemini: geminiProfile,
|
|
47088
48584
|
"gemini-codeassist": geminiCodeAssistProfile,
|
|
47089
48585
|
antigravity: antigravityProfile,
|
|
48586
|
+
devin: devinProfile,
|
|
47090
48587
|
openai: openaiProfile,
|
|
47091
48588
|
"openai-codex": openaiCodexProfile,
|
|
47092
48589
|
"x-ai": openaiProfile,
|
|
@@ -47825,9 +49322,9 @@ var init_poe = __esm(() => {
|
|
|
47825
49322
|
});
|
|
47826
49323
|
|
|
47827
49324
|
// src/services/pricing-cache.ts
|
|
47828
|
-
import { existsSync as existsSync18, readFileSync as
|
|
47829
|
-
import { homedir as
|
|
47830
|
-
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";
|
|
47831
49328
|
function prefixMatch(modelName) {
|
|
47832
49329
|
for (const [key, pricing] of pricingMap) {
|
|
47833
49330
|
if (modelName.startsWith(key))
|
|
@@ -47870,7 +49367,7 @@ function loadDiskCache() {
|
|
|
47870
49367
|
const stat2 = statSync4(CACHE_FILE);
|
|
47871
49368
|
const age = Date.now() - stat2.mtimeMs;
|
|
47872
49369
|
const isFresh = age < CACHE_TTL_MS3;
|
|
47873
|
-
const raw2 =
|
|
49370
|
+
const raw2 = readFileSync17(CACHE_FILE, "utf-8");
|
|
47874
49371
|
const data = JSON.parse(raw2);
|
|
47875
49372
|
for (const [key, pricing] of Object.entries(data)) {
|
|
47876
49373
|
pricingMap.set(key, pricing);
|
|
@@ -47886,8 +49383,8 @@ var init_pricing_cache = __esm(() => {
|
|
|
47886
49383
|
init_logger();
|
|
47887
49384
|
init_catalog_query();
|
|
47888
49385
|
pricingMap = new Map;
|
|
47889
|
-
CACHE_DIR =
|
|
47890
|
-
CACHE_FILE =
|
|
49386
|
+
CACHE_DIR = join27(homedir27(), ".claudish");
|
|
49387
|
+
CACHE_FILE = join27(CACHE_DIR, "pricing-cache.json");
|
|
47891
49388
|
CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
|
|
47892
49389
|
});
|
|
47893
49390
|
|
|
@@ -48382,20 +49879,20 @@ var init_redact = __esm(() => {
|
|
|
48382
49879
|
});
|
|
48383
49880
|
|
|
48384
49881
|
// src/team-stats.ts
|
|
48385
|
-
import { existsSync as existsSync19, readFileSync as
|
|
48386
|
-
import { join as
|
|
49882
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync11 } from "fs";
|
|
49883
|
+
import { join as join28 } from "path";
|
|
48387
49884
|
function statsDir(sessionPath) {
|
|
48388
|
-
return
|
|
49885
|
+
return join28(sessionPath, "stats");
|
|
48389
49886
|
}
|
|
48390
49887
|
function tokenFileFor(sessionPath, anonId) {
|
|
48391
|
-
return
|
|
49888
|
+
return join28(statsDir(sessionPath), `${anonId}.json`);
|
|
48392
49889
|
}
|
|
48393
49890
|
function readTokenStats(sessionPath, anonId) {
|
|
48394
49891
|
const path = tokenFileFor(sessionPath, anonId);
|
|
48395
49892
|
if (!existsSync19(path))
|
|
48396
49893
|
return null;
|
|
48397
49894
|
try {
|
|
48398
|
-
return JSON.parse(
|
|
49895
|
+
return JSON.parse(readFileSync18(path, "utf-8"));
|
|
48399
49896
|
} catch {
|
|
48400
49897
|
return null;
|
|
48401
49898
|
}
|
|
@@ -48472,10 +49969,10 @@ function renderTeamStats(sessionPath, manifest, status, opts) {
|
|
|
48472
49969
|
if (stats?.is_free)
|
|
48473
49970
|
anyFree = true;
|
|
48474
49971
|
const name = model.length > nameWidth ? `${model.slice(0, nameWidth - 1)}\u2026` : model;
|
|
48475
|
-
const
|
|
49972
|
+
const bytes2 = m.outputSize > 0 ? fmtBytes(m.outputSize) : "";
|
|
48476
49973
|
const tokens = stats ? `${fmtTokens(inTok)}/${outTok > 0 ? fmtTokens(outTok) : "-"}` : "";
|
|
48477
49974
|
const cost = stats ? fmtCost(stats.total_cost, stats.is_free) : "";
|
|
48478
|
-
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());
|
|
48479
49976
|
}
|
|
48480
49977
|
const parts = [`${ids.length} models`];
|
|
48481
49978
|
if (done)
|
|
@@ -48543,7 +50040,7 @@ ${segs.join(" \xB7 ")}`;
|
|
|
48543
50040
|
}
|
|
48544
50041
|
function writeStatusFile(sessionPath, manifest, status, opts) {
|
|
48545
50042
|
try {
|
|
48546
|
-
writeFileSync11(
|
|
50043
|
+
writeFileSync11(join28(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
|
|
48547
50044
|
`, "utf-8");
|
|
48548
50045
|
} catch {}
|
|
48549
50046
|
}
|
|
@@ -48571,11 +50068,11 @@ import {
|
|
|
48571
50068
|
createWriteStream as createWriteStream2,
|
|
48572
50069
|
existsSync as existsSync20,
|
|
48573
50070
|
mkdirSync as mkdirSync12,
|
|
48574
|
-
readFileSync as
|
|
50071
|
+
readFileSync as readFileSync19,
|
|
48575
50072
|
readdirSync as readdirSync3,
|
|
48576
50073
|
writeFileSync as writeFileSync12
|
|
48577
50074
|
} from "fs";
|
|
48578
|
-
import { join as
|
|
50075
|
+
import { join as join29, resolve as resolve3 } from "path";
|
|
48579
50076
|
function classifyRunOutput(opts) {
|
|
48580
50077
|
const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
|
|
48581
50078
|
const apiError = API_ERROR_RE.exec(stdoutTail);
|
|
@@ -48636,18 +50133,18 @@ function setupSession(sessionPath, models, input) {
|
|
|
48636
50133
|
if (models.length === 0) {
|
|
48637
50134
|
throw new Error("At least one model is required");
|
|
48638
50135
|
}
|
|
48639
|
-
if (existsSync20(
|
|
50136
|
+
if (existsSync20(join29(sessionPath, "manifest.json"))) {
|
|
48640
50137
|
throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
|
|
48641
50138
|
}
|
|
48642
50139
|
const sentinels = models.filter(isSentinelModel);
|
|
48643
50140
|
if (sentinels.length > 0) {
|
|
48644
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.`);
|
|
48645
50142
|
}
|
|
48646
|
-
mkdirSync12(
|
|
48647
|
-
mkdirSync12(
|
|
50143
|
+
mkdirSync12(join29(sessionPath, "work"), { recursive: true });
|
|
50144
|
+
mkdirSync12(join29(sessionPath, "errors"), { recursive: true });
|
|
48648
50145
|
if (input !== undefined) {
|
|
48649
|
-
writeFileSync12(
|
|
48650
|
-
} else if (!existsSync20(
|
|
50146
|
+
writeFileSync12(join29(sessionPath, "input.md"), input, "utf-8");
|
|
50147
|
+
} else if (!existsSync20(join29(sessionPath, "input.md"))) {
|
|
48651
50148
|
throw new Error(`No input.md found at ${sessionPath} and no input provided`);
|
|
48652
50149
|
}
|
|
48653
50150
|
const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
|
|
@@ -48664,9 +50161,9 @@ function setupSession(sessionPath, models, input) {
|
|
|
48664
50161
|
model: models[i],
|
|
48665
50162
|
assignedAt: now
|
|
48666
50163
|
};
|
|
48667
|
-
mkdirSync12(
|
|
50164
|
+
mkdirSync12(join29(sessionPath, "work", anonId), { recursive: true });
|
|
48668
50165
|
}
|
|
48669
|
-
writeFileSync12(
|
|
50166
|
+
writeFileSync12(join29(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
48670
50167
|
const status = {
|
|
48671
50168
|
startedAt: now,
|
|
48672
50169
|
models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
|
|
@@ -48680,17 +50177,17 @@ function setupSession(sessionPath, models, input) {
|
|
|
48680
50177
|
}
|
|
48681
50178
|
]))
|
|
48682
50179
|
};
|
|
48683
|
-
writeFileSync12(
|
|
50180
|
+
writeFileSync12(join29(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
|
|
48684
50181
|
return manifest;
|
|
48685
50182
|
}
|
|
48686
50183
|
async function runModels(sessionPath, opts = {}) {
|
|
48687
50184
|
const timeoutMs = (opts.timeout ?? 300) * 1000;
|
|
48688
|
-
const manifest = JSON.parse(
|
|
48689
|
-
const statusPath =
|
|
48690
|
-
const inputPath =
|
|
48691
|
-
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");
|
|
48692
50189
|
const spawnPlan = await (opts.spawnPlanner ?? prehydrateCredentialsForSpawn)(Object.values(manifest.models).map((m) => m.model));
|
|
48693
|
-
const statusCache = JSON.parse(
|
|
50190
|
+
const statusCache = JSON.parse(readFileSync19(statusPath, "utf-8"));
|
|
48694
50191
|
function updateModelStatus(id, update) {
|
|
48695
50192
|
statusCache.models[id] = { ...statusCache.models[id], ...update };
|
|
48696
50193
|
writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
|
|
@@ -48709,8 +50206,8 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
48709
50206
|
process.on("SIGINT", sigintHandler);
|
|
48710
50207
|
const completionPromises = [];
|
|
48711
50208
|
for (const [anonId, entry] of Object.entries(manifest.models)) {
|
|
48712
|
-
const outputPath =
|
|
48713
|
-
const errorLogPath =
|
|
50209
|
+
const outputPath = join29(sessionPath, `response-${anonId}.md`);
|
|
50210
|
+
const errorLogPath = join29(sessionPath, "errors", `${anonId}.log`);
|
|
48714
50211
|
const spawnModel = spawnPlan.pinned.get(entry.model) ?? entry.model;
|
|
48715
50212
|
const args = ["--model", spawnModel, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
|
|
48716
50213
|
updateModelStatus(anonId, {
|
|
@@ -48859,14 +50356,14 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
48859
50356
|
const rt = runtimes.get(id);
|
|
48860
50357
|
const stderr = rt?.getStderr() ?? "";
|
|
48861
50358
|
const stdoutTail = rt?.getStdoutTail() ?? "";
|
|
48862
|
-
const
|
|
48863
|
-
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".`;
|
|
48864
50361
|
if (rt)
|
|
48865
50362
|
persistErrorLog(rt.errorLogPath, `TIMEOUT: ${detail}`, stderr, stdoutTail);
|
|
48866
50363
|
updateModelStatus(id, {
|
|
48867
50364
|
state: "TIMEOUT",
|
|
48868
50365
|
completedAt: new Date().toISOString(),
|
|
48869
|
-
outputSize:
|
|
50366
|
+
outputSize: bytes2,
|
|
48870
50367
|
error: rt ? {
|
|
48871
50368
|
model: id,
|
|
48872
50369
|
command: rt.command,
|
|
@@ -48900,23 +50397,23 @@ async function judgeResponses(sessionPath, opts = {}) {
|
|
|
48900
50397
|
const responses = {};
|
|
48901
50398
|
for (const file2 of responseFiles) {
|
|
48902
50399
|
const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
48903
|
-
responses[id] =
|
|
50400
|
+
responses[id] = readFileSync19(join29(sessionPath, file2), "utf-8");
|
|
48904
50401
|
}
|
|
48905
|
-
const input =
|
|
50402
|
+
const input = readFileSync19(join29(sessionPath, "input.md"), "utf-8");
|
|
48906
50403
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
48907
|
-
writeFileSync12(
|
|
50404
|
+
writeFileSync12(join29(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
48908
50405
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
48909
|
-
const judgePath =
|
|
50406
|
+
const judgePath = join29(sessionPath, "judging");
|
|
48910
50407
|
mkdirSync12(judgePath, { recursive: true });
|
|
48911
50408
|
setupSession(judgePath, judgeModels, judgePrompt);
|
|
48912
50409
|
await runModels(judgePath, { claudeFlags: opts.claudeFlags });
|
|
48913
50410
|
const votes = parseJudgeVotes(judgePath, Object.keys(responses));
|
|
48914
50411
|
const verdict = aggregateVerdict(votes, Object.keys(responses));
|
|
48915
|
-
writeFileSync12(
|
|
50412
|
+
writeFileSync12(join29(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
|
|
48916
50413
|
return verdict;
|
|
48917
50414
|
}
|
|
48918
50415
|
function getStatus(sessionPath) {
|
|
48919
|
-
return JSON.parse(
|
|
50416
|
+
return JSON.parse(readFileSync19(join29(sessionPath, "status.json"), "utf-8"));
|
|
48920
50417
|
}
|
|
48921
50418
|
function fisherYatesShuffle(arr) {
|
|
48922
50419
|
for (let i = arr.length - 1;i > 0; i--) {
|
|
@@ -48926,7 +50423,7 @@ function fisherYatesShuffle(arr) {
|
|
|
48926
50423
|
return arr;
|
|
48927
50424
|
}
|
|
48928
50425
|
function getDefaultJudgeModels(sessionPath) {
|
|
48929
|
-
const manifest = JSON.parse(
|
|
50426
|
+
const manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
48930
50427
|
return Object.values(manifest.models).map((e) => e.model);
|
|
48931
50428
|
}
|
|
48932
50429
|
function buildJudgePrompt(input, responses) {
|
|
@@ -48989,7 +50486,7 @@ function parseJudgeVotes(judgePath, responseIds) {
|
|
|
48989
50486
|
const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
|
|
48990
50487
|
let content;
|
|
48991
50488
|
try {
|
|
48992
|
-
content =
|
|
50489
|
+
content = readFileSync19(join29(judgePath, file2), "utf-8");
|
|
48993
50490
|
} catch {
|
|
48994
50491
|
continue;
|
|
48995
50492
|
}
|
|
@@ -49041,7 +50538,7 @@ function aggregateVerdict(votes, responseIds) {
|
|
|
49041
50538
|
function formatVerdict(verdict, sessionPath) {
|
|
49042
50539
|
let manifest = null;
|
|
49043
50540
|
try {
|
|
49044
|
-
manifest = JSON.parse(
|
|
50541
|
+
manifest = JSON.parse(readFileSync19(join29(sessionPath, "manifest.json"), "utf-8"));
|
|
49045
50542
|
} catch {}
|
|
49046
50543
|
let output = `# Team Verdict
|
|
49047
50544
|
|
|
@@ -49096,14 +50593,14 @@ __export(exports_mcp_server, {
|
|
|
49096
50593
|
parseAnthropicSse: () => parseAnthropicSse,
|
|
49097
50594
|
formatTeamResult: () => formatTeamResult
|
|
49098
50595
|
});
|
|
49099
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as
|
|
49100
|
-
import { homedir as
|
|
49101
|
-
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";
|
|
49102
50599
|
import { fileURLToPath } from "url";
|
|
49103
50600
|
async function loadAllModels(forceRefresh = false) {
|
|
49104
50601
|
if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH2)) {
|
|
49105
50602
|
try {
|
|
49106
|
-
const cacheData = JSON.parse(
|
|
50603
|
+
const cacheData = JSON.parse(readFileSync20(ALL_MODELS_CACHE_PATH2, "utf-8"));
|
|
49107
50604
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
49108
50605
|
const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
|
|
49109
50606
|
if (ageInDays <= CACHE_MAX_AGE_DAYS) {
|
|
@@ -49122,7 +50619,7 @@ async function loadAllModels(forceRefresh = false) {
|
|
|
49122
50619
|
return models;
|
|
49123
50620
|
} catch {
|
|
49124
50621
|
if (existsSync21(ALL_MODELS_CACHE_PATH2)) {
|
|
49125
|
-
const cacheData = JSON.parse(
|
|
50622
|
+
const cacheData = JSON.parse(readFileSync20(ALL_MODELS_CACHE_PATH2, "utf-8"));
|
|
49126
50623
|
return cacheData.models || [];
|
|
49127
50624
|
}
|
|
49128
50625
|
return [];
|
|
@@ -49704,7 +51201,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
|
|
|
49704
51201
|
let stderrFull = stderr_snippet || "";
|
|
49705
51202
|
if (error_log_path) {
|
|
49706
51203
|
try {
|
|
49707
|
-
stderrFull =
|
|
51204
|
+
stderrFull = readFileSync20(error_log_path, "utf-8");
|
|
49708
51205
|
} catch {}
|
|
49709
51206
|
}
|
|
49710
51207
|
const sessionData = {};
|
|
@@ -49712,16 +51209,16 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
|
|
|
49712
51209
|
const sp = session_path;
|
|
49713
51210
|
for (const file2 of ["status.json", "manifest.json", "input.md"]) {
|
|
49714
51211
|
try {
|
|
49715
|
-
sessionData[file2] =
|
|
51212
|
+
sessionData[file2] = readFileSync20(join30(sp, file2), "utf-8");
|
|
49716
51213
|
} catch {}
|
|
49717
51214
|
}
|
|
49718
51215
|
try {
|
|
49719
|
-
const errorDir =
|
|
51216
|
+
const errorDir = join30(sp, "errors");
|
|
49720
51217
|
if (existsSync21(errorDir)) {
|
|
49721
51218
|
for (const f of readdirSync4(errorDir)) {
|
|
49722
51219
|
if (f.endsWith(".log")) {
|
|
49723
51220
|
try {
|
|
49724
|
-
sessionData[`errors/${f}`] =
|
|
51221
|
+
sessionData[`errors/${f}`] = readFileSync20(join30(errorDir, f), "utf-8");
|
|
49725
51222
|
} catch {}
|
|
49726
51223
|
}
|
|
49727
51224
|
}
|
|
@@ -49731,7 +51228,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
|
|
|
49731
51228
|
for (const f of readdirSync4(sp)) {
|
|
49732
51229
|
if (f.startsWith("response-") && f.endsWith(".md")) {
|
|
49733
51230
|
try {
|
|
49734
|
-
const content =
|
|
51231
|
+
const content = readFileSync20(join30(sp, f), "utf-8");
|
|
49735
51232
|
sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
|
|
49736
51233
|
} catch {}
|
|
49737
51234
|
}
|
|
@@ -49740,9 +51237,9 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
|
|
|
49740
51237
|
}
|
|
49741
51238
|
let version2 = "unknown";
|
|
49742
51239
|
try {
|
|
49743
|
-
const pkgPath =
|
|
51240
|
+
const pkgPath = join30(__dirname2, "../package.json");
|
|
49744
51241
|
if (existsSync21(pkgPath)) {
|
|
49745
|
-
version2 = JSON.parse(
|
|
51242
|
+
version2 = JSON.parse(readFileSync20(pkgPath, "utf-8")).version;
|
|
49746
51243
|
}
|
|
49747
51244
|
} catch {}
|
|
49748
51245
|
const report = {
|
|
@@ -50146,8 +51643,8 @@ var init_mcp_server = __esm(() => {
|
|
|
50146
51643
|
import_dotenv2.config({ quiet: true });
|
|
50147
51644
|
__filename2 = fileURLToPath(import.meta.url);
|
|
50148
51645
|
__dirname2 = dirname9(__filename2);
|
|
50149
|
-
CLAUDISH_CACHE_DIR =
|
|
50150
|
-
ALL_MODELS_CACHE_PATH2 =
|
|
51646
|
+
CLAUDISH_CACHE_DIR = join30(homedir28(), ".claudish");
|
|
51647
|
+
ALL_MODELS_CACHE_PATH2 = join30(CLAUDISH_CACHE_DIR, "all-models.json");
|
|
50151
51648
|
NEXT_STEP = {
|
|
50152
51649
|
nonzero_exit: "read the evidence log, then retry or drop the model",
|
|
50153
51650
|
timeout: "raise `timeout`, or pick a faster model",
|
|
@@ -50172,7 +51669,7 @@ var exports_serve_command = {};
|
|
|
50172
51669
|
__export(exports_serve_command, {
|
|
50173
51670
|
serveCommand: () => serveCommand
|
|
50174
51671
|
});
|
|
50175
|
-
import { existsSync as existsSync22, readFileSync as
|
|
51672
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21 } from "fs";
|
|
50176
51673
|
function parseServeArgs(args) {
|
|
50177
51674
|
const out = {};
|
|
50178
51675
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -50196,7 +51693,7 @@ function loadModelMap(path) {
|
|
|
50196
51693
|
}
|
|
50197
51694
|
let raw2;
|
|
50198
51695
|
try {
|
|
50199
|
-
raw2 =
|
|
51696
|
+
raw2 = readFileSync21(path, "utf-8");
|
|
50200
51697
|
} catch (e) {
|
|
50201
51698
|
throw new Error(`failed to read --models file ${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
50202
51699
|
}
|
|
@@ -50273,7 +51770,7 @@ var exports_behavior_command = {};
|
|
|
50273
51770
|
__export(exports_behavior_command, {
|
|
50274
51771
|
behaviorCommand: () => behaviorCommand
|
|
50275
51772
|
});
|
|
50276
|
-
import { existsSync as existsSync23, readFileSync as
|
|
51773
|
+
import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "fs";
|
|
50277
51774
|
function severityColor(sev) {
|
|
50278
51775
|
if (sev === "fix")
|
|
50279
51776
|
return green(sev);
|
|
@@ -50372,7 +51869,7 @@ function setTelemetryEnabled(value) {
|
|
|
50372
51869
|
let cfg = {};
|
|
50373
51870
|
try {
|
|
50374
51871
|
if (existsSync23(path)) {
|
|
50375
|
-
const parsed = JSON.parse(
|
|
51872
|
+
const parsed = JSON.parse(readFileSync22(path, "utf-8"));
|
|
50376
51873
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
50377
51874
|
cfg = parsed;
|
|
50378
51875
|
}
|
|
@@ -50394,7 +51891,7 @@ function showTelemetry(action, json2) {
|
|
|
50394
51891
|
try {
|
|
50395
51892
|
const path = outboxPath();
|
|
50396
51893
|
if (existsSync23(path)) {
|
|
50397
|
-
pending =
|
|
51894
|
+
pending = readFileSync22(path, "utf8").split(`
|
|
50398
51895
|
`).filter(Boolean).length;
|
|
50399
51896
|
}
|
|
50400
51897
|
} catch {}
|
|
@@ -50467,6 +51964,12 @@ function describeSourceSync(p, config3) {
|
|
|
50467
51964
|
return "oauth";
|
|
50468
51965
|
if (p.catalogName === "antigravity" && hasSharedAntigravityToken())
|
|
50469
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
|
+
}
|
|
50470
51973
|
const hasCfg = !!p.apiKeyEnvVar && !!realValue(config3.apiKeys?.[p.apiKeyEnvVar]);
|
|
50471
51974
|
const hasEnv = !!p.apiKeyEnvVar && !!realValue(process.env[p.apiKeyEnvVar]);
|
|
50472
51975
|
if (hasEnv && hasCfg)
|
|
@@ -50487,6 +51990,7 @@ async function describeSource(p, config3) {
|
|
|
50487
51990
|
}
|
|
50488
51991
|
var init_source = __esm(() => {
|
|
50489
51992
|
init_profile_config();
|
|
51993
|
+
init_devin_credentials();
|
|
50490
51994
|
init_antigravity_token();
|
|
50491
51995
|
init_oauth_registry();
|
|
50492
51996
|
init_api_key_credential();
|
|
@@ -50534,8 +52038,8 @@ function providerIsReadyForDisplay(p, config3, localLiveness) {
|
|
|
50534
52038
|
function providerAuthCapabilities(p, config3) {
|
|
50535
52039
|
const apiKeySupported = !!p.apiKeyEnvVar;
|
|
50536
52040
|
const apiKeySet = apiKeySupported && (!!process.env[p.apiKeyEnvVar] || !!config3.apiKeys?.[p.apiKeyEnvVar]);
|
|
50537
|
-
const oauthSupported = !!p.oauthSlug;
|
|
50538
|
-
const oauthSet = oauthSupported && (hasOAuthCredentials(p.catalogName) || p.catalogName === "antigravity" && hasSharedAntigravityToken());
|
|
52041
|
+
const oauthSupported = !!p.oauthSlug || p.catalogName === "devin";
|
|
52042
|
+
const oauthSet = oauthSupported && (hasOAuthCredentials(p.catalogName) || p.catalogName === "antigravity" && hasSharedAntigravityToken() || p.catalogName === "devin" && hasDevinCredentials());
|
|
50539
52043
|
return {
|
|
50540
52044
|
apiKey: { supported: apiKeySupported, set: apiKeySet },
|
|
50541
52045
|
oauth: { supported: oauthSupported, set: oauthSet }
|
|
@@ -50553,6 +52057,7 @@ var init_providers = __esm(() => {
|
|
|
50553
52057
|
init_antigravity_token();
|
|
50554
52058
|
init_source();
|
|
50555
52059
|
init_oauth_registry();
|
|
52060
|
+
init_devin_credentials();
|
|
50556
52061
|
init_provider_definitions();
|
|
50557
52062
|
SKIP = new Set(["qwen", "native-anthropic"]);
|
|
50558
52063
|
PROVIDERS = getAllProviders().filter((d) => !SKIP.has(d.name)).map(toProviderDef);
|
|
@@ -59801,18 +61306,18 @@ var require_dbcs_codec = __commonJS((exports) => {
|
|
|
59801
61306
|
DBCSCodec.prototype.encoder = DBCSEncoder;
|
|
59802
61307
|
DBCSCodec.prototype.decoder = DBCSDecoder;
|
|
59803
61308
|
DBCSCodec.prototype._getDecodeTrieNode = function(addr) {
|
|
59804
|
-
var
|
|
61309
|
+
var bytes2 = [];
|
|
59805
61310
|
for (;addr > 0; addr >>>= 8) {
|
|
59806
|
-
|
|
61311
|
+
bytes2.push(addr & 255);
|
|
59807
61312
|
}
|
|
59808
|
-
if (
|
|
59809
|
-
|
|
61313
|
+
if (bytes2.length == 0) {
|
|
61314
|
+
bytes2.push(0);
|
|
59810
61315
|
}
|
|
59811
61316
|
var node = this.decodeTables[0];
|
|
59812
|
-
for (var i2 =
|
|
59813
|
-
var val = node[
|
|
61317
|
+
for (var i2 = bytes2.length - 1;i2 > 0; i2--) {
|
|
61318
|
+
var val = node[bytes2[i2]];
|
|
59814
61319
|
if (val == UNASSIGNED) {
|
|
59815
|
-
node[
|
|
61320
|
+
node[bytes2[i2]] = NODE_START - this.decodeTables.length;
|
|
59816
61321
|
this.decodeTables.push(node = UNASSIGNED_NODE.slice(0));
|
|
59817
61322
|
} else if (val <= NODE_START) {
|
|
59818
61323
|
node = this.decodeTables[NODE_START - val];
|
|
@@ -61863,10 +63368,10 @@ var init_RemoveFileError = __esm(() => {
|
|
|
61863
63368
|
|
|
61864
63369
|
// ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
|
|
61865
63370
|
import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
|
|
61866
|
-
import { readFileSync as
|
|
63371
|
+
import { readFileSync as readFileSync23, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
|
|
61867
63372
|
import path from "path";
|
|
61868
63373
|
import os from "os";
|
|
61869
|
-
import { randomUUID as
|
|
63374
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
61870
63375
|
function editAsync(text = "", callback, fileOptions) {
|
|
61871
63376
|
const editor = new ExternalEditor(text, fileOptions);
|
|
61872
63377
|
editor.runAsync((err, result) => {
|
|
@@ -61958,7 +63463,7 @@ class ExternalEditor {
|
|
|
61958
63463
|
createTemporaryFile() {
|
|
61959
63464
|
try {
|
|
61960
63465
|
const baseDir = this.fileOptions.dir ?? os.tmpdir();
|
|
61961
|
-
const id =
|
|
63466
|
+
const id = randomUUID7();
|
|
61962
63467
|
const prefix = sanitizeAffix(this.fileOptions.prefix);
|
|
61963
63468
|
const postfix = sanitizeAffix(this.fileOptions.postfix);
|
|
61964
63469
|
const filename = `${prefix}${id}${postfix}`;
|
|
@@ -61979,7 +63484,7 @@ class ExternalEditor {
|
|
|
61979
63484
|
}
|
|
61980
63485
|
readTemporaryFile() {
|
|
61981
63486
|
try {
|
|
61982
|
-
const tempFileBuffer =
|
|
63487
|
+
const tempFileBuffer = readFileSync23(this.tempFile);
|
|
61983
63488
|
if (tempFileBuffer.length === 0) {
|
|
61984
63489
|
this.text = "";
|
|
61985
63490
|
} else {
|
|
@@ -62961,8 +64466,8 @@ var init_dist16 = __esm(() => {
|
|
|
62961
64466
|
// src/auth/antigravity-oauth.ts
|
|
62962
64467
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
62963
64468
|
import { existsSync as existsSync24, unlinkSync as unlinkSync7 } from "fs";
|
|
62964
|
-
import { homedir as
|
|
62965
|
-
import { join as
|
|
64469
|
+
import { homedir as homedir29 } from "os";
|
|
64470
|
+
import { join as join31 } from "path";
|
|
62966
64471
|
async function defaultSuggestModel() {
|
|
62967
64472
|
try {
|
|
62968
64473
|
const tok = readSharedAntigravityToken();
|
|
@@ -63083,7 +64588,7 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
|
|
|
63083
64588
|
async logout(deps) {
|
|
63084
64589
|
deleteSharedAntigravityToken(deps);
|
|
63085
64590
|
try {
|
|
63086
|
-
const tokenFile =
|
|
64591
|
+
const tokenFile = join31(homedir29(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
|
|
63087
64592
|
if (existsSync24(tokenFile))
|
|
63088
64593
|
unlinkSync7(tokenFile);
|
|
63089
64594
|
} catch {}
|
|
@@ -64535,11 +66040,11 @@ async function probeLink(proxyUrl, link, timeoutMs) {
|
|
|
64535
66040
|
} catch (e) {
|
|
64536
66041
|
const latencyMs = Date.now() - startedAt;
|
|
64537
66042
|
const name = e?.name || "";
|
|
64538
|
-
const
|
|
64539
|
-
if (name === "TimeoutError" || name === "AbortError" || /timeout/i.test(
|
|
64540
|
-
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 };
|
|
64541
66046
|
}
|
|
64542
|
-
return { state: "network-error", latencyMs, errorMessage:
|
|
66047
|
+
return { state: "network-error", latencyMs, errorMessage: msg2 };
|
|
64543
66048
|
}
|
|
64544
66049
|
const ttfbMs = Date.now() - startedAt;
|
|
64545
66050
|
if (!response.ok) {
|
|
@@ -64568,7 +66073,7 @@ function annotateOAuthHint(result, provider, isOAuth) {
|
|
|
64568
66073
|
return result;
|
|
64569
66074
|
if (result.state === "live")
|
|
64570
66075
|
return result;
|
|
64571
|
-
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;
|
|
64572
66077
|
if (!loginCommand2)
|
|
64573
66078
|
return result;
|
|
64574
66079
|
if (result.httpStatus === 403)
|
|
@@ -64676,9 +66181,9 @@ function extractErrorMessage(body) {
|
|
|
64676
66181
|
return;
|
|
64677
66182
|
try {
|
|
64678
66183
|
const parsed = JSON.parse(body);
|
|
64679
|
-
const
|
|
64680
|
-
if (typeof
|
|
64681
|
-
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;
|
|
64682
66187
|
}
|
|
64683
66188
|
} catch {}
|
|
64684
66189
|
const trimmed2 = body.trim();
|
|
@@ -64894,7 +66399,7 @@ function isFailureState(state) {
|
|
|
64894
66399
|
}
|
|
64895
66400
|
var STREAM_MS_FLOOR = 50, OAUTH_PROVIDERS2, PROBE_PROMPT = "Count from one to twenty in words, one per line.", PROBE_MAX_TOKENS = 512;
|
|
64896
66401
|
var init_probe_live = __esm(() => {
|
|
64897
|
-
OAUTH_PROVIDERS2 = new Set(["vertex", "gemini-codeassist"]);
|
|
66402
|
+
OAUTH_PROVIDERS2 = new Set(["vertex", "gemini-codeassist", "devin"]);
|
|
64898
66403
|
});
|
|
64899
66404
|
|
|
64900
66405
|
// src/tui/theme.ts
|
|
@@ -67172,19 +68677,19 @@ import {
|
|
|
67172
68677
|
copyFileSync as copyFileSync2,
|
|
67173
68678
|
existsSync as existsSync25,
|
|
67174
68679
|
mkdirSync as mkdirSync14,
|
|
67175
|
-
readFileSync as
|
|
68680
|
+
readFileSync as readFileSync24,
|
|
67176
68681
|
readdirSync as readdirSync5,
|
|
67177
68682
|
unlinkSync as unlinkSync8,
|
|
67178
68683
|
writeFileSync as writeFileSync16
|
|
67179
68684
|
} from "fs";
|
|
67180
|
-
import { homedir as
|
|
67181
|
-
import { dirname as dirname10, join as
|
|
68685
|
+
import { homedir as homedir30 } from "os";
|
|
68686
|
+
import { dirname as dirname10, join as join32 } from "path";
|
|
67182
68687
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
67183
68688
|
function getVersion3() {
|
|
67184
68689
|
return VERSION;
|
|
67185
68690
|
}
|
|
67186
68691
|
function clearAllModelCaches() {
|
|
67187
|
-
const cacheDir =
|
|
68692
|
+
const cacheDir = join32(homedir30(), ".claudish");
|
|
67188
68693
|
if (!existsSync25(cacheDir))
|
|
67189
68694
|
return;
|
|
67190
68695
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
|
|
@@ -67193,7 +68698,7 @@ function clearAllModelCaches() {
|
|
|
67193
68698
|
const files = readdirSync5(cacheDir);
|
|
67194
68699
|
for (const file2 of files) {
|
|
67195
68700
|
if (cachePatterns.includes(file2)) {
|
|
67196
|
-
unlinkSync8(
|
|
68701
|
+
unlinkSync8(join32(cacheDir, file2));
|
|
67197
68702
|
cleared++;
|
|
67198
68703
|
}
|
|
67199
68704
|
}
|
|
@@ -67603,7 +69108,7 @@ Usage: claudish --models --provider <slug>`);
|
|
|
67603
69108
|
});
|
|
67604
69109
|
config3.resolvedDefaultProvider = resolved;
|
|
67605
69110
|
if (resolved.legacyAutoPromoted && !config3.quiet) {
|
|
67606
|
-
const markerFile =
|
|
69111
|
+
const markerFile = join32(homedir30(), ".claudish", ".legacy-litellm-hint-shown");
|
|
67607
69112
|
if (!existsSync25(markerFile)) {
|
|
67608
69113
|
const hint = buildLegacyHint(resolved);
|
|
67609
69114
|
if (hint) {
|
|
@@ -68074,6 +69579,9 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
68074
69579
|
} else if (providerName === "litellm") {
|
|
68075
69580
|
formatAdapterName = "LiteLLMAPIFormat";
|
|
68076
69581
|
declaredStreamFormat = "openai-sse";
|
|
69582
|
+
} else if (providerName === "devin") {
|
|
69583
|
+
formatAdapterName = "DevinAPIFormat";
|
|
69584
|
+
declaredStreamFormat = "connect-proto";
|
|
68077
69585
|
} else {
|
|
68078
69586
|
formatAdapterName = "OpenAIAPIFormat";
|
|
68079
69587
|
declaredStreamFormat = "openai-sse";
|
|
@@ -68112,8 +69620,8 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
68112
69620
|
console.error(`${DIM}Probing providers via live requests (may incur small cost, use --no-probe to skip)...${RESET}`);
|
|
68113
69621
|
liveProxy2 = await createProxyServer2(probePort, process.env.OPENROUTER_API_KEY, undefined, false, process.env.ANTHROPIC_API_KEY, undefined, { quiet: true });
|
|
68114
69622
|
} catch (e) {
|
|
68115
|
-
const
|
|
68116
|
-
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}`);
|
|
68117
69625
|
liveProxy2 = null;
|
|
68118
69626
|
}
|
|
68119
69627
|
}
|
|
@@ -68678,8 +70186,8 @@ ${h("MORE INFO")}
|
|
|
68678
70186
|
}
|
|
68679
70187
|
function printAIAgentGuide() {
|
|
68680
70188
|
try {
|
|
68681
|
-
const guidePath =
|
|
68682
|
-
const guideContent =
|
|
70189
|
+
const guidePath = join32(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
70190
|
+
const guideContent = readFileSync24(guidePath, "utf-8");
|
|
68683
70191
|
console.log(guideContent);
|
|
68684
70192
|
} catch (error46) {
|
|
68685
70193
|
console.error("Error reading AI Agent Guide:");
|
|
@@ -68695,10 +70203,10 @@ async function initializeClaudishSkill() {
|
|
|
68695
70203
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
68696
70204
|
`);
|
|
68697
70205
|
const cwd = process.cwd();
|
|
68698
|
-
const claudeDir =
|
|
68699
|
-
const skillsDir =
|
|
68700
|
-
const claudishSkillDir =
|
|
68701
|
-
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");
|
|
68702
70210
|
if (existsSync25(skillFile)) {
|
|
68703
70211
|
console.log("\u2705 Claudish skill already installed at:");
|
|
68704
70212
|
console.log(` ${skillFile}
|
|
@@ -68706,7 +70214,7 @@ async function initializeClaudishSkill() {
|
|
|
68706
70214
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
68707
70215
|
return;
|
|
68708
70216
|
}
|
|
68709
|
-
const sourceSkillPath =
|
|
70217
|
+
const sourceSkillPath = join32(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
68710
70218
|
if (!existsSync25(sourceSkillPath)) {
|
|
68711
70219
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
68712
70220
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
@@ -68809,24 +70317,24 @@ __export(exports_update_checker, {
|
|
|
68809
70317
|
clearCache: () => clearCache,
|
|
68810
70318
|
checkForUpdates: () => checkForUpdates
|
|
68811
70319
|
});
|
|
68812
|
-
import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as
|
|
68813
|
-
import { homedir as
|
|
68814
|
-
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";
|
|
68815
70323
|
function getCacheFilePath() {
|
|
68816
70324
|
let cacheDir;
|
|
68817
70325
|
if (isWindows) {
|
|
68818
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
68819
|
-
cacheDir =
|
|
70326
|
+
const localAppData = process.env.LOCALAPPDATA || join33(homedir31(), "AppData", "Local");
|
|
70327
|
+
cacheDir = join33(localAppData, "claudish");
|
|
68820
70328
|
} else {
|
|
68821
|
-
cacheDir =
|
|
70329
|
+
cacheDir = join33(homedir31(), ".cache", "claudish");
|
|
68822
70330
|
}
|
|
68823
70331
|
try {
|
|
68824
70332
|
if (!existsSync26(cacheDir)) {
|
|
68825
70333
|
mkdirSync15(cacheDir, { recursive: true });
|
|
68826
70334
|
}
|
|
68827
|
-
return
|
|
70335
|
+
return join33(cacheDir, "update-check.json");
|
|
68828
70336
|
} catch {
|
|
68829
|
-
return
|
|
70337
|
+
return join33(tmpdir(), "claudish-update-check.json");
|
|
68830
70338
|
}
|
|
68831
70339
|
}
|
|
68832
70340
|
function readCache() {
|
|
@@ -68835,7 +70343,7 @@ function readCache() {
|
|
|
68835
70343
|
if (!existsSync26(cachePath)) {
|
|
68836
70344
|
return null;
|
|
68837
70345
|
}
|
|
68838
|
-
const data = JSON.parse(
|
|
70346
|
+
const data = JSON.parse(readFileSync25(cachePath, "utf-8"));
|
|
68839
70347
|
return data;
|
|
68840
70348
|
} catch {
|
|
68841
70349
|
return null;
|
|
@@ -69743,15 +71251,15 @@ var init_local_liveness = __esm(() => {
|
|
|
69743
71251
|
});
|
|
69744
71252
|
|
|
69745
71253
|
// src/providers/probe-catalog.ts
|
|
69746
|
-
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as
|
|
69747
|
-
import { homedir as
|
|
69748
|
-
import { dirname as dirname11, join as
|
|
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";
|
|
69749
71257
|
function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
69750
71258
|
if (!existsSync27(path2))
|
|
69751
71259
|
return null;
|
|
69752
71260
|
let raw2;
|
|
69753
71261
|
try {
|
|
69754
|
-
raw2 = JSON.parse(
|
|
71262
|
+
raw2 = JSON.parse(readFileSync26(path2, "utf-8"));
|
|
69755
71263
|
} catch {
|
|
69756
71264
|
return null;
|
|
69757
71265
|
}
|
|
@@ -69880,7 +71388,7 @@ function isValidResponse(raw2) {
|
|
|
69880
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;
|
|
69881
71389
|
var init_probe_catalog = __esm(() => {
|
|
69882
71390
|
CACHE_TTL_MS4 = 60 * 60 * 1000;
|
|
69883
|
-
PROBE_MODELS_CACHE_PATH =
|
|
71391
|
+
PROBE_MODELS_CACHE_PATH = join34(homedir32(), ".claudish", "probe-models.json");
|
|
69884
71392
|
});
|
|
69885
71393
|
|
|
69886
71394
|
// src/tui/constants.ts
|
|
@@ -74327,8 +75835,8 @@ function useRouteProbe(config3) {
|
|
|
74327
75835
|
try {
|
|
74328
75836
|
proxyUrl = await ensureProbeProxy();
|
|
74329
75837
|
} catch (err) {
|
|
74330
|
-
const
|
|
74331
|
-
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}` })));
|
|
74332
75840
|
setProbeMode("done");
|
|
74333
75841
|
return;
|
|
74334
75842
|
}
|
|
@@ -74682,12 +76190,12 @@ function App({ requestLogin } = {}) {
|
|
|
74682
76190
|
}));
|
|
74683
76191
|
setStatusMsg(`1Password test ok \u2192 ${note}`);
|
|
74684
76192
|
} catch (err) {
|
|
74685
|
-
const
|
|
76193
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74686
76194
|
setOpTestResults((prev) => ({
|
|
74687
76195
|
...prev,
|
|
74688
|
-
[key]: { status: "failed", error:
|
|
76196
|
+
[key]: { status: "failed", error: msg2 }
|
|
74689
76197
|
}));
|
|
74690
|
-
setStatusMsg(
|
|
76198
|
+
setStatusMsg(msg2);
|
|
74691
76199
|
} finally {
|
|
74692
76200
|
setOpBusy(false);
|
|
74693
76201
|
}
|
|
@@ -74762,14 +76270,14 @@ function App({ requestLogin } = {}) {
|
|
|
74762
76270
|
invalidateProbeProxyHandlers();
|
|
74763
76271
|
refreshConfig();
|
|
74764
76272
|
} catch (testErr) {
|
|
74765
|
-
const
|
|
74766
|
-
console.error(`[claudish] 1Password add: saved but live resolve failed: ${
|
|
74767
|
-
setStatusMsg(`1Password ${kindWord} saved (${scope}) \u2014 live resolve failed: ${
|
|
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}`);
|
|
74768
76276
|
}
|
|
74769
76277
|
} catch (err) {
|
|
74770
|
-
const
|
|
74771
|
-
console.error(`[claudish] 1Password add failed to persist: ${
|
|
74772
|
-
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}`);
|
|
74773
76281
|
setMode("browse");
|
|
74774
76282
|
resetOpWizard();
|
|
74775
76283
|
} finally {
|
|
@@ -74789,8 +76297,8 @@ function App({ requestLogin } = {}) {
|
|
|
74789
76297
|
setOpVaults(vaults);
|
|
74790
76298
|
setStatusMsg(`1Password: ${vaults.length} vault${vaults.length === 1 ? "" : "s"}.`);
|
|
74791
76299
|
} catch (err) {
|
|
74792
|
-
const
|
|
74793
|
-
setStatusMsg(
|
|
76300
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
76301
|
+
setStatusMsg(msg2);
|
|
74794
76302
|
setMode("browse");
|
|
74795
76303
|
} finally {
|
|
74796
76304
|
setOpBusy(false);
|
|
@@ -74811,8 +76319,8 @@ function App({ requestLogin } = {}) {
|
|
|
74811
76319
|
setOpItems(items);
|
|
74812
76320
|
setStatusMsg(`1Password: ${items.length} item${items.length === 1 ? "" : "s"}.`);
|
|
74813
76321
|
} catch (err) {
|
|
74814
|
-
const
|
|
74815
|
-
setStatusMsg(
|
|
76322
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
76323
|
+
setStatusMsg(msg2);
|
|
74816
76324
|
setMode("browse");
|
|
74817
76325
|
} finally {
|
|
74818
76326
|
setOpBusy(false);
|
|
@@ -74840,8 +76348,8 @@ function App({ requestLogin } = {}) {
|
|
|
74840
76348
|
setOpFields(fields);
|
|
74841
76349
|
setStatusMsg(`1Password: ${fields.length} field${fields.length === 1 ? "" : "s"}.`);
|
|
74842
76350
|
} catch (err) {
|
|
74843
|
-
const
|
|
74844
|
-
setStatusMsg(
|
|
76351
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
76352
|
+
setStatusMsg(msg2);
|
|
74845
76353
|
setMode("browse");
|
|
74846
76354
|
} finally {
|
|
74847
76355
|
setOpBusy(false);
|
|
@@ -74857,9 +76365,9 @@ function App({ requestLogin } = {}) {
|
|
|
74857
76365
|
setOpEnvPreview(names);
|
|
74858
76366
|
setStatusMsg(`1Password environment \u2192 ${names.length} var${names.length === 1 ? "" : "s"}. Enter to save.`);
|
|
74859
76367
|
} catch (err) {
|
|
74860
|
-
const
|
|
76368
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74861
76369
|
setOpEnvPreview(null);
|
|
74862
|
-
setStatusMsg(
|
|
76370
|
+
setStatusMsg(msg2);
|
|
74863
76371
|
} finally {
|
|
74864
76372
|
setOpBusy(false);
|
|
74865
76373
|
}
|
|
@@ -74967,10 +76475,10 @@ function App({ requestLogin } = {}) {
|
|
|
74967
76475
|
}
|
|
74968
76476
|
} catch (err) {
|
|
74969
76477
|
const ms = Date.now() - startMs;
|
|
74970
|
-
const
|
|
76478
|
+
const msg2 = err instanceof Error ? err.message : String(err);
|
|
74971
76479
|
setTestResults((prev) => ({
|
|
74972
76480
|
...prev,
|
|
74973
|
-
[provName]: { status: "failed", error: `proxy: ${
|
|
76481
|
+
[provName]: { status: "failed", error: `proxy: ${msg2}`, ms }
|
|
74974
76482
|
}));
|
|
74975
76483
|
}
|
|
74976
76484
|
}, []);
|
|
@@ -76237,14 +77745,14 @@ import {
|
|
|
76237
77745
|
existsSync as existsSync28,
|
|
76238
77746
|
mkdirSync as mkdirSync17,
|
|
76239
77747
|
openSync as openSync5,
|
|
76240
|
-
readFileSync as
|
|
77748
|
+
readFileSync as readFileSync27,
|
|
76241
77749
|
readdirSync as readdirSync6,
|
|
76242
77750
|
statSync as statSync5,
|
|
76243
77751
|
unlinkSync as unlinkSync10,
|
|
76244
77752
|
writeFileSync as writeFileSync19
|
|
76245
77753
|
} from "fs";
|
|
76246
|
-
import { homedir as
|
|
76247
|
-
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";
|
|
76248
77756
|
import { isatty } from "tty";
|
|
76249
77757
|
function releaseTerminalIsolation() {
|
|
76250
77758
|
if (!restoreTerminal)
|
|
@@ -76279,14 +77787,14 @@ function isProxyAuthMode(config3) {
|
|
|
76279
77787
|
}
|
|
76280
77788
|
function managedSettingsPath() {
|
|
76281
77789
|
if (isWindows2()) {
|
|
76282
|
-
return
|
|
77790
|
+
return join35(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
|
|
76283
77791
|
}
|
|
76284
77792
|
if (process.platform === "darwin") {
|
|
76285
77793
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
76286
77794
|
}
|
|
76287
77795
|
return "/etc/claude-code/managed-settings.json";
|
|
76288
77796
|
}
|
|
76289
|
-
function managedSettingsForcesClaudeAi(readFile3 =
|
|
77797
|
+
function managedSettingsForcesClaudeAi(readFile3 = readFileSync27) {
|
|
76290
77798
|
try {
|
|
76291
77799
|
const raw2 = readFile3(managedSettingsPath(), "utf-8");
|
|
76292
77800
|
const parsed = JSON.parse(raw2);
|
|
@@ -76300,9 +77808,9 @@ function isWindows2() {
|
|
|
76300
77808
|
}
|
|
76301
77809
|
function createStatusLineScript(tokenFilePath) {
|
|
76302
77810
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
76303
|
-
const claudishDir =
|
|
77811
|
+
const claudishDir = join35(homeDir, ".claudish");
|
|
76304
77812
|
const timestamp = Date.now();
|
|
76305
|
-
const scriptPath =
|
|
77813
|
+
const scriptPath = join35(claudishDir, `status-${timestamp}.js`);
|
|
76306
77814
|
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
76307
77815
|
const script = `
|
|
76308
77816
|
const fs = require('fs');
|
|
@@ -76466,7 +77974,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
|
|
|
76466
77974
|
if (!name.startsWith("tokens-") || !name.endsWith(".json"))
|
|
76467
77975
|
continue;
|
|
76468
77976
|
scanned++;
|
|
76469
|
-
const full =
|
|
77977
|
+
const full = join35(dir, name);
|
|
76470
77978
|
try {
|
|
76471
77979
|
if (statSync5(full).mtimeMs >= cutoff)
|
|
76472
77980
|
continue;
|
|
@@ -76483,7 +77991,7 @@ function parseSettingsArg(value) {
|
|
|
76483
77991
|
if (value.trimStart().startsWith("{")) {
|
|
76484
77992
|
return JSON.parse(value);
|
|
76485
77993
|
}
|
|
76486
|
-
return JSON.parse(
|
|
77994
|
+
return JSON.parse(readFileSync27(value, "utf-8"));
|
|
76487
77995
|
}
|
|
76488
77996
|
function parseSettingsArgSafe(value) {
|
|
76489
77997
|
try {
|
|
@@ -76495,9 +78003,9 @@ function parseSettingsArgSafe(value) {
|
|
|
76495
78003
|
}
|
|
76496
78004
|
function userSettingsFileCandidates(cwd) {
|
|
76497
78005
|
return [
|
|
76498
|
-
|
|
76499
|
-
|
|
76500
|
-
|
|
78006
|
+
join35(homedir33(), ".claude", "settings.json"),
|
|
78007
|
+
join35(cwd, ".claude", "settings.json"),
|
|
78008
|
+
join35(cwd, ".claude", "settings.local.json")
|
|
76501
78009
|
];
|
|
76502
78010
|
}
|
|
76503
78011
|
function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
|
|
@@ -76538,13 +78046,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
|
|
|
76538
78046
|
}
|
|
76539
78047
|
function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
|
|
76540
78048
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
76541
|
-
const claudishDir =
|
|
78049
|
+
const claudishDir = join35(homeDir, ".claudish");
|
|
76542
78050
|
try {
|
|
76543
78051
|
mkdirSync17(claudishDir, { recursive: true });
|
|
76544
78052
|
} catch {}
|
|
76545
78053
|
const timestamp = Date.now();
|
|
76546
|
-
const tempPath =
|
|
76547
|
-
const tokenFilePath =
|
|
78054
|
+
const tempPath = join35(claudishDir, `settings-${timestamp}.json`);
|
|
78055
|
+
const tokenFilePath = join35(claudishDir, `tokens-${port}.json`);
|
|
76548
78056
|
cleanupStaleTokenFiles(claudishDir);
|
|
76549
78057
|
initializeTokenFile(tokenFilePath);
|
|
76550
78058
|
let statusCommand;
|
|
@@ -76817,8 +78325,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
76817
78325
|
console.error("Install it from: https://claude.com/claude-code");
|
|
76818
78326
|
console.error(`
|
|
76819
78327
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
76820
|
-
const home =
|
|
76821
|
-
const localPath = isWindows2() ?
|
|
78328
|
+
const home = homedir33();
|
|
78329
|
+
const localPath = isWindows2() ? join35(home, ".claude", "local", "claude.exe") : join35(home, ".claude", "local", "claude");
|
|
76822
78330
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
76823
78331
|
process.exit(1);
|
|
76824
78332
|
}
|
|
@@ -76902,16 +78410,16 @@ async function findClaudeBinary() {
|
|
|
76902
78410
|
return process.env.CLAUDE_PATH;
|
|
76903
78411
|
}
|
|
76904
78412
|
}
|
|
76905
|
-
const home =
|
|
76906
|
-
const localPath = isWindows3 ?
|
|
78413
|
+
const home = homedir33();
|
|
78414
|
+
const localPath = isWindows3 ? join35(home, ".claude", "local", "claude.exe") : join35(home, ".claude", "local", "claude");
|
|
76907
78415
|
if (existsSync28(localPath)) {
|
|
76908
78416
|
return localPath;
|
|
76909
78417
|
}
|
|
76910
78418
|
if (isWindows3) {
|
|
76911
78419
|
const windowsPaths = [
|
|
76912
|
-
|
|
76913
|
-
|
|
76914
|
-
|
|
78420
|
+
join35(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
78421
|
+
join35(home, ".npm-global", "claude.cmd"),
|
|
78422
|
+
join35(home, "node_modules", ".bin", "claude.cmd")
|
|
76915
78423
|
];
|
|
76916
78424
|
for (const path2 of windowsPaths) {
|
|
76917
78425
|
if (existsSync28(path2)) {
|
|
@@ -76922,11 +78430,11 @@ async function findClaudeBinary() {
|
|
|
76922
78430
|
const commonPaths = [
|
|
76923
78431
|
"/usr/local/bin/claude",
|
|
76924
78432
|
"/opt/homebrew/bin/claude",
|
|
76925
|
-
|
|
76926
|
-
|
|
76927
|
-
|
|
78433
|
+
join35(home, ".npm-global/bin/claude"),
|
|
78434
|
+
join35(home, ".local/bin/claude"),
|
|
78435
|
+
join35(home, "node_modules/.bin/claude"),
|
|
76928
78436
|
"/data/data/com.termux/files/usr/bin/claude",
|
|
76929
|
-
|
|
78437
|
+
join35(home, "../usr/bin/claude")
|
|
76930
78438
|
];
|
|
76931
78439
|
for (const path2 of commonPaths) {
|
|
76932
78440
|
if (existsSync28(path2)) {
|
|
@@ -76990,17 +78498,17 @@ __export(exports_diag_output, {
|
|
|
76990
78498
|
LogFileDiagOutput: () => LogFileDiagOutput
|
|
76991
78499
|
});
|
|
76992
78500
|
import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync18, unlinkSync as unlinkSync11, writeFileSync as writeFileSync20 } from "fs";
|
|
76993
|
-
import { homedir as
|
|
76994
|
-
import { join as
|
|
78501
|
+
import { homedir as homedir34 } from "os";
|
|
78502
|
+
import { join as join36 } from "path";
|
|
76995
78503
|
function getClaudishDir() {
|
|
76996
|
-
const dir =
|
|
78504
|
+
const dir = join36(homedir34(), ".claudish");
|
|
76997
78505
|
try {
|
|
76998
78506
|
mkdirSync18(dir, { recursive: true });
|
|
76999
78507
|
} catch {}
|
|
77000
78508
|
return dir;
|
|
77001
78509
|
}
|
|
77002
78510
|
function getDiagLogPath() {
|
|
77003
|
-
return
|
|
78511
|
+
return join36(getClaudishDir(), `diag-${process.pid}.log`);
|
|
77004
78512
|
}
|
|
77005
78513
|
|
|
77006
78514
|
class LogFileDiagOutput {
|
|
@@ -77015,9 +78523,9 @@ class LogFileDiagOutput {
|
|
|
77015
78523
|
this.stream = createWriteStream3(this.logPath, { flags: "a" });
|
|
77016
78524
|
this.stream.on("error", () => {});
|
|
77017
78525
|
}
|
|
77018
|
-
write(
|
|
78526
|
+
write(msg2) {
|
|
77019
78527
|
const timestamp = new Date().toISOString();
|
|
77020
|
-
const line = `[${timestamp}] ${
|
|
78528
|
+
const line = `[${timestamp}] ${msg2}
|
|
77021
78529
|
`;
|
|
77022
78530
|
try {
|
|
77023
78531
|
this.stream.write(line);
|
|
@@ -77211,9 +78719,9 @@ __export(exports_team_grid, {
|
|
|
77211
78719
|
});
|
|
77212
78720
|
import { spawn as spawn5 } from "child_process";
|
|
77213
78721
|
import { execSync as execSync2 } from "child_process";
|
|
77214
|
-
import { existsSync as existsSync29, readFileSync as
|
|
78722
|
+
import { existsSync as existsSync29, readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "fs";
|
|
77215
78723
|
import { connect as netConnect } from "net";
|
|
77216
|
-
import { dirname as dirname13, join as
|
|
78724
|
+
import { dirname as dirname13, join as join37 } from "path";
|
|
77217
78725
|
import { setTimeout as wait } from "timers/promises";
|
|
77218
78726
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
77219
78727
|
function resolveRouteInfo(modelId) {
|
|
@@ -77307,17 +78815,17 @@ function buildPaneHeader(model, prompt, bg) {
|
|
|
77307
78815
|
function findMagmuxBinary() {
|
|
77308
78816
|
const thisFile = fileURLToPath3(import.meta.url);
|
|
77309
78817
|
const thisDir = dirname13(thisFile);
|
|
77310
|
-
const pkgRoot =
|
|
78818
|
+
const pkgRoot = join37(thisDir, "..");
|
|
77311
78819
|
const platform3 = process.platform;
|
|
77312
78820
|
const arch = process.arch;
|
|
77313
|
-
const bundledMagmux =
|
|
78821
|
+
const bundledMagmux = join37(pkgRoot, "native", `magmux-${platform3}-${arch}`);
|
|
77314
78822
|
if (existsSync29(bundledMagmux))
|
|
77315
78823
|
return bundledMagmux;
|
|
77316
78824
|
try {
|
|
77317
78825
|
const pkgName = `@claudish/magmux-${platform3}-${arch}`;
|
|
77318
78826
|
let searchDir = pkgRoot;
|
|
77319
78827
|
for (let i = 0;i < 5; i++) {
|
|
77320
|
-
const candidate =
|
|
78828
|
+
const candidate = join37(searchDir, "node_modules", pkgName, "bin", "magmux");
|
|
77321
78829
|
if (existsSync29(candidate))
|
|
77322
78830
|
return candidate;
|
|
77323
78831
|
const parent = dirname13(searchDir);
|
|
@@ -77424,9 +78932,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
77424
78932
|
const keep = opts?.keep ?? false;
|
|
77425
78933
|
const manifest = setupSession(sessionPath, models, input);
|
|
77426
78934
|
const startedAt = new Date().toISOString();
|
|
77427
|
-
const gridfilePath =
|
|
77428
|
-
const prompt =
|
|
77429
|
-
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");
|
|
77430
78938
|
const usedBannerColors = new Set;
|
|
77431
78939
|
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
77432
78940
|
const model = manifest.models[anonId].model;
|
|
@@ -77457,7 +78965,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
77457
78965
|
});
|
|
77458
78966
|
const [{ results: results2 }] = await Promise.all([subscription, procExit]);
|
|
77459
78967
|
const status = buildTeamStatus(manifest, startedAt, results2?.panes ?? null);
|
|
77460
|
-
const statusPath =
|
|
78968
|
+
const statusPath = join37(sessionPath, "status.json");
|
|
77461
78969
|
writeFileSync21(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
77462
78970
|
return status;
|
|
77463
78971
|
}
|
|
@@ -77481,8 +78989,8 @@ var init_team_grid = __esm(() => {
|
|
|
77481
78989
|
init_op_source();
|
|
77482
78990
|
init_startup_trace();
|
|
77483
78991
|
var import_dotenv3 = __toESM(require_main(), 1);
|
|
77484
|
-
import { existsSync as existsSync30, readFileSync as
|
|
77485
|
-
import { join as
|
|
78992
|
+
import { existsSync as existsSync30, readFileSync as readFileSync29 } from "fs";
|
|
78993
|
+
import { join as join38, resolve as resolve5 } from "path";
|
|
77486
78994
|
import_dotenv3.config({ quiet: true });
|
|
77487
78995
|
function classifyStartupKind() {
|
|
77488
78996
|
const argv = process.argv.slice(2);
|
|
@@ -77729,14 +79237,14 @@ async function runCli() {
|
|
|
77729
79237
|
if (cliConfig.team && cliConfig.team.length > 0) {
|
|
77730
79238
|
let prompt = cliConfig.claudeArgs.join(" ");
|
|
77731
79239
|
if (cliConfig.inputFile) {
|
|
77732
|
-
prompt =
|
|
79240
|
+
prompt = readFileSync29(cliConfig.inputFile, "utf-8");
|
|
77733
79241
|
}
|
|
77734
79242
|
if (!prompt.trim()) {
|
|
77735
79243
|
console.error("Error: --team requires a prompt (positional args or -f <file>)");
|
|
77736
79244
|
process.exit(1);
|
|
77737
79245
|
}
|
|
77738
79246
|
const mode = cliConfig.teamMode ?? "default";
|
|
77739
|
-
const sessionPath =
|
|
79247
|
+
const sessionPath = join38(process.cwd(), `.claudish-team-${Date.now()}`);
|
|
77740
79248
|
if (mode === "json") {
|
|
77741
79249
|
const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
|
|
77742
79250
|
setupSession2(sessionPath, cliConfig.team, prompt);
|
|
@@ -77746,9 +79254,9 @@ async function runCli() {
|
|
|
77746
79254
|
});
|
|
77747
79255
|
const result = { ...status2, responses: {} };
|
|
77748
79256
|
for (const anonId of Object.keys(status2.models)) {
|
|
77749
|
-
const responsePath =
|
|
79257
|
+
const responsePath = join38(sessionPath, `response-${anonId}.md`);
|
|
77750
79258
|
try {
|
|
77751
|
-
const raw2 =
|
|
79259
|
+
const raw2 = readFileSync29(responsePath, "utf-8").trim();
|
|
77752
79260
|
try {
|
|
77753
79261
|
result.responses[anonId] = JSON.parse(raw2);
|
|
77754
79262
|
} catch {
|