neko-harness 0.4.5 → 0.4.6
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 -3
- package/dist/client/assets/{index-zaSSWfyH.js → index--Ml3HA5z.js} +58 -58
- package/dist/client/assets/index-Cdi87SA6.css +2 -0
- package/dist/client/index.html +2 -2
- package/dist/gateway.js +274 -61
- package/dist/neko.js +711 -168
- package/package.json +1 -1
- package/dist/client/assets/index-Bwk2sNhZ.css +0 -2
package/dist/gateway.js
CHANGED
|
@@ -16497,14 +16497,16 @@ var GATEWAY_USAGE = `\u7528\u6CD5: neko serve [\u9009\u9879]
|
|
|
16497
16497
|
--no-socket \u7981\u7528 Unix socket \u4F20\u8F93\uFF08\u4EC5 WebSocket\uFF09
|
|
16498
16498
|
--server-id <id> \u903B\u8F91\u670D\u52A1\u5668\u8EAB\u4EFD\uFF08\u9ED8\u8BA4\u8BFB\u53D6/\u751F\u6210 <\u6570\u636E\u76EE\u5F55>/gateway-server-id\uFF09
|
|
16499
16499
|
--cwd <dir> \u4F1A\u8BDD\u5DE5\u5177\u7684\u5DE5\u4F5C\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09
|
|
16500
|
-
--model <ref> \u6A21\u578B\uFF0C\u683C\u5F0F provider/modelId\
|
|
16500
|
+
--model <ref> \u6A21\u578B\uFF0C\u683C\u5F0F provider/modelId\uFF08modelId \u53EF\u542B /\uFF0C\u9ED8\u8BA4 deepseek/deepseek-flash\uFF09
|
|
16501
16501
|
--storage <path> SQLite \u5B58\u50A8\u6587\u4EF6\uFF08\u9ED8\u8BA4 ~/.neko/neko.sqlite\uFF09
|
|
16502
16502
|
--credentials <path> \u7528\u6237\u51ED\u636E\u6587\u4EF6\uFF08\u9ED8\u8BA4 ~/.neko/credentials.json\uFF09
|
|
16503
16503
|
--config <dir> neko.config.json \u67E5\u627E\u8D77\u59CB\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09
|
|
16504
16504
|
-h, --help \u663E\u793A\u6B64\u5E2E\u52A9
|
|
16505
16505
|
|
|
16506
|
-
\u53EF\u901A\u8FC7\u524D\u7AEF\u8BBE\u7F6E\u6216
|
|
16507
|
-
\
|
|
16506
|
+
\u53EF\u901A\u8FC7\u524D\u7AEF\u8BBE\u7F6E\u6216\u73AF\u5883\u53D8\u91CF\uFF08DEEPSEEK_API_KEY / OPENROUTER_API_KEY / OPENCODE_API_KEY / TAVILY_API_KEY \u7B49\uFF09\u914D\u7F6E\u51ED\u636E\uFF1B
|
|
16507
|
+
\u9664 DeepSeek \u5916\u7684\u6A21\u578B provider \u9700\u5148\u5728\u524D\u7AEF\u542F\u7528\uFF0C--model \u6307\u5411\u672A\u542F\u7528\u7684 provider \u65F6\u63D0\u4EA4\u4F1A\u88AB\u62D2\u7EDD\uFF1B
|
|
16508
|
+
\u8054\u7F51\u641C\u7D22\u670D\u52A1\u53EF\u5728\u524D\u7AEF\u8BBE\u7F6E\uFF0C\u6216\u7528\u914D\u7F6E\u6587\u4EF6 webSearch.provider\uFF08tavily / deepseek\uFF0C\u9ED8\u8BA4 tavily\uFF09\uFF1B
|
|
16509
|
+
\u9ED8\u8BA4\u6A21\u578B\u8FD8\u53EF\u5728 TUI /model \u6216 Web \u6A21\u578B\u9009\u62E9\u5668\u4E2D\u300C\u8BBE\u4E3A\u9ED8\u8BA4\u300D\uFF0C\u4F18\u5148\u7EA7\u4F4E\u4E8E --model\u3001\u9AD8\u4E8E\u914D\u7F6E\u6587\u4EF6 defaultModel\u3002`;
|
|
16508
16510
|
function parseGatewayArgs(argv) {
|
|
16509
16511
|
let port;
|
|
16510
16512
|
const options = {};
|
|
@@ -16912,16 +16914,70 @@ import { homedir as homedir2 } from "os";
|
|
|
16912
16914
|
import { dirname as dirname2, join as join2 } from "path";
|
|
16913
16915
|
|
|
16914
16916
|
// packages/core/src/credential-providers.ts
|
|
16917
|
+
var model = (id, name, envVar, signupUrl) => ({ id, kind: "model", name, envVar, signupUrl, keyless: false });
|
|
16918
|
+
var MODEL_PROVIDERS = [
|
|
16919
|
+
model("deepseek", "DeepSeek", "DEEPSEEK_API_KEY", "https://platform.deepseek.com/api_keys"),
|
|
16920
|
+
model("openrouter", "OpenRouter", "OPENROUTER_API_KEY", "https://openrouter.ai/keys"),
|
|
16921
|
+
model("opencode-go", "OpenCode Go", "OPENCODE_API_KEY", "https://opencode.ai/auth"),
|
|
16922
|
+
model("opencode", "OpenCode Zen", "OPENCODE_API_KEY", "https://opencode.ai/auth"),
|
|
16923
|
+
model("openai", "OpenAI", "OPENAI_API_KEY", "https://platform.openai.com/api-keys"),
|
|
16924
|
+
model("google", "Google", "GEMINI_API_KEY", "https://aistudio.google.com/apikey"),
|
|
16925
|
+
model("groq", "Groq", "GROQ_API_KEY", "https://console.groq.com/keys"),
|
|
16926
|
+
model("mistral", "Mistral", "MISTRAL_API_KEY", "https://console.mistral.ai/api-keys"),
|
|
16927
|
+
model("xai", "xAI", "XAI_API_KEY", "https://console.x.ai"),
|
|
16928
|
+
model("together", "Together", "TOGETHER_API_KEY", "https://api.together.ai/settings/api-keys"),
|
|
16929
|
+
model("fireworks", "Fireworks", "FIREWORKS_API_KEY", "https://fireworks.ai/account/api-keys"),
|
|
16930
|
+
model("cerebras", "Cerebras", "CEREBRAS_API_KEY", "https://cloud.cerebras.ai"),
|
|
16931
|
+
model("nvidia", "NVIDIA", "NVIDIA_API_KEY", "https://build.nvidia.com/settings/api-keys"),
|
|
16932
|
+
model("huggingface", "Hugging Face", "HF_TOKEN", "https://huggingface.co/settings/tokens"),
|
|
16933
|
+
model("vercel-ai-gateway", "Vercel AI Gateway", "AI_GATEWAY_API_KEY", "https://vercel.com/ai-gateway"),
|
|
16934
|
+
model("moonshotai", "Moonshot AI", "MOONSHOT_API_KEY", "https://platform.moonshot.ai/console/api-keys"),
|
|
16935
|
+
model("moonshotai-cn", "Moonshot AI CN", "MOONSHOT_API_KEY", "https://platform.moonshot.cn/console/api-keys"),
|
|
16936
|
+
model("minimax", "MiniMax", "MINIMAX_API_KEY", "https://platform.minimax.io"),
|
|
16937
|
+
model("minimax-cn", "MiniMax CN", "MINIMAX_CN_API_KEY", "https://platform.minimaxi.com"),
|
|
16938
|
+
model("zai", "Z.AI", "ZAI_API_KEY", "https://z.ai/manage-apikey/apikey-list"),
|
|
16939
|
+
model("zai-coding-cn", "Z.AI Coding CN", "ZAI_CODING_CN_API_KEY", "https://bigmodel.cn/usercenter/proj-mgmt/apikeys"),
|
|
16940
|
+
model("qwen-token-plan", "Qwen Token Plan", "QWEN_TOKEN_PLAN_API_KEY", "https://modelstudio.console.alibabacloud.com"),
|
|
16941
|
+
model("qwen-token-plan-cn", "Qwen Token Plan CN", "QWEN_TOKEN_PLAN_CN_API_KEY", "https://bailian.console.aliyun.com"),
|
|
16942
|
+
model("qwen-token-plan-individual", "Qwen Token Plan Individual", "QWEN_TOKEN_PLAN_API_KEY", "https://modelstudio.console.alibabacloud.com"),
|
|
16943
|
+
model("xiaomi", "Xiaomi MiMo", "XIAOMI_API_KEY", "https://platform.xiaomimimo.com"),
|
|
16944
|
+
model("xiaomi-token-plan-cn", "Xiaomi Token Plan CN", "XIAOMI_TOKEN_PLAN_CN_API_KEY", "https://platform.xiaomimimo.com"),
|
|
16945
|
+
model("xiaomi-token-plan-ams", "Xiaomi Token Plan AMS", "XIAOMI_TOKEN_PLAN_AMS_API_KEY", "https://platform.xiaomimimo.com"),
|
|
16946
|
+
model("xiaomi-token-plan-sgp", "Xiaomi Token Plan SGP", "XIAOMI_TOKEN_PLAN_SGP_API_KEY", "https://platform.xiaomimimo.com"),
|
|
16947
|
+
model("baseten", "Baseten", "BASETEN_API_KEY", "https://app.baseten.co/settings/api_keys"),
|
|
16948
|
+
model("ant-ling", "Ant Ling", "ANT_LING_API_KEY", "https://ling.tbox.cn"),
|
|
16949
|
+
model("kimi-coding", "Kimi For Coding", "KIMI_API_KEY", "https://www.kimi.com/code/console"),
|
|
16950
|
+
model("meta", "Meta", "META_API_KEY", "https://llama.developer.meta.com")
|
|
16951
|
+
];
|
|
16952
|
+
var SEARCH_CREDENTIAL_PROVIDERS = [
|
|
16953
|
+
{
|
|
16954
|
+
id: "tavily",
|
|
16955
|
+
kind: "search",
|
|
16956
|
+
name: "Tavily",
|
|
16957
|
+
envVar: "TAVILY_API_KEY",
|
|
16958
|
+
signupUrl: "https://app.tavily.com",
|
|
16959
|
+
keyless: true
|
|
16960
|
+
}
|
|
16961
|
+
];
|
|
16915
16962
|
var CREDENTIAL_PROVIDERS = [
|
|
16916
|
-
|
|
16917
|
-
|
|
16963
|
+
...MODEL_PROVIDERS,
|
|
16964
|
+
...SEARCH_CREDENTIAL_PROVIDERS
|
|
16918
16965
|
];
|
|
16966
|
+
var DEFAULT_ENABLED_PROVIDERS = ["deepseek"];
|
|
16967
|
+
var LOCKED_PROVIDERS = ["deepseek"];
|
|
16968
|
+
function isModelProvider(id) {
|
|
16969
|
+
return MODEL_PROVIDERS.some((item) => item.id === id);
|
|
16970
|
+
}
|
|
16919
16971
|
function credentialProvider(id) {
|
|
16920
16972
|
const spec = CREDENTIAL_PROVIDERS.find((item) => item.id === id);
|
|
16921
16973
|
if (!spec)
|
|
16922
16974
|
throw new Error(`Unknown credential provider: ${id}`);
|
|
16923
16975
|
return spec;
|
|
16924
16976
|
}
|
|
16977
|
+
function normalizeEnabledProviders(saved) {
|
|
16978
|
+
const wanted = new Set([...LOCKED_PROVIDERS, ...saved ?? DEFAULT_ENABLED_PROVIDERS]);
|
|
16979
|
+
return MODEL_PROVIDERS.map((item) => item.id).filter((id) => wanted.has(id));
|
|
16980
|
+
}
|
|
16925
16981
|
|
|
16926
16982
|
// packages/core/src/credentials.ts
|
|
16927
16983
|
import { InMemoryCredentialStore } from "@earendil-works/pi-ai";
|
|
@@ -17815,7 +17871,7 @@ var structuredOutputSchema = Type.Union([
|
|
|
17815
17871
|
next: Type.Union([Type.Integer(), Type.Null()])
|
|
17816
17872
|
}, { additionalProperties: false })
|
|
17817
17873
|
]);
|
|
17818
|
-
function createSubagentExtension(prepare, discard) {
|
|
17874
|
+
function createSubagentExtension(prepare, discard, guard) {
|
|
17819
17875
|
const finish = async (tx, input, status, report) => {
|
|
17820
17876
|
const round = (await tx.doc(DelegationsDoc, input.parentId)).items.find((r) => r.taskId === input.taskId);
|
|
17821
17877
|
round.status = status;
|
|
@@ -17959,6 +18015,8 @@ function createSubagentExtension(prepare, discard) {
|
|
|
17959
18015
|
if (!args.task.trim() || !args.title.trim() || Buffer.byteLength(args.task) > 32768)
|
|
17960
18016
|
throw new Error("Task/title must be nonempty; task limit is 32 KiB.");
|
|
17961
18017
|
const agent = await api.agent(context);
|
|
18018
|
+
if (agent.model)
|
|
18019
|
+
await guard?.(agent.model);
|
|
17962
18020
|
const round = await api.commit(async (tx) => {
|
|
17963
18021
|
const rounds = await refreshDelegations(tx, api.conversationId);
|
|
17964
18022
|
const receipt = rounds.find((r) => r.taskId === api.taskId);
|
|
@@ -18868,7 +18926,7 @@ import { homedir as homedir4 } from "os";
|
|
|
18868
18926
|
import { join as join5 } from "path";
|
|
18869
18927
|
import { BACKGROUND_CONTEXT as BACKGROUND_CONTEXT3 } from "@earendil-works/chord/context";
|
|
18870
18928
|
import { clampThinkingLevel, createModels, getSupportedThinkingLevels as getSupportedThinkingLevels2 } from "@earendil-works/pi-ai/models";
|
|
18871
|
-
import {
|
|
18929
|
+
import { builtinProviders } from "@earendil-works/pi-ai/providers/all";
|
|
18872
18930
|
import {
|
|
18873
18931
|
AssistantEntry as AssistantEntry2,
|
|
18874
18932
|
createRegistry,
|
|
@@ -20443,7 +20501,7 @@ function mergeUsage(base, extra) {
|
|
|
20443
20501
|
}
|
|
20444
20502
|
return result;
|
|
20445
20503
|
}
|
|
20446
|
-
function namingTask() {
|
|
20504
|
+
function namingTask(canUse) {
|
|
20447
20505
|
let active = 0;
|
|
20448
20506
|
const waits = new Set;
|
|
20449
20507
|
return defineTask3({
|
|
@@ -20480,7 +20538,7 @@ function namingTask() {
|
|
|
20480
20538
|
try {
|
|
20481
20539
|
const saved = await runtime.snapshot(SessionMetadataDoc, runtime.conversationId, context);
|
|
20482
20540
|
const model = saved?.model && runtime.models.getModel(saved.model.provider, saved.model.modelId);
|
|
20483
|
-
if (!saved || !model || saved.attempts >= 2 || !getSupportedThinkingLevels(model).includes("off")) {
|
|
20541
|
+
if (!saved || !model || saved.attempts >= 2 || !getSupportedThinkingLevels(model).includes("off") || !await canUse(model.provider, model.id)) {
|
|
20484
20542
|
await runtime.commit(async (tx) => {
|
|
20485
20543
|
(await tx.doc(SessionMetadataDoc, runtime.conversationId)).naming = "fallback";
|
|
20486
20544
|
return { status: "terminal", outcome: { status: "completed", result: null } };
|
|
@@ -20560,12 +20618,13 @@ class SessionMetadataManager {
|
|
|
20560
20618
|
#known = new Set;
|
|
20561
20619
|
#unsubscribe;
|
|
20562
20620
|
#live = new Map;
|
|
20563
|
-
task
|
|
20621
|
+
task;
|
|
20564
20622
|
harness;
|
|
20565
20623
|
storage;
|
|
20566
20624
|
context;
|
|
20567
20625
|
report;
|
|
20568
|
-
constructor(harness, storage, context, registry, report = console.error) {
|
|
20626
|
+
constructor(harness, storage, context, registry, report = console.error, canUseModel = async () => true) {
|
|
20627
|
+
this.task = namingTask(canUseModel);
|
|
20569
20628
|
this.harness = harness;
|
|
20570
20629
|
this.storage = storage;
|
|
20571
20630
|
this.context = context;
|
|
@@ -21852,6 +21911,22 @@ var SearchSettingsDoc = defineDoc7({
|
|
|
21852
21911
|
fork: "initial",
|
|
21853
21912
|
initial: () => ({ provider: null })
|
|
21854
21913
|
});
|
|
21914
|
+
var ProviderSettingsDoc = defineDoc7({
|
|
21915
|
+
kind: "app.neko.provider-settings",
|
|
21916
|
+
version: 1,
|
|
21917
|
+
scope: "conversation",
|
|
21918
|
+
history: "latest",
|
|
21919
|
+
fork: "initial",
|
|
21920
|
+
initial: () => ({ enabled: null })
|
|
21921
|
+
});
|
|
21922
|
+
var DefaultModelDoc = defineDoc7({
|
|
21923
|
+
kind: "app.neko.default-model",
|
|
21924
|
+
version: 1,
|
|
21925
|
+
scope: "conversation",
|
|
21926
|
+
history: "latest",
|
|
21927
|
+
fork: "initial",
|
|
21928
|
+
initial: () => ({ model: null })
|
|
21929
|
+
});
|
|
21855
21930
|
var ContextSettingsDoc = defineDoc7({
|
|
21856
21931
|
kind: "app.neko.context-settings",
|
|
21857
21932
|
version: 1,
|
|
@@ -21872,6 +21947,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
21872
21947
|
const context = options.context ?? BACKGROUND_CONTEXT3;
|
|
21873
21948
|
const defaultCwd = normalizeWorkspace(options.cwd);
|
|
21874
21949
|
const model = options.model ?? DEFAULT_MODEL;
|
|
21950
|
+
const modelOverride = options.modelOverride;
|
|
21875
21951
|
const providers = options.providers ?? [];
|
|
21876
21952
|
const credentials = options.credentials ?? (options.storage === "memory" && !options.credentialsPath ? new InMemoryCredentialStore : new FileCredentialStore(options.credentialsPath));
|
|
21877
21953
|
const runtimeKeys = new Map;
|
|
@@ -21891,15 +21967,45 @@ async function createNekoRuntime(options = {}) {
|
|
|
21891
21967
|
delete: (id) => credentials.delete(id)
|
|
21892
21968
|
} : credentials;
|
|
21893
21969
|
const models = createModels({ credentials: effectiveCredentials });
|
|
21894
|
-
|
|
21970
|
+
for (const provider of builtinProviders())
|
|
21971
|
+
if (isModelProvider(provider.id))
|
|
21972
|
+
models.setProvider(provider);
|
|
21895
21973
|
for (const provider of providers)
|
|
21896
21974
|
models.setProvider(provider);
|
|
21975
|
+
let enabled = new Set(normalizeEnabledProviders(null));
|
|
21976
|
+
const guardProvider = async (ref) => {
|
|
21977
|
+
if (!ref || !isModelProvider(ref.provider))
|
|
21978
|
+
return;
|
|
21979
|
+
const spec = credentialProvider(ref.provider);
|
|
21980
|
+
if (!enabled.has(ref.provider))
|
|
21981
|
+
throw new Error(`PROVIDER_DISABLED: ${spec.name} is not enabled. Enable it in /login or Web settings, or switch model.`);
|
|
21982
|
+
if (!await models.checkAuth(ref.provider))
|
|
21983
|
+
throw new Error(`PROVIDER_KEY_REQUIRED: Configure a ${spec.name} API key in /login or Web settings.`);
|
|
21984
|
+
};
|
|
21897
21985
|
const resolveLevel = (ref, level) => {
|
|
21898
21986
|
const info = models.getModel(ref.provider, ref.modelId);
|
|
21899
21987
|
if (!info)
|
|
21900
21988
|
throw new Error("Unknown model");
|
|
21901
21989
|
return clampThinkingLevel(info, level);
|
|
21902
21990
|
};
|
|
21991
|
+
let modelInfoCache;
|
|
21992
|
+
const allModels = () => {
|
|
21993
|
+
modelInfoCache ??= models.getModels().map((model) => ({
|
|
21994
|
+
provider: model.provider,
|
|
21995
|
+
modelId: model.id,
|
|
21996
|
+
name: model.name,
|
|
21997
|
+
contextWindow: model.contextWindow,
|
|
21998
|
+
input: model.input,
|
|
21999
|
+
...model.inputLimits ? { inputLimits: model.inputLimits } : {},
|
|
22000
|
+
reasoning: model.reasoning,
|
|
22001
|
+
supportedThinkingLevels: getSupportedThinkingLevels2(model),
|
|
22002
|
+
thinkingLevelAdjustments: Object.fromEntries(["off", "minimal", "low", "medium", "high", "xhigh", "max"].map((level) => [
|
|
22003
|
+
level,
|
|
22004
|
+
clampThinkingLevel(model, level)
|
|
22005
|
+
]))
|
|
22006
|
+
}));
|
|
22007
|
+
return modelInfoCache;
|
|
22008
|
+
};
|
|
21903
22009
|
const workspaceFiles = new WorkspaceFiles;
|
|
21904
22010
|
const storage = options.storage === "memory" ? new MemoryStorage : await openNodeSqliteStorage(options.storagePath ?? DEFAULT_STORAGE_PATH);
|
|
21905
22011
|
const registry = createRegistry();
|
|
@@ -21926,7 +22032,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
21926
22032
|
registry.install(createNekoPrompt(resourceSnapshots.current));
|
|
21927
22033
|
registry.install(createSubagentExtension(async (id, requestId, cwd) => {
|
|
21928
22034
|
resourceSnapshots.stage(id, requestId, cwd, await loadResources(cwd));
|
|
21929
|
-
}, resourceSnapshots.discard));
|
|
22035
|
+
}, resourceSnapshots.discard, (ref) => guardProvider(ref)));
|
|
21930
22036
|
const jobs = new JobManager;
|
|
21931
22037
|
registry.install(jobs.extension);
|
|
21932
22038
|
registry.install(createTodoExtension());
|
|
@@ -21944,7 +22050,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
21944
22050
|
registry,
|
|
21945
22051
|
settings: {
|
|
21946
22052
|
get compaction() {
|
|
21947
|
-
return compactionPolicy(contextState,
|
|
22053
|
+
return compactionPolicy(contextState, allModels().filter((model) => !isModelProvider(model.provider) || enabled.has(model.provider)).map((model) => model.contextWindow));
|
|
21948
22054
|
}
|
|
21949
22055
|
},
|
|
21950
22056
|
onReport: options.onReport,
|
|
@@ -21986,13 +22092,15 @@ async function createNekoRuntime(options = {}) {
|
|
|
21986
22092
|
throw error;
|
|
21987
22093
|
}
|
|
21988
22094
|
await questions.reconcileAll();
|
|
22095
|
+
const rootModel = modelOverride ?? model;
|
|
21989
22096
|
const conversation = await harness.root(context, {
|
|
21990
22097
|
agent: {
|
|
21991
|
-
model,
|
|
21992
|
-
thinkingLevel: resolveLevel(
|
|
22098
|
+
model: rootModel,
|
|
22099
|
+
thinkingLevel: resolveLevel(rootModel, options.thinkingLevel ?? "high"),
|
|
21993
22100
|
cwd: defaultCwd
|
|
21994
22101
|
}
|
|
21995
22102
|
});
|
|
22103
|
+
enabled = new Set(normalizeEnabledProviders((await harness.snapshot(ProviderSettingsDoc, conversation.id, context))?.enabled));
|
|
21996
22104
|
const savedSearch = (await harness.snapshot(SearchSettingsDoc, conversation.id, context))?.provider;
|
|
21997
22105
|
if (isSearchProvider(savedSearch))
|
|
21998
22106
|
searchProvider = savedSearch;
|
|
@@ -22038,7 +22146,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
22038
22146
|
};
|
|
22039
22147
|
if (existing.length === 0)
|
|
22040
22148
|
await touchConversation(conversation.id);
|
|
22041
|
-
const metadata = new SessionMetadataManager(harness, storage, context, registry, options.onReport);
|
|
22149
|
+
const metadata = new SessionMetadataManager(harness, storage, context, registry, options.onReport, (provider, modelId) => guardProvider({ provider, modelId }).then(() => true, () => false));
|
|
22042
22150
|
if (existing.length === 0)
|
|
22043
22151
|
await metadata.initialize(conversation.id);
|
|
22044
22152
|
for (const record of existing)
|
|
@@ -22099,9 +22207,8 @@ async function createNekoRuntime(options = {}) {
|
|
|
22099
22207
|
data.skill = skill;
|
|
22100
22208
|
});
|
|
22101
22209
|
}
|
|
22102
|
-
if (!duplicate
|
|
22103
|
-
|
|
22104
|
-
}
|
|
22210
|
+
if (!duplicate)
|
|
22211
|
+
await guardProvider(agent.model);
|
|
22105
22212
|
if (!duplicate && agent.model) {
|
|
22106
22213
|
const resolved = models.getModel(agent.model.provider, agent.model.modelId);
|
|
22107
22214
|
if (resolved)
|
|
@@ -22233,8 +22340,7 @@ async function createNekoRuntime(options = {}) {
|
|
|
22233
22340
|
},
|
|
22234
22341
|
async compact(instructions) {
|
|
22235
22342
|
const agent = await target.agent(context);
|
|
22236
|
-
|
|
22237
|
-
throw new Error("DEEPSEEK_KEY_REQUIRED: Configure DeepSeek in /login or Web settings.");
|
|
22343
|
+
await guardProvider(agent.model);
|
|
22238
22344
|
await admit(target.id, async () => {
|
|
22239
22345
|
const live = await harness.snapshot(importLiveDoc, target.id, context);
|
|
22240
22346
|
if (live?.compactions?.length || (await readCompaction(harness, storage, target.id, context))?.phase === "waiting-to-apply")
|
|
@@ -22460,11 +22566,13 @@ async function createNekoRuntime(options = {}) {
|
|
|
22460
22566
|
},
|
|
22461
22567
|
async createConversation(createOptions) {
|
|
22462
22568
|
const workspace = await addWorkspace(createOptions?.cwd ?? defaultCwd);
|
|
22569
|
+
const savedDefault = (await harness.snapshot(DefaultModelDoc, conversation.id, context))?.model ?? null;
|
|
22570
|
+
const effective = createOptions?.model ?? modelOverride ?? savedDefault ?? model;
|
|
22463
22571
|
const created = await harness.createConversation({
|
|
22464
22572
|
ownership: { kind: "ownerless" },
|
|
22465
22573
|
agent: {
|
|
22466
|
-
model:
|
|
22467
|
-
thinkingLevel: resolveLevel(
|
|
22574
|
+
model: effective,
|
|
22575
|
+
thinkingLevel: resolveLevel(effective, createOptions?.thinkingLevel ?? options.thinkingLevel ?? "high"),
|
|
22468
22576
|
cwd: workspace.path
|
|
22469
22577
|
}
|
|
22470
22578
|
}, context);
|
|
@@ -22494,6 +22602,8 @@ async function createNekoRuntime(options = {}) {
|
|
|
22494
22602
|
const targetModel = ref && models.getModel(ref.provider, ref.modelId);
|
|
22495
22603
|
if (!targetModel)
|
|
22496
22604
|
throw new Error("Unknown model");
|
|
22605
|
+
if (change.model && isModelProvider(ref.provider) && !enabled.has(ref.provider))
|
|
22606
|
+
throw new Error(`PROVIDER_DISABLED: ${credentialProvider(ref.provider).name} is not enabled.`);
|
|
22497
22607
|
await session.conversation.configure({ model: ref, thinkingLevel: clampThinkingLevel(targetModel, change.thinkingLevel ?? current.thinkingLevel) }, context);
|
|
22498
22608
|
return true;
|
|
22499
22609
|
});
|
|
@@ -22548,20 +22658,62 @@ async function createNekoRuntime(options = {}) {
|
|
|
22548
22658
|
}
|
|
22549
22659
|
},
|
|
22550
22660
|
listModels() {
|
|
22551
|
-
return
|
|
22552
|
-
|
|
22553
|
-
|
|
22554
|
-
|
|
22555
|
-
|
|
22556
|
-
|
|
22557
|
-
|
|
22558
|
-
|
|
22559
|
-
|
|
22560
|
-
|
|
22561
|
-
|
|
22562
|
-
|
|
22563
|
-
|
|
22564
|
-
|
|
22661
|
+
return allModels();
|
|
22662
|
+
},
|
|
22663
|
+
async listSelectableModels() {
|
|
22664
|
+
const availability = new Map;
|
|
22665
|
+
const result = [];
|
|
22666
|
+
for (const info of allModels()) {
|
|
22667
|
+
const managed = isModelProvider(info.provider);
|
|
22668
|
+
if (managed && !enabled.has(info.provider))
|
|
22669
|
+
continue;
|
|
22670
|
+
if (!availability.has(info.provider))
|
|
22671
|
+
availability.set(info.provider, !managed || Boolean(await models.checkAuth(info.provider)));
|
|
22672
|
+
result.push({ ...info, available: availability.get(info.provider) ?? false });
|
|
22673
|
+
}
|
|
22674
|
+
return result;
|
|
22675
|
+
},
|
|
22676
|
+
enabledProviders() {
|
|
22677
|
+
return MODEL_PROVIDERS.map((item) => item.id).filter((id) => enabled.has(id));
|
|
22678
|
+
},
|
|
22679
|
+
async setProviderEnabled(provider, value) {
|
|
22680
|
+
if (!isModelProvider(provider))
|
|
22681
|
+
throw new Error("Unknown model provider.");
|
|
22682
|
+
if (typeof value !== "boolean")
|
|
22683
|
+
throw new Error("Enabled must be a boolean.");
|
|
22684
|
+
if (!value && LOCKED_PROVIDERS.includes(provider))
|
|
22685
|
+
throw new Error("DeepSeek is always enabled.");
|
|
22686
|
+
const next = new Set(enabled);
|
|
22687
|
+
if (value)
|
|
22688
|
+
next.add(provider);
|
|
22689
|
+
else
|
|
22690
|
+
next.delete(provider);
|
|
22691
|
+
const list = normalizeEnabledProviders([...next]);
|
|
22692
|
+
await harness.commit(async (tx) => {
|
|
22693
|
+
(await tx.doc(ProviderSettingsDoc, conversation.id)).enabled = list;
|
|
22694
|
+
}, context);
|
|
22695
|
+
enabled = new Set(list);
|
|
22696
|
+
},
|
|
22697
|
+
async defaultModel() {
|
|
22698
|
+
const saved = (await harness.snapshot(DefaultModelDoc, conversation.id, context))?.model ?? null;
|
|
22699
|
+
if (modelOverride)
|
|
22700
|
+
return { effective: modelOverride, source: "cli" };
|
|
22701
|
+
if (saved)
|
|
22702
|
+
return { effective: saved, source: "saved" };
|
|
22703
|
+
if (options.model)
|
|
22704
|
+
return { effective: model, source: "config" };
|
|
22705
|
+
return { effective: model, source: "default" };
|
|
22706
|
+
},
|
|
22707
|
+
async setDefaultModel(ref) {
|
|
22708
|
+
if (ref !== null) {
|
|
22709
|
+
if (!models.getModel(ref.provider, ref.modelId))
|
|
22710
|
+
throw new Error("Unknown model");
|
|
22711
|
+
if (isModelProvider(ref.provider) && !enabled.has(ref.provider))
|
|
22712
|
+
throw new Error(`PROVIDER_DISABLED: ${credentialProvider(ref.provider).name} is not enabled.`);
|
|
22713
|
+
}
|
|
22714
|
+
await harness.commit(async (tx) => {
|
|
22715
|
+
(await tx.doc(DefaultModelDoc, conversation.id)).model = ref;
|
|
22716
|
+
}, context);
|
|
22565
22717
|
},
|
|
22566
22718
|
async getAgent(id) {
|
|
22567
22719
|
const session = await sessionFor(id);
|
|
@@ -22626,8 +22778,8 @@ var nullableString = Type7.Union([str, nil]);
|
|
|
22626
22778
|
var phase = Type7.Enum(["pending", "running", "done"]);
|
|
22627
22779
|
var level = Type7.Enum(["project", "user", "builtin"]);
|
|
22628
22780
|
var thinking = Type7.Enum(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
22629
|
-
var
|
|
22630
|
-
var change = Type7.Object({ model: Type7.Optional(
|
|
22781
|
+
var model2 = Type7.Object({ provider: str, modelId: str });
|
|
22782
|
+
var change = Type7.Object({ model: Type7.Optional(model2), thinkingLevel: Type7.Optional(thinking) }, { additionalProperties: false });
|
|
22631
22783
|
var usage = Type7.Object({ input: num, output: num, cacheRead: num, cacheWrite: num, cost: num });
|
|
22632
22784
|
var image = Type7.Object({
|
|
22633
22785
|
name: str,
|
|
@@ -22865,7 +23017,7 @@ var ChatViewSchema = Type7.Object({
|
|
|
22865
23017
|
subagents: Type7.Optional(Type7.Array(DelegationSchema)),
|
|
22866
23018
|
taskUsage: Type7.Optional(usage),
|
|
22867
23019
|
model: str,
|
|
22868
|
-
agent: Type7.Object({ model: Type7.Union([
|
|
23020
|
+
agent: Type7.Object({ model: Type7.Union([model2, nil]), thinkingLevel: Type7.Union([thinking, nil]) }),
|
|
22869
23021
|
cwd: str,
|
|
22870
23022
|
busy: bool,
|
|
22871
23023
|
status: nullableString,
|
|
@@ -22950,7 +23102,7 @@ var SessionSummarySchema = Type7.Object({
|
|
|
22950
23102
|
firstPromptPreview: str,
|
|
22951
23103
|
createdAt: num,
|
|
22952
23104
|
lastMessageAt: Type7.Union([num, nil]),
|
|
22953
|
-
model: Type7.Union([
|
|
23105
|
+
model: Type7.Union([model2, nil]),
|
|
22954
23106
|
status: Type7.Enum(["idle", "running", "error"]),
|
|
22955
23107
|
awaitingAnswer: Type7.Optional(bool),
|
|
22956
23108
|
id: str
|
|
@@ -22961,11 +23113,12 @@ var WorkspaceStateSchema = Type7.Object({ revision: integer, workspaces: Type7.A
|
|
|
22961
23113
|
var credentialStatus = Type7.Object({
|
|
22962
23114
|
savedConfigured: bool,
|
|
22963
23115
|
environmentConfigured: bool,
|
|
22964
|
-
source: Type7.Enum(["saved", "environment", "runtime", "keyless", "none"])
|
|
23116
|
+
source: Type7.Enum(["saved", "environment", "runtime", "keyless", "none"]),
|
|
23117
|
+
enabled: Type7.Optional(bool)
|
|
22965
23118
|
});
|
|
22966
23119
|
var CredentialStateSchema = Type7.Object({
|
|
22967
23120
|
revision: integer,
|
|
22968
|
-
statuses: Type7.
|
|
23121
|
+
statuses: Type7.Record(str, credentialStatus)
|
|
22969
23122
|
});
|
|
22970
23123
|
var AttachmentSchema = Type7.Object({ sessionId: str, attachmentId: str });
|
|
22971
23124
|
var chatInput = Type7.Object({ sessionId: str, attachmentId: str }, { additionalProperties: false });
|
|
@@ -23007,6 +23160,7 @@ var modelInfo = Type7.Object({
|
|
|
23007
23160
|
provider: str,
|
|
23008
23161
|
modelId: str,
|
|
23009
23162
|
name: str,
|
|
23163
|
+
available: bool,
|
|
23010
23164
|
contextWindow: num,
|
|
23011
23165
|
input: Type7.Array(str),
|
|
23012
23166
|
inputLimits: Type7.Optional(inputLimits),
|
|
@@ -23112,16 +23266,17 @@ var NekoWorkspaces = contract("neko.workspaces", {
|
|
|
23112
23266
|
}
|
|
23113
23267
|
}
|
|
23114
23268
|
});
|
|
23115
|
-
var provider = Type7.
|
|
23269
|
+
var provider = Type7.String({ minLength: 1, maxLength: 64 });
|
|
23116
23270
|
var NekoCredentials = contract("neko.credentials", {
|
|
23117
|
-
version:
|
|
23271
|
+
version: 2,
|
|
23118
23272
|
input: Type7.Object({}, { additionalProperties: false }),
|
|
23119
23273
|
variants: {
|
|
23120
23274
|
ready: {
|
|
23121
23275
|
state: { state: CredentialStateSchema },
|
|
23122
23276
|
methods: {
|
|
23123
23277
|
save: rpc(Type7.Object({ provider, key: Type7.String({ minLength: 1, maxLength: 8192 }) }, { additionalProperties: false }), nil),
|
|
23124
|
-
remove: rpc(Type7.Object({ provider }, { additionalProperties: false }), nil)
|
|
23278
|
+
remove: rpc(Type7.Object({ provider }, { additionalProperties: false }), nil),
|
|
23279
|
+
setEnabled: rpc(Type7.Object({ provider, enabled: bool }, { additionalProperties: false }), nil)
|
|
23125
23280
|
}
|
|
23126
23281
|
}
|
|
23127
23282
|
}
|
|
@@ -23198,6 +23353,24 @@ var NekoContextSettings = contract("neko.context-settings", {
|
|
|
23198
23353
|
}
|
|
23199
23354
|
}
|
|
23200
23355
|
});
|
|
23356
|
+
var defaultModelSource = Type7.Enum(["cli", "saved", "config", "default"]);
|
|
23357
|
+
var DefaultModelStateSchema = Type7.Object({
|
|
23358
|
+
effective: model2,
|
|
23359
|
+
source: defaultModelSource
|
|
23360
|
+
});
|
|
23361
|
+
var NekoDefaultModel = contract("neko.default-model", {
|
|
23362
|
+
version: 1,
|
|
23363
|
+
input: Type7.Object({}, { additionalProperties: false }),
|
|
23364
|
+
variants: {
|
|
23365
|
+
ready: {
|
|
23366
|
+
state: { state: DefaultModelStateSchema },
|
|
23367
|
+
methods: {
|
|
23368
|
+
set: rpc(model2, nil),
|
|
23369
|
+
clear: rpc(nil, nil)
|
|
23370
|
+
}
|
|
23371
|
+
}
|
|
23372
|
+
}
|
|
23373
|
+
});
|
|
23201
23374
|
var FileCandidatesSchema = Type7.Object({
|
|
23202
23375
|
entries: Type7.Array(Type7.Object({ name: str, path: str, kind: Type7.Enum(["file", "directory"]) }), { maxItems: 100 }),
|
|
23203
23376
|
limited: bool,
|
|
@@ -23976,8 +24149,8 @@ function subagentClient(connect) {
|
|
|
23976
24149
|
import { createHash as createHash2 } from "crypto";
|
|
23977
24150
|
|
|
23978
24151
|
// packages/core/src/application-version.ts
|
|
23979
|
-
var RUNNING_VERSION = "0.4.
|
|
23980
|
-
var APPLICATION_PROTOCOL =
|
|
24152
|
+
var RUNNING_VERSION = "0.4.6";
|
|
24153
|
+
var APPLICATION_PROTOCOL = 8;
|
|
23981
24154
|
function stableVersion(value) {
|
|
23982
24155
|
return typeof value === "string" && /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(value) && value.split(".").every((n) => Number.isSafeInteger(Number(n)));
|
|
23983
24156
|
}
|
|
@@ -27995,8 +28168,6 @@ function serveSessions(host, runtime, context) {
|
|
|
27995
28168
|
for (const id of input.images ?? [])
|
|
27996
28169
|
uploads.value.release(id);
|
|
27997
28170
|
} catch (error) {
|
|
27998
|
-
if (error instanceof Error && error.message.startsWith("DEEPSEEK_KEY_REQUIRED:"))
|
|
27999
|
-
throw new ChordError4("invalid", "DEEPSEEK_KEY_REQUIRED: Configure DeepSeek in /login or Web settings.");
|
|
28000
28171
|
throw new ChordError4("invalid", error instanceof Error ? error.message : "Cannot submit message");
|
|
28001
28172
|
}
|
|
28002
28173
|
return null;
|
|
@@ -28788,9 +28959,11 @@ var ServerState = local3("neko.server-state", {
|
|
|
28788
28959
|
credentials: CredentialStateSchema,
|
|
28789
28960
|
searchSettings: SearchSettingsStateSchema,
|
|
28790
28961
|
contextSettings: ContextSettingsStateSchema,
|
|
28962
|
+
defaultModel: DefaultModelStateSchema,
|
|
28791
28963
|
refreshCredentials: method2(Type12.Null(), Type12.Null()),
|
|
28792
28964
|
refreshSearchSettings: method2(Type12.Null(), Type12.Null()),
|
|
28793
|
-
refreshContextSettings: method2(Type12.Null(), Type12.Null())
|
|
28965
|
+
refreshContextSettings: method2(Type12.Null(), Type12.Null()),
|
|
28966
|
+
refreshDefaultModel: method2(Type12.Null(), Type12.Null())
|
|
28794
28967
|
}
|
|
28795
28968
|
});
|
|
28796
28969
|
async function createNekoServerServices(options) {
|
|
@@ -28868,13 +29041,20 @@ async function createNekoServerServices(options) {
|
|
|
28868
29041
|
status: info.status,
|
|
28869
29042
|
awaitingAnswer: info.awaitingAnswer
|
|
28870
29043
|
}));
|
|
28871
|
-
const readStatuses = async () =>
|
|
28872
|
-
|
|
29044
|
+
const readStatuses = async () => {
|
|
29045
|
+
const enabled = new Set(runtime.enabledProviders());
|
|
29046
|
+
return Object.fromEntries(await Promise.all(CREDENTIAL_PROVIDERS.map(async (spec) => {
|
|
29047
|
+
const status = await runtime.credentialStatus(spec.id);
|
|
29048
|
+
return [spec.id, spec.kind === "model" ? { ...status, enabled: enabled.has(spec.id) } : status];
|
|
29049
|
+
})));
|
|
29050
|
+
};
|
|
29051
|
+
const [sessions, workspaces, statuses, search, contextSettings0, defaultModel0] = await Promise.all([
|
|
28873
29052
|
list(),
|
|
28874
29053
|
runtime.listWorkspaces(),
|
|
28875
29054
|
readStatuses(),
|
|
28876
29055
|
runtime.searchSettings(),
|
|
28877
|
-
runtime.contextSettings()
|
|
29056
|
+
runtime.contextSettings(),
|
|
29057
|
+
runtime.defaultModel()
|
|
28878
29058
|
]);
|
|
28879
29059
|
let mutationTail = Promise.resolve();
|
|
28880
29060
|
const serialize = (fn) => {
|
|
@@ -28891,6 +29071,7 @@ async function createNekoServerServices(options) {
|
|
|
28891
29071
|
revision: 1,
|
|
28892
29072
|
...contextSettings0
|
|
28893
29073
|
});
|
|
29074
|
+
const defaultModel = self2.state("defaultModel", DefaultModelStateSchema, defaultModel0);
|
|
28894
29075
|
const refreshContextSettings = async (_input, ctx) => {
|
|
28895
29076
|
const next = await runtime.contextSettings();
|
|
28896
29077
|
const { revision, ...current } = contextSettings.value;
|
|
@@ -28898,6 +29079,12 @@ async function createNekoServerServices(options) {
|
|
|
28898
29079
|
contextSettings.replace(ctx, { revision: revision + 1, ...next });
|
|
28899
29080
|
return null;
|
|
28900
29081
|
};
|
|
29082
|
+
const refreshDefaultModel = async (_input, ctx) => {
|
|
29083
|
+
const next = await runtime.defaultModel();
|
|
29084
|
+
if (JSON.stringify(next) !== JSON.stringify(defaultModel.value))
|
|
29085
|
+
defaultModel.replace(ctx, next);
|
|
29086
|
+
return null;
|
|
29087
|
+
};
|
|
28901
29088
|
const refreshSearchSettings = async (_input, ctx) => {
|
|
28902
29089
|
const next = await runtime.searchSettings();
|
|
28903
29090
|
const current = searchSettings.value;
|
|
@@ -28926,6 +29113,7 @@ async function createNekoServerServices(options) {
|
|
|
28926
29113
|
credentials,
|
|
28927
29114
|
searchSettings,
|
|
28928
29115
|
contextSettings,
|
|
29116
|
+
defaultModel,
|
|
28929
29117
|
async refreshCredentials(_input, ctx) {
|
|
28930
29118
|
credentials.replace(ctx, {
|
|
28931
29119
|
revision: credentials.value.revision + 1,
|
|
@@ -28934,7 +29122,8 @@ async function createNekoServerServices(options) {
|
|
|
28934
29122
|
return null;
|
|
28935
29123
|
},
|
|
28936
29124
|
refreshSearchSettings,
|
|
28937
|
-
refreshContextSettings
|
|
29125
|
+
refreshContextSettings,
|
|
29126
|
+
refreshDefaultModel
|
|
28938
29127
|
};
|
|
28939
29128
|
}, { lifetime: "host" });
|
|
28940
29129
|
const shared = (self2) => self2.get(ServerState, {});
|
|
@@ -28957,7 +29146,17 @@ async function createNekoServerServices(options) {
|
|
|
28957
29146
|
remove: async (input, ctx) => {
|
|
28958
29147
|
await runtime.removeCredential(input.provider);
|
|
28959
29148
|
return hub.refreshCredentials(null, ctx);
|
|
28960
|
-
}
|
|
29149
|
+
},
|
|
29150
|
+
setEnabled: (input, ctx) => serialize(async () => {
|
|
29151
|
+
if (!isModelProvider(input.provider))
|
|
29152
|
+
throw new ChordError5("invalid", "Unknown model provider.");
|
|
29153
|
+
try {
|
|
29154
|
+
await runtime.setProviderEnabled(input.provider, input.enabled);
|
|
29155
|
+
} catch (error) {
|
|
29156
|
+
throw new ChordError5("invalid", error instanceof Error ? error.message : "Cannot change provider.");
|
|
29157
|
+
}
|
|
29158
|
+
return hub.refreshCredentials(null, ctx);
|
|
29159
|
+
})
|
|
28961
29160
|
};
|
|
28962
29161
|
});
|
|
28963
29162
|
host.serve(NekoSearchSettings, (_input, _principal, self2) => {
|
|
@@ -28986,9 +29185,24 @@ async function createNekoServerServices(options) {
|
|
|
28986
29185
|
})
|
|
28987
29186
|
};
|
|
28988
29187
|
});
|
|
29188
|
+
host.serve(NekoDefaultModel, (_input, _principal, self2) => {
|
|
29189
|
+
const hub = shared(self2);
|
|
29190
|
+
return {
|
|
29191
|
+
variant: "ready",
|
|
29192
|
+
state: hub.defaultModel,
|
|
29193
|
+
set: (input, ctx) => serialize(async () => {
|
|
29194
|
+
await runtime.setDefaultModel(input);
|
|
29195
|
+
return hub.refreshDefaultModel(null, ctx);
|
|
29196
|
+
}),
|
|
29197
|
+
clear: (_input, ctx) => serialize(async () => {
|
|
29198
|
+
await runtime.setDefaultModel(null);
|
|
29199
|
+
return hub.refreshDefaultModel(null, ctx);
|
|
29200
|
+
})
|
|
29201
|
+
};
|
|
29202
|
+
});
|
|
28989
29203
|
host.serve(NekoModels, () => ({
|
|
28990
29204
|
variant: "ready",
|
|
28991
|
-
list: async () =>
|
|
29205
|
+
list: async () => (await runtime.listSelectableModels()).map((value) => ({
|
|
28992
29206
|
...value,
|
|
28993
29207
|
input: [...value.input],
|
|
28994
29208
|
supportedThinkingLevels: [...value.supportedThinkingLevels]
|
|
@@ -29282,7 +29496,6 @@ var SERVER_ID_FILENAME = "gateway-server-id";
|
|
|
29282
29496
|
async function startGateway(options = {}) {
|
|
29283
29497
|
const context = options.context ?? BACKGROUND_CONTEXT4;
|
|
29284
29498
|
const fileConfig = loadNekoConfig(options.configDir);
|
|
29285
|
-
const model = options.model ?? fileConfig.defaultModel ?? DEFAULT_MODEL;
|
|
29286
29499
|
const storagePath = options.storagePath ?? fileConfig.storagePath ?? DEFAULT_STORAGE_PATH;
|
|
29287
29500
|
const host = options.host ?? fileConfig.gateway?.host ?? DEFAULT_HOST;
|
|
29288
29501
|
const port = options.port !== undefined ? options.port : fileConfig.gateway?.port ?? (process.platform === "win32" ? 0 : DEFAULT_PORT);
|
|
@@ -29300,7 +29513,8 @@ async function startGateway(options = {}) {
|
|
|
29300
29513
|
...options.apiKey !== undefined ? { apiKey: options.apiKey } : {},
|
|
29301
29514
|
...searchProvider !== undefined ? { searchProvider } : {},
|
|
29302
29515
|
...fileConfig.context !== undefined ? { contextSettings: fileConfig.context } : {},
|
|
29303
|
-
model,
|
|
29516
|
+
...fileConfig.defaultModel !== undefined ? { model: fileConfig.defaultModel } : {},
|
|
29517
|
+
...options.model !== undefined ? { modelOverride: options.model } : {},
|
|
29304
29518
|
thinkingLevel: options.thinkingLevel ?? fileConfig.thinkingLevel ?? "high",
|
|
29305
29519
|
...options.cwd !== undefined ? { cwd: options.cwd } : {},
|
|
29306
29520
|
...options.providers !== undefined ? { providers: options.providers } : {},
|
|
@@ -29315,7 +29529,6 @@ async function startGateway(options = {}) {
|
|
|
29315
29529
|
socketPath,
|
|
29316
29530
|
serverId,
|
|
29317
29531
|
nekoDir,
|
|
29318
|
-
model,
|
|
29319
29532
|
marketUrl,
|
|
29320
29533
|
promptHome: options.promptHome,
|
|
29321
29534
|
updates: options.updates,
|