@co0ontty/wand 1.69.0 → 1.70.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.
- package/dist/build-info.json +3 -3
- package/dist/middleware/path-safety.d.ts +3 -1
- package/dist/middleware/path-safety.js +13 -2
- package/dist/process-manager.js +2 -3
- package/dist/server-session-routes.js +3 -2
- package/dist/server.js +9 -4
- package/dist/session-cwd.d.ts +1 -0
- package/dist/session-cwd.js +31 -0
- package/dist/structured-session-manager.js +4 -2
- package/dist/web-ui/content/scripts.js +35 -35
- 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-06-
|
|
4
|
-
"version": "1.
|
|
2
|
+
"commit": "ecf86ef6a882537ff9c72de8c11b2ee8b962a5a6",
|
|
3
|
+
"builtAt": "2026-06-18T12:24:26.578Z",
|
|
4
|
+
"version": "1.70.0",
|
|
5
5
|
"channel": "stable"
|
|
6
6
|
}
|
|
@@ -2,5 +2,7 @@
|
|
|
2
2
|
export declare function isPathWithinBase(targetPath: string, basePath: string): boolean;
|
|
3
3
|
/** Check if targetPath is inside any blocked system folder. */
|
|
4
4
|
export declare function isBlockedFolderPath(targetPath: string): boolean;
|
|
5
|
+
/** Expand shell-style home shortcuts accepted by the UI. */
|
|
6
|
+
export declare function expandHomePath(inputPath: string): string;
|
|
5
7
|
/** Normalize a folder path to its absolute form. */
|
|
6
|
-
export declare function normalizeFolderPath(inputPath: string): string;
|
|
8
|
+
export declare function normalizeFolderPath(inputPath: string, basePath?: string): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
/** Check that targetPath is within basePath (or equal to it). */
|
|
3
4
|
export function isPathWithinBase(targetPath, basePath) {
|
|
4
5
|
const relativePath = path.relative(basePath, targetPath);
|
|
@@ -13,7 +14,17 @@ export function isBlockedFolderPath(targetPath) {
|
|
|
13
14
|
return relativePath === "" || (!relativePath.startsWith("..") && !path.isAbsolute(relativePath));
|
|
14
15
|
});
|
|
15
16
|
}
|
|
17
|
+
/** Expand shell-style home shortcuts accepted by the UI. */
|
|
18
|
+
export function expandHomePath(inputPath) {
|
|
19
|
+
const trimmed = inputPath.trim();
|
|
20
|
+
if (trimmed === "~")
|
|
21
|
+
return os.homedir();
|
|
22
|
+
if (trimmed.startsWith("~/") || trimmed.startsWith("~\\")) {
|
|
23
|
+
return path.join(os.homedir(), trimmed.slice(2));
|
|
24
|
+
}
|
|
25
|
+
return trimmed;
|
|
26
|
+
}
|
|
16
27
|
/** Normalize a folder path to its absolute form. */
|
|
17
|
-
export function normalizeFolderPath(inputPath) {
|
|
18
|
-
return path.resolve(inputPath);
|
|
28
|
+
export function normalizeFolderPath(inputPath, basePath = process.cwd()) {
|
|
29
|
+
return path.resolve(basePath, expandHomePath(inputPath));
|
|
19
30
|
}
|
package/dist/process-manager.js
CHANGED
|
@@ -17,6 +17,7 @@ import { getCodexResumeCommandSessionId, getResumeCommandSessionId } from "./res
|
|
|
17
17
|
import { applyThinkingEffortToPrompt, normalizeThinkingEffort } from "./structured-session-manager.js";
|
|
18
18
|
import { generateSessionTopic } from "./session-topic.js";
|
|
19
19
|
import { getErrorMessage } from "./error-utils.js";
|
|
20
|
+
import { resolveSessionCwd } from "./session-cwd.js";
|
|
20
21
|
function resolveProviderFromCommand(command) {
|
|
21
22
|
return /^codex\b/.test(command.trim()) ? "codex" : "claude";
|
|
22
23
|
}
|
|
@@ -752,9 +753,7 @@ export class ProcessManager extends EventEmitter {
|
|
|
752
753
|
}
|
|
753
754
|
start(command, cwd, mode, initialInput, opts) {
|
|
754
755
|
this.assertCommandAllowed(command);
|
|
755
|
-
const baseCwd = cwd
|
|
756
|
-
? path.resolve(process.cwd(), cwd)
|
|
757
|
-
: path.resolve(process.cwd(), this.config.defaultCwd);
|
|
756
|
+
const baseCwd = resolveSessionCwd(cwd, this.config.defaultCwd);
|
|
758
757
|
const id = opts?.reuseId || randomUUID();
|
|
759
758
|
// When a session is being resumed under the same id, capture its prior
|
|
760
759
|
// structured messages so the new bridge can present them as the chat
|
|
@@ -3,6 +3,7 @@ import { SessionInputError } from "./process-manager.js";
|
|
|
3
3
|
import { 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
|
+
import { resolveSessionCwd } from "./session-cwd.js";
|
|
6
7
|
import { getGitStatus, QuickCommitError, runQuickCommit, runTagHead, runPush, generateCommitMessageOnly, } from "./git-quick-commit.js";
|
|
7
8
|
import { getErrorMessage } from "./error-utils.js";
|
|
8
9
|
export { getErrorMessage };
|
|
@@ -155,7 +156,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
155
156
|
}
|
|
156
157
|
const provider = body.provider === "codex" ? "codex" : "claude";
|
|
157
158
|
const snapshot = structured.createSession({
|
|
158
|
-
cwd: body.cwd
|
|
159
|
+
cwd: resolveSessionCwd(body.cwd, config.defaultCwd),
|
|
159
160
|
mode: normalizeMode(body.mode, defaultMode),
|
|
160
161
|
provider,
|
|
161
162
|
runner: body.runner ?? (provider === "codex" ? "codex-cli-exec" : "claude-cli-print"),
|
|
@@ -165,7 +166,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
165
166
|
? body.thinkingEffort
|
|
166
167
|
: config.defaultThinkingEffort,
|
|
167
168
|
});
|
|
168
|
-
onSessionCreated?.(
|
|
169
|
+
onSessionCreated?.(snapshot.cwd);
|
|
169
170
|
const prompt = body.prompt?.trim();
|
|
170
171
|
if (prompt) {
|
|
171
172
|
const finished = await structured.sendMessage(snapshot.id, prompt);
|
package/dist/server.js
CHANGED
|
@@ -566,12 +566,16 @@ async function resolveAndroidApkAsset(configDir, config, channel = "beta") {
|
|
|
566
566
|
const fileStat = await stat(filePath);
|
|
567
567
|
if (!fileStat.isFile())
|
|
568
568
|
return null;
|
|
569
|
+
const fileName = path.basename(filePath);
|
|
570
|
+
const version = extractAndroidApkVersion(fileName);
|
|
571
|
+
if (channel === "stable" && isPrereleaseApkVersion(version))
|
|
572
|
+
return null;
|
|
569
573
|
return {
|
|
570
|
-
fileName
|
|
574
|
+
fileName,
|
|
571
575
|
filePath,
|
|
572
576
|
size: fileStat.size,
|
|
573
577
|
updatedAt: fileStat.mtime.toISOString(),
|
|
574
|
-
version
|
|
578
|
+
version,
|
|
575
579
|
downloadUrl: "/android/download",
|
|
576
580
|
source: "local",
|
|
577
581
|
};
|
|
@@ -710,7 +714,7 @@ async function resolveMacosDmgAsset(configDir, config) {
|
|
|
710
714
|
async function listPathSuggestions(input, fallbackCwd) {
|
|
711
715
|
const normalizedInput = input.trim();
|
|
712
716
|
const baseInput = normalizedInput || fallbackCwd;
|
|
713
|
-
const resolvedInput =
|
|
717
|
+
const resolvedInput = normalizeFolderPath(baseInput);
|
|
714
718
|
const endsWithSeparator = /[\\/]$/.test(normalizedInput);
|
|
715
719
|
let searchDir = resolvedInput;
|
|
716
720
|
let partialName = "";
|
|
@@ -1256,6 +1260,7 @@ export async function startServer(config, configPath) {
|
|
|
1256
1260
|
language: config.language ?? "",
|
|
1257
1261
|
updateAvailable: cachedUpdateInfo?.updateAvailable ?? false,
|
|
1258
1262
|
latestVersion: cachedUpdateInfo?.latest ?? null,
|
|
1263
|
+
updateChannel: getUpdateChannel(),
|
|
1259
1264
|
currentVersion: DISPLAY_VERSION,
|
|
1260
1265
|
});
|
|
1261
1266
|
});
|
|
@@ -2092,7 +2097,7 @@ export async function startServer(config, configPath) {
|
|
|
2092
2097
|
rows: reqRows,
|
|
2093
2098
|
thinkingEffort: body.thinkingEffort ?? config.defaultThinkingEffort,
|
|
2094
2099
|
});
|
|
2095
|
-
recordRecentPath(storage,
|
|
2100
|
+
recordRecentPath(storage, snapshot.cwd);
|
|
2096
2101
|
res.status(201).json(snapshot);
|
|
2097
2102
|
}
|
|
2098
2103
|
catch (error) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveSessionCwd(cwd: string | null | undefined, fallbackCwd: string | null | undefined): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { statSync } from "node:fs";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
4
|
+
import { normalizeFolderPath } from "./middleware/path-safety.js";
|
|
5
|
+
function getNodeErrorCode(error) {
|
|
6
|
+
return error && typeof error === "object" && "code" in error
|
|
7
|
+
? String(error.code)
|
|
8
|
+
: "";
|
|
9
|
+
}
|
|
10
|
+
export function resolveSessionCwd(cwd, fallbackCwd) {
|
|
11
|
+
const raw = cwd?.trim() || fallbackCwd?.trim() || process.cwd();
|
|
12
|
+
const resolved = normalizeFolderPath(raw);
|
|
13
|
+
let fileStat;
|
|
14
|
+
try {
|
|
15
|
+
fileStat = statSync(resolved);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
const code = getNodeErrorCode(error);
|
|
19
|
+
if (code === "ENOENT") {
|
|
20
|
+
throw new Error(`工作目录不存在:${resolved}`);
|
|
21
|
+
}
|
|
22
|
+
if (code === "EACCES" || code === "EPERM") {
|
|
23
|
+
throw new Error(`没有权限访问工作目录:${resolved}`);
|
|
24
|
+
}
|
|
25
|
+
throw new Error(`无法访问工作目录:${resolved}(${getErrorMessage(error)})`);
|
|
26
|
+
}
|
|
27
|
+
if (!fileStat.isDirectory()) {
|
|
28
|
+
throw new Error(`工作目录不是目录:${resolved}`);
|
|
29
|
+
}
|
|
30
|
+
return resolved;
|
|
31
|
+
}
|
|
@@ -11,6 +11,7 @@ import { getErrorMessage } from "./error-utils.js";
|
|
|
11
11
|
import { resolveSdkClaudeBinary } from "./claude-sdk-runner.js";
|
|
12
12
|
import { buildLanguageDirective, buildManagedAutonomyDirective } from "./language-prompt.js";
|
|
13
13
|
import { generateSessionTopic } from "./session-topic.js";
|
|
14
|
+
import { resolveSessionCwd } from "./session-cwd.js";
|
|
14
15
|
function defaultStructuredRunner(provider) {
|
|
15
16
|
return provider === "codex" ? "codex-cli-exec" : "claude-cli-print";
|
|
16
17
|
}
|
|
@@ -541,8 +542,9 @@ export class StructuredSessionManager {
|
|
|
541
542
|
const prompt = options.prompt?.trim();
|
|
542
543
|
const provider = options.provider === "codex" ? "codex" : "claude";
|
|
543
544
|
const runner = options.runner ?? defaultStructuredRunner(provider);
|
|
545
|
+
const baseCwd = resolveSessionCwd(options.cwd, this.config.defaultCwd);
|
|
544
546
|
const worktreeSetup = options.worktreeEnabled
|
|
545
|
-
? prepareSessionWorktree({ cwd:
|
|
547
|
+
? prepareSessionWorktree({ cwd: baseCwd, sessionId: id })
|
|
546
548
|
: null;
|
|
547
549
|
const selectedModel = options.model?.trim() || null;
|
|
548
550
|
const initialThinkingEffort = normalizeThinkingEffort(options.thinkingEffort);
|
|
@@ -556,7 +558,7 @@ export class StructuredSessionManager {
|
|
|
556
558
|
: runner === "claude-sdk"
|
|
557
559
|
? "claude-agent-sdk (stream-json)"
|
|
558
560
|
: "claude -p --output-format stream-json",
|
|
559
|
-
cwd: worktreeSetup?.cwd ??
|
|
561
|
+
cwd: worktreeSetup?.cwd ?? baseCwd,
|
|
560
562
|
mode: options.mode,
|
|
561
563
|
worktreeEnabled: Boolean(worktreeSetup),
|
|
562
564
|
worktree: worktreeSetup?.worktree ?? null,
|