@botcord/daemon 0.2.77 → 0.2.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-discovery.d.ts +6 -0
- package/dist/agent-discovery.js +6 -0
- package/dist/daemon-config-map.d.ts +6 -0
- package/dist/daemon-config-map.js +5 -4
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.js +11 -1
- package/dist/gateway/runtimes/deepseek-tui.js +55 -7
- package/dist/provision.d.ts +2 -0
- package/dist/provision.js +66 -1
- package/dist/runtime-models.d.ts +17 -0
- package/dist/runtime-models.js +953 -0
- package/dist/runtime-route-options.d.ts +7 -0
- package/dist/runtime-route-options.js +45 -0
- package/package.json +1 -1
- package/src/__tests__/daemon-config-map.test.ts +26 -1
- package/src/__tests__/provision.test.ts +59 -0
- package/src/__tests__/runtime-discovery.test.ts +68 -9
- package/src/__tests__/runtime-models.test.ts +333 -0
- package/src/agent-discovery.ts +9 -0
- package/src/daemon-config-map.ts +17 -4
- package/src/daemon.ts +15 -3
- package/src/gateway/__tests__/deepseek-tui-adapter.test.ts +30 -1
- package/src/gateway/runtimes/deepseek-tui.ts +49 -7
- package/src/provision.ts +69 -4
- package/src/runtime-models.ts +972 -0
- package/src/runtime-route-options.ts +52 -0
|
@@ -22,6 +22,12 @@ export interface DiscoveredAgentCredential {
|
|
|
22
22
|
* in that case.
|
|
23
23
|
*/
|
|
24
24
|
runtime?: string;
|
|
25
|
+
/** Runtime model id/alias selected for this agent. */
|
|
26
|
+
runtimeModel?: string;
|
|
27
|
+
/** Runtime reasoning effort selected for this agent. */
|
|
28
|
+
reasoningEffort?: string;
|
|
29
|
+
/** Kimi-style thinking toggle selected for this agent. */
|
|
30
|
+
thinking?: boolean;
|
|
25
31
|
/** Working directory cached alongside `runtime`. */
|
|
26
32
|
cwd?: string;
|
|
27
33
|
/** OpenClaw gateway profile name from credentials (only meaningful for openclaw-acp). */
|
package/dist/agent-discovery.js
CHANGED
|
@@ -96,6 +96,12 @@ export function discoverAgentCredentials(opts = {}) {
|
|
|
96
96
|
entry.displayName = creds.displayName;
|
|
97
97
|
if (creds.runtime)
|
|
98
98
|
entry.runtime = creds.runtime;
|
|
99
|
+
if (creds.runtimeModel)
|
|
100
|
+
entry.runtimeModel = creds.runtimeModel;
|
|
101
|
+
if (creds.reasoningEffort)
|
|
102
|
+
entry.reasoningEffort = creds.reasoningEffort;
|
|
103
|
+
if (typeof creds.thinking === "boolean")
|
|
104
|
+
entry.thinking = creds.thinking;
|
|
99
105
|
if (creds.cwd)
|
|
100
106
|
entry.cwd = creds.cwd;
|
|
101
107
|
if (creds.openclawGateway)
|
|
@@ -3,6 +3,12 @@ import type { DaemonConfig, OpenclawGatewayProfile } from "./config.js";
|
|
|
3
3
|
/** Per-agent metadata cached from credentials, used by `buildManagedRoutes`. */
|
|
4
4
|
export interface AgentRuntimeMeta {
|
|
5
5
|
runtime?: string;
|
|
6
|
+
/** Runtime model id/alias selected for this agent. */
|
|
7
|
+
runtimeModel?: string;
|
|
8
|
+
/** Runtime reasoning effort selected for this agent. */
|
|
9
|
+
reasoningEffort?: string;
|
|
10
|
+
/** Kimi-style thinking toggle selected for this agent. */
|
|
11
|
+
thinking?: boolean;
|
|
6
12
|
cwd?: string;
|
|
7
13
|
/** OpenClaw gateway profile name to lookup in the registry. */
|
|
8
14
|
openclawGateway?: string;
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { resolveAgentIds } from "./config.js";
|
|
5
5
|
import { agentWorkspaceDir } from "./agent-workspace.js";
|
|
6
6
|
import { log as daemonLog } from "./log.js";
|
|
7
|
+
import { buildRuntimeSelectionExtraArgs, mergeRuntimeExtraArgs, } from "./runtime-route-options.js";
|
|
7
8
|
function expandHome(p) {
|
|
8
9
|
if (p === "~")
|
|
9
10
|
return homedir();
|
|
@@ -259,10 +260,10 @@ export function buildManagedRoutes(agentIds, agentRuntimes, defaultRoute, opencl
|
|
|
259
260
|
match: { accountId: agentId },
|
|
260
261
|
runtime,
|
|
261
262
|
cwd: meta.cwd || agentWorkspaceDir(agentId),
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
263
|
+
...(() => {
|
|
264
|
+
const extraArgs = mergeRuntimeExtraArgs(defaultRoute.extraArgs, buildRuntimeSelectionExtraArgs(runtime, meta));
|
|
265
|
+
return extraArgs ? { extraArgs } : {};
|
|
266
|
+
})(),
|
|
266
267
|
};
|
|
267
268
|
if (runtime === "openclaw-acp") {
|
|
268
269
|
// Per RFC §3.4: prefer credentials, fall back to defaultRoute.gateway.
|
package/dist/daemon.d.ts
CHANGED
|
@@ -121,6 +121,9 @@ export interface BootBackfillResult {
|
|
|
121
121
|
credentialPathByAgentId: Map<string, string>;
|
|
122
122
|
agentRuntimes: Record<string, {
|
|
123
123
|
runtime?: string;
|
|
124
|
+
runtimeModel?: string;
|
|
125
|
+
reasoningEffort?: string;
|
|
126
|
+
thinking?: boolean;
|
|
124
127
|
cwd?: string;
|
|
125
128
|
openclawGateway?: string;
|
|
126
129
|
openclawAgent?: string;
|
package/dist/daemon.js
CHANGED
|
@@ -527,9 +527,19 @@ export function backfillBootAgents(agents, opts) {
|
|
|
527
527
|
for (const a of agents) {
|
|
528
528
|
if (a.credentialsFile)
|
|
529
529
|
credentialPathByAgentId.set(a.agentId, a.credentialsFile);
|
|
530
|
-
if (a.runtime ||
|
|
530
|
+
if (a.runtime ||
|
|
531
|
+
a.runtimeModel ||
|
|
532
|
+
a.reasoningEffort ||
|
|
533
|
+
typeof a.thinking === "boolean" ||
|
|
534
|
+
a.cwd ||
|
|
535
|
+
a.openclawGateway ||
|
|
536
|
+
a.openclawAgent ||
|
|
537
|
+
a.hermesProfile) {
|
|
531
538
|
agentRuntimes[a.agentId] = {
|
|
532
539
|
...(a.runtime ? { runtime: a.runtime } : {}),
|
|
540
|
+
...(a.runtimeModel ? { runtimeModel: a.runtimeModel } : {}),
|
|
541
|
+
...(a.reasoningEffort ? { reasoningEffort: a.reasoningEffort } : {}),
|
|
542
|
+
...(typeof a.thinking === "boolean" ? { thinking: a.thinking } : {}),
|
|
533
543
|
...(a.cwd ? { cwd: a.cwd } : {}),
|
|
534
544
|
...(a.openclawGateway ? { openclawGateway: a.openclawGateway } : {}),
|
|
535
545
|
...(a.openclawAgent ? { openclawAgent: a.openclawAgent } : {}),
|
|
@@ -202,6 +202,11 @@ export class DeepseekTuiAdapter {
|
|
|
202
202
|
auto_approve: opts.trustLevel !== "public",
|
|
203
203
|
archived: false,
|
|
204
204
|
};
|
|
205
|
+
const selection = parseDeepseekRuntimeSelection(opts.extraArgs);
|
|
206
|
+
if (selection.model)
|
|
207
|
+
body.model = selection.model;
|
|
208
|
+
if (selection.reasoningEffort)
|
|
209
|
+
body.reasoning_effort = selection.reasoningEffort;
|
|
205
210
|
if (opts.systemContext)
|
|
206
211
|
body.system_prompt = opts.systemContext;
|
|
207
212
|
const res = await this.requestJson(`${baseUrl}/v1/threads`, {
|
|
@@ -236,16 +241,22 @@ export class DeepseekTuiAdapter {
|
|
|
236
241
|
});
|
|
237
242
|
let turnId = "";
|
|
238
243
|
try {
|
|
244
|
+
const selection = parseDeepseekRuntimeSelection(opts.extraArgs);
|
|
245
|
+
const body = {
|
|
246
|
+
prompt: opts.text,
|
|
247
|
+
mode: "agent",
|
|
248
|
+
allow_shell: opts.trustLevel !== "public",
|
|
249
|
+
trust_mode: opts.trustLevel !== "public",
|
|
250
|
+
auto_approve: opts.trustLevel !== "public",
|
|
251
|
+
};
|
|
252
|
+
if (selection.model)
|
|
253
|
+
body.model = selection.model;
|
|
254
|
+
if (selection.reasoningEffort)
|
|
255
|
+
body.reasoning_effort = selection.reasoningEffort;
|
|
239
256
|
const started = await this.requestJson(`${baseUrl}/v1/threads/${encodeURIComponent(threadId)}/turns`, {
|
|
240
257
|
method: "POST",
|
|
241
258
|
headers,
|
|
242
|
-
body: JSON.stringify(
|
|
243
|
-
prompt: opts.text,
|
|
244
|
-
mode: "agent",
|
|
245
|
-
allow_shell: opts.trustLevel !== "public",
|
|
246
|
-
trust_mode: opts.trustLevel !== "public",
|
|
247
|
-
auto_approve: opts.trustLevel !== "public",
|
|
248
|
-
}),
|
|
259
|
+
body: JSON.stringify(body),
|
|
249
260
|
signal,
|
|
250
261
|
});
|
|
251
262
|
turnId = stringField(started?.turn, "id") ?? stringField(started, "turn_id") ?? "";
|
|
@@ -457,6 +468,43 @@ function parseSseFrame(raw) {
|
|
|
457
468
|
function authHeaders(token) {
|
|
458
469
|
return token ? { authorization: `Bearer ${token}` } : {};
|
|
459
470
|
}
|
|
471
|
+
function parseDeepseekRuntimeSelection(extraArgs) {
|
|
472
|
+
const out = {};
|
|
473
|
+
if (!extraArgs?.length)
|
|
474
|
+
return out;
|
|
475
|
+
for (let i = 0; i < extraArgs.length; i += 1) {
|
|
476
|
+
const arg = extraArgs[i];
|
|
477
|
+
if (arg === "--model") {
|
|
478
|
+
const value = nextArgValue(extraArgs, i);
|
|
479
|
+
if (value !== undefined) {
|
|
480
|
+
out.model = value;
|
|
481
|
+
i += 1;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
else if (arg.startsWith("--model=")) {
|
|
485
|
+
out.model = arg.slice("--model=".length);
|
|
486
|
+
}
|
|
487
|
+
else if (arg === "--reasoning-effort") {
|
|
488
|
+
const value = nextArgValue(extraArgs, i);
|
|
489
|
+
if (value !== undefined) {
|
|
490
|
+
out.reasoningEffort = value;
|
|
491
|
+
i += 1;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
else if (arg.startsWith("--reasoning-effort=")) {
|
|
495
|
+
out.reasoningEffort = arg.slice("--reasoning-effort=".length);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return out;
|
|
499
|
+
}
|
|
500
|
+
function nextArgValue(args, index) {
|
|
501
|
+
const next = args[index + 1];
|
|
502
|
+
if (typeof next !== "string")
|
|
503
|
+
return undefined;
|
|
504
|
+
if (!next.startsWith("-"))
|
|
505
|
+
return next;
|
|
506
|
+
return /^-\d/.test(next) ? next : undefined;
|
|
507
|
+
}
|
|
460
508
|
function poolKey(opts) {
|
|
461
509
|
return opts.accountId || "default";
|
|
462
510
|
}
|
package/dist/provision.d.ts
CHANGED
|
@@ -107,6 +107,8 @@ export declare function collectRuntimeSnapshot(opts?: {
|
|
|
107
107
|
export declare function attachRuntimeHealth(snapshot: ListRuntimesResult, live: GatewayRuntimeSnapshot): ListRuntimesResult;
|
|
108
108
|
/** Maximum number of `endpoints[]` entries persisted per runtime (RFC §3.8.2). */
|
|
109
109
|
export declare const RUNTIME_ENDPOINTS_CAP = 32;
|
|
110
|
+
export declare const RUNTIME_MODELS_CAP = 128;
|
|
111
|
+
export declare const RUNTIME_PARAMETERS_CAP = 64;
|
|
110
112
|
/** Injection seam for L2 + L3 endpoint probes — kept testable + side-effect-free. */
|
|
111
113
|
export type WsEndpointProbeFn = (args: {
|
|
112
114
|
url: string;
|
package/dist/provision.js
CHANGED
|
@@ -18,6 +18,8 @@ import { hermesProfileHomeDir, isValidHermesProfileName, listHermesProfiles, } f
|
|
|
18
18
|
import { log as daemonLog } from "./log.js";
|
|
19
19
|
import { discoverAgentCredentials } from "./agent-discovery.js";
|
|
20
20
|
import { resolveMemoryDir } from "./working-memory.js";
|
|
21
|
+
import { discoverRuntimeModelCatalog } from "./runtime-models.js";
|
|
22
|
+
import { buildRuntimeSelectionExtraArgs, mergeRuntimeExtraArgs, } from "./runtime-route-options.js";
|
|
21
23
|
/**
|
|
22
24
|
* Build a dispatcher function that routes a `ControlFrame` to the right
|
|
23
25
|
* handler. Returned function signature matches
|
|
@@ -783,6 +785,9 @@ function upsertManagedRouteForCredentials(credentials, cfg, gateway) {
|
|
|
783
785
|
runtime: credentials.runtime ?? cfg.defaultRoute.adapter,
|
|
784
786
|
cwd: credentials.cwd ?? agentWorkspaceDir(credentials.agentId),
|
|
785
787
|
};
|
|
788
|
+
const extraArgs = mergeRuntimeExtraArgs(cfg.defaultRoute.extraArgs, buildRuntimeSelectionExtraArgs(synthRoute.runtime, credentials));
|
|
789
|
+
if (extraArgs)
|
|
790
|
+
synthRoute.extraArgs = extraArgs;
|
|
786
791
|
if (synthRoute.runtime === "openclaw-acp") {
|
|
787
792
|
const profile = (cfg.openclawGateways ?? []).find((g) => g.name === credentials.openclawGateway);
|
|
788
793
|
if (profile) {
|
|
@@ -887,6 +892,13 @@ async function materializeCredentials(params, cfg, ctx, explicitCwd) {
|
|
|
887
892
|
record.tokenExpiresAt = c.tokenExpiresAt;
|
|
888
893
|
if (runtime)
|
|
889
894
|
record.runtime = runtime;
|
|
895
|
+
const runtimeSelection = pickRuntimeSelection(params);
|
|
896
|
+
if (runtimeSelection.runtimeModel)
|
|
897
|
+
record.runtimeModel = runtimeSelection.runtimeModel;
|
|
898
|
+
if (runtimeSelection.reasoningEffort)
|
|
899
|
+
record.reasoningEffort = runtimeSelection.reasoningEffort;
|
|
900
|
+
if (typeof runtimeSelection.thinking === "boolean")
|
|
901
|
+
record.thinking = runtimeSelection.thinking;
|
|
890
902
|
record.cwd = cwd;
|
|
891
903
|
const openclawSel = pickOpenclawSelection(params);
|
|
892
904
|
if (openclawSel.gateway)
|
|
@@ -922,6 +934,13 @@ async function materializeCredentials(params, cfg, ctx, explicitCwd) {
|
|
|
922
934
|
};
|
|
923
935
|
if (runtime)
|
|
924
936
|
record.runtime = runtime;
|
|
937
|
+
const runtimeSelection = pickRuntimeSelection(params);
|
|
938
|
+
if (runtimeSelection.runtimeModel)
|
|
939
|
+
record.runtimeModel = runtimeSelection.runtimeModel;
|
|
940
|
+
if (runtimeSelection.reasoningEffort)
|
|
941
|
+
record.reasoningEffort = runtimeSelection.reasoningEffort;
|
|
942
|
+
if (typeof runtimeSelection.thinking === "boolean")
|
|
943
|
+
record.thinking = runtimeSelection.thinking;
|
|
925
944
|
record.cwd = cwd;
|
|
926
945
|
const openclawSel = pickOpenclawSelection(params);
|
|
927
946
|
if (openclawSel.gateway)
|
|
@@ -1449,6 +1468,12 @@ export function collectRuntimeSnapshot(opts = {}) {
|
|
|
1449
1468
|
record.version = entry.result.version;
|
|
1450
1469
|
if (entry.result.path)
|
|
1451
1470
|
record.path = entry.result.path;
|
|
1471
|
+
const catalog = discoverRuntimeModelCatalog(entry);
|
|
1472
|
+
const models = catalog.models;
|
|
1473
|
+
if (models?.length)
|
|
1474
|
+
record.models = models.slice(0, RUNTIME_MODELS_CAP);
|
|
1475
|
+
if (catalog.parameters?.length)
|
|
1476
|
+
record.parameters = catalog.parameters.slice(0, RUNTIME_PARAMETERS_CAP);
|
|
1452
1477
|
// Gateway's probe surface doesn't expose an `error` string today — it
|
|
1453
1478
|
// already swallows throws into `{available: false}`. We leave the wire
|
|
1454
1479
|
// field blank in that case and let callers treat `!available` as reason
|
|
@@ -1502,6 +1527,8 @@ export function attachRuntimeHealth(snapshot, live) {
|
|
|
1502
1527
|
}
|
|
1503
1528
|
/** Maximum number of `endpoints[]` entries persisted per runtime (RFC §3.8.2). */
|
|
1504
1529
|
export const RUNTIME_ENDPOINTS_CAP = 32;
|
|
1530
|
+
export const RUNTIME_MODELS_CAP = 128;
|
|
1531
|
+
export const RUNTIME_PARAMETERS_CAP = 64;
|
|
1505
1532
|
export function classifyOpenclawAuthError(message) {
|
|
1506
1533
|
const text = (message ?? "").toLowerCase();
|
|
1507
1534
|
if (!text)
|
|
@@ -2096,6 +2123,12 @@ function readAgentRuntimesFromCredentials(agentIds) {
|
|
|
2096
2123
|
const entry = {};
|
|
2097
2124
|
if (creds.runtime)
|
|
2098
2125
|
entry.runtime = creds.runtime;
|
|
2126
|
+
if (creds.runtimeModel)
|
|
2127
|
+
entry.runtimeModel = creds.runtimeModel;
|
|
2128
|
+
if (creds.reasoningEffort)
|
|
2129
|
+
entry.reasoningEffort = creds.reasoningEffort;
|
|
2130
|
+
if (typeof creds.thinking === "boolean")
|
|
2131
|
+
entry.thinking = creds.thinking;
|
|
2099
2132
|
if (creds.cwd)
|
|
2100
2133
|
entry.cwd = creds.cwd;
|
|
2101
2134
|
if (creds.openclawGateway)
|
|
@@ -2104,8 +2137,16 @@ function readAgentRuntimesFromCredentials(agentIds) {
|
|
|
2104
2137
|
entry.openclawAgent = creds.openclawAgent;
|
|
2105
2138
|
if (creds.hermesProfile)
|
|
2106
2139
|
entry.hermesProfile = creds.hermesProfile;
|
|
2107
|
-
if (entry.runtime ||
|
|
2140
|
+
if (entry.runtime ||
|
|
2141
|
+
entry.runtimeModel ||
|
|
2142
|
+
entry.reasoningEffort ||
|
|
2143
|
+
typeof entry.thinking === "boolean" ||
|
|
2144
|
+
entry.cwd ||
|
|
2145
|
+
entry.openclawGateway ||
|
|
2146
|
+
entry.openclawAgent ||
|
|
2147
|
+
entry.hermesProfile) {
|
|
2108
2148
|
out[id] = entry;
|
|
2149
|
+
}
|
|
2109
2150
|
}
|
|
2110
2151
|
catch {
|
|
2111
2152
|
// best-effort — skip agents with unreadable credentials
|
|
@@ -2309,6 +2350,30 @@ function pickRuntime(params) {
|
|
|
2309
2350
|
}
|
|
2310
2351
|
return undefined;
|
|
2311
2352
|
}
|
|
2353
|
+
function pickRuntimeSelection(params) {
|
|
2354
|
+
const out = {};
|
|
2355
|
+
const runtimeModel = pickString(params.runtimeModel, params.credentials?.runtimeModel);
|
|
2356
|
+
const reasoningEffort = pickString(params.reasoningEffort, params.credentials?.reasoningEffort);
|
|
2357
|
+
if (runtimeModel)
|
|
2358
|
+
out.runtimeModel = runtimeModel;
|
|
2359
|
+
if (reasoningEffort)
|
|
2360
|
+
out.reasoningEffort = reasoningEffort;
|
|
2361
|
+
if (typeof params.thinking === "boolean") {
|
|
2362
|
+
out.thinking = params.thinking;
|
|
2363
|
+
}
|
|
2364
|
+
else if (typeof params.credentials?.thinking === "boolean") {
|
|
2365
|
+
out.thinking = params.credentials.thinking;
|
|
2366
|
+
}
|
|
2367
|
+
return out;
|
|
2368
|
+
}
|
|
2369
|
+
function pickString(...values) {
|
|
2370
|
+
for (const value of values) {
|
|
2371
|
+
const trimmed = value?.trim();
|
|
2372
|
+
if (trimmed)
|
|
2373
|
+
return trimmed;
|
|
2374
|
+
}
|
|
2375
|
+
return undefined;
|
|
2376
|
+
}
|
|
2312
2377
|
function assertKnownRuntime(runtime) {
|
|
2313
2378
|
const mod = getAdapterModule(runtime);
|
|
2314
2379
|
if (!mod) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RuntimeModelProbe, RuntimeParameterProbe } from "@botcord/protocol-core";
|
|
2
|
+
import type { RuntimeProbeEntry } from "./adapters/runtimes.js";
|
|
3
|
+
export interface RuntimeModelDiscovery {
|
|
4
|
+
models?: RuntimeModelProbe[];
|
|
5
|
+
parameters?: RuntimeParameterProbe[];
|
|
6
|
+
}
|
|
7
|
+
export declare function discoverRuntimeModelCatalog(entry: RuntimeProbeEntry): RuntimeModelDiscovery;
|
|
8
|
+
export declare function discoverRuntimeModels(entry: RuntimeProbeEntry): RuntimeModelProbe[] | undefined;
|
|
9
|
+
export declare function discoverRuntimeParameters(entry: RuntimeProbeEntry): RuntimeParameterProbe[] | undefined;
|
|
10
|
+
export declare function discoverClaudeModels(): RuntimeModelProbe[];
|
|
11
|
+
export declare function discoverCodexModels(command: string | undefined): RuntimeModelProbe[] | undefined;
|
|
12
|
+
export declare function parseCodexModelCatalog(raw: string): RuntimeModelProbe[] | undefined;
|
|
13
|
+
export declare function discoverDeepseekModels(command: string | undefined): RuntimeModelProbe[] | undefined;
|
|
14
|
+
export declare function parseDeepseekModelList(raw: string): RuntimeModelProbe[] | undefined;
|
|
15
|
+
export declare function discoverKimiModels(): RuntimeModelProbe[] | undefined;
|
|
16
|
+
export declare function parseKimiConfigModels(raw: string): RuntimeModelProbe[] | undefined;
|
|
17
|
+
export declare function parseKimiRuntimeParameters(raw: string): RuntimeParameterProbe[];
|