demian-cli 1.0.8 → 1.0.9
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 +13 -2
- package/dist/cli.mjs +68 -24
- package/dist/index.mjs +29 -3
- package/dist/tui.mjs +67 -23
- package/dist/vscode-worker.mjs +69 -25
- package/docs/ko/README.md +6 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,8 +116,11 @@ Create `~/.demian/config.jsond`:
|
|
|
116
116
|
"openai": {
|
|
117
117
|
"type": "openai-compatible",
|
|
118
118
|
"baseURL": "https://api.openai.com/v1",
|
|
119
|
+
"apiKey": "",
|
|
119
120
|
"apiKeyEnv": "OPENAI_API_KEY",
|
|
120
|
-
"
|
|
121
|
+
"modelProfiles": [
|
|
122
|
+
{ "name": "main", "displayName": "GPT 5.5", "model": "gpt-5.5" }
|
|
123
|
+
]
|
|
121
124
|
}
|
|
122
125
|
}
|
|
123
126
|
}
|
|
@@ -130,6 +133,11 @@ export OPENAI_API_KEY="..."
|
|
|
130
133
|
demian --provider openai --model gpt-5.5
|
|
131
134
|
```
|
|
132
135
|
|
|
136
|
+
Providers that can expose many local or self-hosted models, such as `lmstudio`,
|
|
137
|
+
`ollama-local`, `ollama-cloud`, `llamacpp`, and `vllm`, also use
|
|
138
|
+
`modelProfiles`. Add one array entry per model you want to show in the model
|
|
139
|
+
selector.
|
|
140
|
+
|
|
133
141
|
### Local Model Example: Ollama
|
|
134
142
|
|
|
135
143
|
```sh
|
|
@@ -307,12 +315,15 @@ Demian supports Brave, Tavily, and Exa through the `web_search` tool.
|
|
|
307
315
|
"defaultProvider": "brave",
|
|
308
316
|
"providers": {
|
|
309
317
|
"brave": {
|
|
318
|
+
"apiKey": "",
|
|
310
319
|
"apiKeyEnv": "BRAVE_SEARCH_API_KEY"
|
|
311
320
|
},
|
|
312
321
|
"tavily": {
|
|
322
|
+
"apiKey": "",
|
|
313
323
|
"apiKeyEnv": "TAVILY_API_KEY"
|
|
314
324
|
},
|
|
315
325
|
"exa": {
|
|
326
|
+
"apiKey": "",
|
|
316
327
|
"apiKeyEnv": "EXA_API_KEY"
|
|
317
328
|
}
|
|
318
329
|
}
|
|
@@ -334,7 +345,7 @@ Demian uses both user-level and project-level storage:
|
|
|
334
345
|
- `.demian/goals/`: active and archived goal state.
|
|
335
346
|
- `.demian/`: transcripts and workspace-scoped runtime files.
|
|
336
347
|
|
|
337
|
-
|
|
348
|
+
Leave `apiKey` empty and prefer `apiKeyEnv` for shared project config. Paste into `apiKey` only for local private config.
|
|
338
349
|
|
|
339
350
|
## Troubleshooting
|
|
340
351
|
|
package/dist/cli.mjs
CHANGED
|
@@ -23639,6 +23639,7 @@ var defaultConfig = {
|
|
|
23639
23639
|
defaultProvider: "brave",
|
|
23640
23640
|
providers: {
|
|
23641
23641
|
brave: {
|
|
23642
|
+
apiKey: "",
|
|
23642
23643
|
apiKeyEnv: "BRAVE_SEARCH_API_KEY",
|
|
23643
23644
|
endpoint: "https://api.search.brave.com/res/v1/web/search",
|
|
23644
23645
|
count: 10,
|
|
@@ -23647,12 +23648,14 @@ var defaultConfig = {
|
|
|
23647
23648
|
safeSearch: "moderate"
|
|
23648
23649
|
},
|
|
23649
23650
|
tavily: {
|
|
23651
|
+
apiKey: "",
|
|
23650
23652
|
apiKeyEnv: "TAVILY_API_KEY",
|
|
23651
23653
|
endpoint: "https://api.tavily.com/search",
|
|
23652
23654
|
maxResults: 5,
|
|
23653
23655
|
searchDepth: "basic"
|
|
23654
23656
|
},
|
|
23655
23657
|
exa: {
|
|
23658
|
+
apiKey: "",
|
|
23656
23659
|
apiKeyEnv: "EXA_API_KEY",
|
|
23657
23660
|
endpoint: "https://api.exa.ai/search",
|
|
23658
23661
|
numResults: 5,
|
|
@@ -23707,6 +23710,7 @@ var defaultConfig = {
|
|
|
23707
23710
|
openai: {
|
|
23708
23711
|
type: "openai-compatible",
|
|
23709
23712
|
baseURL: "https://api.openai.com/v1",
|
|
23713
|
+
apiKey: "",
|
|
23710
23714
|
apiKeyEnv: "OPENAI_API_KEY",
|
|
23711
23715
|
catalog: {
|
|
23712
23716
|
type: "openai-models",
|
|
@@ -23716,6 +23720,7 @@ var defaultConfig = {
|
|
|
23716
23720
|
anthropic: {
|
|
23717
23721
|
type: "anthropic",
|
|
23718
23722
|
baseURL: "https://api.anthropic.com/v1",
|
|
23723
|
+
apiKey: "",
|
|
23719
23724
|
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
23720
23725
|
catalog: {
|
|
23721
23726
|
type: "anthropic-models",
|
|
@@ -23725,6 +23730,7 @@ var defaultConfig = {
|
|
|
23725
23730
|
gemini: {
|
|
23726
23731
|
type: "openai-compatible",
|
|
23727
23732
|
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/",
|
|
23733
|
+
apiKey: "",
|
|
23728
23734
|
apiKeyEnv: "GEMINI_API_KEY",
|
|
23729
23735
|
apiKeyEnvAliases: ["GOOGLE_API_KEY"],
|
|
23730
23736
|
catalog: {
|
|
@@ -23735,6 +23741,7 @@ var defaultConfig = {
|
|
|
23735
23741
|
groq: {
|
|
23736
23742
|
type: "openai-compatible",
|
|
23737
23743
|
baseURL: "https://api.groq.com/openai/v1",
|
|
23744
|
+
apiKey: "",
|
|
23738
23745
|
apiKeyEnv: "GROQ_API_KEY",
|
|
23739
23746
|
catalog: {
|
|
23740
23747
|
type: "groq-models",
|
|
@@ -23750,6 +23757,7 @@ var defaultConfig = {
|
|
|
23750
23757
|
displayName: "Azure example",
|
|
23751
23758
|
model: "azure-deployment-name",
|
|
23752
23759
|
baseURL: "https://example.openai.azure.com/openai/v1",
|
|
23760
|
+
apiKey: "",
|
|
23753
23761
|
apiKeyEnv: "AZURE_OPENAI_API_KEY"
|
|
23754
23762
|
}
|
|
23755
23763
|
]
|
|
@@ -23758,6 +23766,7 @@ var defaultConfig = {
|
|
|
23758
23766
|
type: "openai-compatible",
|
|
23759
23767
|
baseURL: "http://localhost:1234/v1",
|
|
23760
23768
|
apiKey: "lm-studio",
|
|
23769
|
+
modelProfiles: [],
|
|
23761
23770
|
catalog: {
|
|
23762
23771
|
type: "openai-compatible-models",
|
|
23763
23772
|
endpoint: "http://localhost:1234/v1/models"
|
|
@@ -23767,6 +23776,7 @@ var defaultConfig = {
|
|
|
23767
23776
|
type: "openai-compatible",
|
|
23768
23777
|
baseURL: "http://localhost:11434/v1",
|
|
23769
23778
|
apiKey: "ollama",
|
|
23779
|
+
modelProfiles: [],
|
|
23770
23780
|
quirks: { omitTemperature: true },
|
|
23771
23781
|
catalog: {
|
|
23772
23782
|
type: "openai-compatible-models",
|
|
@@ -23776,7 +23786,9 @@ var defaultConfig = {
|
|
|
23776
23786
|
"ollama-cloud": {
|
|
23777
23787
|
type: "ollama",
|
|
23778
23788
|
baseURL: "https://ollama.com/api",
|
|
23789
|
+
apiKey: "",
|
|
23779
23790
|
apiKeyEnv: "OLLAMA_API_KEY",
|
|
23791
|
+
modelProfiles: [],
|
|
23780
23792
|
catalog: {
|
|
23781
23793
|
type: "ollama-tags",
|
|
23782
23794
|
endpoint: "https://ollama.com/api/tags"
|
|
@@ -23786,6 +23798,7 @@ var defaultConfig = {
|
|
|
23786
23798
|
type: "openai-compatible",
|
|
23787
23799
|
baseURL: "http://localhost:8080/v1",
|
|
23788
23800
|
apiKey: "llama.cpp",
|
|
23801
|
+
modelProfiles: [],
|
|
23789
23802
|
catalog: {
|
|
23790
23803
|
type: "openai-compatible-models",
|
|
23791
23804
|
endpoint: "http://localhost:8080/v1/models"
|
|
@@ -23795,6 +23808,7 @@ var defaultConfig = {
|
|
|
23795
23808
|
type: "openai-compatible",
|
|
23796
23809
|
baseURL: "http://localhost:8000/v1",
|
|
23797
23810
|
apiKey: "vllm",
|
|
23811
|
+
modelProfiles: [],
|
|
23798
23812
|
catalog: {
|
|
23799
23813
|
type: "openai-compatible-models",
|
|
23800
23814
|
endpoint: "http://localhost:8000/v1/models"
|
|
@@ -24127,11 +24141,18 @@ function providerModelProfiles(providerName, providerConfig) {
|
|
|
24127
24141
|
return out;
|
|
24128
24142
|
}
|
|
24129
24143
|
function providerModelOptions(providerName, providerConfig) {
|
|
24130
|
-
return providerModelProfiles(providerName, providerConfig).filter((profile) => !profile.hidden).map((profile) => profile
|
|
24144
|
+
return providerModelProfiles(providerName, providerConfig).filter((profile) => !profile.hidden).map((profile) => displayModelForProfile(profile));
|
|
24131
24145
|
}
|
|
24132
24146
|
function defaultModelForProvider(providerName, providerConfig) {
|
|
24133
24147
|
return providerModelProfiles(providerName, providerConfig)[0]?.model ?? "";
|
|
24134
24148
|
}
|
|
24149
|
+
function displayModelForProfile(profile) {
|
|
24150
|
+
return profile.displayName?.trim() || profile.name?.trim() || profile.model;
|
|
24151
|
+
}
|
|
24152
|
+
function defaultDisplayModelForProvider(providerName, providerConfig) {
|
|
24153
|
+
const profile = providerModelProfiles(providerName, providerConfig)[0];
|
|
24154
|
+
return profile ? displayModelForProfile(profile) : defaultModelForProvider(providerName, providerConfig);
|
|
24155
|
+
}
|
|
24135
24156
|
function resolveConfiguredApiKey(providerConfig) {
|
|
24136
24157
|
if (providerConfig.apiKey) return { value: providerConfig.apiKey };
|
|
24137
24158
|
for (const envName of [providerConfig.apiKeyEnv, ...providerConfig.apiKeyEnvAliases ?? []]) {
|
|
@@ -24168,7 +24189,7 @@ function mergeModelProfile(providerConfig, profile) {
|
|
|
24168
24189
|
...providerConfig,
|
|
24169
24190
|
...definedOnly({
|
|
24170
24191
|
baseURL: profile.baseURL,
|
|
24171
|
-
apiKey: profile.apiKey,
|
|
24192
|
+
apiKey: nonEmptyString(profile.apiKey),
|
|
24172
24193
|
apiKeyEnv: profile.apiKeyEnv,
|
|
24173
24194
|
apiKeyEnvAliases: profile.apiKeyEnvAliases,
|
|
24174
24195
|
auth: profile.auth,
|
|
@@ -24183,6 +24204,9 @@ function mergeModelProfile(providerConfig, profile) {
|
|
|
24183
24204
|
function definedOnly(input2) {
|
|
24184
24205
|
return Object.fromEntries(Object.entries(input2).filter(([, value]) => value !== void 0));
|
|
24185
24206
|
}
|
|
24207
|
+
function nonEmptyString(value) {
|
|
24208
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
24209
|
+
}
|
|
24186
24210
|
function fallbackModelForProvider(providerName, providerConfig) {
|
|
24187
24211
|
if (typeof providerConfig.model === "string" && providerConfig.model.trim()) return providerConfig.model.trim();
|
|
24188
24212
|
if (providerName === "openai") return "gpt-5.5";
|
|
@@ -24439,18 +24463,21 @@ function defaultUserConfig(defaultProvider = detectDefaultProvider()) {
|
|
|
24439
24463
|
openai: {
|
|
24440
24464
|
type: "openai-compatible",
|
|
24441
24465
|
baseURL: "https://api.openai.com/v1",
|
|
24466
|
+
apiKey: "",
|
|
24442
24467
|
apiKeyEnv: "OPENAI_API_KEY",
|
|
24443
24468
|
catalog: { type: "openai-models", endpoint: "https://api.openai.com/v1/models" }
|
|
24444
24469
|
},
|
|
24445
24470
|
anthropic: {
|
|
24446
24471
|
type: "anthropic",
|
|
24447
24472
|
baseURL: "https://api.anthropic.com/v1",
|
|
24473
|
+
apiKey: "",
|
|
24448
24474
|
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
24449
24475
|
catalog: { type: "anthropic-models", endpoint: "https://api.anthropic.com/v1/models" }
|
|
24450
24476
|
},
|
|
24451
24477
|
gemini: {
|
|
24452
24478
|
type: "openai-compatible",
|
|
24453
24479
|
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/",
|
|
24480
|
+
apiKey: "",
|
|
24454
24481
|
apiKeyEnv: "GEMINI_API_KEY",
|
|
24455
24482
|
apiKeyEnvAliases: ["GOOGLE_API_KEY"],
|
|
24456
24483
|
catalog: { type: "gemini-openai-models", endpoint: "https://generativelanguage.googleapis.com/v1beta/openai/models" }
|
|
@@ -24458,6 +24485,7 @@ function defaultUserConfig(defaultProvider = detectDefaultProvider()) {
|
|
|
24458
24485
|
groq: {
|
|
24459
24486
|
type: "openai-compatible",
|
|
24460
24487
|
baseURL: "https://api.groq.com/openai/v1",
|
|
24488
|
+
apiKey: "",
|
|
24461
24489
|
apiKeyEnv: "GROQ_API_KEY",
|
|
24462
24490
|
catalog: { type: "groq-models", endpoint: "https://api.groq.com/openai/v1/models" }
|
|
24463
24491
|
},
|
|
@@ -24470,6 +24498,7 @@ function defaultUserConfig(defaultProvider = detectDefaultProvider()) {
|
|
|
24470
24498
|
displayName: "Azure example",
|
|
24471
24499
|
model: "azure-deployment-name",
|
|
24472
24500
|
baseURL: "https://example.openai.azure.com/openai/v1",
|
|
24501
|
+
apiKey: "",
|
|
24473
24502
|
apiKeyEnv: "AZURE_OPENAI_API_KEY"
|
|
24474
24503
|
}
|
|
24475
24504
|
]
|
|
@@ -24478,31 +24507,37 @@ function defaultUserConfig(defaultProvider = detectDefaultProvider()) {
|
|
|
24478
24507
|
type: "openai-compatible",
|
|
24479
24508
|
baseURL: "http://localhost:1234/v1",
|
|
24480
24509
|
apiKey: "lm-studio",
|
|
24510
|
+
modelProfiles: [],
|
|
24481
24511
|
catalog: { type: "openai-compatible-models", endpoint: "http://localhost:1234/v1/models" }
|
|
24482
24512
|
},
|
|
24483
24513
|
"ollama-local": {
|
|
24484
24514
|
type: "openai-compatible",
|
|
24485
24515
|
baseURL: "http://localhost:11434/v1",
|
|
24486
24516
|
apiKey: "ollama",
|
|
24517
|
+
modelProfiles: [],
|
|
24487
24518
|
quirks: { omitTemperature: true },
|
|
24488
24519
|
catalog: { type: "openai-compatible-models", endpoint: "http://localhost:11434/v1/models" }
|
|
24489
24520
|
},
|
|
24490
24521
|
"ollama-cloud": {
|
|
24491
24522
|
type: "ollama",
|
|
24492
24523
|
baseURL: "https://ollama.com/api",
|
|
24524
|
+
apiKey: "",
|
|
24493
24525
|
apiKeyEnv: "OLLAMA_API_KEY",
|
|
24526
|
+
modelProfiles: [],
|
|
24494
24527
|
catalog: { type: "ollama-tags", endpoint: "https://ollama.com/api/tags" }
|
|
24495
24528
|
},
|
|
24496
24529
|
llamacpp: {
|
|
24497
24530
|
type: "openai-compatible",
|
|
24498
24531
|
baseURL: "http://localhost:8080/v1",
|
|
24499
24532
|
apiKey: "llama.cpp",
|
|
24533
|
+
modelProfiles: [],
|
|
24500
24534
|
catalog: { type: "openai-compatible-models", endpoint: "http://localhost:8080/v1/models" }
|
|
24501
24535
|
},
|
|
24502
24536
|
vllm: {
|
|
24503
24537
|
type: "openai-compatible",
|
|
24504
24538
|
baseURL: "http://localhost:8000/v1",
|
|
24505
24539
|
apiKey: "vllm",
|
|
24540
|
+
modelProfiles: [],
|
|
24506
24541
|
catalog: { type: "openai-compatible-models", endpoint: "http://localhost:8000/v1/models" }
|
|
24507
24542
|
},
|
|
24508
24543
|
codex: {
|
|
@@ -24574,7 +24609,7 @@ async function addModelProfile(options) {
|
|
|
24574
24609
|
displayName,
|
|
24575
24610
|
model: options.model,
|
|
24576
24611
|
...options.baseURL ? { baseURL: options.baseURL } : {},
|
|
24577
|
-
...options.apiKey ? { apiKey: options.apiKey } : {},
|
|
24612
|
+
...options.apiKey !== void 0 || options.apiKeyEnv ? { apiKey: options.apiKey ?? "" } : {},
|
|
24578
24613
|
...options.apiKeyEnv ? { apiKeyEnv: options.apiKeyEnv } : {}
|
|
24579
24614
|
};
|
|
24580
24615
|
if (existingByName >= 0) profiles[existingByName] = next;
|
|
@@ -24596,18 +24631,15 @@ async function readConfigObject(filePath) {
|
|
|
24596
24631
|
}
|
|
24597
24632
|
function providerPreset(options) {
|
|
24598
24633
|
const preset = options.preset ?? options.name;
|
|
24599
|
-
const auth =
|
|
24600
|
-
...options.apiKey ? { apiKey: options.apiKey } : {},
|
|
24601
|
-
...options.apiKeyEnv ? { apiKeyEnv: options.apiKeyEnv } : {}
|
|
24602
|
-
};
|
|
24634
|
+
const auth = apiKeyAuthFields(options);
|
|
24603
24635
|
const openAIAuth = options.authHeader ? { auth: { type: "api-key", header: options.authHeader } } : {};
|
|
24604
|
-
if (preset === "openai") return { type: "openai-compatible", baseURL: options.baseURL ?? "https://api.openai.com/v1",
|
|
24605
|
-
if (preset === "anthropic") return { type: "anthropic", baseURL: options.baseURL ?? "https://api.anthropic.com/v1",
|
|
24636
|
+
if (preset === "openai") return { type: "openai-compatible", baseURL: options.baseURL ?? "https://api.openai.com/v1", ...apiKeyAuthFields(options, "OPENAI_API_KEY"), ...openAIAuth, catalog: { type: "openai-models", endpoint: `${(options.baseURL ?? "https://api.openai.com/v1").replace(/\/+$/, "")}/models` } };
|
|
24637
|
+
if (preset === "anthropic") return { type: "anthropic", baseURL: options.baseURL ?? "https://api.anthropic.com/v1", ...apiKeyAuthFields(options, "ANTHROPIC_API_KEY"), catalog: { type: "anthropic-models", endpoint: `${(options.baseURL ?? "https://api.anthropic.com/v1").replace(/\/+$/, "")}/models` } };
|
|
24606
24638
|
if (preset === "gemini") {
|
|
24607
24639
|
const geminiBase = options.baseURL ?? "https://generativelanguage.googleapis.com/v1beta/openai/";
|
|
24608
|
-
return { type: "openai-compatible", baseURL: geminiBase,
|
|
24640
|
+
return { type: "openai-compatible", baseURL: geminiBase, ...apiKeyAuthFields(options, "GEMINI_API_KEY"), apiKeyEnvAliases: ["GOOGLE_API_KEY"], ...openAIAuth, catalog: { type: "gemini-openai-models", endpoint: `${geminiBase.replace(/\/+$/, "")}/models` } };
|
|
24609
24641
|
}
|
|
24610
|
-
if (preset === "groq") return { type: "openai-compatible", baseURL: options.baseURL ?? "https://api.groq.com/openai/v1",
|
|
24642
|
+
if (preset === "groq") return { type: "openai-compatible", baseURL: options.baseURL ?? "https://api.groq.com/openai/v1", ...apiKeyAuthFields(options, "GROQ_API_KEY"), ...openAIAuth, catalog: { type: "groq-models", endpoint: `${(options.baseURL ?? "https://api.groq.com/openai/v1").replace(/\/+$/, "")}/models` } };
|
|
24611
24643
|
if (preset === "azure") {
|
|
24612
24644
|
return {
|
|
24613
24645
|
type: "openai-compatible",
|
|
@@ -24619,16 +24651,17 @@ function providerPreset(options) {
|
|
|
24619
24651
|
displayName: "Azure example",
|
|
24620
24652
|
model: "azure-deployment-name",
|
|
24621
24653
|
baseURL: options.baseURL ?? "https://example.openai.azure.com/openai/v1",
|
|
24654
|
+
...options.apiKey ? {} : { apiKey: "" },
|
|
24622
24655
|
apiKeyEnv: options.apiKeyEnv ?? "AZURE_OPENAI_API_KEY"
|
|
24623
24656
|
}
|
|
24624
24657
|
]
|
|
24625
24658
|
};
|
|
24626
24659
|
}
|
|
24627
|
-
if (preset === "lmstudio") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:1234/v1", apiKey: options.apiKey ?? "lm-studio", catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:1234/v1").replace(/\/+$/, "")}/models` } };
|
|
24628
|
-
if (preset === "ollama-local" || preset === "ollama") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:11434/v1", apiKey: options.apiKey ?? "ollama", quirks: { omitTemperature: true }, catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:11434/v1").replace(/\/+$/, "")}/models` } };
|
|
24629
|
-
if (preset === "ollama-cloud") return { type: "ollama", baseURL: options.baseURL ?? "https://ollama.com/api", ...
|
|
24630
|
-
if (preset === "llamacpp") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:8080/v1", apiKey: options.apiKey ?? "llama.cpp", catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:8080/v1").replace(/\/+$/, "")}/models` } };
|
|
24631
|
-
if (preset === "vllm") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:8000/v1", apiKey: options.apiKey ?? "vllm", catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:8000/v1").replace(/\/+$/, "")}/models` } };
|
|
24660
|
+
if (preset === "lmstudio") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:1234/v1", apiKey: options.apiKey ?? "lm-studio", modelProfiles: [], catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:1234/v1").replace(/\/+$/, "")}/models` } };
|
|
24661
|
+
if (preset === "ollama-local" || preset === "ollama") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:11434/v1", apiKey: options.apiKey ?? "ollama", modelProfiles: [], quirks: { omitTemperature: true }, catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:11434/v1").replace(/\/+$/, "")}/models` } };
|
|
24662
|
+
if (preset === "ollama-cloud") return { type: "ollama", baseURL: options.baseURL ?? "https://ollama.com/api", ...apiKeyAuthFields(options, "OLLAMA_API_KEY"), modelProfiles: [], catalog: { type: "ollama-tags", endpoint: `${(options.baseURL ?? "https://ollama.com/api").replace(/\/+$/, "")}/tags` } };
|
|
24663
|
+
if (preset === "llamacpp") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:8080/v1", apiKey: options.apiKey ?? "llama.cpp", modelProfiles: [], catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:8080/v1").replace(/\/+$/, "")}/models` } };
|
|
24664
|
+
if (preset === "vllm") return { type: "openai-compatible", baseURL: options.baseURL ?? "http://localhost:8000/v1", apiKey: options.apiKey ?? "vllm", modelProfiles: [], catalog: { type: "openai-compatible-models", endpoint: `${(options.baseURL ?? "http://localhost:8000/v1").replace(/\/+$/, "")}/models` } };
|
|
24632
24665
|
if (preset === "codex") return { type: "codex", baseURL: options.baseURL ?? "https://chatgpt.com/backend-api/codex", authStore: "auto", allowApiKeyFallback: false, promptCacheKey: "root-session", catalog: { type: "codex-oauth-models" } };
|
|
24633
24666
|
if (preset === "claudecode") return { type: "claudecode", runtime: "agent-sdk", cliPath: "~/.local/bin/claude", cwdMode: "session", historyPolicy: "passthrough-resume", onInvalidResume: "fresh", attachmentFallback: "block", allowSubagents: false, sanitizeApiKeyEnv: true, authPreflight: true, useBareMode: false, usageLedgerScope: "process", sessionLock: true, abortPolicy: "record-only", catalog: { type: "claudecode-supported-models" } };
|
|
24634
24667
|
if ((options.type ?? preset) === "openai-compatible") {
|
|
@@ -24637,14 +24670,20 @@ function providerPreset(options) {
|
|
|
24637
24670
|
return {
|
|
24638
24671
|
type: "openai-compatible",
|
|
24639
24672
|
baseURL,
|
|
24640
|
-
...
|
|
24641
|
-
...options.apiKeyEnv ? { apiKeyEnv: options.apiKeyEnv } : {},
|
|
24673
|
+
...auth,
|
|
24642
24674
|
...openAIAuth,
|
|
24643
24675
|
catalog: { type: "openai-compatible-models", endpoint: `${baseURL.replace(/\/+$/, "")}/models` }
|
|
24644
24676
|
};
|
|
24645
24677
|
}
|
|
24646
24678
|
throw new Error(`Unknown provider preset: ${preset}`);
|
|
24647
24679
|
}
|
|
24680
|
+
function apiKeyAuthFields(options, defaultApiKeyEnv) {
|
|
24681
|
+
const apiKeyEnv = options.apiKeyEnv ?? defaultApiKeyEnv;
|
|
24682
|
+
return {
|
|
24683
|
+
...options.apiKey !== void 0 || apiKeyEnv ? { apiKey: options.apiKey ?? "" } : {},
|
|
24684
|
+
...apiKeyEnv ? { apiKeyEnv } : {}
|
|
24685
|
+
};
|
|
24686
|
+
}
|
|
24648
24687
|
async function writeJsonAtomic(filePath, content) {
|
|
24649
24688
|
await mkdir6(path14.dirname(filePath), { recursive: true, mode: 448 });
|
|
24650
24689
|
const temp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
@@ -28019,7 +28058,7 @@ async function runExaSearch(config, options) {
|
|
|
28019
28058
|
return searchResult("exa", options.query, results, json.value);
|
|
28020
28059
|
}
|
|
28021
28060
|
function resolveApiKey(provider, config) {
|
|
28022
|
-
const value = config.apiKey
|
|
28061
|
+
const value = config.apiKey || (config.apiKeyEnv ? process.env[config.apiKeyEnv] : void 0);
|
|
28023
28062
|
if (value) return { ok: true, value };
|
|
28024
28063
|
return toolFail(`Missing API key for web_search provider "${provider}". Set webSearch.providers.${provider}.apiKey or set ${config.apiKeyEnv ?? "the configured apiKeyEnv"}.`);
|
|
28025
28064
|
}
|
|
@@ -31090,7 +31129,7 @@ function providerOptions(config, catalogs = {}) {
|
|
|
31090
31129
|
isDefault: model.isDefault
|
|
31091
31130
|
})) : providerModelProfiles(name, provider);
|
|
31092
31131
|
const modelProfiles = profiles.map((profile) => {
|
|
31093
|
-
const displayName = profile
|
|
31132
|
+
const displayName = displayModelForProfile(profile);
|
|
31094
31133
|
return {
|
|
31095
31134
|
...profile,
|
|
31096
31135
|
label: available ? displayName : unavailableLabel(displayName),
|
|
@@ -31098,7 +31137,7 @@ function providerOptions(config, catalogs = {}) {
|
|
|
31098
31137
|
};
|
|
31099
31138
|
});
|
|
31100
31139
|
const models = modelProfiles.length ? [...new Set(modelProfiles.map((item) => item.model).filter((item) => typeof item === "string" && item.trim()))] : providerModelOptions(name, provider);
|
|
31101
|
-
const defaultModel =
|
|
31140
|
+
const defaultModel = defaultDisplayModelForProvider(name, provider);
|
|
31102
31141
|
return {
|
|
31103
31142
|
name,
|
|
31104
31143
|
label: available ? name : unavailableLabel(name),
|
|
@@ -31144,13 +31183,18 @@ function createInteractiveModelSelection(config, flags = {}, saved) {
|
|
|
31144
31183
|
}
|
|
31145
31184
|
const usesSavedProvider = !flags.provider && savedProviderExists && providerName === savedProviderName;
|
|
31146
31185
|
const savedModel = usesSavedProvider && saved?.model ? saved.model : void 0;
|
|
31147
|
-
const
|
|
31186
|
+
const profiles = providerModelProfiles(providerName, providerConfig);
|
|
31187
|
+
const savedProfile = savedModel ? profiles.find((profile) => profile.model === savedModel || profile.displayName === savedModel || profile.name === savedModel) : void 0;
|
|
31188
|
+
const defaultModel = displayModelForProfile(profiles[0] ?? { name: "", displayName: "", model: "" }) || defaultDisplayModelForProvider(providerName, providerConfig);
|
|
31189
|
+
const flagProfile = flags.model ? profiles.find((profile) => profile.model === flags.model || profile.displayName === flags.model || profile.name === flags.model) : void 0;
|
|
31190
|
+
const selectedProfile = flags.model ? flagProfile : savedModel ? savedProfile : profiles[0];
|
|
31191
|
+
const model = flags.model ?? (savedProfile ? displayModelForProfile(savedProfile) : savedModel) ?? defaultModel;
|
|
31148
31192
|
return {
|
|
31149
31193
|
providerName,
|
|
31150
31194
|
providerSource: flags.provider ? "flag" : usesSavedProvider ? "saved" : "config",
|
|
31151
31195
|
model,
|
|
31152
31196
|
modelSource: flags.model ? "flag" : savedModel ? "saved" : "config",
|
|
31153
|
-
modelProfileName:
|
|
31197
|
+
modelProfileName: selectedProfile?.name
|
|
31154
31198
|
};
|
|
31155
31199
|
}
|
|
31156
31200
|
function selectProvider(config, selection, providerName) {
|
|
@@ -31161,7 +31205,7 @@ function selectProvider(config, selection, providerName) {
|
|
|
31161
31205
|
...selection,
|
|
31162
31206
|
providerName,
|
|
31163
31207
|
providerSource: "interactive",
|
|
31164
|
-
model: profile
|
|
31208
|
+
model: profile ? displayModelForProfile(profile) : defaultDisplayModelForProvider(providerName, providerConfig),
|
|
31165
31209
|
modelSource: "config",
|
|
31166
31210
|
modelProfileName: profile?.name
|
|
31167
31211
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -23641,6 +23641,7 @@ var defaultConfig = {
|
|
|
23641
23641
|
defaultProvider: "brave",
|
|
23642
23642
|
providers: {
|
|
23643
23643
|
brave: {
|
|
23644
|
+
apiKey: "",
|
|
23644
23645
|
apiKeyEnv: "BRAVE_SEARCH_API_KEY",
|
|
23645
23646
|
endpoint: "https://api.search.brave.com/res/v1/web/search",
|
|
23646
23647
|
count: 10,
|
|
@@ -23649,12 +23650,14 @@ var defaultConfig = {
|
|
|
23649
23650
|
safeSearch: "moderate"
|
|
23650
23651
|
},
|
|
23651
23652
|
tavily: {
|
|
23653
|
+
apiKey: "",
|
|
23652
23654
|
apiKeyEnv: "TAVILY_API_KEY",
|
|
23653
23655
|
endpoint: "https://api.tavily.com/search",
|
|
23654
23656
|
maxResults: 5,
|
|
23655
23657
|
searchDepth: "basic"
|
|
23656
23658
|
},
|
|
23657
23659
|
exa: {
|
|
23660
|
+
apiKey: "",
|
|
23658
23661
|
apiKeyEnv: "EXA_API_KEY",
|
|
23659
23662
|
endpoint: "https://api.exa.ai/search",
|
|
23660
23663
|
numResults: 5,
|
|
@@ -23709,6 +23712,7 @@ var defaultConfig = {
|
|
|
23709
23712
|
openai: {
|
|
23710
23713
|
type: "openai-compatible",
|
|
23711
23714
|
baseURL: "https://api.openai.com/v1",
|
|
23715
|
+
apiKey: "",
|
|
23712
23716
|
apiKeyEnv: "OPENAI_API_KEY",
|
|
23713
23717
|
catalog: {
|
|
23714
23718
|
type: "openai-models",
|
|
@@ -23718,6 +23722,7 @@ var defaultConfig = {
|
|
|
23718
23722
|
anthropic: {
|
|
23719
23723
|
type: "anthropic",
|
|
23720
23724
|
baseURL: "https://api.anthropic.com/v1",
|
|
23725
|
+
apiKey: "",
|
|
23721
23726
|
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
23722
23727
|
catalog: {
|
|
23723
23728
|
type: "anthropic-models",
|
|
@@ -23727,6 +23732,7 @@ var defaultConfig = {
|
|
|
23727
23732
|
gemini: {
|
|
23728
23733
|
type: "openai-compatible",
|
|
23729
23734
|
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/",
|
|
23735
|
+
apiKey: "",
|
|
23730
23736
|
apiKeyEnv: "GEMINI_API_KEY",
|
|
23731
23737
|
apiKeyEnvAliases: ["GOOGLE_API_KEY"],
|
|
23732
23738
|
catalog: {
|
|
@@ -23737,6 +23743,7 @@ var defaultConfig = {
|
|
|
23737
23743
|
groq: {
|
|
23738
23744
|
type: "openai-compatible",
|
|
23739
23745
|
baseURL: "https://api.groq.com/openai/v1",
|
|
23746
|
+
apiKey: "",
|
|
23740
23747
|
apiKeyEnv: "GROQ_API_KEY",
|
|
23741
23748
|
catalog: {
|
|
23742
23749
|
type: "groq-models",
|
|
@@ -23752,6 +23759,7 @@ var defaultConfig = {
|
|
|
23752
23759
|
displayName: "Azure example",
|
|
23753
23760
|
model: "azure-deployment-name",
|
|
23754
23761
|
baseURL: "https://example.openai.azure.com/openai/v1",
|
|
23762
|
+
apiKey: "",
|
|
23755
23763
|
apiKeyEnv: "AZURE_OPENAI_API_KEY"
|
|
23756
23764
|
}
|
|
23757
23765
|
]
|
|
@@ -23760,6 +23768,7 @@ var defaultConfig = {
|
|
|
23760
23768
|
type: "openai-compatible",
|
|
23761
23769
|
baseURL: "http://localhost:1234/v1",
|
|
23762
23770
|
apiKey: "lm-studio",
|
|
23771
|
+
modelProfiles: [],
|
|
23763
23772
|
catalog: {
|
|
23764
23773
|
type: "openai-compatible-models",
|
|
23765
23774
|
endpoint: "http://localhost:1234/v1/models"
|
|
@@ -23769,6 +23778,7 @@ var defaultConfig = {
|
|
|
23769
23778
|
type: "openai-compatible",
|
|
23770
23779
|
baseURL: "http://localhost:11434/v1",
|
|
23771
23780
|
apiKey: "ollama",
|
|
23781
|
+
modelProfiles: [],
|
|
23772
23782
|
quirks: { omitTemperature: true },
|
|
23773
23783
|
catalog: {
|
|
23774
23784
|
type: "openai-compatible-models",
|
|
@@ -23778,7 +23788,9 @@ var defaultConfig = {
|
|
|
23778
23788
|
"ollama-cloud": {
|
|
23779
23789
|
type: "ollama",
|
|
23780
23790
|
baseURL: "https://ollama.com/api",
|
|
23791
|
+
apiKey: "",
|
|
23781
23792
|
apiKeyEnv: "OLLAMA_API_KEY",
|
|
23793
|
+
modelProfiles: [],
|
|
23782
23794
|
catalog: {
|
|
23783
23795
|
type: "ollama-tags",
|
|
23784
23796
|
endpoint: "https://ollama.com/api/tags"
|
|
@@ -23788,6 +23800,7 @@ var defaultConfig = {
|
|
|
23788
23800
|
type: "openai-compatible",
|
|
23789
23801
|
baseURL: "http://localhost:8080/v1",
|
|
23790
23802
|
apiKey: "llama.cpp",
|
|
23803
|
+
modelProfiles: [],
|
|
23791
23804
|
catalog: {
|
|
23792
23805
|
type: "openai-compatible-models",
|
|
23793
23806
|
endpoint: "http://localhost:8080/v1/models"
|
|
@@ -23797,6 +23810,7 @@ var defaultConfig = {
|
|
|
23797
23810
|
type: "openai-compatible",
|
|
23798
23811
|
baseURL: "http://localhost:8000/v1",
|
|
23799
23812
|
apiKey: "vllm",
|
|
23813
|
+
modelProfiles: [],
|
|
23800
23814
|
catalog: {
|
|
23801
23815
|
type: "openai-compatible-models",
|
|
23802
23816
|
endpoint: "http://localhost:8000/v1/models"
|
|
@@ -24129,11 +24143,18 @@ function providerModelProfiles(providerName, providerConfig) {
|
|
|
24129
24143
|
return out;
|
|
24130
24144
|
}
|
|
24131
24145
|
function providerModelOptions(providerName, providerConfig) {
|
|
24132
|
-
return providerModelProfiles(providerName, providerConfig).filter((profile) => !profile.hidden).map((profile) => profile
|
|
24146
|
+
return providerModelProfiles(providerName, providerConfig).filter((profile) => !profile.hidden).map((profile) => displayModelForProfile(profile));
|
|
24133
24147
|
}
|
|
24134
24148
|
function defaultModelForProvider(providerName, providerConfig) {
|
|
24135
24149
|
return providerModelProfiles(providerName, providerConfig)[0]?.model ?? "";
|
|
24136
24150
|
}
|
|
24151
|
+
function displayModelForProfile(profile) {
|
|
24152
|
+
return profile.displayName?.trim() || profile.name?.trim() || profile.model;
|
|
24153
|
+
}
|
|
24154
|
+
function defaultDisplayModelForProvider(providerName, providerConfig) {
|
|
24155
|
+
const profile = providerModelProfiles(providerName, providerConfig)[0];
|
|
24156
|
+
return profile ? displayModelForProfile(profile) : defaultModelForProvider(providerName, providerConfig);
|
|
24157
|
+
}
|
|
24137
24158
|
function resolveConfiguredApiKey(providerConfig) {
|
|
24138
24159
|
if (providerConfig.apiKey) return { value: providerConfig.apiKey };
|
|
24139
24160
|
for (const envName of [providerConfig.apiKeyEnv, ...providerConfig.apiKeyEnvAliases ?? []]) {
|
|
@@ -24211,7 +24232,7 @@ function mergeModelProfile(providerConfig, profile) {
|
|
|
24211
24232
|
...providerConfig,
|
|
24212
24233
|
...definedOnly({
|
|
24213
24234
|
baseURL: profile.baseURL,
|
|
24214
|
-
apiKey: profile.apiKey,
|
|
24235
|
+
apiKey: nonEmptyString(profile.apiKey),
|
|
24215
24236
|
apiKeyEnv: profile.apiKeyEnv,
|
|
24216
24237
|
apiKeyEnvAliases: profile.apiKeyEnvAliases,
|
|
24217
24238
|
auth: profile.auth,
|
|
@@ -24226,6 +24247,9 @@ function mergeModelProfile(providerConfig, profile) {
|
|
|
24226
24247
|
function definedOnly(input2) {
|
|
24227
24248
|
return Object.fromEntries(Object.entries(input2).filter(([, value]) => value !== void 0));
|
|
24228
24249
|
}
|
|
24250
|
+
function nonEmptyString(value) {
|
|
24251
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
24252
|
+
}
|
|
24229
24253
|
function fallbackModelForProvider(providerName, providerConfig) {
|
|
24230
24254
|
if (typeof providerConfig.model === "string" && providerConfig.model.trim()) return providerConfig.model.trim();
|
|
24231
24255
|
if (providerName === "openai") return "gpt-5.5";
|
|
@@ -27220,7 +27244,7 @@ async function runExaSearch(config, options) {
|
|
|
27220
27244
|
return searchResult("exa", options.query, results, json.value);
|
|
27221
27245
|
}
|
|
27222
27246
|
function resolveApiKey(provider, config) {
|
|
27223
|
-
const value = config.apiKey
|
|
27247
|
+
const value = config.apiKey || (config.apiKeyEnv ? process.env[config.apiKeyEnv] : void 0);
|
|
27224
27248
|
if (value) return { ok: true, value };
|
|
27225
27249
|
return toolFail(`Missing API key for web_search provider "${provider}". Set webSearch.providers.${provider}.apiKey or set ${config.apiKeyEnv ?? "the configured apiKeyEnv"}.`);
|
|
27226
27250
|
}
|
|
@@ -29490,7 +29514,9 @@ export {
|
|
|
29490
29514
|
defaultConfig,
|
|
29491
29515
|
defaultDecisionForPermissionPreset,
|
|
29492
29516
|
defaultDemianStorageDir,
|
|
29517
|
+
defaultDisplayModelForProvider,
|
|
29493
29518
|
defaultModelForProvider,
|
|
29519
|
+
displayModelForProfile,
|
|
29494
29520
|
estimateMessageTokens,
|
|
29495
29521
|
estimateMessagesTokens,
|
|
29496
29522
|
estimateToolSchemaTokens,
|