@rethinkingstudio/clawpilot 1.0.18 → 1.1.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.
@@ -0,0 +1,20 @@
1
+ export interface ProviderEntry {
2
+ id: string;
3
+ type: string;
4
+ baseUrl: string;
5
+ keyMasked: string | null;
6
+ hasKey: boolean;
7
+ isDefault: boolean;
8
+ }
9
+ export declare function listProviderEntries(): Promise<ProviderEntry[]>;
10
+ export declare function addProvider(params: {
11
+ id: string;
12
+ type: string;
13
+ apiKey: string | null;
14
+ baseUrl: string;
15
+ api: string;
16
+ apiKeyEnvName: string;
17
+ modelId?: string;
18
+ }): Promise<void>;
19
+ export declare function deleteProvider(id: string): Promise<void>;
20
+ export declare function setDefaultProvider(id: string): Promise<void>;
@@ -0,0 +1,162 @@
1
+ import { readFile, writeFile, mkdir, readdir } from "fs/promises";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
4
+ const OPENCLAW_DIR = join(homedir(), ".openclaw");
5
+ const OPENCLAW_CONFIG = join(OPENCLAW_DIR, "openclaw.json");
6
+ const AGENTS_DIR = join(OPENCLAW_DIR, "agents");
7
+ // ---------------------------------------------------------------------------
8
+ // Internal helpers
9
+ // ---------------------------------------------------------------------------
10
+ function maskKey(key) {
11
+ if (key.length <= 8)
12
+ return key.slice(0, 2) + "***" + key.slice(-2);
13
+ return key.slice(0, 4) + "***" + key.slice(-4);
14
+ }
15
+ async function resolveAgentId() {
16
+ try {
17
+ const entries = await readdir(AGENTS_DIR, { withFileTypes: true });
18
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
19
+ if (dirs.length > 0) {
20
+ return dirs[0];
21
+ }
22
+ }
23
+ catch {
24
+ // agents dir missing or unreadable
25
+ }
26
+ return "main";
27
+ }
28
+ async function readJson(filePath) {
29
+ try {
30
+ const raw = await readFile(filePath, "utf-8");
31
+ return JSON.parse(raw);
32
+ }
33
+ catch {
34
+ return {};
35
+ }
36
+ }
37
+ async function writeJson(filePath, data) {
38
+ await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
39
+ }
40
+ function getNestedObj(root, keys) {
41
+ let cur = root;
42
+ for (const key of keys) {
43
+ if (cur[key] == null || typeof cur[key] !== "object" || Array.isArray(cur[key])) {
44
+ cur[key] = {};
45
+ }
46
+ cur = cur[key];
47
+ }
48
+ return cur;
49
+ }
50
+ function authProfilesPath(agentId) {
51
+ return join(AGENTS_DIR, agentId, "agent", "auth-profiles.json");
52
+ }
53
+ // ---------------------------------------------------------------------------
54
+ // Public API
55
+ // ---------------------------------------------------------------------------
56
+ export async function listProviderEntries() {
57
+ const config = await readJson(OPENCLAW_CONFIG);
58
+ // Dig out models.providers
59
+ const models = config["models"] ?? {};
60
+ const providers = models["providers"] ?? {};
61
+ // Determine current default model primary string
62
+ const agents = config["agents"] ?? {};
63
+ const defaults = agents["defaults"] ?? {};
64
+ const model = defaults["model"] ?? {};
65
+ const primaryModel = typeof model["primary"] === "string" ? model["primary"] : "";
66
+ // Read auth profiles for key lookup
67
+ const agentId = await resolveAgentId();
68
+ const authProfiles = await readJson(authProfilesPath(agentId));
69
+ const profiles = authProfiles["profiles"] ?? {};
70
+ const entries = [];
71
+ for (const [id, providerRaw] of Object.entries(providers)) {
72
+ const provider = providerRaw ?? {};
73
+ const type = typeof provider["type"] === "string" ? provider["type"] : id;
74
+ const baseUrl = typeof provider["baseUrl"] === "string" ? provider["baseUrl"] : "";
75
+ // Key lookup: profile key is "<type>:default"
76
+ const profileKey = `${type}:default`;
77
+ const profileRaw = profiles[profileKey];
78
+ const profile = profileRaw != null && typeof profileRaw === "object" && !Array.isArray(profileRaw)
79
+ ? profileRaw
80
+ : null;
81
+ const apiKey = profile != null && typeof profile["apiKey"] === "string"
82
+ ? profile["apiKey"]
83
+ : null;
84
+ const hasKey = apiKey != null && apiKey.length > 0;
85
+ const keyMasked = hasKey ? maskKey(apiKey) : null;
86
+ // isDefault: primary model string starts with "<id>/"
87
+ const isDefault = primaryModel === id || primaryModel.startsWith(`${id}/`);
88
+ entries.push({ id, type, baseUrl, keyMasked, hasKey, isDefault });
89
+ }
90
+ return entries;
91
+ }
92
+ export async function addProvider(params) {
93
+ const { id, type, apiKey, baseUrl, api, apiKeyEnvName, modelId } = params;
94
+ // --- Update openclaw.json ---
95
+ const config = await readJson(OPENCLAW_CONFIG);
96
+ const models = getNestedObj(config, ["models"]);
97
+ const providers = getNestedObj(models, ["providers"]);
98
+ const providerEntry = { type, baseUrl, api, apiKeyEnvName };
99
+ if (modelId !== undefined) {
100
+ providerEntry["modelId"] = modelId;
101
+ }
102
+ providers[id] = providerEntry;
103
+ await writeJson(OPENCLAW_CONFIG, config);
104
+ // Note: writes are not atomic. openclaw.json is updated first, then auth-profiles.json.
105
+ // If auth-profiles write fails, the provider will appear in the list without a key.
106
+ // This is acceptable since config files are user-owned and easily recoverable.
107
+ // --- Update auth-profiles.json (only if apiKey provided) ---
108
+ if (apiKey != null && apiKey.length > 0) {
109
+ const agentId = await resolveAgentId();
110
+ const profilesPath = authProfilesPath(agentId);
111
+ const profilesDir = join(AGENTS_DIR, agentId, "agent");
112
+ await mkdir(profilesDir, { recursive: true });
113
+ const authProfiles = await readJson(profilesPath);
114
+ const profiles = getNestedObj(authProfiles, ["profiles"]);
115
+ const profileKey = `${type}:default`;
116
+ profiles[profileKey] = { apiKey };
117
+ await writeJson(profilesPath, authProfiles);
118
+ }
119
+ }
120
+ export async function deleteProvider(id) {
121
+ // --- Update openclaw.json ---
122
+ const config = await readJson(OPENCLAW_CONFIG);
123
+ const models = getNestedObj(config, ["models"]);
124
+ const providers = getNestedObj(models, ["providers"]);
125
+ const providerRaw = providers[id];
126
+ const type = providerRaw != null &&
127
+ typeof providerRaw === "object" &&
128
+ !Array.isArray(providerRaw) &&
129
+ typeof providerRaw["type"] === "string"
130
+ ? providerRaw["type"]
131
+ : id;
132
+ delete providers[id];
133
+ // Note: writes are not atomic. openclaw.json is updated first, then auth-profiles.json.
134
+ // If auth-profiles write fails, the provider will appear in the list without a key.
135
+ // This is acceptable since config files are user-owned and easily recoverable.
136
+ await writeJson(OPENCLAW_CONFIG, config);
137
+ // --- Update auth-profiles.json ---
138
+ const agentId = await resolveAgentId();
139
+ const profilesPath = authProfilesPath(agentId);
140
+ const authProfiles = await readJson(profilesPath);
141
+ const profiles = getNestedObj(authProfiles, ["profiles"]);
142
+ const profileKey = `${type}:default`;
143
+ if (profileKey in profiles) {
144
+ delete profiles[profileKey];
145
+ await writeJson(profilesPath, authProfiles);
146
+ }
147
+ }
148
+ export async function setDefaultProvider(id) {
149
+ const config = await readJson(OPENCLAW_CONFIG);
150
+ // Preserve existing model suffix if present
151
+ const agents = getNestedObj(config, ["agents"]);
152
+ const defaults = getNestedObj(agents, ["defaults"]);
153
+ const model = getNestedObj(defaults, ["model"]);
154
+ const currentPrimary = typeof model["primary"] === "string" ? model["primary"] : "";
155
+ let modelSuffix = "default";
156
+ if (currentPrimary.includes("/")) {
157
+ modelSuffix = currentPrimary.split("/").slice(1).join("/");
158
+ }
159
+ model["primary"] = `${id}/${modelSuffix}`;
160
+ await writeJson(OPENCLAW_CONFIG, config);
161
+ }
162
+ //# sourceMappingURL=provider-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-config.js","sourceRoot":"","sources":["../../src/commands/provider-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { LocalResult } from "./local-handlers.js";
2
+ export declare function handleProviderCommand(method: string, params: unknown): Promise<LocalResult> | null;
@@ -0,0 +1,197 @@
1
+ import { execSync } from "child_process";
2
+ import { existsSync } from "fs";
3
+ import { dirname } from "path";
4
+ import { homedir } from "os";
5
+ import { randomUUID } from "crypto";
6
+ import { PROVIDER_REGISTRY } from "./provider-registry.js";
7
+ import { listProviderEntries, addProvider, deleteProvider, setDefaultProvider, } from "./provider-config.js";
8
+ // ---------------------------------------------------------------------------
9
+ // Subprocess env (mirrors local-handlers.ts)
10
+ // ---------------------------------------------------------------------------
11
+ const NODE_BIN_DIR = dirname(process.execPath);
12
+ const SUBPROCESS_ENV = {
13
+ ...process.env,
14
+ HOME: homedir(),
15
+ PATH: [
16
+ NODE_BIN_DIR,
17
+ "/opt/homebrew/bin",
18
+ "/opt/homebrew/sbin",
19
+ "/usr/local/bin",
20
+ "/usr/local/sbin",
21
+ process.env.PATH ?? "/usr/bin:/bin",
22
+ ].join(":"),
23
+ };
24
+ function resolveOpenclawBin() {
25
+ try {
26
+ const p = execSync("which openclaw", { stdio: "pipe", env: SUBPROCESS_ENV, timeout: 3000 })
27
+ .toString().trim();
28
+ if (p && existsSync(p))
29
+ return p;
30
+ }
31
+ catch { /* fall through */ }
32
+ return "openclaw";
33
+ }
34
+ const OPENCLAW_BIN = resolveOpenclawBin();
35
+ function restartGateway() {
36
+ try {
37
+ execSync(`"${OPENCLAW_BIN}" gateway restart`, { stdio: "pipe", env: SUBPROCESS_ENV });
38
+ console.log("[provider] gateway restarted");
39
+ }
40
+ catch (err) {
41
+ console.warn("[provider] gateway restart failed:", String(err));
42
+ }
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // HTTP key validation
46
+ // ---------------------------------------------------------------------------
47
+ async function validateApiKey(type, apiKey, baseUrl) {
48
+ const info = PROVIDER_REGISTRY[type];
49
+ if (!info)
50
+ return { ok: false, error: `Unknown provider type: ${type}` };
51
+ if (!info.requiresApiKey || !apiKey)
52
+ return { ok: true };
53
+ return new Promise((resolve) => {
54
+ try {
55
+ const url = new URL(info.validationPath, baseUrl);
56
+ if (info.validationAuth === "google-query-param") {
57
+ url.searchParams.set("key", apiKey);
58
+ }
59
+ const headers = {};
60
+ if (info.validationAuth === "bearer") {
61
+ headers["Authorization"] = `Bearer ${apiKey}`;
62
+ }
63
+ else if (info.validationAuth === "x-api-key") {
64
+ headers["x-api-key"] = apiKey;
65
+ headers["anthropic-version"] = "2023-06-01";
66
+ }
67
+ // Use http or https based on protocol
68
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
69
+ const mod = url.protocol === "https:" ? require("https") : require("http");
70
+ const req = mod.get({
71
+ hostname: url.hostname,
72
+ port: url.port || undefined,
73
+ path: url.pathname + url.search,
74
+ headers,
75
+ }, (res) => {
76
+ res.resume(); // drain body
77
+ const status = res.statusCode ?? 0;
78
+ if (status >= 200 && status < 300) {
79
+ resolve({ ok: true });
80
+ }
81
+ else if (status === 401 || status === 403) {
82
+ resolve({ ok: false, error: "API Key 无效" });
83
+ }
84
+ else {
85
+ resolve({ ok: false, error: `验证失败 (HTTP ${status})` });
86
+ }
87
+ });
88
+ req.setTimeout(10_000, () => {
89
+ req.destroy();
90
+ resolve({ ok: false, error: "验证超时" });
91
+ });
92
+ req.on("error", (e) => resolve({ ok: false, error: e.message }));
93
+ }
94
+ catch (e) {
95
+ resolve({ ok: false, error: String(e) });
96
+ }
97
+ });
98
+ }
99
+ // ---------------------------------------------------------------------------
100
+ // Command handlers
101
+ // ---------------------------------------------------------------------------
102
+ async function cmdList() {
103
+ try {
104
+ const providers = await listProviderEntries();
105
+ return { ok: true, payload: { providers } };
106
+ }
107
+ catch (err) {
108
+ return { ok: false, error: String(err) };
109
+ }
110
+ }
111
+ async function cmdValidateKey(params) {
112
+ try {
113
+ const type = params.type;
114
+ const apiKey = params.apiKey;
115
+ const baseUrl = params.baseUrl ?? PROVIDER_REGISTRY[type]?.defaultBaseUrl ?? "";
116
+ const result = await validateApiKey(type, apiKey, baseUrl);
117
+ if (result.ok)
118
+ return { ok: true };
119
+ return { ok: false, error: result.error ?? "验证失败" };
120
+ }
121
+ catch (err) {
122
+ return { ok: false, error: String(err) };
123
+ }
124
+ }
125
+ async function cmdAdd(params) {
126
+ try {
127
+ const type = params.type;
128
+ const apiKey = params.apiKey ?? null;
129
+ const info = PROVIDER_REGISTRY[type];
130
+ if (!info)
131
+ return { ok: false, error: `Unknown provider type: ${type}` };
132
+ const baseUrl = params.baseUrl || info.defaultBaseUrl;
133
+ const modelId = params.modelId ?? info.defaultModelId;
134
+ // Validate key before writing config
135
+ if (info.requiresApiKey && apiKey) {
136
+ const v = await validateApiKey(type, apiKey, baseUrl);
137
+ if (!v.ok)
138
+ return { ok: false, error: v.error ?? "API Key 无效" };
139
+ }
140
+ // custom providers get a UUID suffix; id and apiKeyEnvName share the same UUID so they're traceable
141
+ const uuid = info.allowMultiple ? randomUUID() : null;
142
+ const id = uuid ? `custom-${uuid}` : type;
143
+ const apiKeyEnvName = uuid
144
+ ? `CUSTOM_${uuid.replace(/-/g, "_").toUpperCase()}_API_KEY`
145
+ : info.apiKeyEnvName;
146
+ await addProvider({ id, type, apiKey, baseUrl, api: info.api, apiKeyEnvName, modelId });
147
+ restartGateway();
148
+ return { ok: true, payload: { id } };
149
+ }
150
+ catch (err) {
151
+ return { ok: false, error: String(err) };
152
+ }
153
+ }
154
+ async function cmdDelete(params) {
155
+ try {
156
+ const id = params.id;
157
+ if (!id)
158
+ return { ok: false, error: "id required" };
159
+ await deleteProvider(id);
160
+ restartGateway();
161
+ return { ok: true };
162
+ }
163
+ catch (err) {
164
+ return { ok: false, error: String(err) };
165
+ }
166
+ }
167
+ async function cmdSetDefault(params) {
168
+ try {
169
+ const id = params.id;
170
+ if (!id)
171
+ return { ok: false, error: "id required" };
172
+ await setDefaultProvider(id);
173
+ restartGateway();
174
+ return { ok: true };
175
+ }
176
+ catch (err) {
177
+ return { ok: false, error: String(err) };
178
+ }
179
+ }
180
+ // ---------------------------------------------------------------------------
181
+ // Main dispatch
182
+ // ---------------------------------------------------------------------------
183
+ export function handleProviderCommand(method, params) {
184
+ if (!method.startsWith("clawpilot.provider."))
185
+ return null;
186
+ const p = (params ?? {});
187
+ switch (method) {
188
+ case "clawpilot.provider.list": return cmdList();
189
+ case "clawpilot.provider.validateKey": return cmdValidateKey(p);
190
+ case "clawpilot.provider.add": return cmdAdd(p);
191
+ case "clawpilot.provider.delete": return cmdDelete(p);
192
+ case "clawpilot.provider.setDefault": return cmdSetDefault(p);
193
+ default:
194
+ return Promise.resolve({ ok: false, error: `Unknown provider command: ${method}` });
195
+ }
196
+ }
197
+ //# sourceMappingURL=provider-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-handlers.js","sourceRoot":"","sources":["../../src/commands/provider-handlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface ProviderTypeInfo {
2
+ displayName: string;
3
+ defaultBaseUrl: string;
4
+ api: "anthropic-messages" | "openai-completions" | "openai-responses";
5
+ apiKeyEnvName: string;
6
+ validationPath: string;
7
+ validationAuth: "bearer" | "x-api-key" | "google-query-param" | "none";
8
+ requiresApiKey: boolean;
9
+ allowMultiple: boolean;
10
+ showBaseUrl: boolean;
11
+ showModelId: boolean;
12
+ defaultModelId?: string;
13
+ }
14
+ export declare const PROVIDER_REGISTRY: Record<string, ProviderTypeInfo>;
@@ -0,0 +1,112 @@
1
+ export const PROVIDER_REGISTRY = {
2
+ anthropic: {
3
+ displayName: "Anthropic",
4
+ defaultBaseUrl: "https://api.anthropic.com",
5
+ api: "anthropic-messages",
6
+ apiKeyEnvName: "ANTHROPIC_API_KEY",
7
+ validationPath: "/v1/models",
8
+ validationAuth: "x-api-key",
9
+ requiresApiKey: true,
10
+ allowMultiple: false,
11
+ showBaseUrl: false,
12
+ showModelId: false,
13
+ },
14
+ openai: {
15
+ displayName: "OpenAI",
16
+ defaultBaseUrl: "https://api.openai.com",
17
+ api: "openai-responses",
18
+ apiKeyEnvName: "OPENAI_API_KEY",
19
+ validationPath: "/v1/models",
20
+ validationAuth: "bearer",
21
+ requiresApiKey: true,
22
+ allowMultiple: false,
23
+ showBaseUrl: false,
24
+ showModelId: false,
25
+ },
26
+ google: {
27
+ displayName: "Google",
28
+ defaultBaseUrl: "https://generativelanguage.googleapis.com",
29
+ api: "openai-completions",
30
+ apiKeyEnvName: "GOOGLE_API_KEY",
31
+ validationPath: "/v1beta/models",
32
+ validationAuth: "google-query-param",
33
+ requiresApiKey: true,
34
+ allowMultiple: false,
35
+ showBaseUrl: false,
36
+ showModelId: false,
37
+ },
38
+ openrouter: {
39
+ displayName: "OpenRouter",
40
+ defaultBaseUrl: "https://openrouter.ai",
41
+ api: "openai-completions",
42
+ apiKeyEnvName: "OPENROUTER_API_KEY",
43
+ validationPath: "/api/v1/models",
44
+ validationAuth: "bearer",
45
+ requiresApiKey: true,
46
+ allowMultiple: false,
47
+ showBaseUrl: false,
48
+ showModelId: false,
49
+ },
50
+ ark: {
51
+ displayName: "ByteDance (Ark)",
52
+ defaultBaseUrl: "https://ark.cn-beijing.volces.com",
53
+ api: "openai-completions",
54
+ apiKeyEnvName: "ARK_API_KEY",
55
+ validationPath: "/api/v3/models",
56
+ validationAuth: "bearer",
57
+ requiresApiKey: true,
58
+ allowMultiple: false,
59
+ showBaseUrl: false,
60
+ showModelId: false,
61
+ },
62
+ moonshot: {
63
+ displayName: "Moonshot (Kimi)",
64
+ defaultBaseUrl: "https://api.moonshot.cn",
65
+ api: "openai-completions",
66
+ apiKeyEnvName: "MOONSHOT_API_KEY",
67
+ validationPath: "/v1/models",
68
+ validationAuth: "bearer",
69
+ requiresApiKey: true,
70
+ allowMultiple: false,
71
+ showBaseUrl: false,
72
+ showModelId: false,
73
+ },
74
+ siliconflow: {
75
+ displayName: "SiliconFlow",
76
+ defaultBaseUrl: "https://api.siliconflow.cn",
77
+ api: "openai-completions",
78
+ apiKeyEnvName: "SILICONFLOW_API_KEY",
79
+ validationPath: "/v1/models",
80
+ validationAuth: "bearer",
81
+ requiresApiKey: true,
82
+ allowMultiple: false,
83
+ showBaseUrl: false,
84
+ showModelId: false,
85
+ },
86
+ ollama: {
87
+ displayName: "Ollama",
88
+ defaultBaseUrl: "http://localhost:11434",
89
+ api: "openai-completions",
90
+ apiKeyEnvName: "OLLAMA_API_KEY",
91
+ validationPath: "/api/tags",
92
+ validationAuth: "none",
93
+ requiresApiKey: false,
94
+ allowMultiple: false,
95
+ showBaseUrl: true,
96
+ showModelId: false,
97
+ },
98
+ custom: {
99
+ displayName: "Custom",
100
+ defaultBaseUrl: "",
101
+ api: "openai-completions",
102
+ apiKeyEnvName: "CUSTOM_API_KEY",
103
+ validationPath: "/v1/models",
104
+ validationAuth: "bearer",
105
+ requiresApiKey: false,
106
+ allowMultiple: true,
107
+ showBaseUrl: true,
108
+ showModelId: true,
109
+ defaultModelId: "custom-model",
110
+ },
111
+ };
112
+ //# sourceMappingURL=provider-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-registry.js","sourceRoot":"","sources":["../../src/commands/provider-registry.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
+ import { createRequire } from "module";
3
4
  import { pairCommand } from "./commands/pair.js";
4
5
  import { runCommand } from "./commands/run.js";
5
6
  import { installCommand, uninstallCommand, stopCommand, restartCommand, resetCommand } from "./commands/install.js";
6
7
  import { statusCommand } from "./commands/status.js";
7
8
  import { setTokenCommand } from "./commands/set-token.js";
8
- const version = "1.0.18";
9
+ const require = createRequire(import.meta.url);
10
+ const { version } = require("../package.json");
9
11
  const program = new Command();
10
12
  program
11
13
  .name("clawpilot")
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { WebSocket } from "ws";
2
2
  import { OpenClawGatewayClient } from "./gateway-client.js";
3
3
  import { handleLocalCommand } from "../commands/local-handlers.js";
4
+ import { handleProviderCommand } from "../commands/provider-handlers.js";
4
5
  import { homedir } from "os";
5
6
  import { join } from "path";
6
7
  import { mkdir, writeFile } from "fs/promises";
@@ -73,6 +74,22 @@ export async function runRelayManager(opts) {
73
74
  return;
74
75
  const requestId = msg.id;
75
76
  console.log(`[relay] cmd received method=${msg.method} id=${requestId ?? "(no-id)"}`);
77
+ // Handle clawpilot.provider.* commands locally (async)
78
+ const providerPromise = handleProviderCommand(msg.method, msg.params);
79
+ if (providerPromise !== null) {
80
+ const result = await providerPromise;
81
+ if (requestId) {
82
+ send({
83
+ type: "res",
84
+ id: requestId,
85
+ ok: result.ok,
86
+ ...(result.ok
87
+ ? { payload: result.payload }
88
+ : { error: { message: result.error } }),
89
+ });
90
+ }
91
+ return;
92
+ }
76
93
  // Handle clawpilot.* commands locally without forwarding to the gateway
77
94
  const localResult = handleLocalCommand(msg.method);
78
95
  if (localResult !== null) {
@@ -1 +1 @@
1
- {"version":3,"file":"relay-manager.js","sourceRoot":"","sources":["../../src/relay/relay-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relay-manager.js","sourceRoot":"","sources":["../../src/relay/relay-manager.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rethinkingstudio/clawpilot",
3
- "version": "1.0.18",
3
+ "version": "1.1.0",
4
4
  "description": "ClawAI relay client for Mac mini",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,224 @@
1
+ import { readFile, writeFile, mkdir, readdir } from "fs/promises";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
4
+
5
+ const OPENCLAW_DIR = join(homedir(), ".openclaw");
6
+ const OPENCLAW_CONFIG = join(OPENCLAW_DIR, "openclaw.json");
7
+ const AGENTS_DIR = join(OPENCLAW_DIR, "agents");
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Types
11
+ // ---------------------------------------------------------------------------
12
+
13
+ export interface ProviderEntry {
14
+ id: string; // e.g. "anthropic", "custom-<uuid>"
15
+ type: string; // provider type key
16
+ baseUrl: string;
17
+ keyMasked: string | null; // e.g. "sk-a***xyz", null if no key
18
+ hasKey: boolean;
19
+ isDefault: boolean;
20
+ }
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Internal helpers
24
+ // ---------------------------------------------------------------------------
25
+
26
+ function maskKey(key: string): string {
27
+ if (key.length <= 8) return key.slice(0, 2) + "***" + key.slice(-2);
28
+ return key.slice(0, 4) + "***" + key.slice(-4);
29
+ }
30
+
31
+ async function resolveAgentId(): Promise<string> {
32
+ try {
33
+ const entries = await readdir(AGENTS_DIR, { withFileTypes: true });
34
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
35
+ if (dirs.length > 0) {
36
+ return dirs[0];
37
+ }
38
+ } catch {
39
+ // agents dir missing or unreadable
40
+ }
41
+ return "main";
42
+ }
43
+
44
+ async function readJson(filePath: string): Promise<Record<string, unknown>> {
45
+ try {
46
+ const raw = await readFile(filePath, "utf-8");
47
+ return JSON.parse(raw) as Record<string, unknown>;
48
+ } catch {
49
+ return {};
50
+ }
51
+ }
52
+
53
+ async function writeJson(filePath: string, data: unknown): Promise<void> {
54
+ await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
55
+ }
56
+
57
+ function getNestedObj(
58
+ root: Record<string, unknown>,
59
+ keys: string[],
60
+ ): Record<string, unknown> {
61
+ let cur: Record<string, unknown> = root;
62
+ for (const key of keys) {
63
+ if (cur[key] == null || typeof cur[key] !== "object" || Array.isArray(cur[key])) {
64
+ cur[key] = {};
65
+ }
66
+ cur = cur[key] as Record<string, unknown>;
67
+ }
68
+ return cur;
69
+ }
70
+
71
+ function authProfilesPath(agentId: string): string {
72
+ return join(AGENTS_DIR, agentId, "agent", "auth-profiles.json");
73
+ }
74
+
75
+ // ---------------------------------------------------------------------------
76
+ // Public API
77
+ // ---------------------------------------------------------------------------
78
+
79
+ export async function listProviderEntries(): Promise<ProviderEntry[]> {
80
+ const config = await readJson(OPENCLAW_CONFIG);
81
+
82
+ // Dig out models.providers
83
+ const models = (config["models"] as Record<string, unknown> | undefined) ?? {};
84
+ const providers = (models["providers"] as Record<string, unknown> | undefined) ?? {};
85
+
86
+ // Determine current default model primary string
87
+ const agents = (config["agents"] as Record<string, unknown> | undefined) ?? {};
88
+ const defaults = (agents["defaults"] as Record<string, unknown> | undefined) ?? {};
89
+ const model = (defaults["model"] as Record<string, unknown> | undefined) ?? {};
90
+ const primaryModel = typeof model["primary"] === "string" ? model["primary"] : "";
91
+
92
+ // Read auth profiles for key lookup
93
+ const agentId = await resolveAgentId();
94
+ const authProfiles = await readJson(authProfilesPath(agentId));
95
+ const profiles = (authProfiles["profiles"] as Record<string, unknown> | undefined) ?? {};
96
+
97
+ const entries: ProviderEntry[] = [];
98
+
99
+ for (const [id, providerRaw] of Object.entries(providers)) {
100
+ const provider = (providerRaw as Record<string, unknown>) ?? {};
101
+ const type = typeof provider["type"] === "string" ? provider["type"] : id;
102
+ const baseUrl = typeof provider["baseUrl"] === "string" ? provider["baseUrl"] : "";
103
+
104
+ // Key lookup: profile key is "<type>:default"
105
+ const profileKey = `${type}:default`;
106
+ const profileRaw = profiles[profileKey];
107
+ const profile = profileRaw != null && typeof profileRaw === "object" && !Array.isArray(profileRaw)
108
+ ? (profileRaw as Record<string, unknown>)
109
+ : null;
110
+ const apiKey = profile != null && typeof profile["apiKey"] === "string"
111
+ ? profile["apiKey"]
112
+ : null;
113
+
114
+ const hasKey = apiKey != null && apiKey.length > 0;
115
+ const keyMasked = hasKey ? maskKey(apiKey!) : null;
116
+
117
+ // isDefault: primary model string starts with "<id>/"
118
+ const isDefault = primaryModel === id || primaryModel.startsWith(`${id}/`);
119
+
120
+ entries.push({ id, type, baseUrl, keyMasked, hasKey, isDefault });
121
+ }
122
+
123
+ return entries;
124
+ }
125
+
126
+ export async function addProvider(params: {
127
+ id: string;
128
+ type: string;
129
+ apiKey: string | null;
130
+ baseUrl: string;
131
+ api: string;
132
+ apiKeyEnvName: string;
133
+ modelId?: string;
134
+ }): Promise<void> {
135
+ const { id, type, apiKey, baseUrl, api, apiKeyEnvName, modelId } = params;
136
+
137
+ // --- Update openclaw.json ---
138
+ const config = await readJson(OPENCLAW_CONFIG);
139
+ const models = getNestedObj(config, ["models"]);
140
+ const providers = getNestedObj(models, ["providers"]);
141
+
142
+ const providerEntry: Record<string, unknown> = { type, baseUrl, api, apiKeyEnvName };
143
+ if (modelId !== undefined) {
144
+ providerEntry["modelId"] = modelId;
145
+ }
146
+ providers[id] = providerEntry;
147
+
148
+ await writeJson(OPENCLAW_CONFIG, config);
149
+
150
+ // Note: writes are not atomic. openclaw.json is updated first, then auth-profiles.json.
151
+ // If auth-profiles write fails, the provider will appear in the list without a key.
152
+ // This is acceptable since config files are user-owned and easily recoverable.
153
+
154
+ // --- Update auth-profiles.json (only if apiKey provided) ---
155
+ if (apiKey != null && apiKey.length > 0) {
156
+ const agentId = await resolveAgentId();
157
+ const profilesPath = authProfilesPath(agentId);
158
+ const profilesDir = join(AGENTS_DIR, agentId, "agent");
159
+
160
+ await mkdir(profilesDir, { recursive: true });
161
+
162
+ const authProfiles = await readJson(profilesPath);
163
+ const profiles = getNestedObj(authProfiles, ["profiles"]);
164
+
165
+ const profileKey = `${type}:default`;
166
+ profiles[profileKey] = { apiKey };
167
+
168
+ await writeJson(profilesPath, authProfiles);
169
+ }
170
+ }
171
+
172
+ export async function deleteProvider(id: string): Promise<void> {
173
+ // --- Update openclaw.json ---
174
+ const config = await readJson(OPENCLAW_CONFIG);
175
+ const models = getNestedObj(config, ["models"]);
176
+ const providers = getNestedObj(models, ["providers"]);
177
+
178
+ const providerRaw = providers[id];
179
+ const type = providerRaw != null &&
180
+ typeof providerRaw === "object" &&
181
+ !Array.isArray(providerRaw) &&
182
+ typeof (providerRaw as Record<string, unknown>)["type"] === "string"
183
+ ? (providerRaw as Record<string, unknown>)["type"] as string
184
+ : id;
185
+
186
+ delete providers[id];
187
+
188
+ // Note: writes are not atomic. openclaw.json is updated first, then auth-profiles.json.
189
+ // If auth-profiles write fails, the provider will appear in the list without a key.
190
+ // This is acceptable since config files are user-owned and easily recoverable.
191
+
192
+ await writeJson(OPENCLAW_CONFIG, config);
193
+
194
+ // --- Update auth-profiles.json ---
195
+ const agentId = await resolveAgentId();
196
+ const profilesPath = authProfilesPath(agentId);
197
+ const authProfiles = await readJson(profilesPath);
198
+ const profiles = getNestedObj(authProfiles, ["profiles"]);
199
+
200
+ const profileKey = `${type}:default`;
201
+ if (profileKey in profiles) {
202
+ delete profiles[profileKey];
203
+ await writeJson(profilesPath, authProfiles);
204
+ }
205
+ }
206
+
207
+ export async function setDefaultProvider(id: string): Promise<void> {
208
+ const config = await readJson(OPENCLAW_CONFIG);
209
+
210
+ // Preserve existing model suffix if present
211
+ const agents = getNestedObj(config, ["agents"]);
212
+ const defaults = getNestedObj(agents, ["defaults"]);
213
+ const model = getNestedObj(defaults, ["model"]);
214
+
215
+ const currentPrimary = typeof model["primary"] === "string" ? model["primary"] : "";
216
+ let modelSuffix = "default";
217
+ if (currentPrimary.includes("/")) {
218
+ modelSuffix = currentPrimary.split("/").slice(1).join("/");
219
+ }
220
+
221
+ model["primary"] = `${id}/${modelSuffix}`;
222
+
223
+ await writeJson(OPENCLAW_CONFIG, config);
224
+ }
@@ -0,0 +1,216 @@
1
+ import { execSync } from "child_process";
2
+ import { existsSync } from "fs";
3
+ import { dirname } from "path";
4
+ import { homedir } from "os";
5
+ import { randomUUID } from "crypto";
6
+ import type { LocalResult } from "./local-handlers.js";
7
+ import { PROVIDER_REGISTRY } from "./provider-registry.js";
8
+ import {
9
+ listProviderEntries,
10
+ addProvider,
11
+ deleteProvider,
12
+ setDefaultProvider,
13
+ } from "./provider-config.js";
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Subprocess env (mirrors local-handlers.ts)
17
+ // ---------------------------------------------------------------------------
18
+
19
+ const NODE_BIN_DIR = dirname(process.execPath);
20
+
21
+ const SUBPROCESS_ENV: NodeJS.ProcessEnv = {
22
+ ...process.env,
23
+ HOME: homedir(),
24
+ PATH: [
25
+ NODE_BIN_DIR,
26
+ "/opt/homebrew/bin",
27
+ "/opt/homebrew/sbin",
28
+ "/usr/local/bin",
29
+ "/usr/local/sbin",
30
+ process.env.PATH ?? "/usr/bin:/bin",
31
+ ].join(":"),
32
+ };
33
+
34
+ function resolveOpenclawBin(): string {
35
+ try {
36
+ const p = execSync("which openclaw", { stdio: "pipe", env: SUBPROCESS_ENV, timeout: 3000 })
37
+ .toString().trim();
38
+ if (p && existsSync(p)) return p;
39
+ } catch { /* fall through */ }
40
+ return "openclaw";
41
+ }
42
+
43
+ const OPENCLAW_BIN = resolveOpenclawBin();
44
+
45
+ function restartGateway(): void {
46
+ try {
47
+ execSync(`"${OPENCLAW_BIN}" gateway restart`, { stdio: "pipe", env: SUBPROCESS_ENV });
48
+ console.log("[provider] gateway restarted");
49
+ } catch (err) {
50
+ console.warn("[provider] gateway restart failed:", String(err));
51
+ }
52
+ }
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // HTTP key validation
56
+ // ---------------------------------------------------------------------------
57
+
58
+ async function validateApiKey(
59
+ type: string,
60
+ apiKey: string,
61
+ baseUrl: string
62
+ ): Promise<{ ok: boolean; error?: string }> {
63
+ const info = PROVIDER_REGISTRY[type];
64
+ if (!info) return { ok: false, error: `Unknown provider type: ${type}` };
65
+ if (!info.requiresApiKey || !apiKey) return { ok: true };
66
+
67
+ return new Promise((resolve) => {
68
+ try {
69
+ const url = new URL(info.validationPath, baseUrl);
70
+ if (info.validationAuth === "google-query-param") {
71
+ url.searchParams.set("key", apiKey);
72
+ }
73
+
74
+ const headers: Record<string, string> = {};
75
+ if (info.validationAuth === "bearer") {
76
+ headers["Authorization"] = `Bearer ${apiKey}`;
77
+ } else if (info.validationAuth === "x-api-key") {
78
+ headers["x-api-key"] = apiKey;
79
+ headers["anthropic-version"] = "2023-06-01";
80
+ }
81
+
82
+ // Use http or https based on protocol
83
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
84
+ const mod = url.protocol === "https:" ? require("https") : require("http");
85
+ const req = mod.get(
86
+ {
87
+ hostname: url.hostname,
88
+ port: url.port || undefined,
89
+ path: url.pathname + url.search,
90
+ headers,
91
+ },
92
+ (res: { statusCode?: number; resume: () => void }) => {
93
+ res.resume(); // drain body
94
+ const status = res.statusCode ?? 0;
95
+ if (status >= 200 && status < 300) {
96
+ resolve({ ok: true });
97
+ } else if (status === 401 || status === 403) {
98
+ resolve({ ok: false, error: "API Key 无效" });
99
+ } else {
100
+ resolve({ ok: false, error: `验证失败 (HTTP ${status})` });
101
+ }
102
+ }
103
+ );
104
+ req.setTimeout(10_000, () => {
105
+ req.destroy();
106
+ resolve({ ok: false, error: "验证超时" });
107
+ });
108
+ req.on("error", (e: Error) => resolve({ ok: false, error: e.message }));
109
+ } catch (e) {
110
+ resolve({ ok: false, error: String(e) });
111
+ }
112
+ });
113
+ }
114
+
115
+ // ---------------------------------------------------------------------------
116
+ // Command handlers
117
+ // ---------------------------------------------------------------------------
118
+
119
+ async function cmdList(): Promise<LocalResult> {
120
+ try {
121
+ const providers = await listProviderEntries();
122
+ return { ok: true, payload: { providers } };
123
+ } catch (err) {
124
+ return { ok: false, error: String(err) };
125
+ }
126
+ }
127
+
128
+ async function cmdValidateKey(params: Record<string, unknown>): Promise<LocalResult> {
129
+ try {
130
+ const type = params.type as string;
131
+ const apiKey = params.apiKey as string;
132
+ const baseUrl = (params.baseUrl as string | undefined) ?? PROVIDER_REGISTRY[type]?.defaultBaseUrl ?? "";
133
+ const result = await validateApiKey(type, apiKey, baseUrl);
134
+ if (result.ok) return { ok: true };
135
+ return { ok: false, error: result.error ?? "验证失败" };
136
+ } catch (err) {
137
+ return { ok: false, error: String(err) };
138
+ }
139
+ }
140
+
141
+ async function cmdAdd(params: Record<string, unknown>): Promise<LocalResult> {
142
+ try {
143
+ const type = params.type as string;
144
+ const apiKey = (params.apiKey as string | null | undefined) ?? null;
145
+ const info = PROVIDER_REGISTRY[type];
146
+ if (!info) return { ok: false, error: `Unknown provider type: ${type}` };
147
+
148
+ const baseUrl = (params.baseUrl as string | undefined) || info.defaultBaseUrl;
149
+ const modelId = (params.modelId as string | undefined) ?? info.defaultModelId;
150
+
151
+ // Validate key before writing config
152
+ if (info.requiresApiKey && apiKey) {
153
+ const v = await validateApiKey(type, apiKey, baseUrl);
154
+ if (!v.ok) return { ok: false, error: v.error ?? "API Key 无效" };
155
+ }
156
+
157
+ // custom providers get a UUID suffix; id and apiKeyEnvName share the same UUID so they're traceable
158
+ const uuid = info.allowMultiple ? randomUUID() : null;
159
+ const id = uuid ? `custom-${uuid}` : type;
160
+ const apiKeyEnvName = uuid
161
+ ? `CUSTOM_${uuid.replace(/-/g, "_").toUpperCase()}_API_KEY`
162
+ : info.apiKeyEnvName;
163
+
164
+ await addProvider({ id, type, apiKey, baseUrl, api: info.api, apiKeyEnvName, modelId });
165
+ restartGateway();
166
+ return { ok: true, payload: { id } };
167
+ } catch (err) {
168
+ return { ok: false, error: String(err) };
169
+ }
170
+ }
171
+
172
+ async function cmdDelete(params: Record<string, unknown>): Promise<LocalResult> {
173
+ try {
174
+ const id = params.id as string;
175
+ if (!id) return { ok: false, error: "id required" };
176
+ await deleteProvider(id);
177
+ restartGateway();
178
+ return { ok: true };
179
+ } catch (err) {
180
+ return { ok: false, error: String(err) };
181
+ }
182
+ }
183
+
184
+ async function cmdSetDefault(params: Record<string, unknown>): Promise<LocalResult> {
185
+ try {
186
+ const id = params.id as string;
187
+ if (!id) return { ok: false, error: "id required" };
188
+ await setDefaultProvider(id);
189
+ restartGateway();
190
+ return { ok: true };
191
+ } catch (err) {
192
+ return { ok: false, error: String(err) };
193
+ }
194
+ }
195
+
196
+ // ---------------------------------------------------------------------------
197
+ // Main dispatch
198
+ // ---------------------------------------------------------------------------
199
+
200
+ export function handleProviderCommand(
201
+ method: string,
202
+ params: unknown
203
+ ): Promise<LocalResult> | null {
204
+ if (!method.startsWith("clawpilot.provider.")) return null;
205
+ const p = (params ?? {}) as Record<string, unknown>;
206
+
207
+ switch (method) {
208
+ case "clawpilot.provider.list": return cmdList();
209
+ case "clawpilot.provider.validateKey": return cmdValidateKey(p);
210
+ case "clawpilot.provider.add": return cmdAdd(p);
211
+ case "clawpilot.provider.delete": return cmdDelete(p);
212
+ case "clawpilot.provider.setDefault": return cmdSetDefault(p);
213
+ default:
214
+ return Promise.resolve({ ok: false, error: `Unknown provider command: ${method}` });
215
+ }
216
+ }
@@ -0,0 +1,125 @@
1
+ export interface ProviderTypeInfo {
2
+ displayName: string;
3
+ defaultBaseUrl: string;
4
+ api: "anthropic-messages" | "openai-completions" | "openai-responses";
5
+ apiKeyEnvName: string;
6
+ validationPath: string;
7
+ validationAuth: "bearer" | "x-api-key" | "google-query-param" | "none";
8
+ requiresApiKey: boolean;
9
+ allowMultiple: boolean;
10
+ showBaseUrl: boolean;
11
+ showModelId: boolean;
12
+ defaultModelId?: string;
13
+ }
14
+
15
+ export const PROVIDER_REGISTRY: Record<string, ProviderTypeInfo> = {
16
+ anthropic: {
17
+ displayName: "Anthropic",
18
+ defaultBaseUrl: "https://api.anthropic.com",
19
+ api: "anthropic-messages",
20
+ apiKeyEnvName: "ANTHROPIC_API_KEY",
21
+ validationPath: "/v1/models",
22
+ validationAuth: "x-api-key",
23
+ requiresApiKey: true,
24
+ allowMultiple: false,
25
+ showBaseUrl: false,
26
+ showModelId: false,
27
+ },
28
+ openai: {
29
+ displayName: "OpenAI",
30
+ defaultBaseUrl: "https://api.openai.com",
31
+ api: "openai-responses",
32
+ apiKeyEnvName: "OPENAI_API_KEY",
33
+ validationPath: "/v1/models",
34
+ validationAuth: "bearer",
35
+ requiresApiKey: true,
36
+ allowMultiple: false,
37
+ showBaseUrl: false,
38
+ showModelId: false,
39
+ },
40
+ google: {
41
+ displayName: "Google",
42
+ defaultBaseUrl: "https://generativelanguage.googleapis.com",
43
+ api: "openai-completions",
44
+ apiKeyEnvName: "GOOGLE_API_KEY",
45
+ validationPath: "/v1beta/models",
46
+ validationAuth: "google-query-param",
47
+ requiresApiKey: true,
48
+ allowMultiple: false,
49
+ showBaseUrl: false,
50
+ showModelId: false,
51
+ },
52
+ openrouter: {
53
+ displayName: "OpenRouter",
54
+ defaultBaseUrl: "https://openrouter.ai",
55
+ api: "openai-completions",
56
+ apiKeyEnvName: "OPENROUTER_API_KEY",
57
+ validationPath: "/api/v1/models",
58
+ validationAuth: "bearer",
59
+ requiresApiKey: true,
60
+ allowMultiple: false,
61
+ showBaseUrl: false,
62
+ showModelId: false,
63
+ },
64
+ ark: {
65
+ displayName: "ByteDance (Ark)",
66
+ defaultBaseUrl: "https://ark.cn-beijing.volces.com",
67
+ api: "openai-completions",
68
+ apiKeyEnvName: "ARK_API_KEY",
69
+ validationPath: "/api/v3/models",
70
+ validationAuth: "bearer",
71
+ requiresApiKey: true,
72
+ allowMultiple: false,
73
+ showBaseUrl: false,
74
+ showModelId: false,
75
+ },
76
+ moonshot: {
77
+ displayName: "Moonshot (Kimi)",
78
+ defaultBaseUrl: "https://api.moonshot.cn",
79
+ api: "openai-completions",
80
+ apiKeyEnvName: "MOONSHOT_API_KEY",
81
+ validationPath: "/v1/models",
82
+ validationAuth: "bearer",
83
+ requiresApiKey: true,
84
+ allowMultiple: false,
85
+ showBaseUrl: false,
86
+ showModelId: false,
87
+ },
88
+ siliconflow: {
89
+ displayName: "SiliconFlow",
90
+ defaultBaseUrl: "https://api.siliconflow.cn",
91
+ api: "openai-completions",
92
+ apiKeyEnvName: "SILICONFLOW_API_KEY",
93
+ validationPath: "/v1/models",
94
+ validationAuth: "bearer",
95
+ requiresApiKey: true,
96
+ allowMultiple: false,
97
+ showBaseUrl: false,
98
+ showModelId: false,
99
+ },
100
+ ollama: {
101
+ displayName: "Ollama",
102
+ defaultBaseUrl: "http://localhost:11434",
103
+ api: "openai-completions",
104
+ apiKeyEnvName: "OLLAMA_API_KEY",
105
+ validationPath: "/api/tags",
106
+ validationAuth: "none",
107
+ requiresApiKey: false,
108
+ allowMultiple: false,
109
+ showBaseUrl: true,
110
+ showModelId: false,
111
+ },
112
+ custom: {
113
+ displayName: "Custom",
114
+ defaultBaseUrl: "",
115
+ api: "openai-completions",
116
+ apiKeyEnvName: "CUSTOM_API_KEY",
117
+ validationPath: "/v1/models",
118
+ validationAuth: "bearer",
119
+ requiresApiKey: false,
120
+ allowMultiple: true,
121
+ showBaseUrl: true,
122
+ showModelId: true,
123
+ defaultModelId: "custom-model",
124
+ },
125
+ };
package/src/index.ts CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
+ import { createRequire } from "module";
3
4
  import { pairCommand } from "./commands/pair.js";
4
5
  import { runCommand } from "./commands/run.js";
5
6
  import { installCommand, uninstallCommand, stopCommand, restartCommand, resetCommand } from "./commands/install.js";
6
7
  import { statusCommand } from "./commands/status.js";
7
8
  import { setTokenCommand } from "./commands/set-token.js";
8
9
 
9
- const version = "1.0.18";
10
+ const require = createRequire(import.meta.url);
11
+ const { version } = require("../package.json") as { version: string };
10
12
 
11
13
  const program = new Command();
12
14
 
@@ -1,6 +1,7 @@
1
1
  import { WebSocket } from "ws";
2
2
  import { OpenClawGatewayClient } from "./gateway-client.js";
3
3
  import { handleLocalCommand } from "../commands/local-handlers.js";
4
+ import { handleProviderCommand } from "../commands/provider-handlers.js";
4
5
  import { homedir } from "os";
5
6
  import { join } from "path";
6
7
  import { mkdir, writeFile } from "fs/promises";
@@ -121,6 +122,23 @@ export async function runRelayManager(opts: RelayManagerOptions): Promise<boolea
121
122
  const requestId = msg.id;
122
123
  console.log(`[relay] cmd received method=${msg.method} id=${requestId ?? "(no-id)"}`);
123
124
 
125
+ // Handle clawpilot.provider.* commands locally (async)
126
+ const providerPromise = handleProviderCommand(msg.method, msg.params);
127
+ if (providerPromise !== null) {
128
+ const result = await providerPromise;
129
+ if (requestId) {
130
+ send({
131
+ type: "res",
132
+ id: requestId,
133
+ ok: result.ok,
134
+ ...(result.ok
135
+ ? { payload: result.payload }
136
+ : { error: { message: result.error } }),
137
+ });
138
+ }
139
+ return;
140
+ }
141
+
124
142
  // Handle clawpilot.* commands locally without forwarding to the gateway
125
143
  const localResult = handleLocalCommand(msg.method);
126
144
  if (localResult !== null) {