oasis_test_v2 2.2.44 → 2.2.45

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.
Files changed (2) hide show
  1. package/dist/index.js +174 -26
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -4880,7 +4880,7 @@ async function listModels(runtime, executablePath) {
4880
4880
  case "claude-code":
4881
4881
  return claudeStaticModels();
4882
4882
  case "codex":
4883
- return withFallback(runtime, executablePath, () => discoverCodexModels(executablePath), codexStaticModels);
4883
+ return discoverCodexCatalog(executablePath);
4884
4884
  case "gemini":
4885
4885
  return withFallback(runtime, executablePath, async () => await discoverACPModels(executablePath ?? "gemini", "gemini", ["--acp"]) ?? [], geminiStaticModels);
4886
4886
  case "copilot":
@@ -5024,22 +5024,9 @@ function codebuddyStaticModels() {
5024
5024
  function cursorStaticModels() {
5025
5025
  return [{ id: "default[]", label: "Auto", provider: "cursor", default: true }];
5026
5026
  }
5027
- async function isModelValid(runtime, modelId, executablePath) {
5028
- try {
5029
- const models = await listModels(runtime, executablePath);
5030
- if (models.length === 0) return true;
5031
- return models.some((m2) => m2.id === modelId);
5032
- } catch {
5033
- return true;
5034
- }
5035
- }
5036
- async function defaultModelFor(runtime, executablePath) {
5037
- try {
5038
- const models = await listModels(runtime, executablePath);
5039
- return models.find((m2) => m2.default)?.id;
5040
- } catch {
5041
- return void 0;
5042
- }
5027
+ function resolveDispatchModel(candidate, catalog) {
5028
+ if (catalog.length === 0 || catalog.some((m2) => m2.id === candidate)) return { model: candidate, replaced: false };
5029
+ return { model: catalog.find((m2) => m2.default)?.id, replaced: true };
5043
5030
  }
5044
5031
  async function discoverOpenCodeModels(bin) {
5045
5032
  const out = await runCapture(bin ?? "opencode", ["models"]);
@@ -5055,7 +5042,163 @@ async function discoverOpenCodeModels(bin) {
5055
5042
  }
5056
5043
  return models;
5057
5044
  }
5058
- async function discoverCodexModels(bin) {
5045
+ async function discoverCodexCatalog(bin) {
5046
+ const probed = { customProvider: false };
5047
+ const models = await cachedDiscovery(discoveryCacheKey("codex", bin), async () => {
5048
+ const catalog = codexCatalogFromAppServer(await probeCodexAppServer(bin ?? "codex"));
5049
+ if (!catalog) return discoverCodexBundledModels(bin);
5050
+ probed.customProvider = catalog.customProvider;
5051
+ return catalog.models;
5052
+ });
5053
+ return models.length > 0 || probed.customProvider ? models : codexStaticModels();
5054
+ }
5055
+ function codexCatalogFromAppServer(probe) {
5056
+ const config2 = probe?.config;
5057
+ if (!probe || !config2) return null;
5058
+ const providerId = config2.modelProvider?.trim() || "openai";
5059
+ const customProvider = providerId.toLowerCase() !== "openai";
5060
+ if (!customProvider && !probe.models) return null;
5061
+ const provider = customProvider ? config2.providerName?.trim() || providerId : "OpenAI";
5062
+ const listApplies = !customProvider || Boolean(config2.modelCatalogJson);
5063
+ const listed = listApplies ? probe.models ?? [] : [];
5064
+ const configured = config2.model?.trim();
5065
+ const defaultId = configured || listed.find((m2) => m2.isDefault)?.id;
5066
+ const models = listed.map((m2) => ({ id: m2.id, label: m2.label, provider }));
5067
+ if (configured && !models.some((m2) => m2.id === configured)) models.push({ id: configured, label: configured, provider });
5068
+ return { models: models.map((m2) => m2.id === defaultId ? { ...m2, default: true } : m2), customProvider };
5069
+ }
5070
+ async function probeCodexAppServer(bin, timeoutMs = 15e3) {
5071
+ let dir;
5072
+ try {
5073
+ dir = (0, import_node_fs2.mkdtempSync)((0, import_node_path3.join)((0, import_node_os2.tmpdir)(), "oasis-codex-models-"));
5074
+ } catch {
5075
+ return null;
5076
+ }
5077
+ let child;
5078
+ try {
5079
+ child = (0, import_node_child_process5.spawn)(bin, ["app-server", "--stdio", "-c", "allow_login_shell=false"], {
5080
+ cwd: dir,
5081
+ stdio: ["pipe", "pipe", "ignore"],
5082
+ env: { ...process.env }
5083
+ });
5084
+ } catch {
5085
+ (0, import_node_fs2.rmSync)(dir, { recursive: true, force: true });
5086
+ return null;
5087
+ }
5088
+ return await new Promise((resolve10) => {
5089
+ let settled = false;
5090
+ let config2;
5091
+ const listed = [];
5092
+ let listState = "pending";
5093
+ let nextId = 3;
5094
+ const MAX_PAGES = 20;
5095
+ let pages = 0;
5096
+ const finish = (value2) => {
5097
+ if (settled) return;
5098
+ settled = true;
5099
+ clearTimeout(timer);
5100
+ try {
5101
+ child.stdin?.end();
5102
+ } catch {
5103
+ }
5104
+ try {
5105
+ child.kill("SIGKILL");
5106
+ } catch {
5107
+ }
5108
+ try {
5109
+ (0, import_node_fs2.rmSync)(dir, { recursive: true, force: true });
5110
+ } catch {
5111
+ }
5112
+ resolve10(value2);
5113
+ };
5114
+ const maybeFinish = () => {
5115
+ if (config2 === void 0 || listState === "pending") return;
5116
+ finish({ config: config2, models: listState === "done" ? listed : null });
5117
+ };
5118
+ const timer = setTimeout(() => finish(null), timeoutMs);
5119
+ const send = (id, method, params) => {
5120
+ try {
5121
+ child.stdin?.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
5122
+ `);
5123
+ } catch {
5124
+ finish(null);
5125
+ }
5126
+ };
5127
+ child.on("error", () => finish(null));
5128
+ child.stdin?.on("error", () => finish(null));
5129
+ child.on("close", () => finish(null));
5130
+ let buf = "";
5131
+ child.stdout?.on("data", (chunk) => {
5132
+ if (settled) return;
5133
+ buf += chunk.toString("utf8");
5134
+ let nl;
5135
+ while ((nl = buf.indexOf("\n")) >= 0) {
5136
+ const line = buf.slice(0, nl).trim();
5137
+ buf = buf.slice(nl + 1);
5138
+ if (!line) continue;
5139
+ let msg;
5140
+ try {
5141
+ msg = JSON.parse(line);
5142
+ } catch {
5143
+ continue;
5144
+ }
5145
+ if (typeof msg.id !== "number") continue;
5146
+ if (msg.id === 1) {
5147
+ if (msg.error !== void 0) {
5148
+ finish(null);
5149
+ return;
5150
+ }
5151
+ send(2, "config/read", { cwd: dir });
5152
+ send(nextId, "model/list", {});
5153
+ continue;
5154
+ }
5155
+ if (msg.id === 2) {
5156
+ config2 = msg.error !== void 0 ? null : parseCodexConfigRead(msg.result);
5157
+ maybeFinish();
5158
+ continue;
5159
+ }
5160
+ if (msg.id === nextId && listState === "pending") {
5161
+ if (msg.error !== void 0) {
5162
+ listState = "failed";
5163
+ } else {
5164
+ const page = msg.result ?? {};
5165
+ for (const m2 of page.data ?? []) {
5166
+ const id = typeof m2.model === "string" && m2.model ? m2.model : typeof m2.id === "string" ? m2.id : "";
5167
+ if (!id || m2.hidden === true || listed.some((x2) => x2.id === id)) continue;
5168
+ listed.push({ id, label: typeof m2.displayName === "string" && m2.displayName ? m2.displayName : id, isDefault: m2.isDefault === true });
5169
+ }
5170
+ pages += 1;
5171
+ if (typeof page.nextCursor === "string" && page.nextCursor && pages < MAX_PAGES) {
5172
+ nextId += 1;
5173
+ send(nextId, "model/list", { cursor: page.nextCursor });
5174
+ continue;
5175
+ }
5176
+ listState = "done";
5177
+ }
5178
+ maybeFinish();
5179
+ }
5180
+ }
5181
+ });
5182
+ send(1, "initialize", { clientInfo: { name: "oasis-model-discovery", version: "0.1.0" }, capabilities: {} });
5183
+ });
5184
+ }
5185
+ function parseCodexConfigRead(result) {
5186
+ const config2 = (result ?? {}).config ?? {};
5187
+ const str5 = (v2) => typeof v2 === "string" && v2.trim() ? v2.trim() : void 0;
5188
+ const model = str5(config2["model"]);
5189
+ const modelProvider = str5(config2["model_provider"]);
5190
+ const modelCatalogJson = str5(config2["model_catalog_json"]);
5191
+ const providers = config2["model_providers"];
5192
+ const entry = modelProvider && providers && typeof providers === "object" ? providers[modelProvider] : void 0;
5193
+ const providerName = entry && typeof entry === "object" ? str5(entry["name"]) : void 0;
5194
+ return {
5195
+ ...model ? { model } : {},
5196
+ ...modelProvider ? { modelProvider } : {},
5197
+ ...providerName ? { providerName } : {},
5198
+ ...modelCatalogJson ? { modelCatalogJson } : {}
5199
+ };
5200
+ }
5201
+ async function discoverCodexBundledModels(bin) {
5059
5202
  const out = await runCapture(bin ?? "codex", ["debug", "models", "--bundled"]);
5060
5203
  if (out === void 0) return [];
5061
5204
  try {
@@ -5256,6 +5399,7 @@ async function discoverACPModels(bin, provider, args = ["acp"], timeoutMs = 12e3
5256
5399
  };
5257
5400
  const watchdog = setTimeout(fail, timeoutMs);
5258
5401
  child.on("error", fail);
5402
+ child.stdin?.on("error", fail);
5259
5403
  child.on("exit", () => {
5260
5404
  if (!settled) fail();
5261
5405
  });
@@ -270097,6 +270241,9 @@ async function startServe(opts) {
270097
270241
  // actor→runtime→default 模型解析(内部字段;非用户 per-session 选择)。
270098
270242
  // 决策 0032 预派发校验:候选 model 不在该 runtime 的模型目录里 → 不烧会话,
270099
270243
  // 回退目录默认并留 warn(曾因 actor 存了残缺 id "claude-sonnet",CLI 秒拒、节点熔断卡死)。
270244
+ // 目录用**绑定那台节点**的(resolveRuntimeModels,与控制台下拉、会话级校验同一份):控制面本机
270245
+ // 的 isModelValid 看的是控制面自己的 CLI 配置,跨机时回落静态 GPT 目录,会把节点上配好的
270246
+ // deepseek-flash 判无效、悄悄换成 gpt-6-astra 派出去(Bug 0209)。
270100
270247
  resolveModel: async (actorId) => {
270101
270248
  const actors2 = await runActors();
270102
270249
  const binding = await actors2.service.resolveBinding()(actorId);
@@ -270107,13 +270254,14 @@ async function startServe(opts) {
270107
270254
  candidate = runtimeCfg?.model;
270108
270255
  }
270109
270256
  if (!candidate) return void 0;
270110
- const kind = binding ? traceRuntimeKind(binding.runtimeKind) : void 0;
270111
- if (kind && kind !== "custom" && !await isModelValid(kind, candidate)) {
270112
- const fallback = await defaultModelFor(kind);
270113
- console.warn(`[dispatch] ${actorId} \u914D\u7F6E\u7684\u6A21\u578B '${candidate}' \u5BF9 runtime ${kind} \u65E0\u6548\uFF0C\u56DE\u9000 ${fallback ?? "CLI \u9ED8\u8BA4"}\uFF08\u51B3\u7B56 0032\uFF09`);
270114
- return fallback;
270115
- }
270116
- return candidate;
270257
+ if (!binding || traceRuntimeKind(binding.runtimeKind) === "custom") return candidate;
270258
+ const runtimeId = `runtime:${binding.nodeId}:${binding.runtimeKind}`;
270259
+ const catalog = await resolveRuntimeModels({ nodeStore, registry: registryStore, nodeReportedModels }, runtimeId).catch(() => []);
270260
+ const checked = resolveDispatchModel(candidate, catalog);
270261
+ if (checked.replaced) {
270262
+ console.warn(`[dispatch] ${actorId} \u914D\u7F6E\u7684\u6A21\u578B '${candidate}' \u4E0D\u5728 ${runtimeId} \u7684\u5019\u9009\u91CC\uFF0C\u56DE\u9000 ${checked.model ?? "CLI \u9ED8\u8BA4"}\uFF08\u51B3\u7B56 0032\uFF09`);
270263
+ }
270264
+ return checked.model;
270117
270265
  },
270118
270266
  // ADR「agent CLI 启动参数员工级可配置化」:每次派发解析员工 actor_configs.extraArgs 下发(形态同 resolveModel)。
270119
270267
  // 只读员工配置,不叠 runtime 默认、不做「没有员工就找 runtime」回退(ADR §3.3 / §4-A)。
@@ -278735,7 +278883,7 @@ function shimScript() {
278735
278883
  }
278736
278884
 
278737
278885
  // src/index.ts
278738
- var PKG_VERSION = true ? "2.2.44" : "dev";
278886
+ var PKG_VERSION = true ? "2.2.45" : "dev";
278739
278887
  var LOCAL_BIN = localBin();
278740
278888
  var NPM_PREFIX = npmPrefix();
278741
278889
  var INSTANCE = DEFAULT_INSTANCE;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oasis_test_v2",
3
- "version": "2.2.44",
3
+ "version": "2.2.45",
4
4
  "description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
5
5
  "bin": {
6
6
  "oasis": "./dist/index.js"
@@ -26,6 +26,6 @@
26
26
  "node": ">=20"
27
27
  },
28
28
  "oasisRelease": {
29
- "sourceHead": "91d9408678684a3e8cb17fdae1fdc0b7772cdcb4"
29
+ "sourceHead": "c27918782543065f65990ee2acc32b3da89bba06"
30
30
  }
31
31
  }