@co0ontty/wand 1.49.4 → 1.49.5-beta.gde4fdad
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 +4 -4
- package/dist/claude-sdk-runner.js +2 -1
- package/dist/cli.js +2 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +3 -0
- package/dist/ensure-node-pty-helper.js +2 -1
- package/dist/error-utils.d.ts +1 -0
- package/dist/error-utils.js +5 -0
- package/dist/git-quick-commit.js +4 -23
- package/dist/git-utils.d.ts +7 -0
- package/dist/git-utils.js +27 -0
- package/dist/git-worktree.js +3 -19
- package/dist/npm-update-utils.js +8 -7
- package/dist/path-repair.js +2 -1
- package/dist/server-session-routes.d.ts +2 -1
- package/dist/server-session-routes.js +3 -6
- package/dist/server.js +2 -5
- package/dist/service-self-repair.js +2 -1
- package/dist/structured-session-manager.js +3 -2
- package/dist/tui/commands.js +7 -9
- package/dist/tui/ipc-server.js +2 -1
- package/dist/tui/layout.js +1 -4
- package/dist/web-ui/content/scripts.js +30 -30
- package/dist/web-ui/embedded-assets.d.ts +1 -1
- package/dist/web-ui/embedded-assets.js +2 -2
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commit": "
|
|
3
|
-
"builtAt": "2026-06-
|
|
4
|
-
"version": "1.49.
|
|
5
|
-
"channel": "
|
|
2
|
+
"commit": "de4fdad0b45e360901ec2051fcc72101512a5622",
|
|
3
|
+
"builtAt": "2026-06-05T04:16:52.249Z",
|
|
4
|
+
"version": "1.49.5-beta.gde4fdad",
|
|
5
|
+
"channel": "beta"
|
|
6
6
|
}
|
|
@@ -2,6 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { query as sdkQuery, } from "@anthropic-ai/claude-agent-sdk";
|
|
4
4
|
import { buildLanguageDirective } from "./language-prompt.js";
|
|
5
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
5
6
|
export class ClaudeRunError extends Error {
|
|
6
7
|
code;
|
|
7
8
|
constructor(message, code) {
|
|
@@ -125,7 +126,7 @@ export async function runClaudePrint(prompt, options) {
|
|
|
125
126
|
if (abortController.signal.aborted) {
|
|
126
127
|
throw new ClaudeRunError("Claude 调用超时。", "CLAUDE_TIMEOUT");
|
|
127
128
|
}
|
|
128
|
-
const message =
|
|
129
|
+
const message = getErrorMessage(err);
|
|
129
130
|
// SDK 找不到 native binary 时会抛 "Claude Code native binary not found"。
|
|
130
131
|
// 极少数情况下也可能透出 ENOENT。两种都归到"CLI_MISSING",文案给用户。
|
|
131
132
|
if (/Claude Code native binary not found|ENOENT/i.test(message)) {
|
package/dist/cli.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import { hasConfigFile, isPreferenceKey, loadConfigWithStorage, resolveConfigPath, saveConfig, writePreferenceToStorage, } from "./config.js";
|
|
4
4
|
import { readLiveInstance, removePidfile, removeSocketFile, socketPath, writePidfile, } from "./pidfile.js";
|
|
5
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
5
6
|
async function main() {
|
|
6
7
|
const args = process.argv.slice(2);
|
|
7
8
|
const command = args[0] || "help";
|
|
@@ -446,6 +447,6 @@ function printServiceResult(result, verbose) {
|
|
|
446
447
|
}
|
|
447
448
|
}
|
|
448
449
|
main().catch((error) => {
|
|
449
|
-
process.stderr.write(`[wand] ${
|
|
450
|
+
process.stderr.write(`[wand] ${getErrorMessage(error)}\n`);
|
|
450
451
|
process.exitCode = 1;
|
|
451
452
|
});
|
package/dist/config.d.ts
CHANGED
|
@@ -41,3 +41,4 @@ export declare function applyStoragePreferences(config: WandConfig, storage: Wan
|
|
|
41
41
|
export declare function writePreferenceToStorage(config: WandConfig, storage: WandStorage, key: PreferenceKey, value: unknown): void;
|
|
42
42
|
export declare function normalizeCardDefaults(input: unknown): CardExpandDefaults;
|
|
43
43
|
export declare function isExecutionMode(value: unknown): value is ExecutionMode;
|
|
44
|
+
export declare function normalizeMode(input: string | undefined, fallback: ExecutionMode): ExecutionMode;
|
package/dist/config.js
CHANGED
|
@@ -474,6 +474,9 @@ function mergeWithDefaults(input) {
|
|
|
474
474
|
export function isExecutionMode(value) {
|
|
475
475
|
return value === "assist" || value === "agent" || value === "agent-max" || value === "auto-edit" || value === "default" || value === "full-access" || value === "native" || value === "managed";
|
|
476
476
|
}
|
|
477
|
+
export function normalizeMode(input, fallback) {
|
|
478
|
+
return isExecutionMode(input) ? input : fallback;
|
|
479
|
+
}
|
|
477
480
|
function normalizePresetCommand(command) {
|
|
478
481
|
const trimmed = command.trim();
|
|
479
482
|
if (trimmed === "cloud-code" || trimmed === "cloudcode" || trimmed === "claude code") {
|
|
@@ -12,6 +12,7 @@ import { chmodSync, existsSync, statSync } from "node:fs";
|
|
|
12
12
|
import { createRequire } from "node:module";
|
|
13
13
|
import path from "node:path";
|
|
14
14
|
import process from "node:process";
|
|
15
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
15
16
|
const requireFromHere = createRequire(import.meta.url);
|
|
16
17
|
export function ensureNodePtyHelperExecutable() {
|
|
17
18
|
// spawn-helper is only used on Unix-likes. Windows uses winpty / conpty.
|
|
@@ -45,7 +46,7 @@ export function ensureNodePtyHelperExecutable() {
|
|
|
45
46
|
process.stderr.write(`[wand] Restored +x on ${helper} (npm dropped the bit on install)\n`);
|
|
46
47
|
}
|
|
47
48
|
catch (err) {
|
|
48
|
-
process.stderr.write(`[wand] Warning: could not chmod +x ${helper}: ${
|
|
49
|
+
process.stderr.write(`[wand] Warning: could not chmod +x ${helper}: ${getErrorMessage(err)}\n`
|
|
49
50
|
+ `[wand] PTY sessions may fail to start. Run: chmod +x ${JSON.stringify(helper)}\n`);
|
|
50
51
|
}
|
|
51
52
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getErrorMessage(err: unknown, fallback?: string): string;
|
package/dist/git-quick-commit.js
CHANGED
|
@@ -1,36 +1,17 @@
|
|
|
1
|
-
import { execFileSync } from "node:child_process";
|
|
2
1
|
import { existsSync } from "node:fs";
|
|
3
2
|
import { ClaudeRunError, runClaudePrint } from "./claude-sdk-runner.js";
|
|
3
|
+
import { runGit as runGitBase, runGitRaw as runGitRawBase, getGitErrorMessage } from "./git-utils.js";
|
|
4
4
|
const GIT_TIMEOUT_MS = 1500;
|
|
5
5
|
const GIT_PUSH_TIMEOUT_MS = 30_000;
|
|
6
6
|
const MAX_FILE_ENTRIES = 200;
|
|
7
7
|
const CLAUDE_MESSAGE_TIMEOUT_MS = 30_000;
|
|
8
8
|
const MAX_DIFF_FOR_AI = 100_000;
|
|
9
|
+
const GIT_MAX_BUFFER = 16 * 1024 * 1024;
|
|
9
10
|
function runGit(args, cwd, timeoutMs = GIT_TIMEOUT_MS) {
|
|
10
|
-
return
|
|
11
|
-
cwd,
|
|
12
|
-
encoding: "utf8",
|
|
13
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
14
|
-
timeout: timeoutMs,
|
|
15
|
-
maxBuffer: 16 * 1024 * 1024,
|
|
16
|
-
}).trim();
|
|
11
|
+
return runGitBase(args, cwd, { timeout: timeoutMs, maxBuffer: GIT_MAX_BUFFER });
|
|
17
12
|
}
|
|
18
13
|
function runGitAllowEmpty(args, cwd, timeoutMs = GIT_TIMEOUT_MS) {
|
|
19
|
-
return
|
|
20
|
-
cwd,
|
|
21
|
-
encoding: "utf8",
|
|
22
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
23
|
-
timeout: timeoutMs,
|
|
24
|
-
maxBuffer: 16 * 1024 * 1024,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
function getGitErrorMessage(error) {
|
|
28
|
-
const e = error;
|
|
29
|
-
if (e?.stderr && typeof e.stderr === "string")
|
|
30
|
-
return e.stderr.trim() || e.message || "git 命令失败";
|
|
31
|
-
if (e?.message)
|
|
32
|
-
return e.message;
|
|
33
|
-
return String(error);
|
|
14
|
+
return runGitRawBase(args, cwd, { timeout: timeoutMs, maxBuffer: GIT_MAX_BUFFER });
|
|
34
15
|
}
|
|
35
16
|
/** Throws `QuickCommitError` if `cwd` isn't an existing path inside a git work tree. */
|
|
36
17
|
function assertGitWorkTree(cwd) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface RunGitOptions {
|
|
2
|
+
timeout?: number;
|
|
3
|
+
maxBuffer?: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function runGit(args: string[], cwd: string, opts?: RunGitOptions): string;
|
|
6
|
+
export declare function runGitRaw(args: string[], cwd: string, opts?: RunGitOptions): string;
|
|
7
|
+
export declare function getGitErrorMessage(error: unknown): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
export function runGit(args, cwd, opts = {}) {
|
|
3
|
+
return execFileSync("git", args, {
|
|
4
|
+
cwd,
|
|
5
|
+
encoding: "utf8",
|
|
6
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
7
|
+
timeout: opts.timeout,
|
|
8
|
+
maxBuffer: opts.maxBuffer,
|
|
9
|
+
}).trim();
|
|
10
|
+
}
|
|
11
|
+
export function runGitRaw(args, cwd, opts = {}) {
|
|
12
|
+
return execFileSync("git", args, {
|
|
13
|
+
cwd,
|
|
14
|
+
encoding: "utf8",
|
|
15
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
16
|
+
timeout: opts.timeout,
|
|
17
|
+
maxBuffer: opts.maxBuffer,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function getGitErrorMessage(error) {
|
|
21
|
+
const e = error;
|
|
22
|
+
if (e?.stderr && typeof e.stderr === "string")
|
|
23
|
+
return e.stderr.trim() || e.message || "git 命令失败";
|
|
24
|
+
if (e?.message)
|
|
25
|
+
return e.message;
|
|
26
|
+
return String(error);
|
|
27
|
+
}
|
package/dist/git-worktree.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync } from "node:fs";
|
|
2
|
-
import { execFileSync } from "node:child_process";
|
|
3
2
|
import path from "node:path";
|
|
3
|
+
import { runGit, getGitErrorMessage } from "./git-utils.js";
|
|
4
4
|
const WORKTREE_MERGE_ERROR_CODES = {
|
|
5
5
|
MISSING: "WORKTREE_MISSING",
|
|
6
6
|
DIRTY: "WORKTREE_DIRTY",
|
|
@@ -19,13 +19,6 @@ export class WorktreeMergeError extends Error {
|
|
|
19
19
|
this.name = "WorktreeMergeError";
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
function runGit(args, cwd) {
|
|
23
|
-
return execFileSync("git", args, {
|
|
24
|
-
cwd,
|
|
25
|
-
encoding: "utf8",
|
|
26
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
27
|
-
}).trim();
|
|
28
|
-
}
|
|
29
22
|
function sanitizeBranchSegment(value) {
|
|
30
23
|
return value
|
|
31
24
|
.toLowerCase()
|
|
@@ -37,15 +30,6 @@ function getCurrentBranch(repoRoot) {
|
|
|
37
30
|
const branch = runGit(["branch", "--show-current"], repoRoot);
|
|
38
31
|
return branch || "master";
|
|
39
32
|
}
|
|
40
|
-
function isGitCommandError(error) {
|
|
41
|
-
return error instanceof Error;
|
|
42
|
-
}
|
|
43
|
-
function getGitCommandMessage(error) {
|
|
44
|
-
if (isGitCommandError(error)) {
|
|
45
|
-
return error.stderr?.trim() || error.stdout?.trim() || error.message;
|
|
46
|
-
}
|
|
47
|
-
return String(error);
|
|
48
|
-
}
|
|
49
33
|
function refExists(repoRoot, ref) {
|
|
50
34
|
try {
|
|
51
35
|
runGit(["rev-parse", "--verify", ref], repoRoot);
|
|
@@ -227,7 +211,7 @@ export function mergeSessionWorktree(options) {
|
|
|
227
211
|
runGit(["merge", "--no-ff", "--no-edit", context.sourceBranch], context.repoRoot);
|
|
228
212
|
}
|
|
229
213
|
catch (error) {
|
|
230
|
-
const message =
|
|
214
|
+
const message = getGitErrorMessage(error);
|
|
231
215
|
throw new WorktreeMergeError(WORKTREE_MERGE_ERROR_CODES.CONFLICT, message || "合并失败,可能存在冲突。", {
|
|
232
216
|
sourceBranch: context.sourceBranch,
|
|
233
217
|
targetBranch: context.targetBranch,
|
|
@@ -252,7 +236,7 @@ export function mergeSessionWorktree(options) {
|
|
|
252
236
|
};
|
|
253
237
|
}
|
|
254
238
|
catch (error) {
|
|
255
|
-
throw new WorktreeMergeError(WORKTREE_MERGE_ERROR_CODES.CLEANUP_FAILED,
|
|
239
|
+
throw new WorktreeMergeError(WORKTREE_MERGE_ERROR_CODES.CLEANUP_FAILED, getGitErrorMessage(error) || "已合并,但清理 worktree 失败。", {
|
|
256
240
|
sourceBranch: context.sourceBranch,
|
|
257
241
|
targetBranch: context.targetBranch,
|
|
258
242
|
repoRoot: context.repoRoot,
|
package/dist/npm-update-utils.js
CHANGED
|
@@ -19,6 +19,7 @@ import process from "node:process";
|
|
|
19
19
|
import { promisify } from "node:util";
|
|
20
20
|
import { whichSync } from "./path-repair.js";
|
|
21
21
|
import { compareSemver } from "./version-utils.js";
|
|
22
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
22
23
|
const execFileAsync = promisify(execFile);
|
|
23
24
|
export const PACKAGE_NAME = "@co0ontty/wand";
|
|
24
25
|
const PACKAGE_SCOPE = "@co0ontty";
|
|
@@ -182,7 +183,7 @@ export function cleanupNpmLeftovers() {
|
|
|
182
183
|
entries = readdirSync(scopeDir);
|
|
183
184
|
}
|
|
184
185
|
catch (err) {
|
|
185
|
-
errors.push(`readdir ${scopeDir}: ${
|
|
186
|
+
errors.push(`readdir ${scopeDir}: ${getErrorMessage(err)}`);
|
|
186
187
|
return { removed, errors };
|
|
187
188
|
}
|
|
188
189
|
// 残留目录形如 `.wand-PdFXStca`:以点开头 + 包基名 + 短横线 + 随机后缀
|
|
@@ -199,7 +200,7 @@ export function cleanupNpmLeftovers() {
|
|
|
199
200
|
removed.push(fullPath);
|
|
200
201
|
}
|
|
201
202
|
catch (err) {
|
|
202
|
-
errors.push(`rm ${fullPath}: ${
|
|
203
|
+
errors.push(`rm ${fullPath}: ${getErrorMessage(err)}`);
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
206
|
return { removed, errors };
|
|
@@ -255,7 +256,7 @@ function validateGlobalWandInstall() {
|
|
|
255
256
|
catch (err) {
|
|
256
257
|
return {
|
|
257
258
|
ok: false,
|
|
258
|
-
message: `全局 wand CLI 无法设置执行权限: ${cliPath}: ${
|
|
259
|
+
message: `全局 wand CLI 无法设置执行权限: ${cliPath}: ${getErrorMessage(err)}`,
|
|
259
260
|
};
|
|
260
261
|
}
|
|
261
262
|
}
|
|
@@ -288,7 +289,7 @@ function createGlobalInstallBackup(note) {
|
|
|
288
289
|
}
|
|
289
290
|
catch (err) {
|
|
290
291
|
rmSync(backupRoot, { recursive: true, force: true });
|
|
291
|
-
note?.(`[wand] 全局安装备份失败,继续尝试更新: ${
|
|
292
|
+
note?.(`[wand] 全局安装备份失败,继续尝试更新: ${getErrorMessage(err)}`);
|
|
292
293
|
return { packageDir, backupDir: null };
|
|
293
294
|
}
|
|
294
295
|
}
|
|
@@ -311,7 +312,7 @@ function restoreGlobalInstallBackup(backup, note) {
|
|
|
311
312
|
return true;
|
|
312
313
|
}
|
|
313
314
|
catch (err) {
|
|
314
|
-
note?.(`[wand] 恢复更新前安装失败: ${
|
|
315
|
+
note?.(`[wand] 恢复更新前安装失败: ${getErrorMessage(err)}`);
|
|
315
316
|
return false;
|
|
316
317
|
}
|
|
317
318
|
}
|
|
@@ -351,7 +352,7 @@ export async function installPackageGloballyAsync(pkg, timeoutMs, log) {
|
|
|
351
352
|
return;
|
|
352
353
|
}
|
|
353
354
|
catch (error) {
|
|
354
|
-
const msg =
|
|
355
|
+
const msg = getErrorMessage(error);
|
|
355
356
|
if (!isRecoverableInstallError(msg)) {
|
|
356
357
|
throw error;
|
|
357
358
|
}
|
|
@@ -368,7 +369,7 @@ export async function installPackageGloballyAsync(pkg, timeoutMs, log) {
|
|
|
368
369
|
return;
|
|
369
370
|
}
|
|
370
371
|
catch (retryError) {
|
|
371
|
-
const retryMsg =
|
|
372
|
+
const retryMsg = getErrorMessage(retryError);
|
|
372
373
|
if (!isRecoverableInstallError(retryMsg)) {
|
|
373
374
|
throw retryError;
|
|
374
375
|
}
|
package/dist/path-repair.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync } from "node:fs";
|
|
2
2
|
import { compareSemver } from "./version-utils.js";
|
|
3
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import process from "node:process";
|
|
@@ -178,7 +179,7 @@ export async function deepRepairRuntimePath(result, opts = {}) {
|
|
|
178
179
|
probe = await probeLoginShell(shell, opts.timeoutMs ?? DEEP_PROBE_TIMEOUT_MS);
|
|
179
180
|
}
|
|
180
181
|
catch (err) {
|
|
181
|
-
result.warnings.push(`login shell 探测失败 (${shell}): ${
|
|
182
|
+
result.warnings.push(`login shell 探测失败 (${shell}): ${getErrorMessage(err)}`);
|
|
182
183
|
result.deepProbe = "failed";
|
|
183
184
|
return result;
|
|
184
185
|
}
|
|
@@ -3,6 +3,7 @@ import { ProcessManager } from "./process-manager.js";
|
|
|
3
3
|
import { StructuredSessionManager } from "./structured-session-manager.js";
|
|
4
4
|
import { WandStorage } from "./storage.js";
|
|
5
5
|
import { ExecutionMode, WandConfig } from "./types.js";
|
|
6
|
-
|
|
6
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
7
|
+
export { getErrorMessage };
|
|
7
8
|
export declare function registerSessionRoutes(app: Express, processes: ProcessManager, structured: StructuredSessionManager, storage: WandStorage, defaultMode: ExecutionMode, config: WandConfig, onSessionCreated?: (cwd: string | undefined | null) => void): void;
|
|
8
9
|
export declare function registerClaudeHistoryRoutes(app: Express, processes: ProcessManager, storage: WandStorage): void;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import express from "express";
|
|
2
2
|
import { SessionInputError } from "./process-manager.js";
|
|
3
|
+
import { normalizeMode } from "./config.js";
|
|
3
4
|
import { checkSessionWorktreeMergeability, cleanupSessionWorktree, getWorktreeMergeErrorCode, mergeSessionWorktree, WorktreeMergeError } from "./git-worktree.js";
|
|
4
5
|
import { getGitStatus, QuickCommitError, runQuickCommit, runTagHead, runPush, generateCommitMessageOnly, } from "./git-quick-commit.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
6
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
7
|
+
export { getErrorMessage };
|
|
8
8
|
function getInputErrorResponse(error, sessionId) {
|
|
9
9
|
if (error instanceof SessionInputError) {
|
|
10
10
|
const statusCode = error.code === "SESSION_NOT_FOUND" ? 404 : 409;
|
|
@@ -34,9 +34,6 @@ function getInputDebugMeta(error) {
|
|
|
34
34
|
}
|
|
35
35
|
return { error };
|
|
36
36
|
}
|
|
37
|
-
function normalizeMode(mode, defaultMode) {
|
|
38
|
-
return mode ?? defaultMode;
|
|
39
|
-
}
|
|
40
37
|
function getHiddenClaudeSessionIds(storage) {
|
|
41
38
|
const raw = storage.getConfigValue("hidden_claude_session_ids");
|
|
42
39
|
if (!raw)
|
package/dist/server.js
CHANGED
|
@@ -15,7 +15,7 @@ import { ensureAvatarSeed, getAvatarSvg } from "./avatar.js";
|
|
|
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, PREFERENCE_KEYS, resolveConfigDir, saveConfig, writePreferenceToStorage, } from "./config.js";
|
|
18
|
+
import { 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";
|
|
@@ -465,9 +465,6 @@ function decodeConnectCode(code) {
|
|
|
465
465
|
return null;
|
|
466
466
|
}
|
|
467
467
|
}
|
|
468
|
-
function normalizeMode(input, fallback) {
|
|
469
|
-
return isExecutionMode(input) ? input : fallback;
|
|
470
|
-
}
|
|
471
468
|
/** Match a semver-looking token in a file name (with optional pre-release / build metadata). */
|
|
472
469
|
function resolveAndroidApkDir(configDir, config) {
|
|
473
470
|
const configuredDir = config.android?.apkDir?.trim();
|
|
@@ -652,7 +649,7 @@ process.on("uncaughtException", (err) => {
|
|
|
652
649
|
process.exit(1);
|
|
653
650
|
});
|
|
654
651
|
process.on("unhandledRejection", (reason) => {
|
|
655
|
-
const msg =
|
|
652
|
+
const msg = getErrorMessage(reason);
|
|
656
653
|
wandError("未处理的异步错误", msg);
|
|
657
654
|
});
|
|
658
655
|
function wandError(label, message, suggestion) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
2
|
import { detectInstalledScope, installService } from "./tui/commands.js";
|
|
3
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
3
4
|
export function repairServiceUnitAfterUpdate(configPath) {
|
|
4
5
|
// 仅 Linux(systemd) / macOS(launchd) 有服务模型。
|
|
5
6
|
if (process.platform !== "linux" && process.platform !== "darwin") {
|
|
@@ -37,7 +38,7 @@ export function repairServiceUnitAfterUpdate(configPath) {
|
|
|
37
38
|
return {
|
|
38
39
|
repaired: false,
|
|
39
40
|
scope,
|
|
40
|
-
message: `服务 unit 重写异常: ${
|
|
41
|
+
message: `服务 unit 重写异常: ${getErrorMessage(err)}`,
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
44
|
}
|
|
@@ -8,6 +8,7 @@ import { query as sdkQuery } from "@anthropic-ai/claude-agent-sdk";
|
|
|
8
8
|
import { prepareSessionWorktree } from "./git-worktree.js";
|
|
9
9
|
import { truncateMessagesForTransport } from "./message-truncator.js";
|
|
10
10
|
import { buildChildEnv, isRunningAsRoot } from "./env-utils.js";
|
|
11
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
11
12
|
import { buildLanguageDirective, buildManagedAutonomyDirective } from "./language-prompt.js";
|
|
12
13
|
function defaultStructuredRunner(provider) {
|
|
13
14
|
return provider === "codex" ? "codex-cli-exec" : "claude-cli-print";
|
|
@@ -740,7 +741,7 @@ export class StructuredSessionManager {
|
|
|
740
741
|
return finished;
|
|
741
742
|
}
|
|
742
743
|
catch (error) {
|
|
743
|
-
const message =
|
|
744
|
+
const message = getErrorMessage(error);
|
|
744
745
|
const current = this.sessions.get(id);
|
|
745
746
|
if (!current)
|
|
746
747
|
throw error;
|
|
@@ -2304,7 +2305,7 @@ export class StructuredSessionManager {
|
|
|
2304
2305
|
kind: "claude-sdk-error",
|
|
2305
2306
|
spawnedAt,
|
|
2306
2307
|
closedAt: new Date().toISOString(),
|
|
2307
|
-
error:
|
|
2308
|
+
error: getErrorMessage(err),
|
|
2308
2309
|
});
|
|
2309
2310
|
throw err;
|
|
2310
2311
|
}
|
package/dist/tui/commands.js
CHANGED
|
@@ -14,6 +14,7 @@ import { checkPackageUpdateSync, getInstallSpecForChannel, installPackageGloball
|
|
|
14
14
|
import { whichSync } from "../path-repair.js";
|
|
15
15
|
import { computeRelaunch } from "../relaunch.js";
|
|
16
16
|
import { ensureDatabaseFile, resolveDatabasePath, WandStorage } from "../storage.js";
|
|
17
|
+
import { getErrorMessage } from "../error-utils.js";
|
|
17
18
|
// ─── 重启 ────────────────────────────────────────────────────────────────
|
|
18
19
|
/**
|
|
19
20
|
* 重启当前进程。
|
|
@@ -45,7 +46,7 @@ export function restartSelf() {
|
|
|
45
46
|
return { ok: true, message: "重启中…新进程已派生" };
|
|
46
47
|
}
|
|
47
48
|
catch (err) {
|
|
48
|
-
return { ok: false, message: `重启失败: ${
|
|
49
|
+
return { ok: false, message: `重启失败: ${getErrorMessage(err)}` };
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
// ─── 检查 / 安装更新 ────────────────────────────────────────────────────
|
|
@@ -126,7 +127,7 @@ export function openInBrowser(url) {
|
|
|
126
127
|
return { ok: true, message: `已在浏览器打开: ${url}` };
|
|
127
128
|
}
|
|
128
129
|
catch (err) {
|
|
129
|
-
return { ok: false, message: `打开失败: ${
|
|
130
|
+
return { ok: false, message: `打开失败: ${getErrorMessage(err)}` };
|
|
130
131
|
}
|
|
131
132
|
}
|
|
132
133
|
// ─── 复制到剪贴板 ───────────────────────────────────────────────────────
|
|
@@ -573,7 +574,7 @@ function installSystemdService(ctx, scope) {
|
|
|
573
574
|
writeFileSync(unitPath, unit, "utf8");
|
|
574
575
|
}
|
|
575
576
|
catch (err) {
|
|
576
|
-
return { ok: false, message: `写入 unit 失败: ${
|
|
577
|
+
return { ok: false, message: `写入 unit 失败: ${getErrorMessage(err)}` };
|
|
577
578
|
}
|
|
578
579
|
const base = systemctlBaseArgs(scope);
|
|
579
580
|
const reload = spawnSync("systemctl", [...base, "daemon-reload"], { encoding: "utf8" });
|
|
@@ -613,7 +614,7 @@ function uninstallSystemdService(scope) {
|
|
|
613
614
|
unlinkSync(unitPath);
|
|
614
615
|
}
|
|
615
616
|
catch (err) {
|
|
616
|
-
return { ok: false, message: `删除 unit 失败: ${
|
|
617
|
+
return { ok: false, message: `删除 unit 失败: ${getErrorMessage(err)}` };
|
|
617
618
|
}
|
|
618
619
|
spawnSync("systemctl", [...base, "daemon-reload"], { encoding: "utf8" });
|
|
619
620
|
return {
|
|
@@ -661,7 +662,7 @@ function installLaunchdService(ctx, scope) {
|
|
|
661
662
|
writeFileSync(plistPath, plist, "utf8");
|
|
662
663
|
}
|
|
663
664
|
catch (err) {
|
|
664
|
-
return { ok: false, message: `写入 plist 失败: ${
|
|
665
|
+
return { ok: false, message: `写入 plist 失败: ${getErrorMessage(err)}` };
|
|
665
666
|
}
|
|
666
667
|
const load = spawnSync("launchctl", ["load", "-w", plistPath], { encoding: "utf8" });
|
|
667
668
|
if (load.status !== 0) {
|
|
@@ -686,7 +687,7 @@ function uninstallLaunchdService(scope) {
|
|
|
686
687
|
unlinkSync(plistPath);
|
|
687
688
|
}
|
|
688
689
|
catch (err) {
|
|
689
|
-
return { ok: false, message: `删除 plist 失败: ${
|
|
690
|
+
return { ok: false, message: `删除 plist 失败: ${getErrorMessage(err)}` };
|
|
690
691
|
}
|
|
691
692
|
return {
|
|
692
693
|
ok: true,
|
|
@@ -695,7 +696,4 @@ function uninstallLaunchdService(scope) {
|
|
|
695
696
|
};
|
|
696
697
|
}
|
|
697
698
|
// ─── 工具 ────────────────────────────────────────────────────────────────
|
|
698
|
-
function errMsg(err) {
|
|
699
|
-
return err instanceof Error ? err.message : String(err);
|
|
700
|
-
}
|
|
701
699
|
// compareSemver 已统一到 ../version-utils.ts
|
package/dist/tui/ipc-server.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import net from "node:net";
|
|
7
7
|
import { existsSync, unlinkSync } from "node:fs";
|
|
8
|
+
import { getErrorMessage } from "../error-utils.js";
|
|
8
9
|
export function startIpcServer(deps) {
|
|
9
10
|
if (!deps.socketPath)
|
|
10
11
|
return null;
|
|
@@ -70,7 +71,7 @@ export function startIpcServer(deps) {
|
|
|
70
71
|
const err = {
|
|
71
72
|
id: req.id,
|
|
72
73
|
ok: false,
|
|
73
|
-
error:
|
|
74
|
+
error: getErrorMessage(e),
|
|
74
75
|
};
|
|
75
76
|
try {
|
|
76
77
|
conn.write(JSON.stringify(err) + "\n");
|
package/dist/tui/layout.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { stripAnsi } from "../pty-text-utils.js";
|
|
2
3
|
const require = createRequire(import.meta.url);
|
|
3
4
|
// neo-blessed 是 CJS,没有匹配 @types/blessed 的 default export,统一当 any 用。
|
|
4
5
|
const blessed = require("neo-blessed");
|
|
@@ -512,10 +513,6 @@ function ansiColorize(level, line) {
|
|
|
512
513
|
return `\x1b[33m${cleaned}\x1b[39m`;
|
|
513
514
|
return cleaned;
|
|
514
515
|
}
|
|
515
|
-
function stripAnsi(line) {
|
|
516
|
-
// eslint-disable-next-line no-control-regex
|
|
517
|
-
return line.replace(/\x1b\[[0-9;]*m/g, "");
|
|
518
|
-
}
|
|
519
516
|
function formatTs(ms) {
|
|
520
517
|
const d = new Date(ms);
|
|
521
518
|
const hh = String(d.getHours()).padStart(2, "0");
|