agent-phonon 0.2.9 → 0.2.11

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/daemon.js CHANGED
@@ -1724,12 +1724,12 @@ var init_rpc = __esm({
1724
1724
  requestRaw(method, params, timeoutMs = 12e4) {
1725
1725
  const id = this.nextId++;
1726
1726
  const msg = { jsonrpc: "2.0", id, method, params };
1727
- return new Promise((resolve5, reject) => {
1727
+ return new Promise((resolve6, reject) => {
1728
1728
  const timer = timeoutMs > 0 ? setTimeout(() => {
1729
1729
  this.pending.delete(id);
1730
1730
  reject(new PhononError("errInternal", `RPC timeout: ${method}`));
1731
1731
  }, timeoutMs) : void 0;
1732
- this.pending.set(id, { resolve: resolve5, reject, timer });
1732
+ this.pending.set(id, { resolve: resolve6, reject, timer });
1733
1733
  this.transport.send(JSON.stringify(msg));
1734
1734
  });
1735
1735
  }
@@ -2185,8 +2185,8 @@ var SessionEngine = class {
2185
2185
  this.interactionWaiters.delete(requestId);
2186
2186
  }
2187
2187
  }
2188
- registerInteractionWaiter(requestId, resolve5) {
2189
- this.interactionWaiters.set(requestId, resolve5);
2188
+ registerInteractionWaiter(requestId, resolve6) {
2189
+ this.interactionWaiters.set(requestId, resolve6);
2190
2190
  }
2191
2191
  list(tenantId, filter) {
2192
2192
  const all = [];
@@ -3761,7 +3761,7 @@ ${message}`;
3761
3761
  return void 0;
3762
3762
  }
3763
3763
  run(args, signal, environment) {
3764
- return new Promise((resolve5, reject) => {
3764
+ return new Promise((resolve6, reject) => {
3765
3765
  const child = spawn2("openclaw", args, { cwd: this.cwd, env: { ...process.env, ...environment ?? {} } });
3766
3766
  this.current = child;
3767
3767
  let out = "";
@@ -3779,9 +3779,9 @@ ${message}`;
3779
3779
  signal?.removeEventListener("abort", onAbort);
3780
3780
  this.current = void 0;
3781
3781
  if (killed)
3782
- return resolve5(null);
3782
+ return resolve6(null);
3783
3783
  if (code === 0)
3784
- resolve5(out);
3784
+ resolve6(out);
3785
3785
  else
3786
3786
  reject(new Error(`openclaw exited ${code}: ${err.slice(0, 500)}`));
3787
3787
  });
@@ -3833,12 +3833,12 @@ var OpenClawAdapter = class {
3833
3833
  return new OpenClawSession(params.sessionId, params.model, params.cwd, openclawAgent);
3834
3834
  }
3835
3835
  probeVersion() {
3836
- return new Promise((resolve5) => {
3836
+ return new Promise((resolve6) => {
3837
3837
  const child = spawn2("openclaw", ["--version"]);
3838
3838
  let out = "";
3839
3839
  child.stdout.on("data", (d) => out += d.toString());
3840
- child.on("error", () => resolve5(null));
3841
- child.on("close", (code) => resolve5(code === 0 ? out.trim() : null));
3840
+ child.on("error", () => resolve6(null));
3841
+ child.on("close", (code) => resolve6(code === 0 ? out.trim() : null));
3842
3842
  });
3843
3843
  }
3844
3844
  };
@@ -3871,7 +3871,7 @@ var GatewayClient = class {
3871
3871
  return this.connectPromise;
3872
3872
  }
3873
3873
  doConnect() {
3874
- return new Promise((resolve5, reject) => {
3874
+ return new Promise((resolve6, reject) => {
3875
3875
  const wsUrl = this.config.baseUrl.replace(/^http/, "ws");
3876
3876
  const ws = new WebSocket(wsUrl);
3877
3877
  this.ws = ws;
@@ -3902,7 +3902,7 @@ var GatewayClient = class {
3902
3902
  } else if (frame.type === "res" && frame.ok && frame.payload?.type === "hello-ok") {
3903
3903
  handshakeDone = true;
3904
3904
  this.connected = true;
3905
- resolve5();
3905
+ resolve6();
3906
3906
  } else if (frame.type === "res" && !frame.ok) {
3907
3907
  reject(new Error(`handshake failed: ${JSON.stringify(frame.error)}`));
3908
3908
  }
@@ -3948,13 +3948,13 @@ var GatewayClient = class {
3948
3948
  async rpc(method, params, timeoutMs = 12e4) {
3949
3949
  if (!this.connected)
3950
3950
  await this.connect();
3951
- return new Promise((resolve5, reject) => {
3951
+ return new Promise((resolve6, reject) => {
3952
3952
  const id = randomUUID();
3953
3953
  const timer = setTimeout(() => {
3954
3954
  this.pending.delete(id);
3955
3955
  reject(new Error(`RPC timeout: ${method}`));
3956
3956
  }, timeoutMs);
3957
- this.pending.set(id, { resolve: resolve5, reject, timer });
3957
+ this.pending.set(id, { resolve: resolve6, reject, timer });
3958
3958
  this.ws.send(JSON.stringify({ type: "req", id, method, params }));
3959
3959
  });
3960
3960
  }
@@ -4081,14 +4081,14 @@ var GatewaySession = class {
4081
4081
 
4082
4082
  ${input}`;
4083
4083
  }
4084
- await new Promise((resolve5) => {
4084
+ await new Promise((resolve6) => {
4085
4085
  let settled = false;
4086
4086
  const finish = () => {
4087
4087
  if (settled)
4088
4088
  return;
4089
4089
  settled = true;
4090
4090
  clearTimeout(guard);
4091
- resolve5();
4091
+ resolve6();
4092
4092
  };
4093
4093
  this.activeTurn = { turnId, emit, verbosity: opts.verbosity, done: finish, acc: "" };
4094
4094
  this.gw.rpc("chat.send", {
@@ -4349,7 +4349,7 @@ var PhononClient = class {
4349
4349
  }
4350
4350
  /** 连接并完成握手,resolve 后即可接收 server 的 session.* 下发。 */
4351
4351
  connect() {
4352
- return new Promise((resolve5, reject) => {
4352
+ return new Promise((resolve6, reject) => {
4353
4353
  const ws = new WebSocket2(this.serverUrl);
4354
4354
  this.ws = ws;
4355
4355
  const transport = {
@@ -4391,7 +4391,7 @@ var PhononClient = class {
4391
4391
  if (wAck && wAck.length > 0) {
4392
4392
  conn.replayPending(wAck.map((a) => ({ sessionId: a.sessionId, fromSeq: a.lastSeq })));
4393
4393
  }
4394
- resolve5({ tenantId: welcome.tenantId });
4394
+ resolve6({ tenantId: welcome.tenantId });
4395
4395
  } catch (err) {
4396
4396
  reject(err);
4397
4397
  }
@@ -4461,12 +4461,12 @@ var HookBridge = class {
4461
4461
  this.token = opts?.token;
4462
4462
  }
4463
4463
  listen(port = 4318, host = "127.0.0.1") {
4464
- return new Promise((resolve5) => {
4464
+ return new Promise((resolve6) => {
4465
4465
  const server = createServer((req, res) => this.onRequest(req, res));
4466
4466
  this.server = server;
4467
4467
  server.listen(port, host, () => {
4468
4468
  const addr = server.address();
4469
- resolve5(typeof addr === "object" && addr ? addr.port : port);
4469
+ resolve6(typeof addr === "object" && addr ? addr.port : port);
4470
4470
  });
4471
4471
  });
4472
4472
  }
@@ -4519,10 +4519,10 @@ var HookBridge = class {
4519
4519
  });
4520
4520
  }
4521
4521
  close() {
4522
- return new Promise((resolve5) => {
4522
+ return new Promise((resolve6) => {
4523
4523
  if (!this.server)
4524
- return resolve5();
4525
- this.server.close(() => resolve5());
4524
+ return resolve6();
4525
+ this.server.close(() => resolve6());
4526
4526
  });
4527
4527
  }
4528
4528
  };
@@ -4623,7 +4623,12 @@ function fileSize(p) {
4623
4623
  import { spawn as spawn3 } from "node:child_process";
4624
4624
  import { homedir as homedir5 } from "node:os";
4625
4625
  import { join as join7 } from "node:path";
4626
- import { existsSync as existsSync7, readdirSync, statSync as statSync2 } from "node:fs";
4626
+ import { existsSync as existsSync7, readdirSync, statSync as statSync2, readFileSync as readFileSync4 } from "node:fs";
4627
+ var CODEX_FALLBACK_MODELS = [
4628
+ { id: "gpt-5.5", available: true },
4629
+ { id: "gpt-5.4", available: true },
4630
+ { id: "gpt-5.3-codex", available: true }
4631
+ ];
4627
4632
  var CAPABILITIES2 = {
4628
4633
  nativeSession: true,
4629
4634
  // exec resume <thread_id>
@@ -4673,6 +4678,60 @@ function resolveCodexSessionFile(threadId, codexHome = join7(homedir5(), ".codex
4673
4678
  hits.sort((a, b) => b.mtime - a.mtime);
4674
4679
  return hits[0].path;
4675
4680
  }
4681
+ function parseCodexConfig(configPath = join7(homedir5(), ".codex", "config.toml")) {
4682
+ if (!existsSync7(configPath))
4683
+ return {};
4684
+ const text = readFileSync4(configPath, "utf8");
4685
+ const model = text.match(/^model\s*=\s*"([^"]+)"/m)?.[1];
4686
+ const providerId = text.match(/^model_provider\s*=\s*"([^"]+)"/m)?.[1];
4687
+ let baseUrl;
4688
+ if (providerId) {
4689
+ const escaped = providerId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4690
+ const section = text.match(new RegExp(`\\[model_providers\\.${escaped}\\]([\\s\\S]*?)(?:\\n\\[|$)`))?.[1];
4691
+ baseUrl = section?.match(/^base_url\s*=\s*"([^"]+)"/m)?.[1];
4692
+ }
4693
+ return { model, providerId, baseUrl };
4694
+ }
4695
+ function normalizeOpenAiModels(data) {
4696
+ const rows = Array.isArray(data.data) ? data.data : Array.isArray(data) ? data : [];
4697
+ const out = [];
4698
+ const seen = /* @__PURE__ */ new Set();
4699
+ for (const row of rows) {
4700
+ const obj = row;
4701
+ const id = typeof obj.id === "string" ? obj.id : void 0;
4702
+ if (!id || seen.has(id))
4703
+ continue;
4704
+ seen.add(id);
4705
+ out.push({ id, ...typeof obj.name === "string" ? { displayName: obj.name } : {}, available: true });
4706
+ }
4707
+ return out;
4708
+ }
4709
+ function fetchJson(url, headers) {
4710
+ return new Promise((resolve6, reject) => {
4711
+ const u = new URL(url);
4712
+ const req = (u.protocol === "http:" ? import("node:http") : import("node:https")).then((mod) => mod.request(url, { method: "GET", headers, timeout: 5e3 }, (res) => {
4713
+ let body = "";
4714
+ res.setEncoding("utf8");
4715
+ res.on("data", (d) => body += d);
4716
+ res.on("end", () => {
4717
+ if ((res.statusCode ?? 500) < 200 || (res.statusCode ?? 500) >= 300) {
4718
+ reject(new Error(`GET ${url} failed: ${res.statusCode}`));
4719
+ return;
4720
+ }
4721
+ try {
4722
+ resolve6(JSON.parse(body));
4723
+ } catch (e) {
4724
+ reject(e);
4725
+ }
4726
+ });
4727
+ }));
4728
+ req.then((r) => {
4729
+ r.on("timeout", () => r.destroy(new Error(`GET ${url} timeout`)));
4730
+ r.on("error", reject);
4731
+ r.end();
4732
+ }, reject);
4733
+ });
4734
+ }
4676
4735
  var CodexSession = class {
4677
4736
  sessionId;
4678
4737
  model;
@@ -4722,7 +4781,7 @@ ${prompt}`;
4722
4781
  await this.run(args, prompt, turnId, emit, opts);
4723
4782
  }
4724
4783
  run(args, stdin, turnId, emit, opts) {
4725
- return new Promise((resolve5) => {
4784
+ return new Promise((resolve6) => {
4726
4785
  const child = spawn3(this.env.binPath ?? "codex", args, {
4727
4786
  cwd: this.cwd,
4728
4787
  shell: process.platform === "win32",
@@ -4743,7 +4802,7 @@ ${prompt}`;
4743
4802
  } else {
4744
4803
  emit({ type: "result", sessionId: this.sessionId, turnId, seq: 0, at: (/* @__PURE__ */ new Date()).toISOString(), text, status, final: true });
4745
4804
  }
4746
- resolve5();
4805
+ resolve6();
4747
4806
  };
4748
4807
  const guard = setTimeout(() => finish("timeout", acc), 18e5);
4749
4808
  opts.signal?.addEventListener("abort", () => {
@@ -4836,6 +4895,7 @@ var CodexAdapter = class {
4836
4895
  async discoverAgents() {
4837
4896
  const version = await this.probeVersion();
4838
4897
  const available = version !== null;
4898
+ const models = await this.discoverModels();
4839
4899
  return [{
4840
4900
  agentId: "codex",
4841
4901
  displayName: "Codex",
@@ -4843,7 +4903,7 @@ var CodexAdapter = class {
4843
4903
  available,
4844
4904
  ...available ? {} : { unavailableReason: "codex CLI not found" },
4845
4905
  ...version ? { version } : {},
4846
- models: this.env.models?.length ? this.env.models : [{ id: this.env.defaultModel, available: true }],
4906
+ models,
4847
4907
  capabilities: CAPABILITIES2,
4848
4908
  scannedAt: (/* @__PURE__ */ new Date()).toISOString()
4849
4909
  }];
@@ -4851,13 +4911,35 @@ var CodexAdapter = class {
4851
4911
  async createSession(params) {
4852
4912
  return new CodexSession(params.sessionId, params.model, params.cwd, this.env);
4853
4913
  }
4914
+ async discoverModels() {
4915
+ if (this.env.models?.length)
4916
+ return this.env.models;
4917
+ const cfg = parseCodexConfig();
4918
+ const baseUrl = this.env.baseUrl ?? cfg.baseUrl;
4919
+ if (baseUrl) {
4920
+ try {
4921
+ const data = await fetchJson(`${baseUrl.replace(/\/$/, "")}/models`, this.env.apiKey ? { Authorization: `Bearer ${this.env.apiKey}` } : void 0);
4922
+ const models = normalizeOpenAiModels(data);
4923
+ if (models.length > 0)
4924
+ return models;
4925
+ } catch {
4926
+ }
4927
+ }
4928
+ const configured = this.env.defaultModel !== "default" ? this.env.defaultModel : cfg.model;
4929
+ const base = configured ? [{ id: configured, available: true }] : [];
4930
+ const seen = new Set(base.map((m) => m.id));
4931
+ for (const m of CODEX_FALLBACK_MODELS)
4932
+ if (!seen.has(m.id))
4933
+ base.push(m);
4934
+ return base.length > 0 ? base : CODEX_FALLBACK_MODELS;
4935
+ }
4854
4936
  probeVersion() {
4855
- return new Promise((resolve5) => {
4937
+ return new Promise((resolve6) => {
4856
4938
  const child = spawn3(this.env.binPath ?? "codex", ["--version"], { shell: process.platform === "win32" });
4857
4939
  let out = "";
4858
4940
  child.stdout.on("data", (d) => out += d.toString());
4859
- child.on("error", () => resolve5(null));
4860
- child.on("close", (code) => resolve5(code === 0 ? out.trim() : null));
4941
+ child.on("error", () => resolve6(null));
4942
+ child.on("close", (code) => resolve6(code === 0 ? out.trim() : null));
4861
4943
  });
4862
4944
  }
4863
4945
  };
@@ -4933,7 +5015,7 @@ ${message}`;
4933
5015
  await this.run(args, turnId, emit, opts);
4934
5016
  }
4935
5017
  run(args, turnId, emit, opts) {
4936
- return new Promise((resolve5) => {
5018
+ return new Promise((resolve6) => {
4937
5019
  const child = spawn4(this.bin, args, { cwd: this.cwd, stdio: ["ignore", "pipe", "pipe"], env: { ...process.env, ...opts.environment ?? {} } });
4938
5020
  this.current = child;
4939
5021
  let buf = "";
@@ -4950,7 +5032,7 @@ ${message}`;
4950
5032
  } else {
4951
5033
  emit({ type: "result", sessionId: this.sessionId, turnId, seq: 0, at: (/* @__PURE__ */ new Date()).toISOString(), text, status, final: true });
4952
5034
  }
4953
- resolve5();
5035
+ resolve6();
4954
5036
  };
4955
5037
  const guard = setTimeout(() => finish("timeout", acc), 18e5);
4956
5038
  opts.signal?.addEventListener("abort", () => {
@@ -5081,12 +5163,12 @@ var OpenCodeAdapter = class {
5081
5163
  return new OpenCodeSession(params.sessionId, model, params.cwd, this.bin);
5082
5164
  }
5083
5165
  probeVersion() {
5084
- return new Promise((resolve5) => {
5166
+ return new Promise((resolve6) => {
5085
5167
  const child = spawn4(this.bin, ["--version"]);
5086
5168
  let out = "";
5087
5169
  child.stdout.on("data", (d) => out += d.toString());
5088
- child.on("error", () => resolve5(null));
5089
- child.on("close", (code) => resolve5(code === 0 ? out.trim() : null));
5170
+ child.on("error", () => resolve6(null));
5171
+ child.on("close", (code) => resolve6(code === 0 ? out.trim() : null));
5090
5172
  });
5091
5173
  }
5092
5174
  };
@@ -5097,7 +5179,29 @@ import { randomUUID as randomUUID3 } from "node:crypto";
5097
5179
  import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
5098
5180
  import { homedir as homedir7 } from "node:os";
5099
5181
  import { join as join9 } from "node:path";
5100
- import { existsSync as existsSync9 } from "node:fs";
5182
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
5183
+ var HERMES_PROVIDER_FALLBACK_MODELS = {
5184
+ // Hermes' built-in Copilot picker exposes these account/integrator-safe model ids.
5185
+ copilot: [
5186
+ "gpt-5.4",
5187
+ "gpt-5.4-mini",
5188
+ "gpt-5-mini",
5189
+ "gpt-5.3-codex",
5190
+ "gpt-5.2-codex",
5191
+ "gpt-4.1",
5192
+ "gpt-4o",
5193
+ "gpt-4o-mini",
5194
+ "claude-sonnet-4.6",
5195
+ "claude-sonnet-4",
5196
+ "claude-sonnet-4.5",
5197
+ "claude-haiku-4.5",
5198
+ "gemini-3.1-pro-preview",
5199
+ "gemini-3-pro-preview",
5200
+ "gemini-3-flash-preview",
5201
+ "gemini-2.5-pro"
5202
+ ],
5203
+ 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"]
5204
+ };
5101
5205
  var CAPABILITIES4 = {
5102
5206
  nativeSession: true,
5103
5207
  // --resume / --pass-session-id
@@ -5117,6 +5221,49 @@ var CAPABILITIES4 = {
5117
5221
  // -z 是纯文本一次性输出,非流式 → 用 final 事件
5118
5222
  limits: { maxConcurrentSessions: 4 }
5119
5223
  };
5224
+ function parseHermesConfig(configPath = join9(homedir7(), ".hermes", "config.yaml")) {
5225
+ if (!existsSync9(configPath))
5226
+ return {};
5227
+ const text = readFileSync5(configPath, "utf8");
5228
+ const modelBlock = text.match(/(?:^|\n)model:\n([\s\S]*?)(?:\n[A-Za-z_][A-Za-z0-9_-]*:|$)/)?.[1] ?? "";
5229
+ const defaultModel = modelBlock.match(/^\s+default:\s*['"]?([^'"\n]+)['"]?/m)?.[1]?.trim();
5230
+ const provider = modelBlock.match(/^\s+provider:\s*['"]?([^'"\n]+)['"]?/m)?.[1]?.trim();
5231
+ const catalogBlock = text.match(/(?:^|\n)model_catalog:\n([\s\S]*?)(?:\n[A-Za-z_][A-Za-z0-9_-]*:|$)/)?.[1] ?? "";
5232
+ const catalogUrl = catalogBlock.match(/^\s+url:\s*['"]?([^'"\n]+)['"]?/m)?.[1]?.trim();
5233
+ return { defaultModel, provider, catalogUrl };
5234
+ }
5235
+ function fetchHermesCatalogModels(url, provider) {
5236
+ return new Promise((resolve6) => {
5237
+ const u = new URL(url);
5238
+ const reqMod = u.protocol === "http:" ? import("node:http") : import("node:https");
5239
+ reqMod.then((mod) => {
5240
+ const req = mod.request(url, { method: "GET", timeout: 5e3 }, (res) => {
5241
+ let body = "";
5242
+ res.setEncoding("utf8");
5243
+ res.on("data", (d) => body += d);
5244
+ res.on("end", () => {
5245
+ try {
5246
+ const data = JSON.parse(body);
5247
+ const providers = data.providers ?? {};
5248
+ const rows = provider ? providers[provider]?.models ?? [] : Object.values(providers).flatMap((p) => p.models ?? []);
5249
+ const seen = /* @__PURE__ */ new Set();
5250
+ resolve6(rows.flatMap((m) => {
5251
+ if (!m.id || seen.has(m.id))
5252
+ return [];
5253
+ seen.add(m.id);
5254
+ return [{ id: m.id, ...m.description ? { displayName: m.description } : {}, available: true }];
5255
+ }));
5256
+ } catch {
5257
+ resolve6([]);
5258
+ }
5259
+ });
5260
+ });
5261
+ req.on("timeout", () => req.destroy());
5262
+ req.on("error", () => resolve6([]));
5263
+ req.end();
5264
+ }, () => resolve6([]));
5265
+ });
5266
+ }
5120
5267
  var HermesSession = class {
5121
5268
  sessionId;
5122
5269
  model;
@@ -5162,7 +5309,7 @@ ${prompt}`;
5162
5309
  await this.run(args, turnId, emit, opts);
5163
5310
  }
5164
5311
  run(args, turnId, emit, opts) {
5165
- return new Promise((resolve5) => {
5312
+ return new Promise((resolve6) => {
5166
5313
  const child = spawn5(this.env.binPath ?? "hermes", args, {
5167
5314
  cwd: this.cwd,
5168
5315
  shell: process.platform === "win32",
@@ -5185,7 +5332,7 @@ ${prompt}`;
5185
5332
  emit({ type: "message", sessionId: this.sessionId, turnId, seq: 0, at: (/* @__PURE__ */ new Date()).toISOString(), role: "assistant", text, delta: false });
5186
5333
  emit({ type: "result", sessionId: this.sessionId, turnId, seq: 0, at: (/* @__PURE__ */ new Date()).toISOString(), text, status, final: true });
5187
5334
  }
5188
- resolve5();
5335
+ resolve6();
5189
5336
  };
5190
5337
  const guard = setTimeout(() => finish("timeout", out), 18e5);
5191
5338
  opts.signal?.addEventListener("abort", () => {
@@ -5310,6 +5457,10 @@ var HermesAdapter = class {
5310
5457
  }];
5311
5458
  }
5312
5459
  const profiles = await this.listProfiles();
5460
+ const cfg = parseHermesConfig();
5461
+ const provider = this.env.provider ?? cfg.provider;
5462
+ const catalogModels = cfg.catalogUrl ? await fetchHermesCatalogModels(cfg.catalogUrl, provider) : [];
5463
+ const providerFallbackModels = provider ? (HERMES_PROVIDER_FALLBACK_MODELS[provider] ?? []).map((id) => ({ id, available: true })) : [];
5313
5464
  const now = (/* @__PURE__ */ new Date()).toISOString();
5314
5465
  return profiles.map((p) => ({
5315
5466
  agentId: `hermes:${p.name}`,
@@ -5317,11 +5468,23 @@ var HermesAdapter = class {
5317
5468
  adapter: "hermes",
5318
5469
  available: true,
5319
5470
  ...version ? { version } : {},
5320
- models: p.model ? [{ id: p.model, available: true }] : this.env.defaultModel ? [{ id: this.env.defaultModel, available: true }] : [{ id: "default", displayName: "Hermes default", available: true }],
5471
+ models: this.modelsForProfile(p.model, [...catalogModels, ...providerFallbackModels], cfg.defaultModel),
5321
5472
  capabilities: CAPABILITIES4,
5322
5473
  scannedAt: now
5323
5474
  }));
5324
5475
  }
5476
+ modelsForProfile(profileModel, catalogModels, configDefault) {
5477
+ const preferred = profileModel ?? this.env.defaultModel ?? configDefault;
5478
+ const models = preferred ? [{ id: preferred, available: true }] : [];
5479
+ const seen = new Set(models.map((m) => m.id));
5480
+ for (const m of catalogModels) {
5481
+ if (!seen.has(m.id)) {
5482
+ models.push(m);
5483
+ seen.add(m.id);
5484
+ }
5485
+ }
5486
+ return models.length > 0 ? models : [{ id: "default", displayName: "Hermes default", available: true }];
5487
+ }
5325
5488
  async createSession(params) {
5326
5489
  const profile = params.agentId.includes(":") ? params.agentId.split(":")[1] : this.defaultProfile;
5327
5490
  const model = params.model && params.model !== "default" ? params.model : this.env.defaultModel ?? "";
@@ -5329,11 +5492,11 @@ var HermesAdapter = class {
5329
5492
  }
5330
5493
  /** 枚举 Hermes profile(去 ANSI 色解析 profile list)。 */
5331
5494
  listProfiles() {
5332
- return new Promise((resolve5) => {
5495
+ return new Promise((resolve6) => {
5333
5496
  const child = spawn5(this.env.binPath ?? "hermes", ["profile", "list"], { shell: process.platform === "win32" });
5334
5497
  let out = "";
5335
5498
  child.stdout.on("data", (d) => out += d.toString());
5336
- child.on("error", () => resolve5([{ name: this.defaultProfile }]));
5499
+ child.on("error", () => resolve6([{ name: this.defaultProfile }]));
5337
5500
  child.on("close", () => {
5338
5501
  const clean = out.replace(/\u001b\[[0-9;]*m/g, "");
5339
5502
  const names = [];
@@ -5344,17 +5507,17 @@ var HermesAdapter = class {
5344
5507
  names.push({ name: m[1], model: rest[0] || void 0 });
5345
5508
  }
5346
5509
  }
5347
- resolve5(names.length > 0 ? names : [{ name: this.defaultProfile }]);
5510
+ resolve6(names.length > 0 ? names : [{ name: this.defaultProfile }]);
5348
5511
  });
5349
5512
  });
5350
5513
  }
5351
5514
  probeVersion() {
5352
- return new Promise((resolve5) => {
5515
+ return new Promise((resolve6) => {
5353
5516
  const child = spawn5(this.env.binPath ?? "hermes", ["--version"], { shell: process.platform === "win32" });
5354
5517
  let out = "";
5355
5518
  child.stdout.on("data", (d) => out += d.toString());
5356
- child.on("error", () => resolve5(null));
5357
- child.on("close", (code) => resolve5(code === 0 ? out.trim().split("\n")[0] ?? "hermes" : null));
5519
+ child.on("error", () => resolve6(null));
5520
+ child.on("close", (code) => resolve6(code === 0 ? out.trim().split("\n")[0] ?? "hermes" : null));
5358
5521
  });
5359
5522
  }
5360
5523
  };
@@ -5577,7 +5740,7 @@ ${prompt}`;
5577
5740
  await this.run(args, envelope, turnId, emit, opts);
5578
5741
  }
5579
5742
  run(args, stdin, turnId, emit, opts) {
5580
- return new Promise((resolve5) => {
5743
+ return new Promise((resolve6) => {
5581
5744
  const childEnv = {};
5582
5745
  for (const [k, v] of Object.entries(process.env)) {
5583
5746
  if (k === "CLAUDECODE" || k.startsWith("CLAUDECODE_") || k.startsWith("CLAUDE_CODE_"))
@@ -5609,7 +5772,7 @@ ${prompt}`;
5609
5772
  } else {
5610
5773
  emit({ type: "result", sessionId: this.sessionId, turnId, seq: 0, at: (/* @__PURE__ */ new Date()).toISOString(), text, status, final: true });
5611
5774
  }
5612
- resolve5();
5775
+ resolve6();
5613
5776
  };
5614
5777
  const guard = setTimeout(() => finish("timeout", acc), 18e5);
5615
5778
  opts.signal?.addEventListener("abort", () => {
@@ -5726,12 +5889,12 @@ var ClaudeCodeAdapter = class {
5726
5889
  return new ClaudeCodeSession(params.sessionId, params.model, params.cwd, this.env);
5727
5890
  }
5728
5891
  probeVersion() {
5729
- return new Promise((resolve5) => {
5892
+ return new Promise((resolve6) => {
5730
5893
  const child = spawn6(this.env.binPath ?? "claude", ["--version"], { shell: process.platform === "win32" });
5731
5894
  let out = "";
5732
5895
  child.stdout.on("data", (d) => out += d.toString());
5733
- child.on("error", () => resolve5(null));
5734
- child.on("close", (code) => resolve5(code === 0 ? out.trim() : null));
5896
+ child.on("error", () => resolve6(null));
5897
+ child.on("close", (code) => resolve6(code === 0 ? out.trim() : null));
5735
5898
  });
5736
5899
  }
5737
5900
  };
@@ -6069,7 +6232,7 @@ var PhononConnection = class {
6069
6232
  };
6070
6233
 
6071
6234
  // src/config.ts
6072
- import { readFileSync as readFileSync4, existsSync as existsSync11, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, chmodSync as chmodSync2 } from "node:fs";
6235
+ import { readFileSync as readFileSync6, existsSync as existsSync11, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, chmodSync as chmodSync2 } from "node:fs";
6073
6236
  import { homedir as homedir9, hostname as hostname2 } from "node:os";
6074
6237
  import { join as join11, dirname as dirname4 } from "node:path";
6075
6238
  var DEFAULT_DIR = join11(homedir9(), ".agent-phonon");
@@ -6077,7 +6240,7 @@ var DEFAULT_CONFIG_PATH = process.env.PHONON_CONFIG ?? join11(DEFAULT_DIR, "conf
6077
6240
  function readOpenClawGatewayToken() {
6078
6241
  try {
6079
6242
  const p = join11(homedir9(), ".openclaw", "openclaw.json");
6080
- const cfg = JSON.parse(readFileSync4(p, "utf8"));
6243
+ const cfg = JSON.parse(readFileSync6(p, "utf8"));
6081
6244
  return cfg?.gateway?.auth?.token;
6082
6245
  } catch {
6083
6246
  return void 0;
@@ -6086,9 +6249,9 @@ function readOpenClawGatewayToken() {
6086
6249
 
6087
6250
  // src/commands.ts
6088
6251
  import { spawnSync } from "node:child_process";
6089
- import { existsSync as existsSync12, cpSync, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync4, readFileSync as readFileSync5 } from "node:fs";
6252
+ import { existsSync as existsSync12, cpSync, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync4, readFileSync as readFileSync7, chmodSync as chmodSync3 } from "node:fs";
6090
6253
  import { homedir as homedir10, platform as platform2 } from "node:os";
6091
- import { join as join12, dirname as dirname5, delimiter } from "node:path";
6254
+ import { join as join12, dirname as dirname5, delimiter, resolve as resolve5 } from "node:path";
6092
6255
  import { fileURLToPath } from "node:url";
6093
6256
  function probe(bin, args = ["--version"]) {
6094
6257
  const r = spawnSync(bin, args, { timeout: 8e3, shell: platform2() === "win32" });
@@ -6171,13 +6334,13 @@ var ObsServer = class {
6171
6334
  deps.bus.onEvent((e) => this.broadcast(e));
6172
6335
  }
6173
6336
  listen(port = 4319, host = "127.0.0.1") {
6174
- return new Promise((resolve5) => {
6337
+ return new Promise((resolve6) => {
6175
6338
  const server = createServer2((req, res) => this.handle(req, res));
6176
6339
  this.server = server;
6177
6340
  server.listen(port, host, () => {
6178
6341
  const addr = server.address();
6179
6342
  this.actualPort = typeof addr === "object" && addr ? addr.port : port;
6180
- resolve5(this.actualPort);
6343
+ resolve6(this.actualPort);
6181
6344
  });
6182
6345
  });
6183
6346
  }
@@ -6255,11 +6418,11 @@ var ObsServer = class {
6255
6418
  return this.actualPort;
6256
6419
  }
6257
6420
  close() {
6258
- return new Promise((resolve5) => {
6421
+ return new Promise((resolve6) => {
6259
6422
  for (const c of this.sseClients) c.end();
6260
6423
  this.sseClients.clear();
6261
- if (!this.server) return resolve5();
6262
- this.server.close(() => resolve5());
6424
+ if (!this.server) return resolve6();
6425
+ this.server.close(() => resolve6());
6263
6426
  });
6264
6427
  }
6265
6428
  };