agent-phonon 0.2.3 → 0.2.5
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 +211 -215
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts +4 -0
- package/dist/daemon.js +78 -34
- package/dist/daemon.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -4245,11 +4245,12 @@ var OpenClawGatewayAdapter = class {
|
|
|
4245
4245
|
if (subAgents.length === 0)
|
|
4246
4246
|
subAgents = [{ id: this.defaultAgent }];
|
|
4247
4247
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4248
|
+
const gatewayModels = await this.listGatewayModels();
|
|
4248
4249
|
return subAgents.map((a) => {
|
|
4249
4250
|
if (a.workspace)
|
|
4250
4251
|
this.workspaceCache.set(`openclaw:${a.id}`, a.workspace);
|
|
4251
4252
|
const primaryModel = typeof a.model === "string" ? a.model : a.model?.primary;
|
|
4252
|
-
const models = primaryModel ? [{ id: primaryModel, available: true }] : [];
|
|
4253
|
+
const models = gatewayModels.length > 0 ? gatewayModels : primaryModel ? [{ id: primaryModel, available: true }] : [];
|
|
4253
4254
|
return {
|
|
4254
4255
|
// 复合 agentId:openclaw:<subAgentId>(design D32)
|
|
4255
4256
|
agentId: `openclaw:${a.id}`,
|
|
@@ -4262,6 +4263,32 @@ var OpenClawGatewayAdapter = class {
|
|
|
4262
4263
|
};
|
|
4263
4264
|
});
|
|
4264
4265
|
}
|
|
4266
|
+
async listGatewayModels() {
|
|
4267
|
+
try {
|
|
4268
|
+
const r = await this.gw.rpc("models.list", { view: "all" }, 8e3);
|
|
4269
|
+
const rows = Array.isArray(r.models) ? r.models : [];
|
|
4270
|
+
const models = [];
|
|
4271
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4272
|
+
for (const row of rows) {
|
|
4273
|
+
const id = typeof row.key === "string" ? row.key : typeof row.id === "string" ? row.id : void 0;
|
|
4274
|
+
if (!id || seen.has(id))
|
|
4275
|
+
continue;
|
|
4276
|
+
if (row.available === false || row.missing === true)
|
|
4277
|
+
continue;
|
|
4278
|
+
seen.add(id);
|
|
4279
|
+
const contextWindow = typeof row.contextWindow === "number" ? row.contextWindow : typeof row.contextTokens === "number" ? row.contextTokens : void 0;
|
|
4280
|
+
models.push({
|
|
4281
|
+
id,
|
|
4282
|
+
...typeof row.name === "string" ? { displayName: row.name } : {},
|
|
4283
|
+
...contextWindow && contextWindow > 0 ? { contextWindow } : {},
|
|
4284
|
+
available: true
|
|
4285
|
+
});
|
|
4286
|
+
}
|
|
4287
|
+
return models;
|
|
4288
|
+
} catch {
|
|
4289
|
+
return [];
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4265
4292
|
async createSession(params) {
|
|
4266
4293
|
await this.gw.connect();
|
|
4267
4294
|
const subAgent = params.agentConfig?.openclawAgent ?? (params.agentId.includes(":") ? params.agentId.split(":")[1] : this.defaultAgent);
|
|
@@ -4663,6 +4690,8 @@ var CodexSession = class {
|
|
|
4663
4690
|
this.env = env;
|
|
4664
4691
|
}
|
|
4665
4692
|
providerArgs() {
|
|
4693
|
+
if (!this.env.baseUrl || !this.env.apiKey)
|
|
4694
|
+
return [];
|
|
4666
4695
|
const id = this.env.providerId ?? "phonon_gateway";
|
|
4667
4696
|
const name = this.env.providerName ?? "phonon-gateway";
|
|
4668
4697
|
return [
|
|
@@ -4690,14 +4719,14 @@ var CodexSession = class {
|
|
|
4690
4719
|
|
|
4691
4720
|
${prompt}`;
|
|
4692
4721
|
}
|
|
4693
|
-
const args2 = this.threadId ? ["exec", "resume", this.threadId, "-", "--json", ...this.providerArgs(), "--model", this.model, "--dangerously-bypass-approvals-and-sandbox"] : ["exec", "-", "--json", ...this.providerArgs(), "--model", this.model, "--dangerously-bypass-approvals-and-sandbox"];
|
|
4722
|
+
const args2 = this.threadId ? ["exec", "resume", this.threadId, "-", "--json", ...this.providerArgs(), ...this.model !== "default" ? ["--model", this.model] : [], "--dangerously-bypass-approvals-and-sandbox"] : ["exec", "-", "--json", ...this.providerArgs(), ...this.model !== "default" ? ["--model", this.model] : [], "--dangerously-bypass-approvals-and-sandbox"];
|
|
4694
4723
|
await this.run(args2, prompt, turnId, emit, opts);
|
|
4695
4724
|
}
|
|
4696
4725
|
run(args2, stdin, turnId, emit, opts) {
|
|
4697
4726
|
return new Promise((resolve5) => {
|
|
4698
4727
|
const child = spawn3("codex", args2, {
|
|
4699
4728
|
cwd: this.cwd,
|
|
4700
|
-
env: { ...process.env, ...opts.environment ?? {}, OPENAI_API_KEY: this.env.apiKey }
|
|
4729
|
+
env: { ...process.env, ...opts.environment ?? {}, ...this.env.apiKey ? { OPENAI_API_KEY: this.env.apiKey } : {} }
|
|
4701
4730
|
});
|
|
4702
4731
|
this.current = child;
|
|
4703
4732
|
let buf = "";
|
|
@@ -4814,10 +4843,7 @@ var CodexAdapter = class {
|
|
|
4814
4843
|
available,
|
|
4815
4844
|
...available ? {} : { unavailableReason: "codex CLI not found" },
|
|
4816
4845
|
...version ? { version } : {},
|
|
4817
|
-
models: [
|
|
4818
|
-
{ id: "gpt-5.5", displayName: "GPT-5.5", available: true },
|
|
4819
|
-
{ id: "gpt-5.3-codex", displayName: "GPT-5.3 Codex", available: true }
|
|
4820
|
-
],
|
|
4846
|
+
models: this.env.models?.length ? this.env.models : [{ id: this.env.defaultModel, available: true }],
|
|
4821
4847
|
capabilities: CAPABILITIES2,
|
|
4822
4848
|
scannedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4823
4849
|
}];
|
|
@@ -5465,16 +5491,20 @@ var CAPABILITIES5 = {
|
|
|
5465
5491
|
limits: { maxConcurrentSessions: 4 }
|
|
5466
5492
|
};
|
|
5467
5493
|
function writeSettingsFile(env, model) {
|
|
5494
|
+
if (!env.baseUrl || !env.authToken)
|
|
5495
|
+
return void 0;
|
|
5468
5496
|
const dir = mkdtempSync(join10(tmpdir2(), "phonon-cc-"));
|
|
5469
5497
|
const file = join10(dir, "settings.json");
|
|
5470
5498
|
const content = JSON.stringify({
|
|
5471
5499
|
env: {
|
|
5472
5500
|
ANTHROPIC_BASE_URL: env.baseUrl,
|
|
5473
5501
|
ANTHROPIC_AUTH_TOKEN: env.authToken,
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5502
|
+
...model !== "default" ? {
|
|
5503
|
+
ANTHROPIC_MODEL: model,
|
|
5504
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: model,
|
|
5505
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: model,
|
|
5506
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: model
|
|
5507
|
+
} : {},
|
|
5478
5508
|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1"
|
|
5479
5509
|
}
|
|
5480
5510
|
});
|
|
@@ -5527,12 +5557,13 @@ ${prompt}`;
|
|
|
5527
5557
|
// 最高权限:bypassPermissions 跳过所有权限确认;不限定 allowedTools = 所有工具可用
|
|
5528
5558
|
// (phonon 定位:全自动执行,牺牲安全换自动化)
|
|
5529
5559
|
"--permission-mode",
|
|
5530
|
-
"bypassPermissions"
|
|
5531
|
-
"--settings",
|
|
5532
|
-
this.settingsFile(),
|
|
5533
|
-
"--model",
|
|
5534
|
-
this.model
|
|
5560
|
+
"bypassPermissions"
|
|
5535
5561
|
];
|
|
5562
|
+
const settings = this.settingsFile();
|
|
5563
|
+
if (settings)
|
|
5564
|
+
args2.push("--settings", settings);
|
|
5565
|
+
if (this.model !== "default")
|
|
5566
|
+
args2.push("--model", this.model);
|
|
5536
5567
|
if (this.started)
|
|
5537
5568
|
args2.push("--resume", this.uuid);
|
|
5538
5569
|
else
|
|
@@ -5685,11 +5716,7 @@ var ClaudeCodeAdapter = class {
|
|
|
5685
5716
|
available,
|
|
5686
5717
|
...available ? {} : { unavailableReason: "claude CLI not found" },
|
|
5687
5718
|
...version ? { version } : {},
|
|
5688
|
-
models: [
|
|
5689
|
-
{ id: "claude-opus-4.6", displayName: "Claude Opus 4.6", available: true },
|
|
5690
|
-
{ id: "claude-opus-4.7", displayName: "Claude Opus 4.7", available: true },
|
|
5691
|
-
{ id: "claude-sonnet-4.6", displayName: "Claude Sonnet 4.6", available: true }
|
|
5692
|
-
],
|
|
5719
|
+
models: this.env.models?.length ? this.env.models : [{ id: this.env.defaultModel, available: true }],
|
|
5693
5720
|
capabilities: CAPABILITIES5,
|
|
5694
5721
|
scannedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5695
5722
|
}];
|
|
@@ -6107,6 +6134,166 @@ function readOpenClawGatewayToken() {
|
|
|
6107
6134
|
}
|
|
6108
6135
|
}
|
|
6109
6136
|
|
|
6137
|
+
// src/commands.ts
|
|
6138
|
+
import { spawnSync } from "node:child_process";
|
|
6139
|
+
import { existsSync as existsSync12, cpSync, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
6140
|
+
import { homedir as homedir10 } from "node:os";
|
|
6141
|
+
import { join as join12, dirname as dirname5 } from "node:path";
|
|
6142
|
+
import { fileURLToPath } from "node:url";
|
|
6143
|
+
function probe(bin, args2 = ["--version"]) {
|
|
6144
|
+
const r = spawnSync(bin, args2, { timeout: 8e3 });
|
|
6145
|
+
return { ok: r.status === 0, out: (r.stdout?.toString() ?? "").trim().split("\n")[0] ?? "" };
|
|
6146
|
+
}
|
|
6147
|
+
function gatewayReachable(url) {
|
|
6148
|
+
try {
|
|
6149
|
+
const u = new URL(url.replace(/^ws/, "http"));
|
|
6150
|
+
const r = spawnSync("bash", ["-c", `exec 3<>/dev/tcp/${u.hostname}/${u.port || 80} && echo ok`], { timeout: 3e3 });
|
|
6151
|
+
return r.status === 0;
|
|
6152
|
+
} catch {
|
|
6153
|
+
return false;
|
|
6154
|
+
}
|
|
6155
|
+
}
|
|
6156
|
+
function openCodeBin() {
|
|
6157
|
+
const bundled = join12(homedir10(), ".opencode", "bin", "opencode");
|
|
6158
|
+
return existsSync12(bundled) ? bundled : "opencode";
|
|
6159
|
+
}
|
|
6160
|
+
function autoDetectAdapters(adapters) {
|
|
6161
|
+
const out = [...adapters];
|
|
6162
|
+
const has = (type2) => out.some((a) => a.type === type2);
|
|
6163
|
+
if (!has("hermes") && probe("hermes").ok) out.push({ type: "hermes" });
|
|
6164
|
+
const ocBin = openCodeBin();
|
|
6165
|
+
if (!has("opencode") && probe(ocBin).ok) out.push({ type: "opencode", opencodeBinPath: ocBin === "opencode" ? void 0 : ocBin });
|
|
6166
|
+
if (!has("claude-code") && probe("claude").ok) out.push({ type: "claude-code", claudeDefaultModel: "default" });
|
|
6167
|
+
if (!has("codex") && probe("codex").ok) out.push({ type: "codex", codexDefaultModel: "default" });
|
|
6168
|
+
return out;
|
|
6169
|
+
}
|
|
6170
|
+
function cmdDoctor() {
|
|
6171
|
+
console.log("agent-phonon doctor\n");
|
|
6172
|
+
const gwToken = readOpenClawGatewayToken();
|
|
6173
|
+
const gwUrl = "ws://127.0.0.1:18789";
|
|
6174
|
+
const gwOk = gatewayReachable(gwUrl);
|
|
6175
|
+
console.log(`OpenClaw Gateway (${gwUrl}): ${gwOk ? "\u2713 reachable" : "\u2717 unreachable"}${gwToken ? " (token found)" : " (no token in ~/.openclaw/openclaw.json)"}`);
|
|
6176
|
+
const pluginDir = join12(homedir10(), ".openclaw", "extensions", "agent-phonon-hitl");
|
|
6177
|
+
console.log(`OpenClaw HITL plugin: ${existsSync12(pluginDir) ? "\u2713 installed" : "\u2717 not installed (run: agent-phonon plugin install openclaw)"}`);
|
|
6178
|
+
console.log("\nCLI agents:");
|
|
6179
|
+
for (const [name, bin] of [["Claude Code", "claude"], ["Codex", "codex"], ["Hermes", "hermes"]]) {
|
|
6180
|
+
const p = probe(bin);
|
|
6181
|
+
console.log(` ${name} (${bin}): ${p.ok ? "\u2713 " + p.out : "\u2717 not found"}`);
|
|
6182
|
+
}
|
|
6183
|
+
const ocBin = openCodeBin();
|
|
6184
|
+
const oc = probe(ocBin);
|
|
6185
|
+
console.log(` OpenCode (${ocBin}): ${oc.ok ? "\u2713 " + oc.out : "\u2717 not found"}`);
|
|
6186
|
+
console.log("");
|
|
6187
|
+
try {
|
|
6188
|
+
const cfg = loadConfig();
|
|
6189
|
+
const effective = autoDetectAdapters(cfg.adapters);
|
|
6190
|
+
console.log(`config: ${cfg.adapters.length} configured adapter(s), ${effective.length} effective adapter(s), ${cfg.servers.length} server(s)`);
|
|
6191
|
+
} catch {
|
|
6192
|
+
console.log("config: not initialized (run: agent-phonon init)");
|
|
6193
|
+
}
|
|
6194
|
+
}
|
|
6195
|
+
async function cmdDiscover() {
|
|
6196
|
+
let cfg;
|
|
6197
|
+
try {
|
|
6198
|
+
cfg = loadConfig();
|
|
6199
|
+
} catch {
|
|
6200
|
+
console.error("config not initialized \u2014 run 'agent-phonon init' first");
|
|
6201
|
+
process.exit(1);
|
|
6202
|
+
return;
|
|
6203
|
+
}
|
|
6204
|
+
const reg = buildRegistry(cfg.adapters);
|
|
6205
|
+
const nested = await Promise.all(reg.all().map((a) => a.discoverAgents()));
|
|
6206
|
+
const agents = nested.flat();
|
|
6207
|
+
console.log(`discovered ${agents.length} agent(s):
|
|
6208
|
+
`);
|
|
6209
|
+
for (const a of agents) {
|
|
6210
|
+
console.log(` ${a.available ? "\u2713" : "\u2717"} ${a.agentId} (${a.displayName})${a.available ? "" : " \u2014 " + (a.unavailableReason ?? "unavailable")}`);
|
|
6211
|
+
if (a.models.length) console.log(` models: ${a.models.map((m) => m.id).join(", ")}`);
|
|
6212
|
+
}
|
|
6213
|
+
}
|
|
6214
|
+
function buildRegistry(adapters) {
|
|
6215
|
+
const reg = new AdapterRegistry();
|
|
6216
|
+
for (const a of autoDetectAdapters(adapters)) {
|
|
6217
|
+
if (a.type === "openclaw-gateway") {
|
|
6218
|
+
const token = a.gatewayToken ?? readOpenClawGatewayToken();
|
|
6219
|
+
if (token) reg.register(new OpenClawGatewayAdapter({ gateway: { baseUrl: a.gatewayUrl ?? "ws://127.0.0.1:18789", token }, defaultAgent: a.defaultAgent ?? "main" }));
|
|
6220
|
+
} else if (a.type === "claude-code") {
|
|
6221
|
+
reg.register(new ClaudeCodeAdapter({ env: { baseUrl: a.claudeBaseUrl, authToken: a.claudeAuthToken, defaultModel: a.claudeDefaultModel ?? "default", models: a.claudeModels } }));
|
|
6222
|
+
} else if (a.type === "codex") {
|
|
6223
|
+
reg.register(new CodexAdapter({ env: { baseUrl: a.codexBaseUrl, apiKey: a.codexApiKey, defaultModel: a.codexDefaultModel ?? "default", models: a.codexModels, wireApi: a.codexWireApi ?? "responses" } }));
|
|
6224
|
+
} else if (a.type === "hermes") {
|
|
6225
|
+
reg.register(new HermesAdapter({ env: { defaultModel: a.hermesModel, provider: a.hermesProvider } }));
|
|
6226
|
+
} else if (a.type === "opencode") {
|
|
6227
|
+
reg.register(new OpenCodeAdapter({ env: { binPath: a.opencodeBinPath, defaultModel: a.opencodeModel } }));
|
|
6228
|
+
}
|
|
6229
|
+
}
|
|
6230
|
+
return reg;
|
|
6231
|
+
}
|
|
6232
|
+
function cmdAdapterAdd(type2, opts) {
|
|
6233
|
+
const cfg = loadConfig();
|
|
6234
|
+
let a;
|
|
6235
|
+
switch (type2) {
|
|
6236
|
+
case "openclaw":
|
|
6237
|
+
case "openclaw-gateway":
|
|
6238
|
+
a = { type: "openclaw-gateway", gatewayUrl: opts.gatewayUrl ?? "ws://127.0.0.1:18789", gatewayToken: opts.token, defaultAgent: opts.defaultAgent ?? "main" };
|
|
6239
|
+
break;
|
|
6240
|
+
case "claude-code":
|
|
6241
|
+
a = { type: "claude-code", claudeBaseUrl: opts.baseUrl, claudeAuthToken: opts.token, claudeDefaultModel: opts.model ?? "default" };
|
|
6242
|
+
break;
|
|
6243
|
+
case "codex":
|
|
6244
|
+
a = { type: "codex", codexBaseUrl: opts.baseUrl, codexApiKey: opts.apiKey, codexDefaultModel: opts.model ?? "default", codexWireApi: opts.wireApi ?? "responses" };
|
|
6245
|
+
break;
|
|
6246
|
+
case "hermes":
|
|
6247
|
+
a = { type: "hermes", hermesModel: opts.model, hermesProvider: opts.provider };
|
|
6248
|
+
break;
|
|
6249
|
+
case "opencode":
|
|
6250
|
+
a = { type: "opencode", opencodeBinPath: opts.bin, opencodeModel: opts.model };
|
|
6251
|
+
break;
|
|
6252
|
+
default:
|
|
6253
|
+
return fail(`unknown adapter type: ${type2} (openclaw|claude-code|codex|hermes|opencode)`);
|
|
6254
|
+
}
|
|
6255
|
+
cfg.adapters = cfg.adapters.filter((x) => x.type !== a.type);
|
|
6256
|
+
cfg.adapters.push(a);
|
|
6257
|
+
writeConfig(cfg);
|
|
6258
|
+
console.log(`added ${a.type} adapter (${cfg.adapters.length} total)`);
|
|
6259
|
+
}
|
|
6260
|
+
function cmdAdapterList() {
|
|
6261
|
+
const cfg = loadConfig();
|
|
6262
|
+
const effective = autoDetectAdapters(cfg.adapters);
|
|
6263
|
+
if (effective.length === 0) {
|
|
6264
|
+
console.log("(no adapters available)");
|
|
6265
|
+
return;
|
|
6266
|
+
}
|
|
6267
|
+
for (const a of effective) {
|
|
6268
|
+
const auto = cfg.adapters.some((x) => x.type === a.type) ? "" : " [auto]";
|
|
6269
|
+
console.log(`- ${a.type}${a.defaultAgent ? ` (agent: ${a.defaultAgent})` : ""}${auto}`);
|
|
6270
|
+
}
|
|
6271
|
+
}
|
|
6272
|
+
function cmdPluginInstall(which) {
|
|
6273
|
+
if (which !== "openclaw") return fail(`plugin install supports: openclaw (got: ${which})`);
|
|
6274
|
+
const here = dirname5(fileURLToPath(import.meta.url));
|
|
6275
|
+
const pluginSrc = join12(here, "..", "..", "openclaw-plugin");
|
|
6276
|
+
if (!existsSync12(join12(pluginSrc, "dist", "index.js"))) {
|
|
6277
|
+
return fail(`plugin not built. Run: cd ${pluginSrc} && pnpm build`);
|
|
6278
|
+
}
|
|
6279
|
+
const dist = join12(homedir10(), ".agent-phonon", "openclaw-plugin-dist");
|
|
6280
|
+
rmSync3(dist, { recursive: true, force: true });
|
|
6281
|
+
mkdirSync4(dist, { recursive: true });
|
|
6282
|
+
cpSync(join12(pluginSrc, "dist"), join12(dist, "dist"), { recursive: true });
|
|
6283
|
+
cpSync(join12(pluginSrc, "openclaw.plugin.json"), join12(dist, "openclaw.plugin.json"));
|
|
6284
|
+
const pkg = JSON.parse(readFileSync5(join12(pluginSrc, "package.json"), "utf8"));
|
|
6285
|
+
delete pkg.devDependencies;
|
|
6286
|
+
writeFileSync4(join12(dist, "package.json"), JSON.stringify(pkg, null, 2));
|
|
6287
|
+
console.log(`exported clean plugin \u2192 ${dist}`);
|
|
6288
|
+
const r = spawnSync("openclaw", ["plugins", "install", "--force", dist], { stdio: "inherit" });
|
|
6289
|
+
if (r.status === 0) console.log("\n\u2713 installed. Restart OpenClaw Gateway to load: systemctl --user restart openclaw-gateway.service");
|
|
6290
|
+
else fail("openclaw plugins install failed");
|
|
6291
|
+
}
|
|
6292
|
+
function fail(msg) {
|
|
6293
|
+
console.error("error:", msg);
|
|
6294
|
+
process.exit(1);
|
|
6295
|
+
}
|
|
6296
|
+
|
|
6110
6297
|
// src/obs-server.ts
|
|
6111
6298
|
import { createServer as createServer2 } from "node:http";
|
|
6112
6299
|
var ObsServer = class {
|
|
@@ -6234,7 +6421,7 @@ var PhononDaemon = class {
|
|
|
6234
6421
|
this.registerAdapters();
|
|
6235
6422
|
}
|
|
6236
6423
|
registerAdapters() {
|
|
6237
|
-
for (const a of this.cfg.adapters) {
|
|
6424
|
+
for (const a of autoDetectAdapters(this.cfg.adapters)) {
|
|
6238
6425
|
if (a.type === "openclaw-gateway") {
|
|
6239
6426
|
const token = a.gatewayToken ?? readOpenClawGatewayToken();
|
|
6240
6427
|
if (!token) {
|
|
@@ -6248,17 +6435,9 @@ var PhononDaemon = class {
|
|
|
6248
6435
|
this.gatewayAdapters.push(ad);
|
|
6249
6436
|
this.registry.register(ad);
|
|
6250
6437
|
} else if (a.type === "claude-code") {
|
|
6251
|
-
|
|
6252
|
-
this.registry.register(new ClaudeCodeAdapter({ env: { baseUrl: a.claudeBaseUrl, authToken: a.claudeAuthToken, defaultModel: a.claudeDefaultModel ?? "claude-opus-4.6" } }));
|
|
6253
|
-
} else {
|
|
6254
|
-
console.warn("[daemon] claude-code adapter skipped: need claudeBaseUrl + claudeAuthToken");
|
|
6255
|
-
}
|
|
6438
|
+
this.registry.register(new ClaudeCodeAdapter({ env: { baseUrl: a.claudeBaseUrl, authToken: a.claudeAuthToken, defaultModel: a.claudeDefaultModel ?? "default", models: a.claudeModels } }));
|
|
6256
6439
|
} else if (a.type === "codex") {
|
|
6257
|
-
|
|
6258
|
-
this.registry.register(new CodexAdapter({ env: { baseUrl: a.codexBaseUrl, apiKey: a.codexApiKey, defaultModel: a.codexDefaultModel ?? "gpt-5.5", wireApi: a.codexWireApi ?? "responses" } }));
|
|
6259
|
-
} else {
|
|
6260
|
-
console.warn("[daemon] codex adapter skipped: need codexBaseUrl + codexApiKey");
|
|
6261
|
-
}
|
|
6440
|
+
this.registry.register(new CodexAdapter({ env: { baseUrl: a.codexBaseUrl, apiKey: a.codexApiKey, defaultModel: a.codexDefaultModel ?? "default", models: a.codexModels, wireApi: a.codexWireApi ?? "responses" } }));
|
|
6262
6441
|
} else if (a.type === "hermes") {
|
|
6263
6442
|
this.registry.register(new HermesAdapter({ env: { defaultModel: a.hermesModel, provider: a.hermesProvider } }));
|
|
6264
6443
|
} else if (a.type === "opencode") {
|
|
@@ -6363,189 +6542,6 @@ var PhononDaemon = class {
|
|
|
6363
6542
|
|
|
6364
6543
|
// src/cli.ts
|
|
6365
6544
|
import { existsSync as existsSync13 } from "node:fs";
|
|
6366
|
-
|
|
6367
|
-
// src/commands.ts
|
|
6368
|
-
import { spawnSync } from "node:child_process";
|
|
6369
|
-
import { existsSync as existsSync12, cpSync, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
6370
|
-
import { homedir as homedir10 } from "node:os";
|
|
6371
|
-
import { join as join12, dirname as dirname5 } from "node:path";
|
|
6372
|
-
import { fileURLToPath } from "node:url";
|
|
6373
|
-
function probe(bin, args2 = ["--version"]) {
|
|
6374
|
-
const r = spawnSync(bin, args2, { timeout: 8e3 });
|
|
6375
|
-
return { ok: r.status === 0, out: (r.stdout?.toString() ?? "").trim().split("\n")[0] ?? "" };
|
|
6376
|
-
}
|
|
6377
|
-
function gatewayReachable(url) {
|
|
6378
|
-
try {
|
|
6379
|
-
const u = new URL(url.replace(/^ws/, "http"));
|
|
6380
|
-
const r = spawnSync("bash", ["-c", `exec 3<>/dev/tcp/${u.hostname}/${u.port || 80} && echo ok`], { timeout: 3e3 });
|
|
6381
|
-
return r.status === 0;
|
|
6382
|
-
} catch {
|
|
6383
|
-
return false;
|
|
6384
|
-
}
|
|
6385
|
-
}
|
|
6386
|
-
function openCodeBin() {
|
|
6387
|
-
const bundled = join12(homedir10(), ".opencode", "bin", "opencode");
|
|
6388
|
-
return existsSync12(bundled) ? bundled : "opencode";
|
|
6389
|
-
}
|
|
6390
|
-
function readDefaultLlmGateway() {
|
|
6391
|
-
try {
|
|
6392
|
-
const p = join12(homedir10(), ".openclaw", "openclaw.json");
|
|
6393
|
-
const j = JSON.parse(readFileSync5(p, "utf8"));
|
|
6394
|
-
const provider = j.models?.providers?.["phgeek-gw"];
|
|
6395
|
-
if (provider?.baseUrl && provider?.apiKey) return { baseUrl: provider.baseUrl.replace(/\/$/, ""), apiKey: provider.apiKey };
|
|
6396
|
-
} catch {
|
|
6397
|
-
}
|
|
6398
|
-
const baseUrl = process.env.PHONON_LLM_BASE_URL;
|
|
6399
|
-
const apiKey = process.env.PHONON_LLM_API_KEY;
|
|
6400
|
-
return baseUrl && apiKey ? { baseUrl: baseUrl.replace(/\/$/, ""), apiKey } : void 0;
|
|
6401
|
-
}
|
|
6402
|
-
function autoDetectAdapters(adapters) {
|
|
6403
|
-
const out = [...adapters];
|
|
6404
|
-
const has = (type2) => out.some((a) => a.type === type2);
|
|
6405
|
-
if (!has("hermes") && probe("hermes").ok) out.push({ type: "hermes" });
|
|
6406
|
-
const ocBin = openCodeBin();
|
|
6407
|
-
if (!has("opencode") && probe(ocBin).ok) out.push({ type: "opencode", opencodeBinPath: ocBin === "opencode" ? void 0 : ocBin });
|
|
6408
|
-
const gw = readDefaultLlmGateway();
|
|
6409
|
-
if (gw) {
|
|
6410
|
-
if (!has("claude-code") && probe("claude").ok) {
|
|
6411
|
-
out.push({ type: "claude-code", claudeBaseUrl: gw.baseUrl, claudeAuthToken: gw.apiKey, claudeDefaultModel: "claude-opus-4.8" });
|
|
6412
|
-
}
|
|
6413
|
-
if (!has("codex") && probe("codex").ok) {
|
|
6414
|
-
out.push({ type: "codex", codexBaseUrl: `${gw.baseUrl}/v1`, codexApiKey: gw.apiKey, codexDefaultModel: "gpt-5.5", codexWireApi: "responses" });
|
|
6415
|
-
}
|
|
6416
|
-
}
|
|
6417
|
-
return out;
|
|
6418
|
-
}
|
|
6419
|
-
function cmdDoctor() {
|
|
6420
|
-
console.log("agent-phonon doctor\n");
|
|
6421
|
-
const gwToken = readOpenClawGatewayToken();
|
|
6422
|
-
const gwUrl = "ws://127.0.0.1:18789";
|
|
6423
|
-
const gwOk = gatewayReachable(gwUrl);
|
|
6424
|
-
console.log(`OpenClaw Gateway (${gwUrl}): ${gwOk ? "\u2713 reachable" : "\u2717 unreachable"}${gwToken ? " (token found)" : " (no token in ~/.openclaw/openclaw.json)"}`);
|
|
6425
|
-
const pluginDir = join12(homedir10(), ".openclaw", "extensions", "agent-phonon-hitl");
|
|
6426
|
-
console.log(`OpenClaw HITL plugin: ${existsSync12(pluginDir) ? "\u2713 installed" : "\u2717 not installed (run: agent-phonon plugin install openclaw)"}`);
|
|
6427
|
-
console.log("\nCLI agents:");
|
|
6428
|
-
for (const [name, bin] of [["Claude Code", "claude"], ["Codex", "codex"], ["Hermes", "hermes"]]) {
|
|
6429
|
-
const p = probe(bin);
|
|
6430
|
-
console.log(` ${name} (${bin}): ${p.ok ? "\u2713 " + p.out : "\u2717 not found"}`);
|
|
6431
|
-
}
|
|
6432
|
-
const ocBin = openCodeBin();
|
|
6433
|
-
const oc = probe(ocBin);
|
|
6434
|
-
console.log(` OpenCode (${ocBin}): ${oc.ok ? "\u2713 " + oc.out : "\u2717 not found"}`);
|
|
6435
|
-
console.log("");
|
|
6436
|
-
try {
|
|
6437
|
-
const cfg = loadConfig();
|
|
6438
|
-
const effective = autoDetectAdapters(cfg.adapters);
|
|
6439
|
-
console.log(`config: ${cfg.adapters.length} configured adapter(s), ${effective.length} effective adapter(s), ${cfg.servers.length} server(s)`);
|
|
6440
|
-
} catch {
|
|
6441
|
-
console.log("config: not initialized (run: agent-phonon init)");
|
|
6442
|
-
}
|
|
6443
|
-
}
|
|
6444
|
-
async function cmdDiscover() {
|
|
6445
|
-
let cfg;
|
|
6446
|
-
try {
|
|
6447
|
-
cfg = loadConfig();
|
|
6448
|
-
} catch {
|
|
6449
|
-
console.error("config not initialized \u2014 run 'agent-phonon init' first");
|
|
6450
|
-
process.exit(1);
|
|
6451
|
-
return;
|
|
6452
|
-
}
|
|
6453
|
-
const reg = buildRegistry(cfg.adapters);
|
|
6454
|
-
const nested = await Promise.all(reg.all().map((a) => a.discoverAgents()));
|
|
6455
|
-
const agents = nested.flat();
|
|
6456
|
-
console.log(`discovered ${agents.length} agent(s):
|
|
6457
|
-
`);
|
|
6458
|
-
for (const a of agents) {
|
|
6459
|
-
console.log(` ${a.available ? "\u2713" : "\u2717"} ${a.agentId} (${a.displayName})${a.available ? "" : " \u2014 " + (a.unavailableReason ?? "unavailable")}`);
|
|
6460
|
-
if (a.models.length) console.log(` models: ${a.models.map((m) => m.id).join(", ")}`);
|
|
6461
|
-
}
|
|
6462
|
-
}
|
|
6463
|
-
function buildRegistry(adapters) {
|
|
6464
|
-
const reg = new AdapterRegistry();
|
|
6465
|
-
for (const a of autoDetectAdapters(adapters)) {
|
|
6466
|
-
if (a.type === "openclaw-gateway") {
|
|
6467
|
-
const token = a.gatewayToken ?? readOpenClawGatewayToken();
|
|
6468
|
-
if (token) reg.register(new OpenClawGatewayAdapter({ gateway: { baseUrl: a.gatewayUrl ?? "ws://127.0.0.1:18789", token }, defaultAgent: a.defaultAgent ?? "main" }));
|
|
6469
|
-
} else if (a.type === "claude-code" && a.claudeBaseUrl && a.claudeAuthToken) {
|
|
6470
|
-
reg.register(new ClaudeCodeAdapter({ env: { baseUrl: a.claudeBaseUrl, authToken: a.claudeAuthToken, defaultModel: a.claudeDefaultModel ?? "claude-opus-4.6" } }));
|
|
6471
|
-
} else if (a.type === "codex" && a.codexBaseUrl && a.codexApiKey) {
|
|
6472
|
-
reg.register(new CodexAdapter({ env: { baseUrl: a.codexBaseUrl, apiKey: a.codexApiKey, defaultModel: a.codexDefaultModel ?? "gpt-5.5", wireApi: a.codexWireApi ?? "responses" } }));
|
|
6473
|
-
} else if (a.type === "hermes") {
|
|
6474
|
-
reg.register(new HermesAdapter({ env: { defaultModel: a.hermesModel, provider: a.hermesProvider } }));
|
|
6475
|
-
} else if (a.type === "opencode") {
|
|
6476
|
-
reg.register(new OpenCodeAdapter({ env: { binPath: a.opencodeBinPath, defaultModel: a.opencodeModel } }));
|
|
6477
|
-
}
|
|
6478
|
-
}
|
|
6479
|
-
return reg;
|
|
6480
|
-
}
|
|
6481
|
-
function cmdAdapterAdd(type2, opts) {
|
|
6482
|
-
const cfg = loadConfig();
|
|
6483
|
-
let a;
|
|
6484
|
-
switch (type2) {
|
|
6485
|
-
case "openclaw":
|
|
6486
|
-
case "openclaw-gateway":
|
|
6487
|
-
a = { type: "openclaw-gateway", gatewayUrl: opts.gatewayUrl ?? "ws://127.0.0.1:18789", gatewayToken: opts.token, defaultAgent: opts.defaultAgent ?? "main" };
|
|
6488
|
-
break;
|
|
6489
|
-
case "claude-code":
|
|
6490
|
-
if (!opts.baseUrl || !opts.token) return fail("claude-code needs --base-url and --token");
|
|
6491
|
-
a = { type: "claude-code", claudeBaseUrl: opts.baseUrl, claudeAuthToken: opts.token, claudeDefaultModel: opts.model ?? "claude-opus-4.6" };
|
|
6492
|
-
break;
|
|
6493
|
-
case "codex":
|
|
6494
|
-
if (!opts.baseUrl || !opts.apiKey) return fail("codex needs --base-url and --api-key");
|
|
6495
|
-
a = { type: "codex", codexBaseUrl: opts.baseUrl, codexApiKey: opts.apiKey, codexDefaultModel: opts.model ?? "gpt-5.5", codexWireApi: opts.wireApi ?? "responses" };
|
|
6496
|
-
break;
|
|
6497
|
-
case "hermes":
|
|
6498
|
-
a = { type: "hermes", hermesModel: opts.model, hermesProvider: opts.provider };
|
|
6499
|
-
break;
|
|
6500
|
-
case "opencode":
|
|
6501
|
-
a = { type: "opencode", opencodeBinPath: opts.bin, opencodeModel: opts.model };
|
|
6502
|
-
break;
|
|
6503
|
-
default:
|
|
6504
|
-
return fail(`unknown adapter type: ${type2} (openclaw|claude-code|codex|hermes|opencode)`);
|
|
6505
|
-
}
|
|
6506
|
-
cfg.adapters = cfg.adapters.filter((x) => x.type !== a.type);
|
|
6507
|
-
cfg.adapters.push(a);
|
|
6508
|
-
writeConfig(cfg);
|
|
6509
|
-
console.log(`added ${a.type} adapter (${cfg.adapters.length} total)`);
|
|
6510
|
-
}
|
|
6511
|
-
function cmdAdapterList() {
|
|
6512
|
-
const cfg = loadConfig();
|
|
6513
|
-
const effective = autoDetectAdapters(cfg.adapters);
|
|
6514
|
-
if (effective.length === 0) {
|
|
6515
|
-
console.log("(no adapters available)");
|
|
6516
|
-
return;
|
|
6517
|
-
}
|
|
6518
|
-
for (const a of effective) {
|
|
6519
|
-
const auto = cfg.adapters.some((x) => x.type === a.type) ? "" : " [auto]";
|
|
6520
|
-
console.log(`- ${a.type}${a.defaultAgent ? ` (agent: ${a.defaultAgent})` : ""}${auto}`);
|
|
6521
|
-
}
|
|
6522
|
-
}
|
|
6523
|
-
function cmdPluginInstall(which) {
|
|
6524
|
-
if (which !== "openclaw") return fail(`plugin install supports: openclaw (got: ${which})`);
|
|
6525
|
-
const here = dirname5(fileURLToPath(import.meta.url));
|
|
6526
|
-
const pluginSrc = join12(here, "..", "..", "openclaw-plugin");
|
|
6527
|
-
if (!existsSync12(join12(pluginSrc, "dist", "index.js"))) {
|
|
6528
|
-
return fail(`plugin not built. Run: cd ${pluginSrc} && pnpm build`);
|
|
6529
|
-
}
|
|
6530
|
-
const dist = join12(homedir10(), ".agent-phonon", "openclaw-plugin-dist");
|
|
6531
|
-
rmSync3(dist, { recursive: true, force: true });
|
|
6532
|
-
mkdirSync4(dist, { recursive: true });
|
|
6533
|
-
cpSync(join12(pluginSrc, "dist"), join12(dist, "dist"), { recursive: true });
|
|
6534
|
-
cpSync(join12(pluginSrc, "openclaw.plugin.json"), join12(dist, "openclaw.plugin.json"));
|
|
6535
|
-
const pkg = JSON.parse(readFileSync5(join12(pluginSrc, "package.json"), "utf8"));
|
|
6536
|
-
delete pkg.devDependencies;
|
|
6537
|
-
writeFileSync4(join12(dist, "package.json"), JSON.stringify(pkg, null, 2));
|
|
6538
|
-
console.log(`exported clean plugin \u2192 ${dist}`);
|
|
6539
|
-
const r = spawnSync("openclaw", ["plugins", "install", "--force", dist], { stdio: "inherit" });
|
|
6540
|
-
if (r.status === 0) console.log("\n\u2713 installed. Restart OpenClaw Gateway to load: systemctl --user restart openclaw-gateway.service");
|
|
6541
|
-
else fail("openclaw plugins install failed");
|
|
6542
|
-
}
|
|
6543
|
-
function fail(msg) {
|
|
6544
|
-
console.error("error:", msg);
|
|
6545
|
-
process.exit(1);
|
|
6546
|
-
}
|
|
6547
|
-
|
|
6548
|
-
// src/cli.ts
|
|
6549
6545
|
var [cmd, ...args] = process.argv.slice(2);
|
|
6550
6546
|
function flag(name) {
|
|
6551
6547
|
return args.includes(`--${name}`);
|