agent-phonon 0.2.8 → 0.2.10
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/cli.js +215 -30
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +213 -28
- package/dist/daemon.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -4624,7 +4624,12 @@ function fileSize(p) {
|
|
|
4624
4624
|
import { spawn as spawn3 } from "node:child_process";
|
|
4625
4625
|
import { homedir as homedir5 } from "node:os";
|
|
4626
4626
|
import { join as join7 } from "node:path";
|
|
4627
|
-
import { existsSync as existsSync7, readdirSync, statSync as statSync2 } from "node:fs";
|
|
4627
|
+
import { existsSync as existsSync7, readdirSync, statSync as statSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
4628
|
+
var CODEX_FALLBACK_MODELS = [
|
|
4629
|
+
{ id: "gpt-5.5", available: true },
|
|
4630
|
+
{ id: "gpt-5.4", available: true },
|
|
4631
|
+
{ id: "gpt-5.3-codex", available: true }
|
|
4632
|
+
];
|
|
4628
4633
|
var CAPABILITIES2 = {
|
|
4629
4634
|
nativeSession: true,
|
|
4630
4635
|
// exec resume <thread_id>
|
|
@@ -4674,6 +4679,60 @@ function resolveCodexSessionFile(threadId, codexHome = join7(homedir5(), ".codex
|
|
|
4674
4679
|
hits.sort((a, b) => b.mtime - a.mtime);
|
|
4675
4680
|
return hits[0].path;
|
|
4676
4681
|
}
|
|
4682
|
+
function parseCodexConfig(configPath = join7(homedir5(), ".codex", "config.toml")) {
|
|
4683
|
+
if (!existsSync7(configPath))
|
|
4684
|
+
return {};
|
|
4685
|
+
const text = readFileSync4(configPath, "utf8");
|
|
4686
|
+
const model = text.match(/^model\s*=\s*"([^"]+)"/m)?.[1];
|
|
4687
|
+
const providerId = text.match(/^model_provider\s*=\s*"([^"]+)"/m)?.[1];
|
|
4688
|
+
let baseUrl;
|
|
4689
|
+
if (providerId) {
|
|
4690
|
+
const escaped = providerId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4691
|
+
const section = text.match(new RegExp(`\\[model_providers\\.${escaped}\\]([\\s\\S]*?)(?:\\n\\[|$)`))?.[1];
|
|
4692
|
+
baseUrl = section?.match(/^base_url\s*=\s*"([^"]+)"/m)?.[1];
|
|
4693
|
+
}
|
|
4694
|
+
return { model, providerId, baseUrl };
|
|
4695
|
+
}
|
|
4696
|
+
function normalizeOpenAiModels(data) {
|
|
4697
|
+
const rows = Array.isArray(data.data) ? data.data : Array.isArray(data) ? data : [];
|
|
4698
|
+
const out = [];
|
|
4699
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4700
|
+
for (const row of rows) {
|
|
4701
|
+
const obj = row;
|
|
4702
|
+
const id = typeof obj.id === "string" ? obj.id : void 0;
|
|
4703
|
+
if (!id || seen.has(id))
|
|
4704
|
+
continue;
|
|
4705
|
+
seen.add(id);
|
|
4706
|
+
out.push({ id, ...typeof obj.name === "string" ? { displayName: obj.name } : {}, available: true });
|
|
4707
|
+
}
|
|
4708
|
+
return out;
|
|
4709
|
+
}
|
|
4710
|
+
function fetchJson(url, headers) {
|
|
4711
|
+
return new Promise((resolve5, reject) => {
|
|
4712
|
+
const u = new URL(url);
|
|
4713
|
+
const req = (u.protocol === "http:" ? import("node:http") : import("node:https")).then((mod) => mod.request(url, { method: "GET", headers, timeout: 5e3 }, (res) => {
|
|
4714
|
+
let body = "";
|
|
4715
|
+
res.setEncoding("utf8");
|
|
4716
|
+
res.on("data", (d) => body += d);
|
|
4717
|
+
res.on("end", () => {
|
|
4718
|
+
if ((res.statusCode ?? 500) < 200 || (res.statusCode ?? 500) >= 300) {
|
|
4719
|
+
reject(new Error(`GET ${url} failed: ${res.statusCode}`));
|
|
4720
|
+
return;
|
|
4721
|
+
}
|
|
4722
|
+
try {
|
|
4723
|
+
resolve5(JSON.parse(body));
|
|
4724
|
+
} catch (e) {
|
|
4725
|
+
reject(e);
|
|
4726
|
+
}
|
|
4727
|
+
});
|
|
4728
|
+
}));
|
|
4729
|
+
req.then((r) => {
|
|
4730
|
+
r.on("timeout", () => r.destroy(new Error(`GET ${url} timeout`)));
|
|
4731
|
+
r.on("error", reject);
|
|
4732
|
+
r.end();
|
|
4733
|
+
}, reject);
|
|
4734
|
+
});
|
|
4735
|
+
}
|
|
4677
4736
|
var CodexSession = class {
|
|
4678
4737
|
sessionId;
|
|
4679
4738
|
model;
|
|
@@ -4726,6 +4785,7 @@ ${prompt}`;
|
|
|
4726
4785
|
return new Promise((resolve5) => {
|
|
4727
4786
|
const child = spawn3(this.env.binPath ?? "codex", args2, {
|
|
4728
4787
|
cwd: this.cwd,
|
|
4788
|
+
shell: process.platform === "win32",
|
|
4729
4789
|
env: { ...process.env, ...opts.environment ?? {}, ...this.env.apiKey ? { OPENAI_API_KEY: this.env.apiKey } : {} }
|
|
4730
4790
|
});
|
|
4731
4791
|
this.current = child;
|
|
@@ -4836,6 +4896,7 @@ var CodexAdapter = class {
|
|
|
4836
4896
|
async discoverAgents() {
|
|
4837
4897
|
const version = await this.probeVersion();
|
|
4838
4898
|
const available = version !== null;
|
|
4899
|
+
const models = await this.discoverModels();
|
|
4839
4900
|
return [{
|
|
4840
4901
|
agentId: "codex",
|
|
4841
4902
|
displayName: "Codex",
|
|
@@ -4843,7 +4904,7 @@ var CodexAdapter = class {
|
|
|
4843
4904
|
available,
|
|
4844
4905
|
...available ? {} : { unavailableReason: "codex CLI not found" },
|
|
4845
4906
|
...version ? { version } : {},
|
|
4846
|
-
models
|
|
4907
|
+
models,
|
|
4847
4908
|
capabilities: CAPABILITIES2,
|
|
4848
4909
|
scannedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4849
4910
|
}];
|
|
@@ -4851,9 +4912,31 @@ var CodexAdapter = class {
|
|
|
4851
4912
|
async createSession(params) {
|
|
4852
4913
|
return new CodexSession(params.sessionId, params.model, params.cwd, this.env);
|
|
4853
4914
|
}
|
|
4915
|
+
async discoverModels() {
|
|
4916
|
+
if (this.env.models?.length)
|
|
4917
|
+
return this.env.models;
|
|
4918
|
+
const cfg = parseCodexConfig();
|
|
4919
|
+
const baseUrl = this.env.baseUrl ?? cfg.baseUrl;
|
|
4920
|
+
if (baseUrl) {
|
|
4921
|
+
try {
|
|
4922
|
+
const data = await fetchJson(`${baseUrl.replace(/\/$/, "")}/models`, this.env.apiKey ? { Authorization: `Bearer ${this.env.apiKey}` } : void 0);
|
|
4923
|
+
const models = normalizeOpenAiModels(data);
|
|
4924
|
+
if (models.length > 0)
|
|
4925
|
+
return models;
|
|
4926
|
+
} catch {
|
|
4927
|
+
}
|
|
4928
|
+
}
|
|
4929
|
+
const configured = this.env.defaultModel !== "default" ? this.env.defaultModel : cfg.model;
|
|
4930
|
+
const base = configured ? [{ id: configured, available: true }] : [];
|
|
4931
|
+
const seen = new Set(base.map((m) => m.id));
|
|
4932
|
+
for (const m of CODEX_FALLBACK_MODELS)
|
|
4933
|
+
if (!seen.has(m.id))
|
|
4934
|
+
base.push(m);
|
|
4935
|
+
return base.length > 0 ? base : CODEX_FALLBACK_MODELS;
|
|
4936
|
+
}
|
|
4854
4937
|
probeVersion() {
|
|
4855
4938
|
return new Promise((resolve5) => {
|
|
4856
|
-
const child = spawn3(this.env.binPath ?? "codex", ["--version"]);
|
|
4939
|
+
const child = spawn3(this.env.binPath ?? "codex", ["--version"], { shell: process.platform === "win32" });
|
|
4857
4940
|
let out = "";
|
|
4858
4941
|
child.stdout.on("data", (d) => out += d.toString());
|
|
4859
4942
|
child.on("error", () => resolve5(null));
|
|
@@ -5097,7 +5180,29 @@ import { randomUUID as randomUUID3 } from "node:crypto";
|
|
|
5097
5180
|
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
5098
5181
|
import { homedir as homedir7 } from "node:os";
|
|
5099
5182
|
import { join as join9 } from "node:path";
|
|
5100
|
-
import { existsSync as existsSync9 } from "node:fs";
|
|
5183
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
|
|
5184
|
+
var HERMES_PROVIDER_FALLBACK_MODELS = {
|
|
5185
|
+
// Hermes' built-in Copilot picker exposes these account/integrator-safe model ids.
|
|
5186
|
+
copilot: [
|
|
5187
|
+
"gpt-5.4",
|
|
5188
|
+
"gpt-5.4-mini",
|
|
5189
|
+
"gpt-5-mini",
|
|
5190
|
+
"gpt-5.3-codex",
|
|
5191
|
+
"gpt-5.2-codex",
|
|
5192
|
+
"gpt-4.1",
|
|
5193
|
+
"gpt-4o",
|
|
5194
|
+
"gpt-4o-mini",
|
|
5195
|
+
"claude-sonnet-4.6",
|
|
5196
|
+
"claude-sonnet-4",
|
|
5197
|
+
"claude-sonnet-4.5",
|
|
5198
|
+
"claude-haiku-4.5",
|
|
5199
|
+
"gemini-3.1-pro-preview",
|
|
5200
|
+
"gemini-3-pro-preview",
|
|
5201
|
+
"gemini-3-flash-preview",
|
|
5202
|
+
"gemini-2.5-pro"
|
|
5203
|
+
],
|
|
5204
|
+
zai: ["glm-4.5", "glm-4.5-air", "glm-4.6", "glm-4.7", "glm-5", "glm-5-turbo", "glm-5.1", "glm-5.2"]
|
|
5205
|
+
};
|
|
5101
5206
|
var CAPABILITIES4 = {
|
|
5102
5207
|
nativeSession: true,
|
|
5103
5208
|
// --resume / --pass-session-id
|
|
@@ -5117,6 +5222,49 @@ var CAPABILITIES4 = {
|
|
|
5117
5222
|
// -z 是纯文本一次性输出,非流式 → 用 final 事件
|
|
5118
5223
|
limits: { maxConcurrentSessions: 4 }
|
|
5119
5224
|
};
|
|
5225
|
+
function parseHermesConfig(configPath = join9(homedir7(), ".hermes", "config.yaml")) {
|
|
5226
|
+
if (!existsSync9(configPath))
|
|
5227
|
+
return {};
|
|
5228
|
+
const text = readFileSync5(configPath, "utf8");
|
|
5229
|
+
const modelBlock = text.match(/(?:^|\n)model:\n([\s\S]*?)(?:\n[A-Za-z_][A-Za-z0-9_-]*:|$)/)?.[1] ?? "";
|
|
5230
|
+
const defaultModel = modelBlock.match(/^\s+default:\s*['"]?([^'"\n]+)['"]?/m)?.[1]?.trim();
|
|
5231
|
+
const provider = modelBlock.match(/^\s+provider:\s*['"]?([^'"\n]+)['"]?/m)?.[1]?.trim();
|
|
5232
|
+
const catalogBlock = text.match(/(?:^|\n)model_catalog:\n([\s\S]*?)(?:\n[A-Za-z_][A-Za-z0-9_-]*:|$)/)?.[1] ?? "";
|
|
5233
|
+
const catalogUrl = catalogBlock.match(/^\s+url:\s*['"]?([^'"\n]+)['"]?/m)?.[1]?.trim();
|
|
5234
|
+
return { defaultModel, provider, catalogUrl };
|
|
5235
|
+
}
|
|
5236
|
+
function fetchHermesCatalogModels(url, provider) {
|
|
5237
|
+
return new Promise((resolve5) => {
|
|
5238
|
+
const u = new URL(url);
|
|
5239
|
+
const reqMod = u.protocol === "http:" ? import("node:http") : import("node:https");
|
|
5240
|
+
reqMod.then((mod) => {
|
|
5241
|
+
const req = mod.request(url, { method: "GET", timeout: 5e3 }, (res) => {
|
|
5242
|
+
let body = "";
|
|
5243
|
+
res.setEncoding("utf8");
|
|
5244
|
+
res.on("data", (d) => body += d);
|
|
5245
|
+
res.on("end", () => {
|
|
5246
|
+
try {
|
|
5247
|
+
const data = JSON.parse(body);
|
|
5248
|
+
const providers = data.providers ?? {};
|
|
5249
|
+
const rows = provider ? providers[provider]?.models ?? [] : Object.values(providers).flatMap((p) => p.models ?? []);
|
|
5250
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5251
|
+
resolve5(rows.flatMap((m) => {
|
|
5252
|
+
if (!m.id || seen.has(m.id))
|
|
5253
|
+
return [];
|
|
5254
|
+
seen.add(m.id);
|
|
5255
|
+
return [{ id: m.id, ...m.description ? { displayName: m.description } : {}, available: true }];
|
|
5256
|
+
}));
|
|
5257
|
+
} catch {
|
|
5258
|
+
resolve5([]);
|
|
5259
|
+
}
|
|
5260
|
+
});
|
|
5261
|
+
});
|
|
5262
|
+
req.on("timeout", () => req.destroy());
|
|
5263
|
+
req.on("error", () => resolve5([]));
|
|
5264
|
+
req.end();
|
|
5265
|
+
}, () => resolve5([]));
|
|
5266
|
+
});
|
|
5267
|
+
}
|
|
5120
5268
|
var HermesSession = class {
|
|
5121
5269
|
sessionId;
|
|
5122
5270
|
model;
|
|
@@ -5165,6 +5313,7 @@ ${prompt}`;
|
|
|
5165
5313
|
return new Promise((resolve5) => {
|
|
5166
5314
|
const child = spawn5(this.env.binPath ?? "hermes", args2, {
|
|
5167
5315
|
cwd: this.cwd,
|
|
5316
|
+
shell: process.platform === "win32",
|
|
5168
5317
|
env: { ...process.env, ...opts.environment ?? {}, HERMES_PROFILE: this.profile }
|
|
5169
5318
|
});
|
|
5170
5319
|
this.current = child;
|
|
@@ -5309,6 +5458,10 @@ var HermesAdapter = class {
|
|
|
5309
5458
|
}];
|
|
5310
5459
|
}
|
|
5311
5460
|
const profiles = await this.listProfiles();
|
|
5461
|
+
const cfg = parseHermesConfig();
|
|
5462
|
+
const provider = this.env.provider ?? cfg.provider;
|
|
5463
|
+
const catalogModels = cfg.catalogUrl ? await fetchHermesCatalogModels(cfg.catalogUrl, provider) : [];
|
|
5464
|
+
const providerFallbackModels = provider ? (HERMES_PROVIDER_FALLBACK_MODELS[provider] ?? []).map((id) => ({ id, available: true })) : [];
|
|
5312
5465
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5313
5466
|
return profiles.map((p) => ({
|
|
5314
5467
|
agentId: `hermes:${p.name}`,
|
|
@@ -5316,11 +5469,23 @@ var HermesAdapter = class {
|
|
|
5316
5469
|
adapter: "hermes",
|
|
5317
5470
|
available: true,
|
|
5318
5471
|
...version ? { version } : {},
|
|
5319
|
-
models:
|
|
5472
|
+
models: this.modelsForProfile(p.model, [...catalogModels, ...providerFallbackModels], cfg.defaultModel),
|
|
5320
5473
|
capabilities: CAPABILITIES4,
|
|
5321
5474
|
scannedAt: now
|
|
5322
5475
|
}));
|
|
5323
5476
|
}
|
|
5477
|
+
modelsForProfile(profileModel, catalogModels, configDefault) {
|
|
5478
|
+
const preferred = profileModel ?? this.env.defaultModel ?? configDefault;
|
|
5479
|
+
const models = preferred ? [{ id: preferred, available: true }] : [];
|
|
5480
|
+
const seen = new Set(models.map((m) => m.id));
|
|
5481
|
+
for (const m of catalogModels) {
|
|
5482
|
+
if (!seen.has(m.id)) {
|
|
5483
|
+
models.push(m);
|
|
5484
|
+
seen.add(m.id);
|
|
5485
|
+
}
|
|
5486
|
+
}
|
|
5487
|
+
return models.length > 0 ? models : [{ id: "default", displayName: "Hermes default", available: true }];
|
|
5488
|
+
}
|
|
5324
5489
|
async createSession(params) {
|
|
5325
5490
|
const profile = params.agentId.includes(":") ? params.agentId.split(":")[1] : this.defaultProfile;
|
|
5326
5491
|
const model = params.model && params.model !== "default" ? params.model : this.env.defaultModel ?? "";
|
|
@@ -5329,7 +5494,7 @@ var HermesAdapter = class {
|
|
|
5329
5494
|
/** 枚举 Hermes profile(去 ANSI 色解析 profile list)。 */
|
|
5330
5495
|
listProfiles() {
|
|
5331
5496
|
return new Promise((resolve5) => {
|
|
5332
|
-
const child = spawn5(this.env.binPath ?? "hermes", ["profile", "list"]);
|
|
5497
|
+
const child = spawn5(this.env.binPath ?? "hermes", ["profile", "list"], { shell: process.platform === "win32" });
|
|
5333
5498
|
let out = "";
|
|
5334
5499
|
child.stdout.on("data", (d) => out += d.toString());
|
|
5335
5500
|
child.on("error", () => resolve5([{ name: this.defaultProfile }]));
|
|
@@ -5349,7 +5514,7 @@ var HermesAdapter = class {
|
|
|
5349
5514
|
}
|
|
5350
5515
|
probeVersion() {
|
|
5351
5516
|
return new Promise((resolve5) => {
|
|
5352
|
-
const child = spawn5(this.env.binPath ?? "hermes", ["--version"]);
|
|
5517
|
+
const child = spawn5(this.env.binPath ?? "hermes", ["--version"], { shell: process.platform === "win32" });
|
|
5353
5518
|
let out = "";
|
|
5354
5519
|
child.stdout.on("data", (d) => out += d.toString());
|
|
5355
5520
|
child.on("error", () => resolve5(null));
|
|
@@ -5584,7 +5749,7 @@ ${prompt}`;
|
|
|
5584
5749
|
if (v !== void 0)
|
|
5585
5750
|
childEnv[k] = v;
|
|
5586
5751
|
}
|
|
5587
|
-
const child = spawn6(this.env.binPath ?? "claude", args2, { cwd: this.cwd, env: { ...childEnv, ...opts.environment ?? {} } });
|
|
5752
|
+
const child = spawn6(this.env.binPath ?? "claude", args2, { cwd: this.cwd, shell: process.platform === "win32", env: { ...childEnv, ...opts.environment ?? {} } });
|
|
5588
5753
|
this.current = child;
|
|
5589
5754
|
let buf = "";
|
|
5590
5755
|
let acc = "";
|
|
@@ -5726,7 +5891,7 @@ var ClaudeCodeAdapter = class {
|
|
|
5726
5891
|
}
|
|
5727
5892
|
probeVersion() {
|
|
5728
5893
|
return new Promise((resolve5) => {
|
|
5729
|
-
const child = spawn6(this.env.binPath ?? "claude", ["--version"]);
|
|
5894
|
+
const child = spawn6(this.env.binPath ?? "claude", ["--version"], { shell: process.platform === "win32" });
|
|
5730
5895
|
let out = "";
|
|
5731
5896
|
child.stdout.on("data", (d) => out += d.toString());
|
|
5732
5897
|
child.on("error", () => resolve5(null));
|
|
@@ -6068,7 +6233,7 @@ var PhononConnection = class {
|
|
|
6068
6233
|
};
|
|
6069
6234
|
|
|
6070
6235
|
// src/config.ts
|
|
6071
|
-
import { readFileSync as
|
|
6236
|
+
import { readFileSync as readFileSync6, existsSync as existsSync11, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, chmodSync as chmodSync2 } from "node:fs";
|
|
6072
6237
|
import { homedir as homedir9, hostname as hostname2 } from "node:os";
|
|
6073
6238
|
import { join as join11, dirname as dirname4 } from "node:path";
|
|
6074
6239
|
var DEFAULT_DIR = join11(homedir9(), ".agent-phonon");
|
|
@@ -6088,7 +6253,7 @@ function loadConfig(path = DEFAULT_CONFIG_PATH) {
|
|
|
6088
6253
|
if (!existsSync11(path)) {
|
|
6089
6254
|
throw new Error(`config not found at ${path} \u2014 run 'agent-phonon init' first`);
|
|
6090
6255
|
}
|
|
6091
|
-
const raw = JSON.parse(
|
|
6256
|
+
const raw = JSON.parse(readFileSync6(path, "utf8"));
|
|
6092
6257
|
const d = defaultConfig();
|
|
6093
6258
|
return {
|
|
6094
6259
|
deviceId: raw.deviceId ?? d.deviceId,
|
|
@@ -6127,7 +6292,7 @@ function redactConfig(cfg) {
|
|
|
6127
6292
|
function readOpenClawGatewayToken() {
|
|
6128
6293
|
try {
|
|
6129
6294
|
const p = join11(homedir9(), ".openclaw", "openclaw.json");
|
|
6130
|
-
const cfg = JSON.parse(
|
|
6295
|
+
const cfg = JSON.parse(readFileSync6(p, "utf8"));
|
|
6131
6296
|
return cfg?.gateway?.auth?.token;
|
|
6132
6297
|
} catch {
|
|
6133
6298
|
return void 0;
|
|
@@ -6136,27 +6301,43 @@ function readOpenClawGatewayToken() {
|
|
|
6136
6301
|
|
|
6137
6302
|
// src/commands.ts
|
|
6138
6303
|
import { spawnSync } from "node:child_process";
|
|
6139
|
-
import { existsSync as existsSync12, cpSync, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync4, readFileSync as
|
|
6140
|
-
import { homedir as homedir10 } from "node:os";
|
|
6141
|
-
import { join as join12, dirname as dirname5 } from "node:path";
|
|
6304
|
+
import { existsSync as existsSync12, cpSync, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync4, readFileSync as readFileSync7 } from "node:fs";
|
|
6305
|
+
import { homedir as homedir10, platform as platform2 } from "node:os";
|
|
6306
|
+
import { join as join12, dirname as dirname5, delimiter } from "node:path";
|
|
6142
6307
|
import { fileURLToPath } from "node:url";
|
|
6143
6308
|
function probe(bin, args2 = ["--version"]) {
|
|
6144
|
-
const r = spawnSync(bin, args2, { timeout: 8e3 });
|
|
6309
|
+
const r = spawnSync(bin, args2, { timeout: 8e3, shell: platform2() === "win32" });
|
|
6145
6310
|
return { ok: r.status === 0, out: (r.stdout?.toString() ?? "").trim().split("\n")[0] ?? "" };
|
|
6146
6311
|
}
|
|
6312
|
+
function executableNames(bin) {
|
|
6313
|
+
if (platform2() !== "win32") return [bin];
|
|
6314
|
+
const exts = (process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").map((e) => e.toLowerCase());
|
|
6315
|
+
return [bin, ...exts.map((e) => `${bin}${e}`), ...exts.map((e) => `${bin}${e.toUpperCase()}`)];
|
|
6316
|
+
}
|
|
6147
6317
|
function commandPath(bin) {
|
|
6148
|
-
const
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
join12(
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6318
|
+
const home = homedir10();
|
|
6319
|
+
const appData = process.env.APPDATA;
|
|
6320
|
+
const localAppData = process.env.LOCALAPPDATA;
|
|
6321
|
+
const dirs = [
|
|
6322
|
+
join12(home, ".npm-global", "bin"),
|
|
6323
|
+
join12(home, ".local", "bin"),
|
|
6324
|
+
join12(home, ".bun", "bin"),
|
|
6325
|
+
join12(home, ".cargo", "bin"),
|
|
6326
|
+
...appData ? [join12(appData, "npm")] : [],
|
|
6327
|
+
...localAppData ? [join12(localAppData, "Programs"), join12(localAppData, "Microsoft", "WindowsApps")] : [],
|
|
6328
|
+
"/opt/homebrew/bin",
|
|
6329
|
+
"/usr/local/bin",
|
|
6330
|
+
"/usr/bin",
|
|
6331
|
+
...(process.env.PATH ?? "").split(delimiter).filter(Boolean)
|
|
6156
6332
|
];
|
|
6157
|
-
for (const
|
|
6158
|
-
|
|
6159
|
-
|
|
6333
|
+
for (const dir of dirs) {
|
|
6334
|
+
for (const name of executableNames(bin)) {
|
|
6335
|
+
const p = join12(dir, name);
|
|
6336
|
+
if (existsSync12(p)) return p;
|
|
6337
|
+
}
|
|
6338
|
+
}
|
|
6339
|
+
const r = platform2() === "win32" ? spawnSync("where.exe", [bin], { timeout: 3e3 }) : spawnSync("sh", ["-lc", `command -v ${bin}`], { timeout: 3e3 });
|
|
6340
|
+
const out = (r.stdout?.toString() ?? "").trim().split(/\r?\n/)[0];
|
|
6160
6341
|
return r.status === 0 && out ? out : void 0;
|
|
6161
6342
|
}
|
|
6162
6343
|
function gatewayReachable(url) {
|
|
@@ -6169,8 +6350,12 @@ function gatewayReachable(url) {
|
|
|
6169
6350
|
}
|
|
6170
6351
|
}
|
|
6171
6352
|
function openCodeBin() {
|
|
6172
|
-
const
|
|
6173
|
-
|
|
6353
|
+
const bundledDir = join12(homedir10(), ".opencode", "bin");
|
|
6354
|
+
for (const name of executableNames("opencode")) {
|
|
6355
|
+
const p = join12(bundledDir, name);
|
|
6356
|
+
if (existsSync12(p)) return p;
|
|
6357
|
+
}
|
|
6358
|
+
return commandPath("opencode") ?? "opencode";
|
|
6174
6359
|
}
|
|
6175
6360
|
function autoDetectAdapters(adapters) {
|
|
6176
6361
|
const out = [...adapters];
|
|
@@ -6310,7 +6495,7 @@ function cmdPluginInstall(which) {
|
|
|
6310
6495
|
mkdirSync4(dist, { recursive: true });
|
|
6311
6496
|
cpSync(join12(pluginSrc, "dist"), join12(dist, "dist"), { recursive: true });
|
|
6312
6497
|
cpSync(join12(pluginSrc, "openclaw.plugin.json"), join12(dist, "openclaw.plugin.json"));
|
|
6313
|
-
const pkg = JSON.parse(
|
|
6498
|
+
const pkg = JSON.parse(readFileSync7(join12(pluginSrc, "package.json"), "utf8"));
|
|
6314
6499
|
delete pkg.devDependencies;
|
|
6315
6500
|
writeFileSync4(join12(dist, "package.json"), JSON.stringify(pkg, null, 2));
|
|
6316
6501
|
console.log(`exported clean plugin \u2192 ${dist}`);
|