@proxysoul/soulforge 2.2.1 → 2.3.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/README.md +7 -2
- package/dist/index.js +118 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ SoulForge doesn't work that way. On startup, it builds a **live dependency graph
|
|
|
63
63
|
|
|
64
64
|
- **Lock-in mode.** Hides agent narration during work, shows only tool activity and the final answer. Toggle via `/lock-in` or config.
|
|
65
65
|
- **Embedded Neovim.** Your actual config, plugins, and LSP servers. The AI works through the same editor you use. [Deep dive →](docs/architecture.md)
|
|
66
|
-
- **
|
|
66
|
+
- **18 providers.** Anthropic, OpenAI, Google, xAI, Groq, DeepSeek, Mistral, Amazon Bedrock, Fireworks, GitHub Copilot, GitHub Models, Ollama, LM Studio, OpenRouter, LLM Gateway, Vercel AI Gateway, Proxy, and any OpenAI-compatible API.
|
|
67
67
|
- **Task router.** Assign different models to different jobs. Spark agents (explore/investigate) and ember agents (code edits) can each use different models. You pick what goes where. [Deep dive →](docs/architecture.md)
|
|
68
68
|
- **Code execution (Smithy).** Sandboxed code execution via Anthropic's `code_execution` tool. The agent can run Python to process data, do calculations, or batch tool calls programmatically.
|
|
69
69
|
- **User steering.** Type while the agent works. Messages queue up and reach the agent at the next step. [Deep dive →](docs/steering.md)
|
|
@@ -88,7 +88,7 @@ SoulForge doesn't work that way. On startup, it builds a **live dependency graph
|
|
|
88
88
|
| **Task routing** | Per-task model assignment (spark, ember, web search, verify, desloppify, compact) | Single model | Single model | Per-agent model | Single model |
|
|
89
89
|
| **Compound tools** | `read` (batch + surgical), `multi_edit` (atomic), `rename_symbol`, `move_symbol`, `rename_file`, `refactor`, `project` | Rename via LSP | — | — | — |
|
|
90
90
|
| **Editor** | Embedded Neovim (your config, your plugins) | No editor | No editor | No editor | No editor |
|
|
91
|
-
| **Providers** |
|
|
91
|
+
| **Providers** | 18 + custom OpenAI-compatible | Anthropic only | Multi-model | OpenAI only | 100+ LLMs |
|
|
92
92
|
| **License** | BSL 1.1 (source-available) | Proprietary | Proprietary | Apache 2.0 | Apache 2.0 |
|
|
93
93
|
|
|
94
94
|
> *Competitor features verified as of March 29, 2026. [Let us know](https://github.com/ProxySoul/soulforge/issues) if something's changed.*
|
|
@@ -215,6 +215,7 @@ soulforge --headless --diff "fix the bug" # Show changed files
|
|
|
215
215
|
| [**GitHub Copilot**](https://github.com/features/copilot) | OAuth token from IDE ([setup](docs/copilot-provider.md)) |
|
|
216
216
|
| [**GitHub Models**](https://github.com/marketplace/models) | `GITHUB_MODELS_API_KEY` (PAT with `models:read`) |
|
|
217
217
|
| [**Ollama**](https://ollama.ai) | Auto-detected |
|
|
218
|
+
| [**LM Studio**](https://lmstudio.ai) | Auto-detected |
|
|
218
219
|
| [**OpenRouter**](https://openrouter.ai) | `OPENROUTER_API_KEY` |
|
|
219
220
|
| [**Vercel AI Gateway**](https://vercel.com/ai-gateway) | `AI_GATEWAY_API_KEY` |
|
|
220
221
|
| [**Proxy**](https://github.com/router-for-me/CLIProxyAPI) | `PROXY_API_KEY` |
|
|
@@ -226,6 +227,10 @@ soulforge --headless --diff "fix the bug" # Show changed files
|
|
|
226
227
|
|
|
227
228
|
**GitHub Models**: Free playground API with per-token billing. Create a fine-grained PAT with `models:read` scope. Lower rate limits than Copilot.
|
|
228
229
|
|
|
230
|
+
**Ollama**: Auto-detected at `localhost:11434`. Override with `OLLAMA_HOST=http://host:port`.
|
|
231
|
+
|
|
232
|
+
**LM Studio**: Auto-detected at `localhost:1234`. Uses the [REST API v0](https://lmstudio.ai/docs/developer/rest/endpoints) for rich model data (context length, type filtering). Override with `LM_STUDIO_URL=http://host:port`. Optional auth: set `LM_API_TOKEN` if you've enabled authentication in LM Studio.
|
|
233
|
+
|
|
229
234
|
Add custom providers in config, no code changes:
|
|
230
235
|
|
|
231
236
|
```json
|
package/dist/index.js
CHANGED
|
@@ -39260,7 +39260,7 @@ var package_default;
|
|
|
39260
39260
|
var init_package = __esm(() => {
|
|
39261
39261
|
package_default = {
|
|
39262
39262
|
name: "@proxysoul/soulforge",
|
|
39263
|
-
version: "2.
|
|
39263
|
+
version: "2.3.0",
|
|
39264
39264
|
description: "Graph-powered code intelligence \u2014 multi-agent coding with codebase-aware AI",
|
|
39265
39265
|
repository: {
|
|
39266
39266
|
type: "git",
|
|
@@ -39982,7 +39982,8 @@ function buildCustomProvider(config2) {
|
|
|
39982
39982
|
id: config2.id,
|
|
39983
39983
|
name: config2.name ?? config2.id,
|
|
39984
39984
|
envVar,
|
|
39985
|
-
icon: "\
|
|
39985
|
+
icon: "\uF29F",
|
|
39986
|
+
asciiIcon: "\u25C7",
|
|
39986
39987
|
custom: true,
|
|
39987
39988
|
createModel(modelId) {
|
|
39988
39989
|
const apiKey = envVar ? getProviderApiKey(envVar) ?? "" : "custom";
|
|
@@ -49575,6 +49576,75 @@ var init_llmgateway = __esm(() => {
|
|
|
49575
49576
|
};
|
|
49576
49577
|
});
|
|
49577
49578
|
|
|
49579
|
+
// src/core/llm/providers/lmstudio.ts
|
|
49580
|
+
function getBaseOrigin() {
|
|
49581
|
+
return (process.env.LM_STUDIO_URL ?? "http://localhost:1234").replace(/\/+$/, "");
|
|
49582
|
+
}
|
|
49583
|
+
function openaiBase() {
|
|
49584
|
+
return `${getBaseOrigin()}/v1`;
|
|
49585
|
+
}
|
|
49586
|
+
function restBase() {
|
|
49587
|
+
return `${getBaseOrigin()}/api/v0`;
|
|
49588
|
+
}
|
|
49589
|
+
function getApiToken() {
|
|
49590
|
+
return process.env.LM_API_TOKEN ?? "lm-studio";
|
|
49591
|
+
}
|
|
49592
|
+
function authHeaders() {
|
|
49593
|
+
const token = getApiToken();
|
|
49594
|
+
return token && token !== "lm-studio" ? {
|
|
49595
|
+
Authorization: `Bearer ${token}`
|
|
49596
|
+
} : {};
|
|
49597
|
+
}
|
|
49598
|
+
var lmstudio;
|
|
49599
|
+
var init_lmstudio = __esm(() => {
|
|
49600
|
+
init_dist6();
|
|
49601
|
+
lmstudio = {
|
|
49602
|
+
id: "lmstudio",
|
|
49603
|
+
name: "LM Studio",
|
|
49604
|
+
envVar: "LM_API_TOKEN",
|
|
49605
|
+
secretKey: "lm-api-token",
|
|
49606
|
+
icon: "\uEA79",
|
|
49607
|
+
asciiIcon: "L",
|
|
49608
|
+
description: "Local models via LM Studio \u2014 no key needed",
|
|
49609
|
+
createModel(modelId) {
|
|
49610
|
+
const client = createOpenAI({
|
|
49611
|
+
baseURL: openaiBase(),
|
|
49612
|
+
apiKey: getApiToken()
|
|
49613
|
+
});
|
|
49614
|
+
return client.chat(modelId);
|
|
49615
|
+
},
|
|
49616
|
+
async fetchModels() {
|
|
49617
|
+
const res = await fetch(`${restBase()}/models`, {
|
|
49618
|
+
headers: authHeaders(),
|
|
49619
|
+
signal: AbortSignal.timeout(3000)
|
|
49620
|
+
});
|
|
49621
|
+
if (!res.ok)
|
|
49622
|
+
throw new Error(`LM Studio API ${String(res.status)}`);
|
|
49623
|
+
const data = await res.json();
|
|
49624
|
+
if (!Array.isArray(data.data))
|
|
49625
|
+
return null;
|
|
49626
|
+
return data.data.filter((m) => m.type === "llm" || m.type === "vlm").map((m) => ({
|
|
49627
|
+
id: m.id,
|
|
49628
|
+
name: m.id,
|
|
49629
|
+
contextWindow: m.max_context_length
|
|
49630
|
+
}));
|
|
49631
|
+
},
|
|
49632
|
+
fallbackModels: [],
|
|
49633
|
+
async checkAvailability() {
|
|
49634
|
+
try {
|
|
49635
|
+
const res = await fetch(`${restBase()}/models`, {
|
|
49636
|
+
headers: authHeaders(),
|
|
49637
|
+
signal: AbortSignal.timeout(1000)
|
|
49638
|
+
});
|
|
49639
|
+
return res.ok;
|
|
49640
|
+
} catch {
|
|
49641
|
+
return false;
|
|
49642
|
+
}
|
|
49643
|
+
},
|
|
49644
|
+
contextWindows: []
|
|
49645
|
+
};
|
|
49646
|
+
});
|
|
49647
|
+
|
|
49578
49648
|
// node_modules/vercel-minimax-ai-provider/node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider/dist/index.mjs
|
|
49579
49649
|
function getErrorMessage4(error48) {
|
|
49580
49650
|
if (error48 == null) {
|
|
@@ -58676,6 +58746,9 @@ var init_mistral = __esm(() => {
|
|
|
58676
58746
|
});
|
|
58677
58747
|
|
|
58678
58748
|
// src/core/llm/providers/ollama.ts
|
|
58749
|
+
function getOllamaHost() {
|
|
58750
|
+
return (process.env.OLLAMA_HOST ?? "http://localhost:11434").replace(/\/+$/, "");
|
|
58751
|
+
}
|
|
58679
58752
|
var ollama;
|
|
58680
58753
|
var init_ollama = __esm(() => {
|
|
58681
58754
|
init_dist6();
|
|
@@ -58683,18 +58756,18 @@ var init_ollama = __esm(() => {
|
|
|
58683
58756
|
id: "ollama",
|
|
58684
58757
|
name: "Ollama",
|
|
58685
58758
|
envVar: "",
|
|
58686
|
-
icon: "\
|
|
58687
|
-
asciiIcon: "
|
|
58759
|
+
icon: "\uEBA2",
|
|
58760
|
+
asciiIcon: "O",
|
|
58688
58761
|
description: "Local models \u2014 no key needed",
|
|
58689
58762
|
createModel(modelId) {
|
|
58690
58763
|
const client = createOpenAI({
|
|
58691
|
-
baseURL:
|
|
58764
|
+
baseURL: `${getOllamaHost()}/v1`,
|
|
58692
58765
|
apiKey: "ollama"
|
|
58693
58766
|
});
|
|
58694
58767
|
return client.chat(modelId);
|
|
58695
58768
|
},
|
|
58696
58769
|
async fetchModels() {
|
|
58697
|
-
const res = await fetch(
|
|
58770
|
+
const res = await fetch(`${getOllamaHost()}/api/tags`);
|
|
58698
58771
|
if (!res.ok)
|
|
58699
58772
|
throw new Error(`Ollama API ${String(res.status)}`);
|
|
58700
58773
|
const data = await res.json();
|
|
@@ -58721,7 +58794,7 @@ var init_ollama = __esm(() => {
|
|
|
58721
58794
|
}],
|
|
58722
58795
|
async checkAvailability() {
|
|
58723
58796
|
try {
|
|
58724
|
-
const res = await fetch(
|
|
58797
|
+
const res = await fetch(`${getOllamaHost()}/api/tags`, {
|
|
58725
58798
|
signal: AbortSignal.timeout(1000)
|
|
58726
58799
|
});
|
|
58727
58800
|
return res.ok;
|
|
@@ -77733,6 +77806,7 @@ __export(exports_providers, {
|
|
|
77733
77806
|
ollama: () => ollama,
|
|
77734
77807
|
mistral: () => mistral2,
|
|
77735
77808
|
minimax: () => minimax2,
|
|
77809
|
+
lmstudio: () => lmstudio,
|
|
77736
77810
|
llmgateway: () => llmgateway2,
|
|
77737
77811
|
groq: () => groq2,
|
|
77738
77812
|
google: () => google2,
|
|
@@ -77793,6 +77867,7 @@ var init_providers = __esm(() => {
|
|
|
77793
77867
|
init_google();
|
|
77794
77868
|
init_groq();
|
|
77795
77869
|
init_llmgateway();
|
|
77870
|
+
init_lmstudio();
|
|
77796
77871
|
init_minimax();
|
|
77797
77872
|
init_mistral();
|
|
77798
77873
|
init_ollama();
|
|
@@ -77811,6 +77886,7 @@ var init_providers = __esm(() => {
|
|
|
77811
77886
|
init_google();
|
|
77812
77887
|
init_groq();
|
|
77813
77888
|
init_llmgateway();
|
|
77889
|
+
init_lmstudio();
|
|
77814
77890
|
init_minimax();
|
|
77815
77891
|
init_mistral();
|
|
77816
77892
|
init_ollama();
|
|
@@ -77819,7 +77895,7 @@ var init_providers = __esm(() => {
|
|
|
77819
77895
|
init_proxy();
|
|
77820
77896
|
init_vercel_gateway();
|
|
77821
77897
|
init_xai();
|
|
77822
|
-
BUILTIN_PROVIDERS = [llmgateway2, anthropic2, proxy2, vercelGatewayProvider, openai2, xai2, google2, groq2, deepseek2, mistral2, bedrock2, fireworks2, minimax2, copilot, githubModels, openrouter2, ollama];
|
|
77898
|
+
BUILTIN_PROVIDERS = [llmgateway2, anthropic2, proxy2, vercelGatewayProvider, openai2, xai2, google2, groq2, deepseek2, mistral2, bedrock2, fireworks2, minimax2, copilot, githubModels, openrouter2, ollama, lmstudio];
|
|
77823
77899
|
allProviders = [...BUILTIN_PROVIDERS];
|
|
77824
77900
|
providerMap = new Map(allProviders.map((p) => [p.id, p]));
|
|
77825
77901
|
});
|
|
@@ -448981,6 +449057,12 @@ function matchCopilotPricing(model) {
|
|
|
448981
449057
|
}
|
|
448982
449058
|
return;
|
|
448983
449059
|
}
|
|
449060
|
+
function isModelLocal(modelId) {
|
|
449061
|
+
const slash = modelId.indexOf("/");
|
|
449062
|
+
if (slash < 0)
|
|
449063
|
+
return false;
|
|
449064
|
+
return LOCAL_PROVIDERS.has(modelId.slice(0, slash).toLowerCase());
|
|
449065
|
+
}
|
|
448984
449066
|
function isModelFree(modelId) {
|
|
448985
449067
|
const id = modelId.toLowerCase();
|
|
448986
449068
|
if (id.endsWith(":free") || id.endsWith("-free"))
|
|
@@ -448995,7 +449077,7 @@ function isModelFree(modelId) {
|
|
|
448995
449077
|
}
|
|
448996
449078
|
function matchPricing(modelId) {
|
|
448997
449079
|
const id = modelId.toLowerCase();
|
|
448998
|
-
if (isModelFree(modelId))
|
|
449080
|
+
if (isModelLocal(modelId) || isModelFree(modelId))
|
|
448999
449081
|
return FREE_PRICING;
|
|
449000
449082
|
if (id.startsWith("copilot/")) {
|
|
449001
449083
|
const model = id.slice("copilot/".length);
|
|
@@ -449219,7 +449301,7 @@ function startMemoryPoll(intervalMs = 2000) {
|
|
|
449219
449301
|
});
|
|
449220
449302
|
}, intervalMs);
|
|
449221
449303
|
}
|
|
449222
|
-
var MODEL_PRICING, FREE_PRICING, DEFAULT_PRICING, FREE, M025, M033, M1, M32, M30, COPILOT_PRICING, ZERO_USAGE, ZERO_PROCESS_RSS, useStatusBarStore, memPollStarted = false, memPollTimer = null;
|
|
449304
|
+
var MODEL_PRICING, FREE_PRICING, DEFAULT_PRICING, FREE, M025, M033, M1, M32, M30, COPILOT_PRICING, LOCAL_PROVIDERS, ZERO_USAGE, ZERO_PROCESS_RSS, useStatusBarStore, memPollStarted = false, memPollTimer = null;
|
|
449223
449305
|
var init_statusbar = __esm(() => {
|
|
449224
449306
|
init_esm();
|
|
449225
449307
|
init_middleware();
|
|
@@ -449619,6 +449701,7 @@ var init_statusbar = __esm(() => {
|
|
|
449619
449701
|
"claude-opus-4.6": M32,
|
|
449620
449702
|
"claude-opus-4.6-fast": M30
|
|
449621
449703
|
};
|
|
449704
|
+
LOCAL_PROVIDERS = new Set(["ollama", "lmstudio"]);
|
|
449622
449705
|
ZERO_USAGE = {
|
|
449623
449706
|
prompt: 0,
|
|
449624
449707
|
completion: 0,
|
|
@@ -475094,8 +475177,10 @@ function fmtCost(usd) {
|
|
|
475094
475177
|
return `$${usd.toFixed(3)}`;
|
|
475095
475178
|
return `$${usd.toFixed(2)}`;
|
|
475096
475179
|
}
|
|
475097
|
-
function buildContent2(costCents, cacheHitPct, free) {
|
|
475180
|
+
function buildContent2(costCents, cacheHitPct, free, local) {
|
|
475098
475181
|
const tk = getThemeTokens();
|
|
475182
|
+
if (local)
|
|
475183
|
+
return new StyledText([fg(tk.success)("Local")]);
|
|
475099
475184
|
if (free)
|
|
475100
475185
|
return new StyledText([fg(tk.success)("FREE")]);
|
|
475101
475186
|
const cost = costCents / 100;
|
|
@@ -475110,11 +475195,13 @@ function TokenDisplay() {
|
|
|
475110
475195
|
const cacheHitRef = import_react59.useRef(0);
|
|
475111
475196
|
const currentCostRef = import_react59.useRef(0);
|
|
475112
475197
|
const freeRef = import_react59.useRef(false);
|
|
475198
|
+
const localRef = import_react59.useRef(false);
|
|
475113
475199
|
import_react59.useEffect(() => useStatusBarStore.subscribe((state) => {
|
|
475114
475200
|
const usage = state.tokenUsage;
|
|
475115
475201
|
const breakdown = usage.modelBreakdown;
|
|
475116
475202
|
const modelIds = Object.keys(breakdown);
|
|
475117
|
-
|
|
475203
|
+
localRef.current = modelIds.length > 0 && modelIds.every((mid) => isModelLocal(mid));
|
|
475204
|
+
freeRef.current = !localRef.current && modelIds.length > 0 && modelIds.every((mid_0) => isModelFree(mid_0));
|
|
475118
475205
|
const rawCost = breakdown && modelIds.length > 0 ? computeTotalCostFromBreakdown(breakdown) : 0;
|
|
475119
475206
|
costRef.current = Math.round(rawCost * 100);
|
|
475120
475207
|
const totalInput = usage.prompt + usage.subagentInput + usage.cacheRead + usage.cacheWrite;
|
|
@@ -475128,7 +475215,7 @@ function TokenDisplay() {
|
|
|
475128
475215
|
currentCostRef.current = approach2(currentCostRef.current, target);
|
|
475129
475216
|
try {
|
|
475130
475217
|
if (textRef.current)
|
|
475131
|
-
textRef.current.content = buildContent2(currentCostRef.current, cacheHitRef.current, freeRef.current);
|
|
475218
|
+
textRef.current.content = buildContent2(currentCostRef.current, cacheHitRef.current, freeRef.current, localRef.current);
|
|
475132
475219
|
} catch {}
|
|
475133
475220
|
}, STEP_MS2);
|
|
475134
475221
|
return () => clearInterval(timer);
|
|
@@ -475136,7 +475223,7 @@ function TokenDisplay() {
|
|
|
475136
475223
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
475137
475224
|
ref: textRef,
|
|
475138
475225
|
truncate: true,
|
|
475139
|
-
content: buildContent2(currentCostRef.current, cacheHitRef.current, freeRef.current)
|
|
475226
|
+
content: buildContent2(currentCostRef.current, cacheHitRef.current, freeRef.current, localRef.current)
|
|
475140
475227
|
}, undefined, false, undefined, this);
|
|
475141
475228
|
}
|
|
475142
475229
|
var import_react59, STEP_MS2 = 50, EASE2 = 0.35;
|
|
@@ -491963,9 +492050,10 @@ function StatusDashboard({
|
|
|
491963
492050
|
innerW
|
|
491964
492051
|
}, "t-total", false, undefined, this));
|
|
491965
492052
|
const sortedBd = Object.entries(su.modelBreakdown ?? {}).sort(([midA, a2], [midB, b5]) => computeModelCost(midB, b5) - computeModelCost(midA, a2));
|
|
491966
|
-
const
|
|
492053
|
+
const allLocal = sortedBd.length > 0 && sortedBd.every(([mid_0]) => isModelLocal(mid_0));
|
|
492054
|
+
const allFree = !allLocal && sortedBd.length > 0 && sortedBd.every(([mid_1]) => isModelFree(mid_1));
|
|
491967
492055
|
const totalCost = sortedBd.length > 0 ? computeTotalCostFromBreakdown(su.modelBreakdown ?? {}) : 0;
|
|
491968
|
-
if (totalCost > 0 || allFree) {
|
|
492056
|
+
if (totalCost > 0 || allFree || allLocal) {
|
|
491969
492057
|
const fmtCost2 = (c) => c < 0.01 ? `${c.toFixed(3)}` : `${c.toFixed(2)}`;
|
|
491970
492058
|
lines.push(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Spacer, {
|
|
491971
492059
|
innerW
|
|
@@ -491976,27 +492064,28 @@ function StatusDashboard({
|
|
|
491976
492064
|
innerW
|
|
491977
492065
|
}, "h-cost", false, undefined, this));
|
|
491978
492066
|
const costLabelW = Math.min(30, innerW - 20);
|
|
491979
|
-
for (const [
|
|
491980
|
-
const
|
|
491981
|
-
const
|
|
491982
|
-
|
|
492067
|
+
for (const [mid_2, usage_0] of sortedBd) {
|
|
492068
|
+
const local = isModelLocal(mid_2);
|
|
492069
|
+
const free = !local && isModelFree(mid_2);
|
|
492070
|
+
const c_0 = computeModelCost(mid_2, usage_0);
|
|
492071
|
+
if (c_0 <= 0 && !free && !local)
|
|
491983
492072
|
continue;
|
|
491984
492073
|
const pct = totalCost > 0 ? Math.round(c_0 / totalCost * 100) : 0;
|
|
491985
492074
|
const maxModelW = costLabelW - 4;
|
|
491986
|
-
const shortId =
|
|
492075
|
+
const shortId = mid_2.length > maxModelW ? `${mid_2.slice(0, maxModelW - 1)}\u2026` : mid_2;
|
|
491987
492076
|
lines.push(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(EntryRow, {
|
|
491988
492077
|
label: ` ${shortId}`,
|
|
491989
|
-
value: free ? "FREE" : `${fmtCost2(c_0)} (${String(pct)}%)`,
|
|
491990
|
-
valueColor: free ? t2.success : t2.textPrimary,
|
|
492078
|
+
value: local ? "Local" : free ? "FREE" : `${fmtCost2(c_0)} (${String(pct)}%)`,
|
|
492079
|
+
valueColor: local || free ? t2.success : t2.textPrimary,
|
|
491991
492080
|
labelW: costLabelW,
|
|
491992
492081
|
rightAlign: true,
|
|
491993
492082
|
innerW
|
|
491994
|
-
}, `cost-${
|
|
492083
|
+
}, `cost-${mid_2}`, false, undefined, this));
|
|
491995
492084
|
}
|
|
491996
492085
|
lines.push(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(EntryRow, {
|
|
491997
492086
|
label: " Total",
|
|
491998
|
-
value: allFree ? "FREE" : fmtCost2(totalCost),
|
|
491999
|
-
valueColor: allFree ? t2.success : t2.warning,
|
|
492087
|
+
value: allLocal ? "Local" : allFree ? "FREE" : fmtCost2(totalCost),
|
|
492088
|
+
valueColor: allLocal || allFree ? t2.success : t2.warning,
|
|
492000
492089
|
labelW: costLabelW,
|
|
492001
492090
|
rightAlign: true,
|
|
492002
492091
|
innerW
|
|
@@ -492012,7 +492101,9 @@ function StatusDashboard({
|
|
|
492012
492101
|
innerW
|
|
492013
492102
|
}, "h-tabs", false, undefined, this));
|
|
492014
492103
|
const fmtCost_0 = (c_1, modelIds) => {
|
|
492015
|
-
if (modelIds && modelIds.length > 0 && modelIds.every((
|
|
492104
|
+
if (modelIds && modelIds.length > 0 && modelIds.every((mid_3) => isModelLocal(mid_3)))
|
|
492105
|
+
return "Local";
|
|
492106
|
+
if (modelIds && modelIds.length > 0 && modelIds.every((mid_4) => isModelFree(mid_4)))
|
|
492016
492107
|
return "FREE";
|
|
492017
492108
|
return c_1 <= 0 ? "\u2014" : c_1 < 0.01 ? `$${c_1.toFixed(3)}` : `$${c_1.toFixed(2)}`;
|
|
492018
492109
|
};
|