atlarix 15.8.1 → 15.9.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.
|
@@ -9587,6 +9587,10 @@ var init_schema = __esm({
|
|
|
9587
9587
|
name: text("name").notNull(),
|
|
9588
9588
|
api_base_url: text("api_base_url").notNull(),
|
|
9589
9589
|
env_var_name: text("env_var_name"),
|
|
9590
|
+
/** Wire format: null / "openai" = OpenAI-compatible, "anthropic" = Messages API. */
|
|
9591
|
+
api_format: text("api_format"),
|
|
9592
|
+
/** How the key is sent: null = the format's usual header, or "x-api-key" / "bearer". */
|
|
9593
|
+
auth_header: text("auth_header"),
|
|
9590
9594
|
createdAt: integer("created_at", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`),
|
|
9591
9595
|
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().default(sql`(unixepoch())`)
|
|
9592
9596
|
}
|
|
@@ -10911,6 +10915,14 @@ var init_usage_stats = __esm({
|
|
|
10911
10915
|
}
|
|
10912
10916
|
});
|
|
10913
10917
|
|
|
10918
|
+
// raw-file:/home/runner/work/Atlarix/Atlarix/drizzle/0080_custom_provider_api_format.sql
|
|
10919
|
+
var custom_provider_api_format_default;
|
|
10920
|
+
var init_custom_provider_api_format = __esm({
|
|
10921
|
+
"raw-file:/home/runner/work/Atlarix/Atlarix/drizzle/0080_custom_provider_api_format.sql"() {
|
|
10922
|
+
custom_provider_api_format_default = "-- The wire format a provider the user added speaks, and how it takes the key.\n--\n-- A custom provider could only be OpenAI-compatible. Many endpoints serve the\n-- Anthropic Messages API instead (Bedrock's /anthropic, gateways, proxies), and\n-- those take the key either as `x-api-key` or as `Authorization: Bearer`.\n--\n-- Additive only (two nullable columns, null = OpenAI-compatible with its usual\n-- Bearer key): an older reader ignores them, so min_reader stays where it is.\nALTER TABLE `language_model_providers` ADD `api_format` text;--> statement-breakpoint\nALTER TABLE `language_model_providers` ADD `auth_header` text;\n";
|
|
10923
|
+
}
|
|
10924
|
+
});
|
|
10925
|
+
|
|
10914
10926
|
// src/db/migrations/bundled.generated.ts
|
|
10915
10927
|
var BUNDLED_MIGRATIONS, DRIZZLE_HASH_TO_NAME;
|
|
10916
10928
|
var init_bundled_generated = __esm({
|
|
@@ -10995,6 +11007,7 @@ var init_bundled_generated = __esm({
|
|
|
10995
11007
|
init_automation_leases();
|
|
10996
11008
|
init_mcp_headers();
|
|
10997
11009
|
init_usage_stats();
|
|
11010
|
+
init_custom_provider_api_format();
|
|
10998
11011
|
BUNDLED_MIGRATIONS = [
|
|
10999
11012
|
{ name: "0000_nebulous_proemial_gods", sql: nebulous_proemial_gods_default, drizzleHash: "2fd0348e72ac1429b9246311e8db17a34078771470c622a13ab09afdee0a0d31", when: 1744692127560 },
|
|
11000
11013
|
{ name: "0001_hesitant_roland_deschain", sql: hesitant_roland_deschain_default, drizzleHash: "b9b37284db688cf3aaaa2719dda788238fd216933d3756c0482f26b5343d0059", when: 1744999922420 },
|
|
@@ -11075,7 +11088,8 @@ var init_bundled_generated = __esm({
|
|
|
11075
11088
|
{ name: "0076_drop_installed_skills", sql: drop_installed_skills_default, drizzleHash: "b361a2b664ce74a3efeaa2f73cdf6de582509c6569a1aab54febbef507b98b3c", when: 17877024e5 },
|
|
11076
11089
|
{ name: "0077_automation_leases", sql: automation_leases_default, drizzleHash: "22f09427b49eb0fcdd2b62cd472735a88e5dd60974af0d0c008f6e6fddfdf545", when: 17877888e5 },
|
|
11077
11090
|
{ name: "0078_mcp_headers", sql: mcp_headers_default, drizzleHash: "2e2b040eac31e336e8e7662555fd8526e8cdfd59929671e9ca6e063a3f2d4004", when: 17878752e5 },
|
|
11078
|
-
{ name: "0079_usage_stats", sql: usage_stats_default, drizzleHash: "8ea9653e8339a4f4c4f0fb140766daace073443ed9e6efae3d4597b2fc6bd60d", when: 17879616e5 }
|
|
11091
|
+
{ name: "0079_usage_stats", sql: usage_stats_default, drizzleHash: "8ea9653e8339a4f4c4f0fb140766daace073443ed9e6efae3d4597b2fc6bd60d", when: 17879616e5 },
|
|
11092
|
+
{ name: "0080_custom_provider_api_format", sql: custom_provider_api_format_default, drizzleHash: "0c66aed1a57dea6a1e9925a9a74dc1ca4f181db3de0c8e446a860a9f3ef7b950", when: 1788048e6 }
|
|
11079
11093
|
];
|
|
11080
11094
|
DRIZZLE_HASH_TO_NAME = {
|
|
11081
11095
|
"2fd0348e72ac1429b9246311e8db17a34078771470c622a13ab09afdee0a0d31": "0000_nebulous_proemial_gods",
|
|
@@ -11157,7 +11171,8 @@ var init_bundled_generated = __esm({
|
|
|
11157
11171
|
"b361a2b664ce74a3efeaa2f73cdf6de582509c6569a1aab54febbef507b98b3c": "0076_drop_installed_skills",
|
|
11158
11172
|
"22f09427b49eb0fcdd2b62cd472735a88e5dd60974af0d0c008f6e6fddfdf545": "0077_automation_leases",
|
|
11159
11173
|
"2e2b040eac31e336e8e7662555fd8526e8cdfd59929671e9ca6e063a3f2d4004": "0078_mcp_headers",
|
|
11160
|
-
"8ea9653e8339a4f4c4f0fb140766daace073443ed9e6efae3d4597b2fc6bd60d": "0079_usage_stats"
|
|
11174
|
+
"8ea9653e8339a4f4c4f0fb140766daace073443ed9e6efae3d4597b2fc6bd60d": "0079_usage_stats",
|
|
11175
|
+
"0c66aed1a57dea6a1e9925a9a74dc1ca4f181db3de0c8e446a860a9f3ef7b950": "0080_custom_provider_api_format"
|
|
11161
11176
|
};
|
|
11162
11177
|
}
|
|
11163
11178
|
});
|
|
@@ -31220,12 +31235,11 @@ You are in ${L2("debug")} mode. Hypothesis-first debugging for this chat turn.
|
|
|
31220
31235
|
|
|
31221
31236
|
You CAN:
|
|
31222
31237
|
- Investigate (read, glob, grep, run_command for repro/tests)
|
|
31223
|
-
- Form a hypothesis (root cause + evidence + files) before any
|
|
31238
|
+
- Form a hypothesis (root cause + evidence + files) before any change
|
|
31224
31239
|
- Minimal file changes that test that hypothesis only
|
|
31225
|
-
- Delegate a scoped fix to a
|
|
31240
|
+
- Delegate a scoped fix to a writer sub-agent once you have a hypothesis (task with write:true), reading each proposed diff before you accept it \u2014 a fix you haven't read is not a fix. Read-only helper: the explore sub-agent
|
|
31226
31241
|
|
|
31227
31242
|
You CANNOT:
|
|
31228
|
-
- Change files before forming a hypothesis
|
|
31229
31243
|
- Refactor unrelated code or add features
|
|
31230
31244
|
|
|
31231
31245
|
Workflow: investigate \u2192 form hypothesis \u2192 minimal fix \u2192 run the project's own tests/checks (run_command) \u2192 revise if needed. Note the root cause when you report the fix.
|
|
@@ -31812,7 +31826,26 @@ function renderModeSystemBlock(activeMode) {
|
|
|
31812
31826
|
lines.push("</mode_system>");
|
|
31813
31827
|
return lines.join("\n");
|
|
31814
31828
|
}
|
|
31815
|
-
|
|
31829
|
+
function joinSystemPromptParts({ stableHeader, dynamicTail }) {
|
|
31830
|
+
return `${stableHeader}
|
|
31831
|
+
|
|
31832
|
+
${dynamicTail}
|
|
31833
|
+
`;
|
|
31834
|
+
}
|
|
31835
|
+
function splitDynamicTail(systemPrompt, dynamicTail) {
|
|
31836
|
+
if (!dynamicTail?.trim()) return systemPrompt;
|
|
31837
|
+
const joined = `
|
|
31838
|
+
|
|
31839
|
+
${dynamicTail}
|
|
31840
|
+
`;
|
|
31841
|
+
const at2 = systemPrompt.indexOf(joined);
|
|
31842
|
+
if (at2 < 0) return systemPrompt;
|
|
31843
|
+
return {
|
|
31844
|
+
systemPromptOverride: systemPrompt.slice(0, at2) + systemPrompt.slice(at2 + joined.length),
|
|
31845
|
+
dynamicSystemTail: dynamicTail
|
|
31846
|
+
};
|
|
31847
|
+
}
|
|
31848
|
+
async function buildSystemPromptPartsWithProjectInstructions(params) {
|
|
31816
31849
|
const {
|
|
31817
31850
|
workspacePath,
|
|
31818
31851
|
workspacePromptContent,
|
|
@@ -31841,7 +31874,7 @@ async function buildSystemPromptWithProjectInstructions(params) {
|
|
|
31841
31874
|
buildInstructionsFromLayers(layers),
|
|
31842
31875
|
projectDocsHint
|
|
31843
31876
|
].filter((s3) => s3.trim().length > 0).join("\n\n");
|
|
31844
|
-
return
|
|
31877
|
+
return constructSystemPromptParts({
|
|
31845
31878
|
contextSize,
|
|
31846
31879
|
chatMode,
|
|
31847
31880
|
effectiveWorkMode,
|
|
@@ -31867,7 +31900,7 @@ async function buildSystemPromptWithProjectInstructions(params) {
|
|
|
31867
31900
|
registeredToolNames
|
|
31868
31901
|
});
|
|
31869
31902
|
}
|
|
31870
|
-
var import_electron_log10, logger8, cachedPromptShell, AGENTS_MD, loadAgentsFile, FALLBACK_AGENTS, getAgentsMdForContextSize, getAgentsMdForWorkMode, MODE_SYSTEM_DESCRIPTIONS, constructSystemPromptParts
|
|
31903
|
+
var import_electron_log10, logger8, cachedPromptShell, AGENTS_MD, loadAgentsFile, FALLBACK_AGENTS, getAgentsMdForContextSize, getAgentsMdForWorkMode, MODE_SYSTEM_DESCRIPTIONS, constructSystemPromptParts;
|
|
31871
31904
|
var init_system_prompt = __esm({
|
|
31872
31905
|
"src/prompts/system_prompt.ts"() {
|
|
31873
31906
|
import_electron_log10 = __toESM(require_src());
|
|
@@ -32048,13 +32081,6 @@ When you need clarification or a decision from the user (architecture choices, d
|
|
|
32048
32081
|
}
|
|
32049
32082
|
return { stableHeader, dynamicTail: tail };
|
|
32050
32083
|
};
|
|
32051
|
-
constructSystemPrompt = (params) => {
|
|
32052
|
-
const { stableHeader, dynamicTail } = constructSystemPromptParts(params);
|
|
32053
|
-
return `${stableHeader}
|
|
32054
|
-
|
|
32055
|
-
${dynamicTail}
|
|
32056
|
-
`;
|
|
32057
|
-
};
|
|
32058
32084
|
}
|
|
32059
32085
|
});
|
|
32060
32086
|
|
|
@@ -67769,7 +67795,11 @@ var init_provider_sdk_factories = __esm({
|
|
|
67769
67795
|
const provider = createOpenAI({ apiKey, ...baseURL ? { baseURL } : {} });
|
|
67770
67796
|
return baseURL ? provider(modelId) : provider.responses(modelId);
|
|
67771
67797
|
},
|
|
67772
|
-
|
|
67798
|
+
// Exactly one of apiKey / authToken: the SDK refuses both.
|
|
67799
|
+
"@ai-sdk/anthropic": ({ modelId, apiKey, baseURL, authHeader }) => createAnthropic({
|
|
67800
|
+
...authHeader === "bearer" ? { authToken: apiKey } : { apiKey },
|
|
67801
|
+
...baseURL ? { baseURL } : {}
|
|
67802
|
+
})(modelId),
|
|
67773
67803
|
"@ai-sdk/google": ({ modelId, apiKey, baseURL }) => createGoogle({ apiKey, ...baseURL ? { baseURL } : {} })(modelId),
|
|
67774
67804
|
"@ai-sdk/xai": ({ modelId, apiKey, baseURL }) => createXai({ apiKey, ...baseURL ? { baseURL } : {} })(modelId)
|
|
67775
67805
|
};
|
|
@@ -68428,7 +68458,7 @@ var init_model_reasoning_profile = __esm({
|
|
|
68428
68458
|
temperatureById = /* @__PURE__ */ new Map();
|
|
68429
68459
|
effortOverrides = /* @__PURE__ */ new Map();
|
|
68430
68460
|
BUDGET_LEVELS = ["low", "medium", "high"];
|
|
68431
|
-
BUDGET_HINT = { low: "
|
|
68461
|
+
BUDGET_HINT = { low: "low", medium: "medium", high: "max" };
|
|
68432
68462
|
NO_REASONING = /* @__PURE__ */ new Set(["none", "minimal"]);
|
|
68433
68463
|
AUTO_EFFORT_LEVELS = ["low", "medium", "max"];
|
|
68434
68464
|
AUTO_EFFORT_CHOICES = { kind: "effort", levels: [...AUTO_EFFORT_LEVELS], defaultLevel: "medium" };
|
|
@@ -68964,6 +68994,18 @@ var init_models_dev = __esm({
|
|
|
68964
68994
|
}
|
|
68965
68995
|
});
|
|
68966
68996
|
|
|
68997
|
+
// src/lib/provider-key-check.ts
|
|
68998
|
+
function anthropicHeaders(apiKey, authHeader) {
|
|
68999
|
+
return {
|
|
69000
|
+
...authHeader === "bearer" ? { Authorization: `Bearer ${apiKey}` } : { "x-api-key": apiKey },
|
|
69001
|
+
"anthropic-version": "2023-06-01"
|
|
69002
|
+
};
|
|
69003
|
+
}
|
|
69004
|
+
var init_provider_key_check = __esm({
|
|
69005
|
+
"src/lib/provider-key-check.ts"() {
|
|
69006
|
+
}
|
|
69007
|
+
});
|
|
69008
|
+
|
|
68967
69009
|
// node_modules/isexe/windows.js
|
|
68968
69010
|
var require_windows = __commonJS({
|
|
68969
69011
|
"node_modules/isexe/windows.js"(exports2, module2) {
|
|
@@ -71124,21 +71166,22 @@ async function fetchModelsFromOpenAI(apiKey) {
|
|
|
71124
71166
|
return [];
|
|
71125
71167
|
}
|
|
71126
71168
|
}
|
|
71127
|
-
async function fetchModelsFromAnthropic(apiKey) {
|
|
71128
|
-
const
|
|
71169
|
+
async function fetchModelsFromAnthropic(apiKey, endpoint2) {
|
|
71170
|
+
const cacheId = endpoint2?.providerId ?? "anthropic";
|
|
71171
|
+
const label = endpoint2 ? endpoint2.providerId : "Anthropic";
|
|
71172
|
+
const cached4 = fromCache(cacheId);
|
|
71129
71173
|
if (cached4) return cached4;
|
|
71130
71174
|
try {
|
|
71131
71175
|
const items = [];
|
|
71132
71176
|
let after2;
|
|
71133
71177
|
for (let page = 0; page < MAX_PAGES; page++) {
|
|
71134
|
-
const url2 = new URL(
|
|
71178
|
+
const url2 = new URL(
|
|
71179
|
+
endpoint2 ? `${endpoint2.baseUrl.replace(/\/+$/, "")}/models` : "https://api.anthropic.com/v1/models"
|
|
71180
|
+
);
|
|
71135
71181
|
url2.searchParams.set("limit", "1000");
|
|
71136
71182
|
if (after2) url2.searchParams.set("after_id", after2);
|
|
71137
71183
|
const res = await fetch(url2, {
|
|
71138
|
-
headers:
|
|
71139
|
-
"x-api-key": apiKey,
|
|
71140
|
-
"anthropic-version": "2023-06-01"
|
|
71141
|
-
},
|
|
71184
|
+
headers: anthropicHeaders(apiKey, endpoint2?.authHeader),
|
|
71142
71185
|
signal: AbortSignal.timeout(15e3)
|
|
71143
71186
|
});
|
|
71144
71187
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
@@ -71150,18 +71193,18 @@ async function fetchModelsFromAnthropic(apiKey) {
|
|
|
71150
71193
|
const models = items.map((m3) => ({
|
|
71151
71194
|
apiName: m3.id,
|
|
71152
71195
|
displayName: m3.display_name ?? m3.id,
|
|
71153
|
-
description: "Claude model with tool support",
|
|
71196
|
+
description: endpoint2 ? "Chat model with tool support" : "Claude model with tool support",
|
|
71154
71197
|
...m3.max_input_tokens ? { contextWindow: m3.max_input_tokens } : {},
|
|
71155
71198
|
...m3.max_tokens ? { maxOutputTokens: m3.max_tokens } : {},
|
|
71156
71199
|
type: "cloud",
|
|
71157
71200
|
supportsToolChoice: true
|
|
71158
71201
|
}));
|
|
71159
71202
|
sortModels(models);
|
|
71160
|
-
toCache(
|
|
71161
|
-
logger10.info(`[
|
|
71203
|
+
toCache(cacheId, models);
|
|
71204
|
+
logger10.info(`[${label}] Fetched ${models.length} models`);
|
|
71162
71205
|
return models;
|
|
71163
71206
|
} catch (e3) {
|
|
71164
|
-
logger10.warn(
|
|
71207
|
+
logger10.warn(`[${label}] Fetch failed`, e3);
|
|
71165
71208
|
return [];
|
|
71166
71209
|
}
|
|
71167
71210
|
}
|
|
@@ -71364,7 +71407,14 @@ async function fetchModelsFromOpenRouter(apiKey) {
|
|
|
71364
71407
|
return [];
|
|
71365
71408
|
}
|
|
71366
71409
|
}
|
|
71367
|
-
async function fetchCustomProviderModels(providerId, baseUrl, apiKey) {
|
|
71410
|
+
async function fetchCustomProviderModels(providerId, baseUrl, apiKey, wire = {}) {
|
|
71411
|
+
if (wire.apiFormat === "anthropic") {
|
|
71412
|
+
return fetchModelsFromAnthropic(apiKey?.trim() || "none", {
|
|
71413
|
+
providerId,
|
|
71414
|
+
baseUrl,
|
|
71415
|
+
authHeader: wire.authHeader
|
|
71416
|
+
});
|
|
71417
|
+
}
|
|
71368
71418
|
return fetchOpenAICompatibleModels({
|
|
71369
71419
|
providerId,
|
|
71370
71420
|
url: `${baseUrl.replace(/\/+$/, "")}/models`,
|
|
@@ -71435,6 +71485,7 @@ var init_provider_model_fetchers = __esm({
|
|
|
71435
71485
|
import_electron_log12 = __toESM(require_src());
|
|
71436
71486
|
init_openrouter_app_headers();
|
|
71437
71487
|
init_language_model_constants();
|
|
71488
|
+
init_provider_key_check();
|
|
71438
71489
|
logger10 = import_electron_log12.default.scope("provider_fetchers");
|
|
71439
71490
|
CACHE_MS = 5 * 60 * 1e3;
|
|
71440
71491
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -71561,6 +71612,29 @@ var init_provider_api_keys = __esm({
|
|
|
71561
71612
|
}
|
|
71562
71613
|
});
|
|
71563
71614
|
|
|
71615
|
+
// src/lib/routing/custom-provider-format.ts
|
|
71616
|
+
function rememberCustomProviderFormats(providers) {
|
|
71617
|
+
anthropicFormat.clear();
|
|
71618
|
+
for (const p2 of providers) {
|
|
71619
|
+
if (p2.apiFormat === "anthropic") anthropicFormat.add(p2.id);
|
|
71620
|
+
}
|
|
71621
|
+
}
|
|
71622
|
+
function isCustomAnthropicFormat(providerId) {
|
|
71623
|
+
return Boolean(providerId && anthropicFormat.has(providerId));
|
|
71624
|
+
}
|
|
71625
|
+
function anthropicFormatCapabilityId(providerId) {
|
|
71626
|
+
return isCustomAnthropicFormat(providerId) ? "anthropic" : providerId;
|
|
71627
|
+
}
|
|
71628
|
+
function anthropicCatalogModelId(modelId) {
|
|
71629
|
+
return modelId.trim().replace(/^(?:[a-z]{2,6}\.)?anthropic\./i, "").replace(/-v\d+(?::\d+)?$/i, "");
|
|
71630
|
+
}
|
|
71631
|
+
var anthropicFormat;
|
|
71632
|
+
var init_custom_provider_format = __esm({
|
|
71633
|
+
"src/lib/routing/custom-provider-format.ts"() {
|
|
71634
|
+
anthropicFormat = /* @__PURE__ */ new Set();
|
|
71635
|
+
}
|
|
71636
|
+
});
|
|
71637
|
+
|
|
71564
71638
|
// src/ipc/utils/thinking_utils.ts
|
|
71565
71639
|
function reasoningCeiling(providerId) {
|
|
71566
71640
|
return providerId && PROVIDERS_THAT_SUPPORT_THINKING.includes(providerId) ? "max" : "high";
|
|
@@ -71584,7 +71658,7 @@ function reasoningBudgetTokens(effort, maxOutputTokens) {
|
|
|
71584
71658
|
const max4 = Math.max(1, Math.floor(maxOutputTokens));
|
|
71585
71659
|
const reserve = Math.max(Math.round(max4 * 0.15), 2048);
|
|
71586
71660
|
const ceil = Math.max(1024, max4 - reserve);
|
|
71587
|
-
const frac = effort === "max" ? 0.85 : effort === "xhigh" ? 0.7 : effort === "high" ? 0.5 : 0.33;
|
|
71661
|
+
const frac = effort === "max" ? 0.85 : effort === "xhigh" ? 0.7 : effort === "high" ? 0.5 : effort === "low" ? 0.15 : 0.33;
|
|
71588
71662
|
return Math.min(ceil, Math.max(1024, Math.round(max4 * frac)));
|
|
71589
71663
|
}
|
|
71590
71664
|
function getExtraProviderOptions(providerId, settings, includeExtendedThinking = false, maxOutputTokens, modelId) {
|
|
@@ -71668,6 +71742,9 @@ function resolveReasoningCatalogModelId(effectiveModel) {
|
|
|
71668
71742
|
if (effectiveModel.provider === "compass") {
|
|
71669
71743
|
return getCoreModelsDevTargetForTier(name29)?.modelId ?? getCoreModelIdForCoreTier(name29) ?? name29;
|
|
71670
71744
|
}
|
|
71745
|
+
if (isCustomAnthropicFormat(effectiveModel.provider)) {
|
|
71746
|
+
return anthropicCatalogModelId(name29);
|
|
71747
|
+
}
|
|
71671
71748
|
return name29;
|
|
71672
71749
|
}
|
|
71673
71750
|
function resolveMediaModelId(effectiveModel) {
|
|
@@ -71678,13 +71755,13 @@ function resolveMediaModelId(effectiveModel) {
|
|
|
71678
71755
|
}
|
|
71679
71756
|
function resolveCapabilityProviderId(effectiveModel) {
|
|
71680
71757
|
const provider = (effectiveModel.provider ?? "").trim();
|
|
71681
|
-
if (provider !== "compass") return provider;
|
|
71758
|
+
if (provider !== "compass") return anthropicFormatCapabilityId(provider);
|
|
71682
71759
|
return getCoreModelsDevTargetForTier(effectiveModel.name ?? "")?.providerId ?? provider;
|
|
71683
71760
|
}
|
|
71684
71761
|
function detectReasoningCapability(modelApiId, builtinProviderId) {
|
|
71685
71762
|
const id = modelApiId.trim();
|
|
71686
71763
|
const lower2 = id.toLowerCase();
|
|
71687
|
-
const pid = builtinProviderId ?? "";
|
|
71764
|
+
const pid = anthropicFormatCapabilityId(builtinProviderId) ?? "";
|
|
71688
71765
|
let useOpenRouterReasoning = false;
|
|
71689
71766
|
if (pid === "openrouter" || pid === "compass") {
|
|
71690
71767
|
const row = id.includes("/") ? getCachedOpenRouterModelRow(id) : void 0;
|
|
@@ -71738,7 +71815,7 @@ function isReasoningCapableModel(model) {
|
|
|
71738
71815
|
return offersAChannel(capabilityProvider) || offersAChannel(model.provider ?? "");
|
|
71739
71816
|
}
|
|
71740
71817
|
function resolveDispatchCapabilityProviderId(effectiveModel, builtinProviderId) {
|
|
71741
|
-
if (builtinProviderId !== "compass") return builtinProviderId;
|
|
71818
|
+
if (builtinProviderId !== "compass") return anthropicFormatCapabilityId(builtinProviderId);
|
|
71742
71819
|
if (effectiveModel.provider !== "compass") return builtinProviderId;
|
|
71743
71820
|
return resolveCapabilityProviderId(effectiveModel);
|
|
71744
71821
|
}
|
|
@@ -71834,6 +71911,7 @@ var init_reasoning_detector = __esm({
|
|
|
71834
71911
|
init_model_capability_profile();
|
|
71835
71912
|
init_language_model_constants();
|
|
71836
71913
|
init_model_reasoning_profile();
|
|
71914
|
+
init_custom_provider_format();
|
|
71837
71915
|
init_thinking_utils();
|
|
71838
71916
|
GEMINI_LEVELS = /* @__PURE__ */ new Set(["minimal", "low", "medium", "high"]);
|
|
71839
71917
|
}
|
|
@@ -72010,11 +72088,16 @@ async function getLanguageModelProviders() {
|
|
|
72010
72088
|
name: cp.name,
|
|
72011
72089
|
apiBaseUrl: cp.api_base_url,
|
|
72012
72090
|
envVarName: cp.env_var_name ?? void 0,
|
|
72091
|
+
// The Anthropic format dispatches through the catalog's own Anthropic SDK
|
|
72092
|
+
// factory (provider-sdk-factories), like any models.dev provider on it.
|
|
72093
|
+
...cp.api_format === "anthropic" ? { apiFormat: "anthropic", npm: ANTHROPIC_NPM } : {},
|
|
72094
|
+
...cp.auth_header === "x-api-key" || cp.auth_header === "bearer" ? { authHeader: cp.auth_header } : {},
|
|
72013
72095
|
type: "custom"
|
|
72014
72096
|
// hasFreeTier, websiteUrl, gatewayPrefix are not in the custom DB schema
|
|
72015
72097
|
// They will be undefined unless overridden by hardcoded values if IDs match
|
|
72016
72098
|
});
|
|
72017
72099
|
}
|
|
72100
|
+
rememberCustomProviderFormats([...customProvidersMap.values()]);
|
|
72018
72101
|
const catalogById = /* @__PURE__ */ new Map();
|
|
72019
72102
|
try {
|
|
72020
72103
|
for (const c2 of await getModelsDevProviderCatalog())
|
|
@@ -72101,15 +72184,15 @@ function providerDisplayName(providerId) {
|
|
|
72101
72184
|
if (!providerId) return void 0;
|
|
72102
72185
|
return providerNames.get(providerId) ?? providerId.replace(/^custom::/, "");
|
|
72103
72186
|
}
|
|
72104
|
-
async function liveCustomModels(providerId, baseUrl, apiKey, now2 = Date.now()) {
|
|
72187
|
+
async function liveCustomModels(providerId, baseUrl, apiKey, now2 = Date.now(), wire = {}) {
|
|
72105
72188
|
const { createHash: createHash10 } = await import("node:crypto");
|
|
72106
72189
|
const keyTag = apiKey?.trim() ? createHash10("sha256").update(apiKey.trim()).digest("hex").slice(0, 12) : "none";
|
|
72107
|
-
const cacheKey = `${providerId}|${baseUrl}|${keyTag}`;
|
|
72190
|
+
const cacheKey = `${providerId}|${baseUrl}|${keyTag}|${wire.apiFormat ?? "openai"}|${wire.authHeader ?? ""}`;
|
|
72108
72191
|
const hit = liveCache.get(cacheKey);
|
|
72109
72192
|
if (hit && now2 - hit.at < LIVE_TTL_MS) return hit.models;
|
|
72110
72193
|
const { fetchCustomProviderModels: fetchCustomProviderModels2 } = await Promise.resolve().then(() => (init_provider_model_fetchers(), provider_model_fetchers_exports));
|
|
72111
72194
|
const models = Promise.race([
|
|
72112
|
-
fetchCustomProviderModels2(providerId, baseUrl, apiKey).catch(
|
|
72195
|
+
fetchCustomProviderModels2(providerId, baseUrl, apiKey, wire).catch(
|
|
72113
72196
|
() => []
|
|
72114
72197
|
),
|
|
72115
72198
|
new Promise(
|
|
@@ -72142,7 +72225,10 @@ async function getLanguageModels({
|
|
|
72142
72225
|
maxOutputTokens: language_models.max_output_tokens,
|
|
72143
72226
|
contextWindow: language_models.context_window
|
|
72144
72227
|
}).from(language_models).where(
|
|
72145
|
-
|
|
72228
|
+
// A provider from the providers table, whatever its id: the CLI's dev
|
|
72229
|
+
// endpoint is `atlarix-cli-dev`, with no `custom::`, and its model row
|
|
72230
|
+
// was looked up as a built-in's and never found (QA B3).
|
|
72231
|
+
provider.type === "custom" || isCustomProvider({ providerId }) ? eq(language_models.customProviderId, providerId) : eq(language_models.builtinProviderId, providerId)
|
|
72146
72232
|
);
|
|
72147
72233
|
customModels = customModelsDb.map((model) => ({
|
|
72148
72234
|
...model,
|
|
@@ -72203,7 +72289,10 @@ async function getLanguageModels({
|
|
|
72203
72289
|
key = readSettings2().providerSettings?.[providerId]?.apiKey?.value;
|
|
72204
72290
|
} catch {
|
|
72205
72291
|
}
|
|
72206
|
-
const listed = await liveCustomModels(providerId, provider.apiBaseUrl, key)
|
|
72292
|
+
const listed = await liveCustomModels(providerId, provider.apiBaseUrl, key, Date.now(), {
|
|
72293
|
+
apiFormat: provider.apiFormat,
|
|
72294
|
+
authHeader: provider.authHeader
|
|
72295
|
+
});
|
|
72207
72296
|
const typed = new Set(customModels.map((m3) => m3.apiName));
|
|
72208
72297
|
return [...customModels, ...listed.filter((m3) => !typed.has(m3.apiName))];
|
|
72209
72298
|
}
|
|
@@ -72314,7 +72403,7 @@ function stampDeepThinkingSupport(modelsByProvider) {
|
|
|
72314
72403
|
function isCustomProvider({ providerId }) {
|
|
72315
72404
|
return providerId.startsWith(CUSTOM_PROVIDER_PREFIX);
|
|
72316
72405
|
}
|
|
72317
|
-
var providerNames, LIVE_TTL_MS, liveCache, CUSTOM_PROVIDER_PREFIX;
|
|
72406
|
+
var ANTHROPIC_NPM, providerNames, LIVE_TTL_MS, liveCache, CUSTOM_PROVIDER_PREFIX;
|
|
72318
72407
|
var init_language_model_helpers = __esm({
|
|
72319
72408
|
"src/ipc/shared/language_model_helpers.ts"() {
|
|
72320
72409
|
init_db2();
|
|
@@ -72329,6 +72418,8 @@ var init_language_model_helpers = __esm({
|
|
|
72329
72418
|
init_compass_constants();
|
|
72330
72419
|
init_reasoning_detector();
|
|
72331
72420
|
init_model_capability_profile();
|
|
72421
|
+
init_custom_provider_format();
|
|
72422
|
+
ANTHROPIC_NPM = "@ai-sdk/anthropic";
|
|
72332
72423
|
providerNames = /* @__PURE__ */ new Map();
|
|
72333
72424
|
LIVE_TTL_MS = 6e4;
|
|
72334
72425
|
liveCache = /* @__PURE__ */ new Map();
|
|
@@ -94587,6 +94678,7 @@ __export(supabase_client_exports, {
|
|
|
94587
94678
|
AUTH_CALLBACK_URL: () => AUTH_CALLBACK_URL,
|
|
94588
94679
|
DEEP_LINK_PROTOCOL: () => DEEP_LINK_PROTOCOL,
|
|
94589
94680
|
SUPABASE_REQUEST_TIMEOUT_MS: () => SUPABASE_REQUEST_TIMEOUT_MS,
|
|
94681
|
+
__resetUserRowForTests: () => __resetUserRowForTests,
|
|
94590
94682
|
cancelPendingOAuthTimeout: () => cancelPendingOAuthTimeout,
|
|
94591
94683
|
fetchPlanSnapshot: () => fetchPlanSnapshot,
|
|
94592
94684
|
fetchWithTimeout: () => fetchWithTimeout,
|
|
@@ -94958,10 +95050,44 @@ async function restoreAuthSessionOnStartup(opts) {
|
|
|
94958
95050
|
);
|
|
94959
95051
|
}
|
|
94960
95052
|
}
|
|
95053
|
+
async function readUserRow(by, fresh = false) {
|
|
95054
|
+
const key = by.id ? `id:${by.id}` : `email:${(by.email ?? "").toLowerCase()}`;
|
|
95055
|
+
const c2 = _userRow;
|
|
95056
|
+
if (!fresh && c2 && Date.now() - c2.at < USER_ROW_TTL_MS && c2.keys.includes(key)) return c2.row;
|
|
95057
|
+
const pending3 = _userRowInFlight.get(key);
|
|
95058
|
+
if (pending3) return pending3;
|
|
95059
|
+
const p2 = (async () => {
|
|
95060
|
+
try {
|
|
95061
|
+
const q3 = getSupabaseClient().from("users").select(USER_ROW_SELECT);
|
|
95062
|
+
const { data, error: error51 } = await (by.id ? q3.eq("id", by.id) : q3.eq("email", by.email)).maybeSingle();
|
|
95063
|
+
if (error51) return void 0;
|
|
95064
|
+
const row = data ?? null;
|
|
95065
|
+
const keys2 = [key];
|
|
95066
|
+
if (row?.id) keys2.push(`id:${row.id}`);
|
|
95067
|
+
if (row?.email) keys2.push(`email:${row.email.toLowerCase()}`);
|
|
95068
|
+
_userRow = { keys: keys2, row, at: Date.now() };
|
|
95069
|
+
return row;
|
|
95070
|
+
} catch {
|
|
95071
|
+
return void 0;
|
|
95072
|
+
} finally {
|
|
95073
|
+
_userRowInFlight.delete(key);
|
|
95074
|
+
}
|
|
95075
|
+
})();
|
|
95076
|
+
_userRowInFlight.set(key, p2);
|
|
95077
|
+
return p2;
|
|
95078
|
+
}
|
|
95079
|
+
function invalidateUserRow() {
|
|
95080
|
+
_userRow = null;
|
|
95081
|
+
}
|
|
95082
|
+
function __resetUserRowForTests() {
|
|
95083
|
+
_userRow = null;
|
|
95084
|
+
_userRowInFlight.clear();
|
|
95085
|
+
}
|
|
94961
95086
|
async function ensureUserExists(user) {
|
|
94962
95087
|
try {
|
|
94963
95088
|
const supabase = getSupabaseClient();
|
|
94964
|
-
const
|
|
95089
|
+
const shared = await readUserRow({ id: user.id });
|
|
95090
|
+
const existingUser = shared !== void 0 ? shared : (await supabase.from("users").select("id").eq("id", user.id).single()).data;
|
|
94965
95091
|
if (!existingUser) {
|
|
94966
95092
|
const { error: error51 } = await supabase.from("users").insert({
|
|
94967
95093
|
id: user.id,
|
|
@@ -94969,6 +95095,7 @@ async function ensureUserExists(user) {
|
|
|
94969
95095
|
plan: "free",
|
|
94970
95096
|
onboarding_completed: false
|
|
94971
95097
|
});
|
|
95098
|
+
invalidateUserRow();
|
|
94972
95099
|
if (error51) {
|
|
94973
95100
|
logger13.error("[Supabase] Failed to create user:", error51);
|
|
94974
95101
|
} else {
|
|
@@ -95020,6 +95147,8 @@ function computeEntitledPlan(row) {
|
|
|
95020
95147
|
return tier;
|
|
95021
95148
|
}
|
|
95022
95149
|
async function fetchPlanRowForUser(supabase, userId) {
|
|
95150
|
+
const shared = await readUserRow({ id: userId });
|
|
95151
|
+
if (shared !== void 0) return { data: shared, error: null };
|
|
95023
95152
|
let data = null;
|
|
95024
95153
|
let error51 = null;
|
|
95025
95154
|
{
|
|
@@ -95051,6 +95180,8 @@ async function getUserPlan(userId) {
|
|
|
95051
95180
|
}
|
|
95052
95181
|
async function isUserBanned(userId) {
|
|
95053
95182
|
try {
|
|
95183
|
+
const shared = await readUserRow({ id: userId });
|
|
95184
|
+
if (shared !== void 0) return !!shared?.banned_at;
|
|
95054
95185
|
const supabase = getSupabaseClient();
|
|
95055
95186
|
const { data, error: error51 } = await supabase.from("users").select("banned_at").eq("id", userId).maybeSingle();
|
|
95056
95187
|
if (error51 || !data) return false;
|
|
@@ -95080,9 +95211,10 @@ function offlinePlanOr(fallback, userId) {
|
|
|
95080
95211
|
function requireSettings() {
|
|
95081
95212
|
return init_settings(), __toCommonJS(settings_exports);
|
|
95082
95213
|
}
|
|
95083
|
-
function invalidatePlanCaches() {
|
|
95214
|
+
function invalidatePlanCaches(opts = {}) {
|
|
95084
95215
|
_tierCache = null;
|
|
95085
95216
|
_subDetailCache = null;
|
|
95217
|
+
if (!opts.keepRow) invalidateUserRow();
|
|
95086
95218
|
}
|
|
95087
95219
|
async function getSubscriptionDetails(email3) {
|
|
95088
95220
|
const c2 = _subDetailCache;
|
|
@@ -95090,8 +95222,8 @@ async function getSubscriptionDetails(email3) {
|
|
|
95090
95222
|
return { status: c2.status, endsAt: c2.endsAt };
|
|
95091
95223
|
}
|
|
95092
95224
|
try {
|
|
95093
|
-
const
|
|
95094
|
-
const
|
|
95225
|
+
const shared = await readUserRow({ email: email3 });
|
|
95226
|
+
const data = shared !== void 0 ? shared : (await getSupabaseClient().from("users").select("subscription_status, subscription_ends_at").eq("email", email3).single()).data;
|
|
95095
95227
|
const status = data?.subscription_status ?? null;
|
|
95096
95228
|
const endsAt = data?.subscription_ends_at ?? null;
|
|
95097
95229
|
_subDetailCache = { email: email3, status, endsAt, at: Date.now() };
|
|
@@ -95123,6 +95255,8 @@ async function getEffectiveTier(userId, ownPlan) {
|
|
|
95123
95255
|
}
|
|
95124
95256
|
async function getOnboardingCompleted(userId) {
|
|
95125
95257
|
try {
|
|
95258
|
+
const shared = await readUserRow({ id: userId });
|
|
95259
|
+
if (shared !== void 0) return shared?.onboarding_completed === true;
|
|
95126
95260
|
const supabase = getSupabaseClient();
|
|
95127
95261
|
const { data, error: error51 } = await supabase.from("users").select("onboarding_completed").eq("id", userId).maybeSingle();
|
|
95128
95262
|
if (error51) {
|
|
@@ -95139,6 +95273,7 @@ async function setOnboardingCompleted(userId, value) {
|
|
|
95139
95273
|
try {
|
|
95140
95274
|
const supabase = getSupabaseClient();
|
|
95141
95275
|
const { error: error51 } = await supabase.from("users").update({ onboarding_completed: value }).eq("id", userId);
|
|
95276
|
+
invalidateUserRow();
|
|
95142
95277
|
if (error51) {
|
|
95143
95278
|
logger13.error("[Supabase] setOnboardingCompleted error:", error51.message);
|
|
95144
95279
|
} else {
|
|
@@ -95162,11 +95297,10 @@ function onAuthStateChange(callback) {
|
|
|
95162
95297
|
});
|
|
95163
95298
|
return () => subscription.unsubscribe();
|
|
95164
95299
|
}
|
|
95165
|
-
async function fetchPlanSnapshot(userEmail) {
|
|
95300
|
+
async function fetchPlanSnapshot(userEmail, fresh = true) {
|
|
95166
95301
|
try {
|
|
95167
|
-
const {
|
|
95168
|
-
|
|
95169
|
-
).eq("email", userEmail).maybeSingle();
|
|
95302
|
+
const shared = await readUserRow({ email: userEmail }, fresh);
|
|
95303
|
+
const { data, error: error51 } = shared !== void 0 ? { data: shared, error: null } : await getSupabaseClient().from("users").select("plan, subscription_status, subscription_ends_at, effective_tier, banned_at").eq("email", userEmail).maybeSingle();
|
|
95170
95304
|
if (error51 || !data) return null;
|
|
95171
95305
|
const row = data;
|
|
95172
95306
|
return {
|
|
@@ -95180,7 +95314,7 @@ async function fetchPlanSnapshot(userEmail) {
|
|
|
95180
95314
|
return null;
|
|
95181
95315
|
}
|
|
95182
95316
|
}
|
|
95183
|
-
var import_electron_log15, logger13, DEEP_LINK_PROTOCOL, AUTH_CALLBACK_PATH, AUTH_CALLBACK_URL, supabaseClient, fileStorage, SUPABASE_REQUEST_TIMEOUT_MS, _oauthTimeoutHandle, _authFlowStartedAt, AUTH_FLOW_MAX_AGE_MS, EMAIL_SIGN_IN_URL, _pendingAuthState, sleep4, PLAN_ROW_SELECT_BASE, PLAN_ROW_SELECT_WITH_VARIANT, EFFECTIVE_TIER_TTL_MS, _tierCache, _subDetailCache;
|
|
95317
|
+
var import_electron_log15, logger13, DEEP_LINK_PROTOCOL, AUTH_CALLBACK_PATH, AUTH_CALLBACK_URL, supabaseClient, fileStorage, SUPABASE_REQUEST_TIMEOUT_MS, _oauthTimeoutHandle, _authFlowStartedAt, AUTH_FLOW_MAX_AGE_MS, EMAIL_SIGN_IN_URL, _pendingAuthState, sleep4, USER_ROW_SELECT, USER_ROW_TTL_MS, _userRow, _userRowInFlight, PLAN_ROW_SELECT_BASE, PLAN_ROW_SELECT_WITH_VARIANT, EFFECTIVE_TIER_TTL_MS, _tierCache, _subDetailCache;
|
|
95184
95318
|
var init_supabase_client = __esm({
|
|
95185
95319
|
"src/lib/auth/supabase-client.ts"() {
|
|
95186
95320
|
init_dist13();
|
|
@@ -95201,6 +95335,10 @@ var init_supabase_client = __esm({
|
|
|
95201
95335
|
EMAIL_SIGN_IN_URL = "https://atlarix.dev/auth/app";
|
|
95202
95336
|
_pendingAuthState = null;
|
|
95203
95337
|
sleep4 = (ms2) => new Promise((r3) => setTimeout(r3, ms2));
|
|
95338
|
+
USER_ROW_SELECT = "id, email, plan, effective_tier, subscription_ends_at, subscription_status, lemon_subscription_id, lemon_variant_id, banned_at, onboarding_completed";
|
|
95339
|
+
USER_ROW_TTL_MS = 1e4;
|
|
95340
|
+
_userRow = null;
|
|
95341
|
+
_userRowInFlight = /* @__PURE__ */ new Map();
|
|
95204
95342
|
PLAN_ROW_SELECT_BASE = "plan, effective_tier, subscription_ends_at, subscription_status, lemon_subscription_id";
|
|
95205
95343
|
PLAN_ROW_SELECT_WITH_VARIANT = `${PLAN_ROW_SELECT_BASE}, lemon_variant_id`;
|
|
95206
95344
|
EFFECTIVE_TIER_TTL_MS = 30 * 60 * 1e3;
|
|
@@ -95699,7 +95837,8 @@ async function resolveModelContextLimit(model, settings) {
|
|
|
95699
95837
|
if (pid.startsWith("custom::")) {
|
|
95700
95838
|
try {
|
|
95701
95839
|
const { getLanguageModelProviders: getLanguageModelProviders2 } = await Promise.resolve().then(() => (init_language_model_helpers(), language_model_helpers_exports));
|
|
95702
|
-
const
|
|
95840
|
+
const custom2 = (await getLanguageModelProviders2()).find((p2) => p2.id.toLowerCase() === pid);
|
|
95841
|
+
const base = custom2?.apiFormat === "anthropic" ? void 0 : custom2?.apiBaseUrl;
|
|
95703
95842
|
if (base) {
|
|
95704
95843
|
const { isOllamaEndpoint: isOllamaEndpoint2, ollamaOrigin: ollamaOrigin2, ollamaNumCtx: ollamaNumCtx2 } = await Promise.resolve().then(() => (init_ollama_native_fetch(), ollama_native_fetch_exports));
|
|
95705
95844
|
if (await isOllamaEndpoint2(base)) {
|
|
@@ -95722,10 +95861,7 @@ async function resolveModelContextLimit(model, settings) {
|
|
|
95722
95861
|
}
|
|
95723
95862
|
try {
|
|
95724
95863
|
const { getModelsDevLimits: getModelsDevLimits2 } = await Promise.resolve().then(() => (init_models_dev(), models_dev_exports));
|
|
95725
|
-
const limits = await getModelsDevLimits2(
|
|
95726
|
-
model.provider ?? "",
|
|
95727
|
-
model.name ?? ""
|
|
95728
|
-
);
|
|
95864
|
+
const limits = isCustomAnthropicFormat(model.provider) ? await getModelsDevLimits2("anthropic", anthropicCatalogModelId(model.name ?? "")) : await getModelsDevLimits2(model.provider ?? "", model.name ?? "");
|
|
95729
95865
|
if (limits?.context && limits.context > 0) {
|
|
95730
95866
|
return {
|
|
95731
95867
|
tierLimit: floorSafe(limits.context * clamp),
|
|
@@ -95747,6 +95883,7 @@ var init_resolve_model_context_limit = __esm({
|
|
|
95747
95883
|
init_compass_constants();
|
|
95748
95884
|
init_findLanguageModel();
|
|
95749
95885
|
import_electron_log16 = __toESM(require_src());
|
|
95886
|
+
init_custom_provider_format();
|
|
95750
95887
|
logger14 = import_electron_log16.default.scope("context-limit");
|
|
95751
95888
|
SAFETY_FACTOR = 0.8;
|
|
95752
95889
|
localContextCache = /* @__PURE__ */ new Map();
|
|
@@ -214995,7 +215132,7 @@ async function getRegularModelClient(model, settings, providerConfig, options) {
|
|
|
214995
215132
|
};
|
|
214996
215133
|
}
|
|
214997
215134
|
default: {
|
|
214998
|
-
if (providerConfig.type === "custom" && providerConfig.apiBaseUrl) {
|
|
215135
|
+
if (providerConfig.type === "custom" && providerConfig.apiBaseUrl && providerConfig.apiFormat !== "anthropic") {
|
|
214999
215136
|
const { isOllamaEndpoint: isOllamaEndpoint2, ollamaOrigin: ollamaOrigin2 } = await Promise.resolve().then(() => (init_ollama_native_fetch(), ollama_native_fetch_exports));
|
|
215000
215137
|
if (await isOllamaEndpoint2(providerConfig.apiBaseUrl)) {
|
|
215001
215138
|
return {
|
|
@@ -215015,7 +215152,8 @@ async function getRegularModelClient(model, settings, providerConfig, options) {
|
|
|
215015
215152
|
modelId: model.name,
|
|
215016
215153
|
apiKey,
|
|
215017
215154
|
baseURL: providerConfig.apiBaseUrl,
|
|
215018
|
-
npm: providerConfig.npm
|
|
215155
|
+
npm: providerConfig.npm,
|
|
215156
|
+
authHeader: providerConfig.authHeader
|
|
215019
215157
|
}),
|
|
215020
215158
|
builtinProviderId: providerConfig.id
|
|
215021
215159
|
},
|
|
@@ -241827,6 +241965,7 @@ var init_dist21 = __esm({
|
|
|
241827
241965
|
function resolveCacheMarkerPlacement(builtinProviderId, modelName) {
|
|
241828
241966
|
if (builtinProviderId === "anthropic") return "message";
|
|
241829
241967
|
if (!/claude|anthropic/i.test(modelName ?? "")) return "none";
|
|
241968
|
+
if (isCustomAnthropicFormat(builtinProviderId)) return "message";
|
|
241830
241969
|
if (builtinProviderId === "bedrock" || builtinProviderId === "vertex") {
|
|
241831
241970
|
return "message";
|
|
241832
241971
|
}
|
|
@@ -241938,6 +242077,7 @@ function advanceCacheBreakpointsForStep(messages, placement) {
|
|
|
241938
242077
|
var CACHE_MARKER, CACHE_MARKER_HEADER_1H, CACHE_KEY_BY_PROVIDER;
|
|
241939
242078
|
var init_anthropic_cache_breakpoints = __esm({
|
|
241940
242079
|
"src/lib/ai/anthropic-cache-breakpoints.ts"() {
|
|
242080
|
+
init_custom_provider_format();
|
|
241941
242081
|
CACHE_MARKER = {
|
|
241942
242082
|
anthropic: { cacheControl: { type: "ephemeral" } },
|
|
241943
242083
|
openrouter: { cacheControl: { type: "ephemeral" } },
|
|
@@ -264469,7 +264609,7 @@ var init_SubscriptionManager = __esm({
|
|
|
264469
264609
|
} catch {
|
|
264470
264610
|
}
|
|
264471
264611
|
if (user.email) {
|
|
264472
|
-
await this.refreshPlanFromServer(0);
|
|
264612
|
+
await this.refreshPlanFromServer(0, false);
|
|
264473
264613
|
}
|
|
264474
264614
|
this.broadcastAuthResolved();
|
|
264475
264615
|
}
|
|
@@ -264630,7 +264770,7 @@ var init_SubscriptionManager = __esm({
|
|
|
264630
264770
|
*/
|
|
264631
264771
|
static lastPlanRefreshAt = 0;
|
|
264632
264772
|
static planRefreshInFlight = null;
|
|
264633
|
-
static async refreshPlanFromServer(minIntervalMs = 15e3) {
|
|
264773
|
+
static async refreshPlanFromServer(minIntervalMs = 15e3, fresh = true) {
|
|
264634
264774
|
const email3 = this.session?.email;
|
|
264635
264775
|
if (!email3) return;
|
|
264636
264776
|
if (this.planRefreshInFlight) return this.planRefreshInFlight;
|
|
@@ -264640,7 +264780,7 @@ var init_SubscriptionManager = __esm({
|
|
|
264640
264780
|
this.planRefreshInFlight = (async () => {
|
|
264641
264781
|
try {
|
|
264642
264782
|
const { fetchPlanSnapshot: fetchPlanSnapshot2 } = await Promise.resolve().then(() => (init_supabase_client(), supabase_client_exports));
|
|
264643
|
-
const next = await fetchPlanSnapshot2(email3);
|
|
264783
|
+
const next = await fetchPlanSnapshot2(email3, fresh);
|
|
264644
264784
|
if (!next) return;
|
|
264645
264785
|
const prev = {
|
|
264646
264786
|
plan: this.session?.plan ?? "free",
|
|
@@ -264650,7 +264790,7 @@ var init_SubscriptionManager = __esm({
|
|
|
264650
264790
|
banned: this.session?.banned ?? false
|
|
264651
264791
|
};
|
|
264652
264792
|
const changed = next.plan !== prev.plan || next.effectiveTier !== prev.effectiveTier || Boolean(next.banned) !== Boolean(prev.banned);
|
|
264653
|
-
invalidatePlanCaches();
|
|
264793
|
+
invalidatePlanCaches({ keepRow: true });
|
|
264654
264794
|
if (changed) await this.applyPlanChange(next, prev);
|
|
264655
264795
|
} catch (e3) {
|
|
264656
264796
|
logger56.warn("[SubscriptionManager] plan refresh failed (non-fatal)", e3);
|
|
@@ -338350,7 +338490,8 @@ async function simpleStreamText(ctx, deps, {
|
|
|
338350
338490
|
...reasoningPatch.anthropic
|
|
338351
338491
|
};
|
|
338352
338492
|
}
|
|
338353
|
-
const handledNatively = offByBudget ||
|
|
338493
|
+
const handledNatively = offByBudget || // The Anthropic SDK reads only its own bucket, in its own shape.
|
|
338494
|
+
isCustomAnthropicFormat(modelClient.builtinProviderId) || Boolean(reasoningPatch.openrouter) || Boolean(reasoningPatch.google) || Boolean(reasoningPatch.openai) || Boolean(reasoningPatch.anthropic);
|
|
338354
338495
|
if (modelClient.builtinProviderId && !handledNatively) {
|
|
338355
338496
|
const compatibleReasoning = getExtraProviderOptions(
|
|
338356
338497
|
capabilityProviderId,
|
|
@@ -338369,6 +338510,7 @@ async function simpleStreamText(ctx, deps, {
|
|
|
338369
338510
|
}
|
|
338370
338511
|
}
|
|
338371
338512
|
const isAnthropic = modelClient.builtinProviderId === "anthropic";
|
|
338513
|
+
const speaksAnthropic = isAnthropic || isCustomAnthropicFormat(modelClient.builtinProviderId);
|
|
338372
338514
|
const cacheMarkerPlacement = resolveCacheMarkerPlacement(
|
|
338373
338515
|
modelClient.builtinProviderId,
|
|
338374
338516
|
effectiveModel?.name
|
|
@@ -338440,7 +338582,7 @@ async function simpleStreamText(ctx, deps, {
|
|
|
338440
338582
|
history,
|
|
338441
338583
|
placement: cacheMarkerPlacement,
|
|
338442
338584
|
// v13.3: header prefix survives >5min between-turn gaps.
|
|
338443
|
-
headerTtl1h:
|
|
338585
|
+
headerTtl1h: speaksAnthropic
|
|
338444
338586
|
});
|
|
338445
338587
|
const completedStepMessages = [];
|
|
338446
338588
|
const recordStepMessages = (msgs) => {
|
|
@@ -338889,6 +339031,7 @@ var init_simple_stream_text = __esm({
|
|
|
338889
339031
|
init_perf_marks();
|
|
338890
339032
|
init_byok_pricing();
|
|
338891
339033
|
init_reasoning_detector();
|
|
339034
|
+
init_custom_provider_format();
|
|
338892
339035
|
init_system_reminder();
|
|
338893
339036
|
init_step_messages();
|
|
338894
339037
|
init_texts();
|
|
@@ -342987,6 +343130,7 @@ async function runBuildBranch(ctx, deps) {
|
|
|
342987
343130
|
modelContextResolved,
|
|
342988
343131
|
placeholderAssistantMessage,
|
|
342989
343132
|
systemPrompt,
|
|
343133
|
+
dynamicTail,
|
|
342990
343134
|
taskLedgerBlock,
|
|
342991
343135
|
simpleStreamTextDeps,
|
|
342992
343136
|
streamTurnId,
|
|
@@ -344234,7 +344378,9 @@ async function runBuildBranch(ctx, deps) {
|
|
|
344234
344378
|
escalationMode: effectiveWorkMode === "plan" ? "plan" : effectiveWorkMode === "build" ? "build" : "agent",
|
|
344235
344379
|
tools,
|
|
344236
344380
|
repetition: agenticRepetition,
|
|
344237
|
-
|
|
344381
|
+
// The per-turn tail in its own system message, after the cached
|
|
344382
|
+
// header, so the next turn reads the cache instead of rewriting it.
|
|
344383
|
+
buildRoundSystemPrompt: () => splitDynamicTail(systemPrompt, dynamicTail),
|
|
344238
344384
|
detectTextToolCalls: (fr2) => useTextToolFallback && containsTextToolCall2(fr2) ? parseTextToolCalls2(fr2) : null,
|
|
344239
344385
|
executeTextToolCalls: (calls) => execBuildTextToolCalls(
|
|
344240
344386
|
calls
|
|
@@ -344377,6 +344523,7 @@ var init_build_branch = __esm({
|
|
|
344377
344523
|
init_dist21();
|
|
344378
344524
|
import_electron_log102 = __toESM(require_src());
|
|
344379
344525
|
init_edit_stats2();
|
|
344526
|
+
init_system_prompt();
|
|
344380
344527
|
logger99 = import_electron_log102.default.scope("chat_stream_handlers");
|
|
344381
344528
|
}
|
|
344382
344529
|
});
|
|
@@ -346424,11 +346571,11 @@ function registerChatStreamHandlers() {
|
|
|
346424
346571
|
providerBrand: modelIdentity.providerBrand,
|
|
346425
346572
|
labelWithProvider: modelIdentity.labelWithProvider
|
|
346426
346573
|
};
|
|
346427
|
-
let
|
|
346574
|
+
let baseParts;
|
|
346428
346575
|
if (hasWorkspace && appPath && effectiveAppId != null) {
|
|
346429
|
-
|
|
346576
|
+
baseParts = await preflight.time(
|
|
346430
346577
|
"system-prompt",
|
|
346431
|
-
() =>
|
|
346578
|
+
() => buildSystemPromptPartsWithProjectInstructions({
|
|
346432
346579
|
workspacePath: appPath,
|
|
346433
346580
|
workspacePromptContent: null,
|
|
346434
346581
|
contextSize,
|
|
@@ -346441,7 +346588,7 @@ function registerChatStreamHandlers() {
|
|
|
346441
346588
|
})
|
|
346442
346589
|
);
|
|
346443
346590
|
} else {
|
|
346444
|
-
|
|
346591
|
+
baseParts = constructSystemPromptParts({
|
|
346445
346592
|
chatMode,
|
|
346446
346593
|
effectiveWorkMode: modeBlockKey,
|
|
346447
346594
|
contextSize,
|
|
@@ -346451,6 +346598,8 @@ function registerChatStreamHandlers() {
|
|
|
346451
346598
|
...promptIdentityOpts
|
|
346452
346599
|
});
|
|
346453
346600
|
}
|
|
346601
|
+
let baseSystemPrompt = joinSystemPromptParts(baseParts);
|
|
346602
|
+
const baseDynamicTail = baseParts.dynamicTail;
|
|
346454
346603
|
if (activeUserAgent) {
|
|
346455
346604
|
const { renderUserAgentSystemBlock: renderUserAgentSystemBlock2 } = await Promise.resolve().then(() => (init_user_agents(), user_agents_exports));
|
|
346456
346605
|
baseSystemPrompt = `${renderUserAgentSystemBlock2(activeUserAgent)}
|
|
@@ -346960,6 +347109,7 @@ ${baseSystemPrompt}`;
|
|
|
346960
347109
|
modelContextResolved,
|
|
346961
347110
|
placeholderAssistantMessage,
|
|
346962
347111
|
systemPrompt,
|
|
347112
|
+
dynamicTail: baseDynamicTail,
|
|
346963
347113
|
taskLedgerBlock,
|
|
346964
347114
|
simpleStreamTextDeps,
|
|
346965
347115
|
streamTurnId,
|
|
@@ -347893,7 +348043,7 @@ ${err2.stack}` : "";
|
|
|
347893
348043
|
}
|
|
347894
348044
|
|
|
347895
348045
|
// src/headless/atlarix-headless.mts
|
|
347896
|
-
var VERSION15 = false ? "dev" : "15.
|
|
348046
|
+
var VERSION15 = false ? "dev" : "15.9.0";
|
|
347897
348047
|
if (process.argv[2] === "run") process.argv.splice(2, 1);
|
|
347898
348048
|
var RUN_HELP = `atlarix run: one turn without the UI, for scripts and CI
|
|
347899
348049
|
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atlarix",
|
|
3
|
-
"version": "15.
|
|
3
|
+
"version": "15.9.0",
|
|
4
4
|
"description": "Atlarix CLI: an AI coding agent in your terminal. Works with any model (Atlarix Auto, your own API key, or a local model) and runs unattended with `atlarix run` for CI.",
|
|
5
5
|
"license": "PROPRIETARY",
|
|
6
6
|
"author": {
|
|
@@ -65,12 +65,12 @@
|
|
|
65
65
|
"provenance": false
|
|
66
66
|
},
|
|
67
67
|
"optionalDependencies": {
|
|
68
|
-
"atlarix-darwin-arm64": "15.
|
|
69
|
-
"atlarix-darwin-x64": "15.
|
|
70
|
-
"atlarix-linux-x64": "15.
|
|
71
|
-
"atlarix-linux-arm64": "15.
|
|
72
|
-
"atlarix-linux-x64-musl": "15.
|
|
73
|
-
"atlarix-linux-arm64-musl": "15.
|
|
74
|
-
"atlarix-windows-x64": "15.
|
|
68
|
+
"atlarix-darwin-arm64": "15.9.0",
|
|
69
|
+
"atlarix-darwin-x64": "15.9.0",
|
|
70
|
+
"atlarix-linux-x64": "15.9.0",
|
|
71
|
+
"atlarix-linux-arm64": "15.9.0",
|
|
72
|
+
"atlarix-linux-x64-musl": "15.9.0",
|
|
73
|
+
"atlarix-linux-arm64-musl": "15.9.0",
|
|
74
|
+
"atlarix-windows-x64": "15.9.0"
|
|
75
75
|
}
|
|
76
76
|
}
|