@co0ontty/wand 4.77.0 → 4.78.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/README.md +21 -46
- package/dist/agent-dispatch.js +3 -2
- package/dist/ai-team-live.d.ts +25 -0
- package/dist/ai-team-live.js +135 -0
- package/dist/ai-team-prompts.d.ts +10 -6
- package/dist/ai-team-prompts.js +74 -41
- package/dist/ai-team-runner.d.ts +85 -3
- package/dist/ai-team-runner.js +336 -33
- package/dist/ai-team-types.d.ts +57 -2
- package/dist/ai-team-types.js +4 -0
- package/dist/build-info.json +3 -3
- package/dist/commit-task-archive.js +14 -18
- package/dist/config.js +14 -6
- package/dist/git-quick-commit.js +1 -1
- package/dist/middleware/rate-limit.d.ts +18 -4
- package/dist/middleware/rate-limit.js +55 -23
- package/dist/missions.js +0 -3
- package/dist/models.d.ts +6 -1
- package/dist/models.js +35 -0
- package/dist/path-repair.d.ts +6 -5
- package/dist/path-repair.js +3 -3
- package/dist/render-protocol.d.ts +1 -1
- package/dist/render-protocol.js +1 -1
- package/dist/server-ai-team-routes.d.ts +1 -0
- package/dist/server-ai-team-routes.js +28 -14
- package/dist/server-local-preview-routes.js +1 -1
- package/dist/server-session-routes.js +0 -3
- package/dist/server-settings-routes.d.ts +1 -1
- package/dist/server-settings-routes.js +3 -2
- package/dist/server-task-routes.js +16 -32
- package/dist/server-workspace-routes.js +31 -24
- package/dist/server.js +60 -21
- package/dist/storage.d.ts +54 -21
- package/dist/storage.js +485 -122
- package/dist/types.d.ts +7 -0
- package/dist/upload-routes.d.ts +2 -2
- package/dist/upload-routes.js +10 -3
- package/dist/wand-task-sync.d.ts +2 -34
- package/dist/wand-task-sync.js +0 -206
- package/dist/web-ui/asset-version.d.ts +5 -0
- package/dist/web-ui/asset-version.js +5 -0
- package/dist/web-ui/content/ai-teams.js +17 -8
- package/dist/web-ui/content/scripts.js +67 -66
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/content/tailwind.css +0 -21
- package/dist/web-ui/embedded-assets.js +8 -7
- package/dist/web-ui/index.js +9 -17
- package/dist/web-ui/scripts.d.ts +3 -1
- package/dist/web-ui/scripts.js +52 -25
- package/dist/web-ui/styles.d.ts +2 -0
- package/dist/web-ui/styles.js +12 -0
- package/package.json +13 -12
- package/scripts/install-render-binary.js +2 -2
- package/scripts/stage-render-binaries.js +1 -1
package/dist/web-ui/index.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
// Main entry point for web
|
|
2
|
-
// Combines CSS and JavaScript into a single HTML document
|
|
1
|
+
// Main entry point for the web UI shell. Only versioned external assets carry JS/CSS.
|
|
3
2
|
import { EMBEDDED_WEB_ASSETS } from "./embedded-assets.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { getStylesAsset } from "./styles.js";
|
|
4
|
+
import { getScriptAsset } from "./scripts.js";
|
|
6
5
|
import { WAND_FAVICON_URL } from "./brand-identity.js";
|
|
7
|
-
// Use String.fromCharCode to avoid template literal interpretation of </script>
|
|
8
|
-
const scriptClose = String.fromCharCode(60, 47) + "script>";
|
|
9
|
-
const scriptOpen = "<" + "script";
|
|
10
6
|
function vendorAssetUrl(relPath) {
|
|
11
7
|
return `${relPath}?v=${EMBEDDED_WEB_ASSETS.vendor[relPath].hash}`;
|
|
12
8
|
}
|
|
13
9
|
export function renderApp(configPath) {
|
|
14
|
-
const
|
|
15
|
-
const
|
|
10
|
+
const stylesHref = `/assets/app.css?v=${getStylesAsset().hash}`;
|
|
11
|
+
const scriptSrc = `/assets/app.js?v=${getScriptAsset(configPath).hash}`;
|
|
16
12
|
const xtermSrc = vendorAssetUrl("/vendor/xterm/xterm.bundle.js");
|
|
17
13
|
const qrcodeSrc = vendorAssetUrl("/vendor/qrcode/qrcode.bundle.js");
|
|
18
14
|
const xtermCssHref = vendorAssetUrl("/vendor/xterm/xterm.css");
|
|
@@ -29,18 +25,14 @@ export function renderApp(configPath) {
|
|
|
29
25
|
<meta name="format-detection" content="telephone=no" />
|
|
30
26
|
<meta name="msapplication-tap-highlight" content="no" />
|
|
31
27
|
<link rel="stylesheet" href="${xtermCssHref}" />
|
|
32
|
-
<
|
|
33
|
-
${cssStyles}
|
|
34
|
-
</style>
|
|
28
|
+
<link rel="stylesheet" href="${stylesHref}" />
|
|
35
29
|
</head>
|
|
36
30
|
<body>
|
|
37
31
|
<div id="app"></div>
|
|
38
32
|
<div id="overlay-root" data-wand-ui-root></div>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
${
|
|
42
|
-
${scriptContent}
|
|
43
|
-
${scriptClose}
|
|
33
|
+
<script src="${xtermSrc}"></script>
|
|
34
|
+
<script src="${qrcodeSrc}"></script>
|
|
35
|
+
<script src="${scriptSrc}"></script>
|
|
44
36
|
</body>
|
|
45
37
|
</html>`;
|
|
46
38
|
}
|
package/dist/web-ui/scripts.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { type VersionedWebAsset } from "./asset-version.js";
|
|
2
|
+
export declare function getScriptAsset(configPath: string, requestedHash?: string): VersionedWebAsset;
|
|
1
3
|
export declare function getScriptContent(configPath: string): string;
|
|
2
4
|
/**
|
|
3
5
|
* 按需加载的 AI 团队脚本(content/ai-teams.js)。与 scripts.js 一样优先读磁盘上的新产物,
|
|
4
6
|
* 自更新期间目录消失时退回内嵌副本;hash 进页面 meta 里的地址,长缓存按它失效。
|
|
5
7
|
*/
|
|
6
|
-
export declare function getAiTeamsChunk(): {
|
|
8
|
+
export declare function getAiTeamsChunk(requestedHash?: string): {
|
|
7
9
|
content: string;
|
|
8
10
|
hash: string;
|
|
9
11
|
};
|
package/dist/web-ui/scripts.js
CHANGED
|
@@ -3,38 +3,62 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { EMBEDDED_WEB_ASSETS } from "./embedded-assets.js";
|
|
6
|
-
|
|
7
|
-
return String(value)
|
|
8
|
-
.replace(/&/g, "&")
|
|
9
|
-
.replace(/</g, "<")
|
|
10
|
-
.replace(/>/g, ">")
|
|
11
|
-
.replace(/"/g, """)
|
|
12
|
-
.replace(/'/g, "'");
|
|
13
|
-
}
|
|
6
|
+
import { versionWebAsset } from "./asset-version.js";
|
|
14
7
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
8
|
let _scriptCache = EMBEDDED_WEB_ASSETS.scriptsJs;
|
|
16
|
-
let
|
|
17
|
-
|
|
9
|
+
let _scriptCacheKey = "";
|
|
10
|
+
let _scriptAsset = null;
|
|
11
|
+
let _embeddedScriptAsset = null;
|
|
12
|
+
function readScriptCache() {
|
|
18
13
|
const scriptPath = path.join(__dirname, "content", "scripts.js");
|
|
19
14
|
try {
|
|
20
15
|
const stat = fs.statSync(scriptPath);
|
|
21
|
-
|
|
16
|
+
const key = `${stat.mtimeMs}:${stat.size}`;
|
|
17
|
+
if (key !== _scriptCacheKey) {
|
|
22
18
|
_scriptCache = fs.readFileSync(scriptPath, "utf-8");
|
|
23
|
-
|
|
19
|
+
_scriptCacheKey = key;
|
|
24
20
|
}
|
|
25
21
|
}
|
|
26
22
|
catch {
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
|
|
23
|
+
// An in-flight npm update can remove content/ before the old process exits.
|
|
24
|
+
// Retain the last disk read, or fall back to the embedded copy.
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function injectRuntimeValues(source, configPath, chunkHash) {
|
|
28
|
+
return source
|
|
29
|
+
// This is a JS string literal, not HTML text. JSON escaping also handles
|
|
30
|
+
// quotes, backslashes and newlines in nonstandard configuration paths.
|
|
31
|
+
.replace('"${wandConfigPath}"', JSON.stringify(configPath))
|
|
32
|
+
.replace("${aiTeamsChunkSrc}", `/assets/ai-teams.js?v=${chunkHash}`);
|
|
33
|
+
}
|
|
34
|
+
export function getScriptAsset(configPath, requestedHash) {
|
|
35
|
+
readScriptCache();
|
|
36
|
+
const chunkHash = getAiTeamsChunk().hash;
|
|
37
|
+
if (!_scriptAsset || _scriptAsset.source !== _scriptCache
|
|
38
|
+
|| _scriptAsset.configPath !== configPath || _scriptAsset.chunkHash !== chunkHash) {
|
|
39
|
+
_scriptAsset = {
|
|
40
|
+
...versionWebAsset(injectRuntimeValues(_scriptCache, configPath, chunkHash)),
|
|
41
|
+
source: _scriptCache, configPath, chunkHash,
|
|
42
|
+
};
|
|
30
43
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
if (requestedHash && requestedHash !== _scriptAsset.hash) {
|
|
45
|
+
if (!_embeddedScriptAsset || _embeddedScriptAsset.configPath !== configPath) {
|
|
46
|
+
_embeddedScriptAsset = {
|
|
47
|
+
...versionWebAsset(injectRuntimeValues(EMBEDDED_WEB_ASSETS.scriptsJs, configPath, embeddedAiTeamsChunk.hash)),
|
|
48
|
+
configPath,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
if (requestedHash === _embeddedScriptAsset.hash)
|
|
52
|
+
return _embeddedScriptAsset;
|
|
53
|
+
}
|
|
54
|
+
return _scriptAsset;
|
|
55
|
+
}
|
|
56
|
+
export function getScriptContent(configPath) {
|
|
57
|
+
return getScriptAsset(configPath).content;
|
|
35
58
|
}
|
|
36
|
-
|
|
37
|
-
let
|
|
59
|
+
const embeddedAiTeamsChunk = withHash(EMBEDDED_WEB_ASSETS.aiTeamsJs);
|
|
60
|
+
let _aiTeamsChunk = embeddedAiTeamsChunk;
|
|
61
|
+
let _aiTeamsChunkKey = "";
|
|
38
62
|
function withHash(content) {
|
|
39
63
|
return { content, hash: createHash("md5").update(content).digest("hex").slice(0, 8) };
|
|
40
64
|
}
|
|
@@ -42,17 +66,20 @@ function withHash(content) {
|
|
|
42
66
|
* 按需加载的 AI 团队脚本(content/ai-teams.js)。与 scripts.js 一样优先读磁盘上的新产物,
|
|
43
67
|
* 自更新期间目录消失时退回内嵌副本;hash 进页面 meta 里的地址,长缓存按它失效。
|
|
44
68
|
*/
|
|
45
|
-
export function getAiTeamsChunk() {
|
|
69
|
+
export function getAiTeamsChunk(requestedHash) {
|
|
46
70
|
const chunkPath = path.join(__dirname, "content", "ai-teams.js");
|
|
47
71
|
try {
|
|
48
72
|
const stat = fs.statSync(chunkPath);
|
|
49
|
-
|
|
73
|
+
const key = `${stat.mtimeMs}:${stat.size}`;
|
|
74
|
+
if (key !== _aiTeamsChunkKey) {
|
|
50
75
|
_aiTeamsChunk = withHash(fs.readFileSync(chunkPath, "utf-8"));
|
|
51
|
-
|
|
76
|
+
_aiTeamsChunkKey = key;
|
|
52
77
|
}
|
|
53
78
|
}
|
|
54
79
|
catch {
|
|
55
|
-
//
|
|
80
|
+
// Same fallback as the main script during self-update.
|
|
56
81
|
}
|
|
82
|
+
if (requestedHash === embeddedAiTeamsChunk.hash)
|
|
83
|
+
return embeddedAiTeamsChunk;
|
|
57
84
|
return _aiTeamsChunk;
|
|
58
85
|
}
|
package/dist/web-ui/styles.d.ts
CHANGED
package/dist/web-ui/styles.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { EMBEDDED_WEB_ASSETS } from "./embedded-assets.js";
|
|
5
|
+
import { versionWebAsset } from "./asset-version.js";
|
|
5
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
7
|
// 顺序即层叠顺序:Tailwind/Appica 编译产物在前,手写 styles.css 在后。
|
|
7
8
|
//
|
|
@@ -41,3 +42,14 @@ export function getCSSStyles() {
|
|
|
41
42
|
}
|
|
42
43
|
return _cssCache;
|
|
43
44
|
}
|
|
45
|
+
let _stylesAsset = null;
|
|
46
|
+
const embeddedStylesAsset = versionWebAsset(EMBEDDED_WEB_ASSETS.stylesCss);
|
|
47
|
+
export function getStylesAsset(requestedHash) {
|
|
48
|
+
const content = getCSSStyles();
|
|
49
|
+
if (!_stylesAsset || _stylesAsset.content !== content) {
|
|
50
|
+
_stylesAsset = versionWebAsset(content);
|
|
51
|
+
}
|
|
52
|
+
if (requestedHash === embeddedStylesAsset.hash)
|
|
53
|
+
return embeddedStylesAsset;
|
|
54
|
+
return _stylesAsset;
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@co0ontty/wand",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.78.0",
|
|
4
4
|
"description": "A web console for Claude Code, Codex, OpenCode, and other local CLI tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,18 +20,19 @@
|
|
|
20
20
|
"preferGlobal": true,
|
|
21
21
|
"scripts": {
|
|
22
22
|
"generate:web-assets": "node scripts/generate-web-assets.js",
|
|
23
|
-
"build": "rm -rf dist && node scripts/bundle-tailwind.js && node scripts/bundle-xterm.js && node scripts/bundle-qrcode.js && node scripts/bundle-browser.js && npm run generate:web-assets && tsc -p tsconfig.json && npm run build:copy-content && node scripts/check-bundle-budget.js && (npm run build:render-bin || echo '[wand] WARNING: build:render-bin failed; dist/native/ has no wand-render (run: npm run build:render-bin)' >&2) && node scripts/stamp-build-info.js && node scripts/fix-dist-permissions.js",
|
|
23
|
+
"build": "node scripts/check-node-version.js && rm -rf dist && node scripts/bundle-tailwind.js && node scripts/bundle-xterm.js && node scripts/bundle-qrcode.js && node scripts/bundle-browser.js && npm run generate:web-assets && tsc -p tsconfig.json && npm run build:copy-content && node scripts/check-bundle-budget.js && (npm run build:render-bin || echo '[wand] WARNING: build:render-bin failed; dist/native/ has no wand-render (run: npm run build:render-bin)' >&2) && node scripts/stamp-build-info.js && node scripts/fix-dist-permissions.js",
|
|
24
24
|
"build:copy-content": "cp -r src/web-ui/content dist/web-ui/ && node scripts/minify-dist-content.js",
|
|
25
25
|
"build:render-bin": "node scripts/stage-render-binaries.js --all",
|
|
26
26
|
"build:render-native": "cargo build --release --manifest-path render/Cargo.toml -p wand-renderd",
|
|
27
27
|
"build:structured-render-native": "cargo build --release --manifest-path render/Cargo.toml -p wand-structured-renderd",
|
|
28
|
-
"dev": "node scripts/bundle-tailwind.js && node scripts/bundle-xterm.js && node scripts/bundle-browser.js --development && npm run generate:web-assets && tsx src/cli.ts web",
|
|
29
|
-
"check": "node scripts/bundle-tailwind.js && node scripts/bundle-xterm.js && node scripts/bundle-browser.js && npm run generate:web-assets && tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.browser.json && tsc --noEmit -p tsconfig.react.json",
|
|
30
|
-
"test": "node --test --import tsx tests/*.test.ts",
|
|
31
|
-
"check:bundle-budget": "node scripts/check-bundle-budget.js",
|
|
28
|
+
"dev": "node scripts/check-node-version.js && node scripts/bundle-tailwind.js && node scripts/bundle-xterm.js && node scripts/bundle-qrcode.js && node scripts/bundle-browser.js --development && npm run generate:web-assets && tsx src/cli.ts web",
|
|
29
|
+
"check": "node scripts/check-node-version.js && node scripts/bundle-tailwind.js && node scripts/bundle-xterm.js && node scripts/bundle-qrcode.js && node scripts/bundle-browser.js && npm run generate:web-assets && tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.browser.json && tsc --noEmit -p tsconfig.react.json",
|
|
30
|
+
"test": "node scripts/check-node-version.js && node --test --import tsx tests/*.test.ts",
|
|
31
|
+
"check:bundle-budget": "node scripts/check-node-version.js && node scripts/check-bundle-budget.js",
|
|
32
32
|
"sync:brand-assets": "node scripts/sync-brand-assets.js",
|
|
33
33
|
"check:brand-assets": "node scripts/sync-brand-assets.js --check",
|
|
34
34
|
"audit:remnants": "node scripts/audit-legacy-remnants.js",
|
|
35
|
+
"clean:build-cache": "node scripts/clean-build-cache.js",
|
|
35
36
|
"prepublishOnly": "VER=${WAND_PUBLISH_VERSION:-$(git tag --sort=-v:refname --list 'v*' | head -1)} && VER=${VER#v} && npm version \"$VER\" --no-git-tag-version --allow-same-version && npm run build",
|
|
36
37
|
"bundle:tailwind": "node scripts/bundle-tailwind.js"
|
|
37
38
|
},
|
|
@@ -43,27 +44,23 @@
|
|
|
43
44
|
],
|
|
44
45
|
"license": "MIT",
|
|
45
46
|
"engines": {
|
|
46
|
-
"node": ">=
|
|
47
|
+
"node": ">=26.10.0"
|
|
47
48
|
},
|
|
48
49
|
"dependencies": {
|
|
49
50
|
"@anthropic-ai/claude-agent-sdk": "^0.2.138",
|
|
50
51
|
"@anthropic-ai/sdk": "^0.81.0",
|
|
51
|
-
"@appica/ui-react": "^1.1.0",
|
|
52
|
-
"@xterm/addon-fit": "^0.11.0",
|
|
53
52
|
"@xterm/addon-serialize": "^0.14.0",
|
|
54
53
|
"@xterm/addon-unicode11": "^0.9.0",
|
|
55
54
|
"@xterm/headless": "^6.0.0",
|
|
56
|
-
"@xterm/xterm": "^6.0.0",
|
|
57
55
|
"compression": "^1.8.1",
|
|
58
56
|
"express": "^4.21.2",
|
|
59
57
|
"multer": "^2.1.1",
|
|
60
58
|
"neo-blessed": "^0.2.0",
|
|
61
59
|
"node-pty": "^1.1.0",
|
|
62
|
-
"react": "^19.2.7",
|
|
63
|
-
"react-dom": "^19.2.7",
|
|
64
60
|
"ws": "^8.19.0"
|
|
65
61
|
},
|
|
66
62
|
"devDependencies": {
|
|
63
|
+
"@appica/ui-react": "^1.1.0",
|
|
67
64
|
"@tailwindcss/cli": "^4.3.3",
|
|
68
65
|
"@types/compression": "^1.8.1",
|
|
69
66
|
"@types/express": "^4.17.21",
|
|
@@ -72,8 +69,12 @@
|
|
|
72
69
|
"@types/react": "^19.2.17",
|
|
73
70
|
"@types/react-dom": "^19.2.3",
|
|
74
71
|
"@types/ws": "^8.18.1",
|
|
72
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
73
|
+
"@xterm/xterm": "^6.0.0",
|
|
75
74
|
"esbuild": "^0.28.0",
|
|
76
75
|
"qrcode": "^1.5.4",
|
|
76
|
+
"react": "^19.2.7",
|
|
77
|
+
"react-dom": "^19.2.7",
|
|
77
78
|
"tailwindcss": "^4.3.3",
|
|
78
79
|
"tsx": "^4.19.3",
|
|
79
80
|
"typescript": "^5.8.2"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* - 不读 config.json 内容(只取其所在目录):既避免把配置里的密钥带进日志,
|
|
13
13
|
* 也允许「配置还没生成」时就能把二进制放好。
|
|
14
14
|
*
|
|
15
|
-
* 用法见 `--help`;设计与回滚见
|
|
15
|
+
* 用法见 `--help`;设计与回滚见 AGENTS.md 的 Server / Render 一节。
|
|
16
16
|
*
|
|
17
17
|
* 依赖的外部约定(与 Node 侧集成方共享,改这里要同步改文档):
|
|
18
18
|
* `wand-render --version` 必须打印含语义化版本号的一行(形如 `wand-render 0.1.0`)并以 0 退出,
|
|
@@ -465,7 +465,7 @@ const USAGE = `用法:node scripts/install-render-binary.js [选项]
|
|
|
465
465
|
3 就位失败(只读盘 / 无写权限 / 磁盘满)
|
|
466
466
|
4 --check 判定需要就位
|
|
467
467
|
|
|
468
|
-
|
|
468
|
+
设计说明与升级/回滚流程见仓库 AGENTS.md 的 Server / Render 一节。`;
|
|
469
469
|
|
|
470
470
|
/**
|
|
471
471
|
* @param {string[]} argv
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* - `render-bin` 子模块没初始化时要**警告并跳过**(退出码 0):没拉子模块的开发机上
|
|
14
14
|
* `npm run build` 不该因此失败;`--strict` 才是「必须内嵌」的场景(CI 发布链路)。
|
|
15
15
|
*
|
|
16
|
-
* 用法见 `--help`;布局与升级路径见
|
|
16
|
+
* 用法见 `--help`;布局与升级路径见 AGENTS.md 的 Server / Render 一节。
|
|
17
17
|
*/
|
|
18
18
|
import { spawnSync } from "node:child_process";
|
|
19
19
|
import { createHash, randomBytes } from "node:crypto";
|