@rynx-ai/runtime 0.1.11-beta.4 → 0.1.11-beta.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/host.js CHANGED
@@ -1536,6 +1536,9 @@ export class LocalAgentHost {
1536
1536
  // Explicit rynx hooks and selected-skill plugin dirs remain enabled.
1537
1537
  settingSources: "",
1538
1538
  model: live.execution.model,
1539
+ ...(live.execution.reasoningEffort
1540
+ ? { reasoningEffort: live.execution.reasoningEffort }
1541
+ : {}),
1539
1542
  ...(live.execution.instructions
1540
1543
  ? { appendSystemPrompt: live.execution.instructions }
1541
1544
  : {}),
@@ -1,11 +1,12 @@
1
1
  import { type AgentRuntimeId, type AppConfig } from "@rynx-ai/core";
2
2
  import type { ModelListResponse } from "./codex-app-server/protocol.js";
3
3
  export interface RuntimeModelCatalogDeps {
4
+ readCodexModels?: () => Promise<unknown>;
4
5
  readTraexModels?: () => Promise<unknown>;
5
6
  readTraexDebugModels?: () => Promise<unknown>;
6
7
  }
7
8
  /**
8
9
  * The model list for a runtime, without an execution backend.
9
- * Falls back to the configured model if live Traex discovery is unavailable.
10
+ * Falls back to the configured model if local/native discovery is unavailable.
10
11
  */
11
12
  export declare function listRuntimeModels(config: AppConfig, runtime: AgentRuntimeId, deps?: RuntimeModelCatalogDeps): Promise<ModelListResponse | null>;
@@ -3,24 +3,37 @@
3
3
  *
4
4
  * The parent control plane no longer holds an app-server, so `/models` can't be
5
5
  * a live `model/list` RPC anymore. Following reference implementation's static-catalog model, we
6
- * serve a config-derived Codex list and Traex's native `models --json` catalog.
6
+ * serve Codex's local model cache and Traex's native `models --json` catalog.
7
7
  * claude already has its own static list ({@link listClaudeModels}).
8
8
  */
9
9
  import { execFile } from "node:child_process";
10
+ import { readFile } from "node:fs/promises";
11
+ import { join } from "node:path";
10
12
  import { promisify } from "node:util";
11
- import { resolveRuntimeBinary, resolveRuntimeModel, } from "@rynx-ai/core";
13
+ import { getRuntimeProfile, resolveRuntimeBinary, resolveRuntimeHome, resolveRuntimeModel, } from "@rynx-ai/core";
12
14
  import { listClaudeModels } from "./claude/models.js";
13
15
  const execFileAsync = promisify(execFile);
14
16
  const TRAEX_MODELS_TIMEOUT_MS = 8_000;
15
17
  const TRAEX_MODELS_MAX_BYTES = 2 * 1024 * 1024;
16
18
  /**
17
19
  * The model list for a runtime, without an execution backend.
18
- * Falls back to the configured model if live Traex discovery is unavailable.
20
+ * Falls back to the configured model if local/native discovery is unavailable.
19
21
  */
20
22
  export async function listRuntimeModels(config, runtime, deps = {}) {
21
23
  if (runtime === "claude") {
22
24
  return listClaudeModels();
23
25
  }
26
+ if (runtime === "codex") {
27
+ try {
28
+ const configuredDefault = resolveRuntimeModel(config, runtime).trim();
29
+ const models = normalizeCodexModels(await (deps.readCodexModels ?? readCodexModels)(), configuredDefault);
30
+ if (models.length > 0)
31
+ return { data: models };
32
+ }
33
+ catch {
34
+ // Keep the configured fallback usable before Codex has populated its cache.
35
+ }
36
+ }
24
37
  if (runtime === "traex") {
25
38
  try {
26
39
  const value = await (deps.readTraexModels ?? readTraexModels)();
@@ -48,6 +61,72 @@ export async function listRuntimeModels(config, runtime, deps = {}) {
48
61
  }
49
62
  return { data: [{ id: model, model, isDefault: true }] };
50
63
  }
64
+ async function readCodexModels() {
65
+ const cachePath = join(resolveRuntimeHome(getRuntimeProfile("codex")), "models_cache.json");
66
+ return JSON.parse(await readFile(cachePath, "utf8"));
67
+ }
68
+ function normalizeCodexModels(value, configuredDefault) {
69
+ if (!value || typeof value !== "object" || Array.isArray(value))
70
+ return [];
71
+ const entries = value.models;
72
+ if (!Array.isArray(entries))
73
+ return [];
74
+ const models = [];
75
+ const seen = new Set();
76
+ for (const item of entries) {
77
+ if (!item || typeof item !== "object" || Array.isArray(item))
78
+ continue;
79
+ const record = item;
80
+ const id = typeof record.slug === "string" ? record.slug.trim() : "";
81
+ if (!id || seen.has(id) || record.visibility === "hide")
82
+ continue;
83
+ seen.add(id);
84
+ const supportedReasoningEfforts = Array.isArray(record.supported_reasoning_levels)
85
+ ? record.supported_reasoning_levels.flatMap((raw) => {
86
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
87
+ return [];
88
+ const effort = typeof raw.effort === "string"
89
+ ? raw.effort.trim()
90
+ : "";
91
+ if (!effort)
92
+ return [];
93
+ const description = raw.description;
94
+ return [{
95
+ reasoningEffort: effort,
96
+ ...(typeof description === "string" && description.trim()
97
+ ? { description: description.trim() }
98
+ : {}),
99
+ }];
100
+ })
101
+ : [];
102
+ const displayName = typeof record.display_name === "string"
103
+ ? record.display_name.trim()
104
+ : "";
105
+ const description = typeof record.description === "string"
106
+ ? record.description.trim()
107
+ : "";
108
+ const defaultReasoningEffort = typeof record.default_reasoning_level === "string"
109
+ ? record.default_reasoning_level.trim()
110
+ : "";
111
+ models.push({
112
+ id,
113
+ model: id,
114
+ ...(displayName ? { displayName } : {}),
115
+ ...(description ? { description } : {}),
116
+ isDefault: id === configuredDefault,
117
+ ...(supportedReasoningEfforts.length > 0 ? { supportedReasoningEfforts } : {}),
118
+ ...(defaultReasoningEffort ? { defaultReasoningEffort } : {}),
119
+ });
120
+ }
121
+ if (configuredDefault && !seen.has(configuredDefault)) {
122
+ models.unshift({
123
+ id: configuredDefault,
124
+ model: configuredDefault,
125
+ isDefault: true,
126
+ });
127
+ }
128
+ return models;
129
+ }
51
130
  async function readTraexModels() {
52
131
  const { stdout } = await execFileAsync(resolveRuntimeBinary("traex"), ["models", "--json"], {
53
132
  encoding: "utf8",
@@ -18,6 +18,8 @@ export interface ClaudeTuiArgs {
18
18
  settingSources?: string;
19
19
  /** Launch model (`--model`); omit to use claude's default. */
20
20
  model?: string;
21
+ /** Native Claude Code effort (`--effort`); omit to use its default. */
22
+ reasoningEffort?: string;
21
23
  /** Agent instructions appended to Claude Code's native system prompt. */
22
24
  appendSystemPrompt?: string;
23
25
  /** Resume a specific prior claude session (`--resume <id>`). */
@@ -36,4 +38,4 @@ export interface ClaudeTuiArgs {
36
38
  * Build the `claude` argv for an interactive, co-drivable TUI:
37
39
  * `[..extra] [--resume <id>] [--model <m>] [--append-system-prompt <text>] --settings <json>`.
38
40
  */
39
- export declare function buildClaudeTuiArgs({ settingsJson, settingSources, model, appendSystemPrompt, resume, forkSession, sessionId, additionalDirs, extraArgs, }: ClaudeTuiArgs): string[];
41
+ export declare function buildClaudeTuiArgs({ settingsJson, settingSources, model, reasoningEffort, appendSystemPrompt, resume, forkSession, sessionId, additionalDirs, extraArgs, }: ClaudeTuiArgs): string[];
@@ -2,7 +2,7 @@
2
2
  * Build the `claude` argv for an interactive, co-drivable TUI:
3
3
  * `[..extra] [--resume <id>] [--model <m>] [--append-system-prompt <text>] --settings <json>`.
4
4
  */
5
- export function buildClaudeTuiArgs({ settingsJson, settingSources, model, appendSystemPrompt, resume, forkSession = false, sessionId, additionalDirs = [], extraArgs = [], }) {
5
+ export function buildClaudeTuiArgs({ settingsJson, settingSources, model, reasoningEffort, appendSystemPrompt, resume, forkSession = false, sessionId, additionalDirs = [], extraArgs = [], }) {
6
6
  const args = [...extraArgs];
7
7
  if (additionalDirs.length > 0)
8
8
  args.push("--add-dir", ...additionalDirs);
@@ -16,6 +16,8 @@ export function buildClaudeTuiArgs({ settingsJson, settingSources, model, append
16
16
  args.push("--session-id", sessionId);
17
17
  if (model)
18
18
  args.push("--model", model);
19
+ if (reasoningEffort)
20
+ args.push("--effort", reasoningEffort);
19
21
  if (appendSystemPrompt)
20
22
  args.push("--append-system-prompt", appendSystemPrompt);
21
23
  args.push("--settings", settingsJson);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rynx-ai/runtime",
3
- "version": "0.1.11-beta.4",
3
+ "version": "0.1.11-beta.5",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/rynx-ai/rynx.git",
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "node-pty": "^1.0.0",
28
28
  "ws": "^8.21.0",
29
- "@rynx-ai/core": "0.1.11-beta.4"
29
+ "@rynx-ai/core": "0.1.11-beta.5"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/ws": "^8.18.1"