agent-phonon 0.2.9 → 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/daemon.js CHANGED
@@ -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((resolve5, 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
+ resolve5(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;
@@ -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,6 +4911,28 @@ 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
4937
  return new Promise((resolve5) => {
4856
4938
  const child = spawn3(this.env.binPath ?? "codex", ["--version"], { shell: process.platform === "win32" });
@@ -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((resolve5) => {
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
+ resolve5(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
+ resolve5([]);
5258
+ }
5259
+ });
5260
+ });
5261
+ req.on("timeout", () => req.destroy());
5262
+ req.on("error", () => resolve5([]));
5263
+ req.end();
5264
+ }, () => resolve5([]));
5265
+ });
5266
+ }
5120
5267
  var HermesSession = class {
5121
5268
  sessionId;
5122
5269
  model;
@@ -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 ?? "";
@@ -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,7 +6249,7 @@ 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 } from "node:fs";
6090
6253
  import { homedir as homedir10, platform as platform2 } from "node:os";
6091
6254
  import { join as join12, dirname as dirname5, delimiter } from "node:path";
6092
6255
  import { fileURLToPath } from "node:url";