@co0ontty/wand 2.7.0 → 2.8.0

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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "commit": "fe6482dc2c6a1a02fbe00800836b78af034d851a",
3
- "builtAt": "2026-07-11T12:18:50.530Z",
4
- "version": "2.7.0",
2
+ "commit": "18413d7915a788ea6eb7460e0819c2df102a17d2",
3
+ "builtAt": "2026-07-11T13:15:01.244Z",
4
+ "version": "2.8.0",
5
5
  "channel": "stable"
6
6
  }
package/dist/config.js CHANGED
@@ -4,6 +4,13 @@ import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import process from "node:process";
6
6
  import { isRunningAsRoot } from "./env-utils.js";
7
+ function isThinkingEffort(value) {
8
+ return value === "off"
9
+ || value === "standard"
10
+ || value === "deep"
11
+ || value === "max"
12
+ || (typeof value === "string" && /^codex:[a-z0-9][a-z0-9_-]{0,31}$/.test(value));
13
+ }
7
14
  const DEFAULT_CONFIG_DIR = ".wand";
8
15
  const DEFAULT_CONFIG_FILE = "config.json";
9
16
  /**
@@ -273,7 +280,7 @@ export function applyStoragePreferences(config, storage) {
273
280
  }
274
281
  if (storage.hasPreference(preferenceStorageKey("defaultThinkingEffort"))) {
275
282
  const v = storage.getPreference(preferenceStorageKey("defaultThinkingEffort"), defaults.defaultThinkingEffort ?? "off");
276
- if (v === "off" || v === "standard" || v === "deep" || v === "max")
283
+ if (isThinkingEffort(v))
277
284
  config.defaultThinkingEffort = v;
278
285
  }
279
286
  if (storage.hasPreference(preferenceStorageKey("structuredRunner"))) {
@@ -339,7 +346,7 @@ export function writePreferenceToStorage(config, storage, key, value) {
339
346
  break;
340
347
  }
341
348
  case "defaultThinkingEffort": {
342
- const v = value === "standard" || value === "deep" || value === "max" ? value : "off";
349
+ const v = isThinkingEffort(value) ? value : "off";
343
350
  storage.setPreference(dbKey, v);
344
351
  config.defaultThinkingEffort = v;
345
352
  break;
@@ -510,11 +517,7 @@ function mergeWithDefaults(input) {
510
517
  defaultCodexModel: typeof input.defaultCodexModel === "string" ? input.defaultCodexModel.trim() : defaults.defaultCodexModel,
511
518
  commitCli: input.commitCli === "codex" ? "codex" : "claude",
512
519
  commitModel: typeof input.commitModel === "string" ? input.commitModel.trim() : defaults.commitModel,
513
- defaultThinkingEffort: input.defaultThinkingEffort === "standard"
514
- || input.defaultThinkingEffort === "deep"
515
- || input.defaultThinkingEffort === "max"
516
- ? input.defaultThinkingEffort
517
- : "off",
520
+ defaultThinkingEffort: isThinkingEffort(input.defaultThinkingEffort) ? input.defaultThinkingEffort : "off",
518
521
  structuredRunner: (input.structuredRunner === "sdk" || input.structuredRunner === "cli") ? input.structuredRunner : defaults.structuredRunner,
519
522
  inheritEnv: typeof input.inheritEnv === "boolean" ? input.inheritEnv : (defaults.inheritEnv ?? true),
520
523
  };
package/dist/models.d.ts CHANGED
@@ -5,6 +5,8 @@ interface ModelCache {
5
5
  claudeVersion: string | null;
6
6
  refreshedAt: string;
7
7
  }
8
+ /** Parse the machine-readable model registry emitted by the installed Codex CLI. */
9
+ export declare function parseCodexModels(stdout: string): ClaudeModelInfo[];
8
10
  export declare function getCachedModels(): ModelCache;
9
11
  export declare function refreshModels(): Promise<ModelCache>;
10
12
  export {};
package/dist/models.js CHANGED
@@ -31,8 +31,18 @@ async function probeClaudeVersion() {
31
31
  async function probeCodexModels() {
32
32
  try {
33
33
  const { stdout } = await execAsync("codex debug models", { timeout: 8000 });
34
+ return parseCodexModels(stdout);
35
+ }
36
+ catch {
37
+ return CODEX_FALLBACK_MODELS.map((m) => ({ ...m }));
38
+ }
39
+ }
40
+ /** Parse the machine-readable model registry emitted by the installed Codex CLI. */
41
+ export function parseCodexModels(stdout) {
42
+ try {
34
43
  const data = JSON.parse(stdout);
35
- const visible = data.models
44
+ const visible = (Array.isArray(data.models) ? data.models : [])
45
+ .filter((m) => typeof m.slug === "string" && m.slug.length > 0)
36
46
  .filter((m) => m.visibility === "list")
37
47
  .sort((a, b) => (a.priority ?? 99) - (b.priority ?? 99));
38
48
  if (!visible.length)
@@ -40,12 +50,18 @@ async function probeCodexModels() {
40
50
  const defaultModel = visible[0];
41
51
  const defaultLabel = formatCodexModelLabel(defaultModel);
42
52
  const result = [
43
- { id: "default", label: `${defaultLabel}(Codex 默认)`, alias: true },
53
+ {
54
+ id: "default",
55
+ label: `${defaultLabel}(Codex 默认)`,
56
+ alias: true,
57
+ ...codexReasoningMetadata(defaultModel),
58
+ },
44
59
  ];
45
60
  for (const m of visible) {
46
61
  result.push({
47
62
  id: m.slug,
48
63
  label: formatCodexModelLabel(m),
64
+ ...codexReasoningMetadata(m),
49
65
  });
50
66
  }
51
67
  return result;
@@ -54,6 +70,20 @@ async function probeCodexModels() {
54
70
  return CODEX_FALLBACK_MODELS.map((m) => ({ ...m }));
55
71
  }
56
72
  }
73
+ function codexReasoningMetadata(model) {
74
+ const reasoningEfforts = (Array.isArray(model.supported_reasoning_levels) ? model.supported_reasoning_levels : [])
75
+ .filter((level) => typeof level?.effort === "string" && level.effort.length > 0)
76
+ .map((level) => ({
77
+ effort: level.effort,
78
+ ...(typeof level.description === "string" && level.description ? { description: level.description } : {}),
79
+ }));
80
+ return {
81
+ ...(reasoningEfforts.length ? { reasoningEfforts } : {}),
82
+ ...(typeof model.default_reasoning_level === "string" && model.default_reasoning_level
83
+ ? { defaultReasoningEffort: model.default_reasoning_level }
84
+ : {}),
85
+ };
86
+ }
57
87
  function formatCodexModelLabel(model) {
58
88
  return model.display_name && model.display_name !== model.slug
59
89
  ? `${model.display_name} · ${model.slug}`
@@ -14,7 +14,7 @@ import { ensureNodePtyHelperExecutable } from "./ensure-node-pty-helper.js";
14
14
  import { buildLanguageDirective, buildManagedAutonomyDirective } from "./language-prompt.js";
15
15
  import { prepareSessionWorktree } from "./git-worktree.js";
16
16
  import { getCodexResumeCommandSessionId, getResumeCommandSessionId } from "./resume-policy.js";
17
- import { normalizeThinkingEffort, thinkingEffortToClaudeCliEffort, thinkingEffortToClaudeSlashEffort } from "./structured-session-manager.js";
17
+ import { normalizeThinkingEffort, thinkingEffortToClaudeCliEffort, thinkingEffortToClaudeSlashEffort, thinkingEffortToCodexReasoningEffort } from "./structured-session-manager.js";
18
18
  import { generateSessionTopic } from "./session-topic.js";
19
19
  import { getErrorMessage } from "./error-utils.js";
20
20
  import { resolveSessionCwd } from "./session-cwd.js";
@@ -2118,6 +2118,10 @@ export class ProcessManager extends EventEmitter {
2118
2118
  const escapedModel = trimmedModel.replace(/'/g, "'\\''");
2119
2119
  result += ` --model '${escapedModel}'`;
2120
2120
  }
2121
+ const reasoningEffort = thinkingEffortToCodexReasoningEffort(thinkingEffort ?? null);
2122
+ if (reasoningEffort && !/model_reasoning_effort\s*=/.test(command)) {
2123
+ result += ` -c 'model_reasoning_effort="${reasoningEffort}"'`;
2124
+ }
2121
2125
  if (mode === "full-access") {
2122
2126
  if (!/--dangerously-bypass-approvals-and-sandbox(?:\s|$)/.test(result)) {
2123
2127
  result += " --dangerously-bypass-approvals-and-sandbox";
@@ -34,6 +34,8 @@ export function normalizeThinkingEffort(value) {
34
34
  const v = value.trim().toLowerCase();
35
35
  if (v === "off" || v === "standard" || v === "deep" || v === "max")
36
36
  return v;
37
+ if (/^codex:[a-z0-9][a-z0-9_-]{0,31}$/.test(v))
38
+ return v;
37
39
  return null;
38
40
  }
39
41
  /** Claude SDK 用:把 thinkingEffort 映射成 `thinking.budget_tokens`。off / 空 → 0(不启用)。 */
@@ -62,6 +64,9 @@ export function thinkingEffortToClaudeSlashEffort(effort) {
62
64
  }
63
65
  /** Codex CLI 用:把 thinkingEffort 映射到 model_reasoning_effort 配置。off → 不覆盖 Codex 默认。 */
64
66
  export function thinkingEffortToCodexReasoningEffort(effort) {
67
+ if (typeof effort === "string" && effort.startsWith("codex:")) {
68
+ return effort.slice("codex:".length) || null;
69
+ }
65
70
  switch (effort) {
66
71
  case "standard": return "low";
67
72
  case "deep": return "medium";
package/dist/types.d.ts CHANGED
@@ -109,7 +109,7 @@ export interface WandConfig {
109
109
  /** 快捷提交专用模型。留空则跟随所选 CLI 的默认模型。 */
110
110
  commitModel?: string;
111
111
  /** 新建会话时默认使用的思考深度。 */
112
- defaultThinkingEffort?: "off" | "standard" | "deep" | "max";
112
+ defaultThinkingEffort?: ThinkingEffort;
113
113
  /** 结构化会话使用的 runner: "cli"(默认,spawn claude -p)或 "sdk"(@anthropic-ai/claude-agent-sdk)。 */
114
114
  structuredRunner?: "cli" | "sdk";
115
115
  /**
@@ -128,7 +128,20 @@ export interface ClaudeModelInfo {
128
128
  note?: string;
129
129
  /** 是否为别名(opus/sonnet 等);完整 ID 为 false */
130
130
  alias?: boolean;
131
+ /** Codex 模型声明的可用推理档位;Claude 模型通常不提供。 */
132
+ reasoningEfforts?: ReasoningEffortInfo[];
133
+ /** Codex 模型的默认推理档位。 */
134
+ defaultReasoningEffort?: string;
131
135
  }
136
+ export interface ReasoningEffortInfo {
137
+ effort: string;
138
+ description?: string;
139
+ }
140
+ /**
141
+ * 旧的四档值需要继续兼容已有会话。Codex 动态档位加 provider 前缀,
142
+ * 避免 `max`(旧值代表 xhigh)与 Codex 新增的原生 max 档位冲突。
143
+ */
144
+ export type ThinkingEffort = "off" | "standard" | "deep" | "max" | `codex:${string}`;
132
145
  interface WorktreeInfo {
133
146
  branch: string;
134
147
  path: string;
@@ -257,7 +270,7 @@ export interface CommandRequest {
257
270
  /** 创建会话时由前端测得的真实行数。 */
258
271
  rows?: number;
259
272
  /** 思考深度。null/缺省 视为 off(不启用思考)。 */
260
- thinkingEffort?: "off" | "standard" | "deep" | "max" | null;
273
+ thinkingEffort?: ThinkingEffort | null;
261
274
  }
262
275
  export interface InputRequest {
263
276
  input?: string;
@@ -446,12 +459,13 @@ export interface SessionSnapshot {
446
459
  selectedModel?: string | null;
447
460
  /**
448
461
  * 用户选定的思考深度。
449
- * - off: 不覆盖默认思考深度(SDK: 不传 thinking;Claude CLI: auto/default;Codex: model_reasoning_effort minimal)
462
+ * - off: 不覆盖默认思考深度(SDK: 不传 thinking;Claude CLI: auto/default;Codex: 使用模型默认值)
450
463
  * - standard: 标准(SDK: budget 4096;Claude CLI: low;Codex: low)
451
464
  * - deep: 深度(SDK: budget 16000;Claude CLI: medium;Codex: medium)
452
- * - max: 最深(SDK: budget 31999;Claude CLI: max;Codex: xhigh)
465
+ * - max: 旧版最深档(SDK: budget 31999;Claude CLI: max;Codex: xhigh)
466
+ * - codex:*: Codex CLI 动态声明的原生推理档位
453
467
  */
454
- thinkingEffort?: "off" | "standard" | "deep" | "max" | null;
468
+ thinkingEffort?: ThinkingEffort | null;
455
469
  /** 当前 PTY 列宽,由最近一次 resize 决定。前端用它来判断本端 fit 是否需要校准。 */
456
470
  ptyCols?: number;
457
471
  /** 当前 PTY 行数,由最近一次 resize 决定。 */