@co0ontty/wand 2.4.1 → 2.4.2
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/build-info.json +3 -3
- package/dist/config.d.ts +6 -1
- package/dist/config.js +24 -0
- package/dist/server-session-routes.js +5 -4
- package/dist/server.js +51 -8
- package/dist/structured-session-manager.d.ts +8 -3
- package/dist/structured-session-manager.js +326 -21
- package/dist/types.d.ts +3 -1
- package/dist/web-ui/content/scripts.js +34 -33
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/embedded-assets.d.ts +1 -1
- package/dist/web-ui/embedded-assets.js +3 -3
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commit": "
|
|
3
|
-
"builtAt": "2026-07-
|
|
4
|
-
"version": "2.4.
|
|
2
|
+
"commit": "618521bbe5e23601be39a6599b110d008f469b01",
|
|
3
|
+
"builtAt": "2026-07-04T11:34:01.260Z",
|
|
4
|
+
"version": "2.4.2",
|
|
5
5
|
"channel": "stable"
|
|
6
6
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { WandStorage } from "./storage.js";
|
|
|
7
7
|
* 升级路径:老 JSON 里仍存有这些字段时,首次启动会被搬到 DB(见 migrateLegacyPreferencesToDb),
|
|
8
8
|
* 然后下一次 saveConfig 写回 JSON 时它们会被剥离(见 stripPreferenceFields)。
|
|
9
9
|
*/
|
|
10
|
-
export declare const PREFERENCE_KEYS: readonly ["defaultMode", "defaultCwd", "defaultModel", "defaultThinkingEffort", "structuredRunner", "language", "cardDefaults", "inheritEnv"];
|
|
10
|
+
export declare const PREFERENCE_KEYS: readonly ["defaultMode", "defaultCwd", "defaultModel", "defaultCodexModel", "defaultThinkingEffort", "structuredRunner", "language", "cardDefaults", "inheritEnv"];
|
|
11
11
|
export type PreferenceKey = (typeof PREFERENCE_KEYS)[number];
|
|
12
12
|
export declare function isPreferenceKey(key: string): key is PreferenceKey;
|
|
13
13
|
export declare const defaultConfig: () => WandConfig;
|
|
@@ -40,4 +40,9 @@ export declare function applyStoragePreferences(config: WandConfig, storage: Wan
|
|
|
40
40
|
export declare function writePreferenceToStorage(config: WandConfig, storage: WandStorage, key: PreferenceKey, value: unknown): void;
|
|
41
41
|
export declare function normalizeCardDefaults(input: unknown): CardExpandDefaults;
|
|
42
42
|
export declare function isExecutionMode(value: unknown): value is ExecutionMode;
|
|
43
|
+
export declare function getProviderDefaultModels(config: Pick<WandConfig, "defaultModel" | "defaultCodexModel">): {
|
|
44
|
+
claude: string;
|
|
45
|
+
codex: string;
|
|
46
|
+
};
|
|
47
|
+
export declare function getDefaultModelForProvider(config: Pick<WandConfig, "defaultModel" | "defaultCodexModel">, provider: "claude" | "codex" | undefined): string;
|
|
43
48
|
export declare function normalizeMode(input: string | undefined, fallback: ExecutionMode): ExecutionMode;
|
package/dist/config.js
CHANGED
|
@@ -17,6 +17,7 @@ export const PREFERENCE_KEYS = [
|
|
|
17
17
|
"defaultMode",
|
|
18
18
|
"defaultCwd",
|
|
19
19
|
"defaultModel",
|
|
20
|
+
"defaultCodexModel",
|
|
20
21
|
"defaultThinkingEffort",
|
|
21
22
|
"structuredRunner",
|
|
22
23
|
"language",
|
|
@@ -51,6 +52,7 @@ export const defaultConfig = () => ({
|
|
|
51
52
|
macos: defaultMacosDmgConfig(),
|
|
52
53
|
cardDefaults: defaultCardExpandDefaults(),
|
|
53
54
|
defaultModel: "",
|
|
55
|
+
defaultCodexModel: "",
|
|
54
56
|
defaultThinkingEffort: "off",
|
|
55
57
|
structuredRunner: "cli",
|
|
56
58
|
inheritEnv: true,
|
|
@@ -250,6 +252,11 @@ export function applyStoragePreferences(config, storage) {
|
|
|
250
252
|
if (typeof v === "string")
|
|
251
253
|
config.defaultModel = v.trim();
|
|
252
254
|
}
|
|
255
|
+
if (storage.hasPreference(preferenceStorageKey("defaultCodexModel"))) {
|
|
256
|
+
const v = storage.getPreference(preferenceStorageKey("defaultCodexModel"), defaults.defaultCodexModel ?? "");
|
|
257
|
+
if (typeof v === "string")
|
|
258
|
+
config.defaultCodexModel = v.trim();
|
|
259
|
+
}
|
|
253
260
|
if (storage.hasPreference(preferenceStorageKey("defaultThinkingEffort"))) {
|
|
254
261
|
const v = storage.getPreference(preferenceStorageKey("defaultThinkingEffort"), defaults.defaultThinkingEffort ?? "off");
|
|
255
262
|
if (v === "off" || v === "standard" || v === "deep" || v === "max")
|
|
@@ -298,6 +305,12 @@ export function writePreferenceToStorage(config, storage, key, value) {
|
|
|
298
305
|
config.defaultModel = v;
|
|
299
306
|
break;
|
|
300
307
|
}
|
|
308
|
+
case "defaultCodexModel": {
|
|
309
|
+
const v = typeof value === "string" ? value.trim() : "";
|
|
310
|
+
storage.setPreference(dbKey, v);
|
|
311
|
+
config.defaultCodexModel = v;
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
301
314
|
case "defaultThinkingEffort": {
|
|
302
315
|
const v = value === "standard" || value === "deep" || value === "max" ? value : "off";
|
|
303
316
|
storage.setPreference(dbKey, v);
|
|
@@ -467,6 +480,7 @@ function mergeWithDefaults(input) {
|
|
|
467
480
|
macos: normalizeMacosDmgConfig(input.macos) ?? defaults.macos,
|
|
468
481
|
cardDefaults: normalizeCardDefaults(input.cardDefaults),
|
|
469
482
|
defaultModel: typeof input.defaultModel === "string" ? input.defaultModel.trim() : defaults.defaultModel,
|
|
483
|
+
defaultCodexModel: typeof input.defaultCodexModel === "string" ? input.defaultCodexModel.trim() : defaults.defaultCodexModel,
|
|
470
484
|
defaultThinkingEffort: input.defaultThinkingEffort === "standard"
|
|
471
485
|
|| input.defaultThinkingEffort === "deep"
|
|
472
486
|
|| input.defaultThinkingEffort === "max"
|
|
@@ -479,6 +493,16 @@ function mergeWithDefaults(input) {
|
|
|
479
493
|
export function isExecutionMode(value) {
|
|
480
494
|
return value === "assist" || value === "agent" || value === "agent-max" || value === "auto-edit" || value === "default" || value === "full-access" || value === "native" || value === "managed";
|
|
481
495
|
}
|
|
496
|
+
export function getProviderDefaultModels(config) {
|
|
497
|
+
return {
|
|
498
|
+
claude: (config.defaultModel ?? "").trim(),
|
|
499
|
+
codex: (config.defaultCodexModel ?? "").trim(),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
export function getDefaultModelForProvider(config, provider) {
|
|
503
|
+
const defaults = getProviderDefaultModels(config);
|
|
504
|
+
return provider === "codex" ? defaults.codex : defaults.claude;
|
|
505
|
+
}
|
|
482
506
|
export function normalizeMode(input, fallback) {
|
|
483
507
|
return isExecutionMode(input) ? input : fallback;
|
|
484
508
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import express from "express";
|
|
2
2
|
import { SessionInputError } from "./process-manager.js";
|
|
3
|
-
import { normalizeMode } from "./config.js";
|
|
3
|
+
import { getDefaultModelForProvider, normalizeMode } from "./config.js";
|
|
4
4
|
import { blockWindowMessagesForTransport, sliceTurnBlocksForTransport, truncateMessagesForTransport, windowMessagesForTransport } from "./message-truncator.js";
|
|
5
5
|
import { checkSessionWorktreeMergeability, cleanupSessionWorktree, getWorktreeMergeErrorCode, mergeSessionWorktree, WorktreeMergeError } from "./git-worktree.js";
|
|
6
6
|
import { resolveSessionCwd } from "./session-cwd.js";
|
|
@@ -221,13 +221,14 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
221
221
|
return;
|
|
222
222
|
}
|
|
223
223
|
const provider = body.provider === "codex" ? "codex" : "claude";
|
|
224
|
+
const rawModel = typeof body.model === "string" ? body.model.trim() : "";
|
|
224
225
|
const snapshot = structured.createSession({
|
|
225
226
|
cwd: resolveSessionCwd(body.cwd, config.defaultCwd),
|
|
226
227
|
mode: normalizeMode(body.mode, defaultMode),
|
|
227
228
|
provider,
|
|
228
229
|
runner: body.runner ?? (provider === "codex" ? "codex-cli-exec" : "claude-cli-print"),
|
|
229
230
|
worktreeEnabled: body.worktreeEnabled === true,
|
|
230
|
-
model:
|
|
231
|
+
model: rawModel || getDefaultModelForProvider(config, provider) || undefined,
|
|
231
232
|
thinkingEffort: typeof body.thinkingEffort === "string"
|
|
232
233
|
? body.thinkingEffort
|
|
233
234
|
: config.defaultThinkingEffort,
|
|
@@ -540,7 +541,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
540
541
|
cwd: snapshot.cwd,
|
|
541
542
|
language: config.language ?? "",
|
|
542
543
|
provider: snapshot.provider,
|
|
543
|
-
model: snapshot.selectedModel ?? snapshot.structuredState?.model ?? config.
|
|
544
|
+
model: snapshot.selectedModel ?? snapshot.structuredState?.model ?? getDefaultModelForProvider(config, snapshot.provider),
|
|
544
545
|
thinkingEffort: snapshot.thinkingEffort ?? config.defaultThinkingEffort,
|
|
545
546
|
inheritEnv: config.inheritEnv,
|
|
546
547
|
autoMessage: body.autoMessage !== false,
|
|
@@ -574,7 +575,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
574
575
|
try {
|
|
575
576
|
const result = await generateCommitMessageOnly(snapshot.cwd, config.language ?? "", {
|
|
576
577
|
provider: snapshot.provider,
|
|
577
|
-
model: snapshot.selectedModel ?? snapshot.structuredState?.model ?? config.
|
|
578
|
+
model: snapshot.selectedModel ?? snapshot.structuredState?.model ?? getDefaultModelForProvider(config, snapshot.provider),
|
|
578
579
|
thinkingEffort: snapshot.thinkingEffort ?? config.defaultThinkingEffort,
|
|
579
580
|
inheritEnv: config.inheritEnv,
|
|
580
581
|
});
|
package/dist/server.js
CHANGED
|
@@ -15,7 +15,7 @@ import { WebSocketServer } from "ws";
|
|
|
15
15
|
import { createSession, readSessionCookie, revokeSession, SESSION_COOKIE_HTTP, SESSION_COOKIE_HTTPS, SESSION_COOKIE_LEGACY, setAuthStorage, validateSession, } from "./auth.js";
|
|
16
16
|
import { ensureCertificates } from "./cert.js";
|
|
17
17
|
import { buildChildEnv } from "./env-utils.js";
|
|
18
|
-
import { isExecutionMode, normalizeMode, PREFERENCE_KEYS, resolveConfigDir, saveConfig, writePreferenceToStorage, } from "./config.js";
|
|
18
|
+
import { getDefaultModelForProvider, getProviderDefaultModels, isExecutionMode, normalizeMode, PREFERENCE_KEYS, resolveConfigDir, saveConfig, writePreferenceToStorage, } from "./config.js";
|
|
19
19
|
import { getCachedModels, refreshModels } from "./models.js";
|
|
20
20
|
import { ProcessManager } from "./process-manager.js";
|
|
21
21
|
import { SessionLogger } from "./session-logger.js";
|
|
@@ -1305,12 +1305,15 @@ export async function startServer(config, configPath) {
|
|
|
1305
1305
|
// ── Config & Session info ──
|
|
1306
1306
|
app.get("/api/config", async (_req, res) => {
|
|
1307
1307
|
const structuredChatPersona = await buildStructuredChatPersonaPayload(configPath, config);
|
|
1308
|
+
const defaultModels = getProviderDefaultModels(config);
|
|
1308
1309
|
res.json({
|
|
1309
1310
|
host: config.host,
|
|
1310
1311
|
port: config.port,
|
|
1311
1312
|
defaultMode: config.defaultMode,
|
|
1312
1313
|
defaultCwd: config.defaultCwd,
|
|
1313
|
-
defaultModel:
|
|
1314
|
+
defaultModel: defaultModels.claude,
|
|
1315
|
+
defaultCodexModel: defaultModels.codex,
|
|
1316
|
+
defaultModels,
|
|
1314
1317
|
defaultThinkingEffort: config.defaultThinkingEffort ?? "off",
|
|
1315
1318
|
commandPresets: config.commandPresets,
|
|
1316
1319
|
structuredRunner: config.structuredRunner ?? "cli",
|
|
@@ -1449,6 +1452,7 @@ export async function startServer(config, configPath) {
|
|
|
1449
1452
|
certPath: path.join(configDir, "server.crt"),
|
|
1450
1453
|
};
|
|
1451
1454
|
const { password: _pw, ...safeConfig } = config;
|
|
1455
|
+
const defaultModels = getProviderDefaultModels(config);
|
|
1452
1456
|
const localApk = await resolveAndroidApkAsset(configDir, config);
|
|
1453
1457
|
const ghApk = await fetchGitHubLatestApk();
|
|
1454
1458
|
const apkDir = resolveAndroidApkDir(configDir, config);
|
|
@@ -1471,7 +1475,12 @@ export async function startServer(config, configPath) {
|
|
|
1471
1475
|
packageName: PKG_NAME,
|
|
1472
1476
|
nodeVersion: PKG_NODE_REQ,
|
|
1473
1477
|
repoUrl: PKG_REPO_URL,
|
|
1474
|
-
config:
|
|
1478
|
+
config: {
|
|
1479
|
+
...safeConfig,
|
|
1480
|
+
defaultModel: defaultModels.claude,
|
|
1481
|
+
defaultCodexModel: defaultModels.codex,
|
|
1482
|
+
defaultModels,
|
|
1483
|
+
},
|
|
1475
1484
|
hasCert: existsSync(certPaths.keyPath) && existsSync(certPaths.certPath),
|
|
1476
1485
|
updateAvailable: cachedUpdateInfo?.updateAvailable ?? false,
|
|
1477
1486
|
latestVersion: cachedUpdateInfo?.latest ?? null,
|
|
@@ -1645,6 +1654,23 @@ export async function startServer(config, configPath) {
|
|
|
1645
1654
|
res.status(400).json({ error: `无效执行模式: ${body.defaultMode}` });
|
|
1646
1655
|
return;
|
|
1647
1656
|
}
|
|
1657
|
+
if (body.defaultModels && typeof body.defaultModels === "object") {
|
|
1658
|
+
const modelDefaults = body.defaultModels;
|
|
1659
|
+
try {
|
|
1660
|
+
if (Object.prototype.hasOwnProperty.call(modelDefaults, "claude")) {
|
|
1661
|
+
writePreferenceToStorage(config, storage, "defaultModel", modelDefaults.claude);
|
|
1662
|
+
touchedPreferenceField = true;
|
|
1663
|
+
}
|
|
1664
|
+
if (Object.prototype.hasOwnProperty.call(modelDefaults, "codex")) {
|
|
1665
|
+
writePreferenceToStorage(config, storage, "defaultCodexModel", modelDefaults.codex);
|
|
1666
|
+
touchedPreferenceField = true;
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
catch (err) {
|
|
1670
|
+
res.status(400).json({ error: getErrorMessage(err, "默认模型配置校验失败") });
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1648
1674
|
for (const field of PREFERENCE_KEYS) {
|
|
1649
1675
|
if (!(field in body) || body[field] === undefined)
|
|
1650
1676
|
continue;
|
|
@@ -1666,8 +1692,18 @@ export async function startServer(config, configPath) {
|
|
|
1666
1692
|
await saveConfig(configPath, config);
|
|
1667
1693
|
}
|
|
1668
1694
|
const { password: _pw, ...safeConfig } = config;
|
|
1695
|
+
const defaultModels = getProviderDefaultModels(config);
|
|
1669
1696
|
// 只有部署字段才需要重启;偏好字段已经热生效。
|
|
1670
|
-
res.json({
|
|
1697
|
+
res.json({
|
|
1698
|
+
ok: true,
|
|
1699
|
+
config: {
|
|
1700
|
+
...safeConfig,
|
|
1701
|
+
defaultModel: defaultModels.claude,
|
|
1702
|
+
defaultCodexModel: defaultModels.codex,
|
|
1703
|
+
defaultModels,
|
|
1704
|
+
},
|
|
1705
|
+
restartRequired: touchedDeployField,
|
|
1706
|
+
});
|
|
1671
1707
|
}
|
|
1672
1708
|
catch (error) {
|
|
1673
1709
|
res.status(500).json({ error: getErrorMessage(error, "保存配置失败。") });
|
|
@@ -1675,23 +1711,29 @@ export async function startServer(config, configPath) {
|
|
|
1675
1711
|
});
|
|
1676
1712
|
app.get("/api/models", (_req, res) => {
|
|
1677
1713
|
const cached = getCachedModels();
|
|
1714
|
+
const defaultModels = getProviderDefaultModels(config);
|
|
1678
1715
|
res.json({
|
|
1679
1716
|
models: cached.models,
|
|
1680
1717
|
codexModels: cached.codexModels,
|
|
1681
1718
|
claudeVersion: cached.claudeVersion,
|
|
1682
1719
|
refreshedAt: cached.refreshedAt,
|
|
1683
|
-
defaultModel:
|
|
1720
|
+
defaultModel: defaultModels.claude,
|
|
1721
|
+
defaultCodexModel: defaultModels.codex,
|
|
1722
|
+
defaultModels,
|
|
1684
1723
|
});
|
|
1685
1724
|
});
|
|
1686
1725
|
app.post("/api/models/refresh", async (_req, res) => {
|
|
1687
1726
|
try {
|
|
1688
1727
|
const refreshed = await refreshModels();
|
|
1728
|
+
const defaultModels = getProviderDefaultModels(config);
|
|
1689
1729
|
res.json({
|
|
1690
1730
|
models: refreshed.models,
|
|
1691
1731
|
codexModels: refreshed.codexModels,
|
|
1692
1732
|
claudeVersion: refreshed.claudeVersion,
|
|
1693
1733
|
refreshedAt: refreshed.refreshedAt,
|
|
1694
|
-
defaultModel:
|
|
1734
|
+
defaultModel: defaultModels.claude,
|
|
1735
|
+
defaultCodexModel: defaultModels.codex,
|
|
1736
|
+
defaultModels,
|
|
1695
1737
|
});
|
|
1696
1738
|
}
|
|
1697
1739
|
catch (error) {
|
|
@@ -2263,12 +2305,13 @@ export async function startServer(config, configPath) {
|
|
|
2263
2305
|
const initialInput = body.initialInput?.trim();
|
|
2264
2306
|
try {
|
|
2265
2307
|
const rawModel = typeof body.model === "string" ? body.model.trim() : "";
|
|
2266
|
-
const
|
|
2308
|
+
const provider = body.provider === "codex" || /^codex\b/.test(body.command.trim()) ? "codex" : "claude";
|
|
2309
|
+
const effectiveModel = rawModel || getDefaultModelForProvider(config, provider) || undefined;
|
|
2267
2310
|
const reqCols = typeof body.cols === "number" && Number.isFinite(body.cols) ? body.cols : undefined;
|
|
2268
2311
|
const reqRows = typeof body.rows === "number" && Number.isFinite(body.rows) ? body.rows : undefined;
|
|
2269
2312
|
const snapshot = processes.start(body.command, body.cwd, normalizeMode(body.mode, config.defaultMode), initialInput || undefined, {
|
|
2270
2313
|
worktreeEnabled: body.worktreeEnabled === true,
|
|
2271
|
-
provider
|
|
2314
|
+
provider,
|
|
2272
2315
|
model: effectiveModel,
|
|
2273
2316
|
cols: reqCols,
|
|
2274
2317
|
rows: reqRows,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SessionLogger } from "./session-logger.js";
|
|
2
2
|
import { WandStorage } from "./storage.js";
|
|
3
|
-
import { ExecutionMode, ProcessEvent, SessionProvider, SessionRunner, SessionSnapshot, WandConfig } from "./types.js";
|
|
3
|
+
import { ContentBlock, ExecutionMode, ProcessEvent, SessionProvider, SessionRunner, SessionSnapshot, WandConfig } from "./types.js";
|
|
4
4
|
interface CreateStructuredSessionOptions {
|
|
5
5
|
cwd: string;
|
|
6
6
|
mode: ExecutionMode;
|
|
@@ -8,7 +8,7 @@ interface CreateStructuredSessionOptions {
|
|
|
8
8
|
provider?: SessionProvider;
|
|
9
9
|
runner?: SessionRunner;
|
|
10
10
|
worktreeEnabled?: boolean;
|
|
11
|
-
/**
|
|
11
|
+
/** 用户指定的模型(别名或完整 ID)。留空则 spawn 时不加 --model。 */
|
|
12
12
|
model?: string;
|
|
13
13
|
/** 用户预设的思考深度。留空 / null 视为 off。 */
|
|
14
14
|
thinkingEffort?: SessionSnapshot["thinkingEffort"];
|
|
@@ -31,8 +31,9 @@ export declare function thinkingEffortToSdkBudget(effort: SessionSnapshot["think
|
|
|
31
31
|
export declare function thinkingEffortToClaudeCliEffort(effort: SessionSnapshot["thinkingEffort"]): string | null;
|
|
32
32
|
/** Claude PTY slash-command 用:off 表示恢复模型默认 effort。 */
|
|
33
33
|
export declare function thinkingEffortToClaudeSlashEffort(effort: SessionSnapshot["thinkingEffort"]): string;
|
|
34
|
-
/** Codex CLI 用:把 thinkingEffort 映射到 model_reasoning_effort 配置。off →
|
|
34
|
+
/** Codex CLI 用:把 thinkingEffort 映射到 model_reasoning_effort 配置。off → 不覆盖 Codex 默认。 */
|
|
35
35
|
export declare function thinkingEffortToCodexReasoningEffort(effort: SessionSnapshot["thinkingEffort"]): string | null;
|
|
36
|
+
export declare function buildCodexPatchApplyBlocks(item: Record<string, unknown>): ContentBlock[];
|
|
36
37
|
export declare class StructuredSessionManager {
|
|
37
38
|
private readonly storage;
|
|
38
39
|
private readonly config;
|
|
@@ -173,6 +174,10 @@ export declare class StructuredSessionManager {
|
|
|
173
174
|
private resolveQueuedMessagesAfterInterrupt;
|
|
174
175
|
private normalizeToolInput;
|
|
175
176
|
private normalizeToolResultContent;
|
|
177
|
+
private unwrapCodexStreamEvent;
|
|
178
|
+
private applyCodexLooseEvent;
|
|
179
|
+
private codexFunctionToolUse;
|
|
180
|
+
private codexMcpToolBlocks;
|
|
176
181
|
private extractCodexText;
|
|
177
182
|
/**
|
|
178
183
|
* Merge one codex `item.*` event into `turnState.blocks`.
|