@clawos-dev/clawd 0.2.121 → 0.2.122-beta.241.0e144f4
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/cli.cjs +736 -97
- package/dist/persona-defaults/persona-app-builder/CLAUDE.md +12 -1
- package/dist/persona-defaults/persona-app-builder/extension-kit/examples/nestjs-react/server/src/main.ts +17 -2
- package/dist/persona-defaults/persona-app-builder/extension-kit/scripts/new-extension.sh +1 -1
- package/dist/persona-defaults/persona-app-builder/extension-kit/scripts/publish.sh +18 -2
- package/dist/persona-defaults/persona-app-builder/extension-kit/scripts/verify.sh +20 -2
- package/package.json +1 -1
|
@@ -239,7 +239,18 @@ await app.listen(Number(process.env.CLAWD_PREVIEW_PORT));
|
|
|
239
239
|
- **dev 预览**:UI 通过 session ↔ project ↔ port 数据流自动加载,daemon state 驱动
|
|
240
240
|
- **prod 预览**:跑完 `publish.sh` 后调 `appBuilder.setProdUrl` RPC(见上文),daemon 写入 `.clawd-project.json.prodUrl` 后 UI 自动切线上 URL
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
### 发布上线(脚手架化 2026-06-03)
|
|
243
|
+
|
|
244
|
+
老板点 PreviewPane「发布上线」按钮走 **daemon RPC 脚手架**(`appBuilder.publish`),happy path 完全跳过你 —— daemon 自己 spawn `publish.sh`、解析 stage marker、调 `appBuilder.setProdUrl` 写 prodUrl,你不会收到任何 chat 消息。
|
|
245
|
+
|
|
246
|
+
**只有发布失败时**,daemon 会以普通消息发来一条以 `发布失败:[<stage>]` 开头的文本(含 stderr 错误摘要 + `.publish.log` 路径)。**收到这种消息时,你接管完成本次发布**:
|
|
247
|
+
|
|
248
|
+
1. 读项目目录下的 `.publish.log` 完整日志
|
|
249
|
+
2. 定位并修复问题(改源码 / 改 `ext.conf` / 检查 `.secrets/aliyun.env` 等)
|
|
250
|
+
3. 重跑 `bash extension-kit/scripts/publish.sh <projDir>` 直到 exit 0 且输出公网 URL
|
|
251
|
+
4. 调 `appBuilder.setProdUrl` 把 URL 写入项目元数据(同上文)
|
|
252
|
+
|
|
253
|
+
**注意**:重跑期间不要自己调 `appBuilder.publish` RPC(那是给 UI 按钮用的,会被 daemon 当作"已 in-flight"拒绝),手动跑脚本即可。失败回灌的消息开头固定是 `发布失败:[`,识别此前缀即触发接管流程。
|
|
243
254
|
|
|
244
255
|
**dev server 起不来怎么排查**:daemon 把 supervisor 输出(`dev-server.start` / `.stdout` / `.stderr` / `.spawn-failed` / `.exit`)打进 `~/.clawd/clawd.log`,老板可以 `grep dev-server ~/.clawd/clawd.log` 看真凶。常见原因:
|
|
245
256
|
- 端口 6XXX 被系统其他进程占了 → 右栏 header 齿轮菜单 → "Update Port..." 换段内另一个
|
|
@@ -62,9 +62,24 @@ async function bootstrap() {
|
|
|
62
62
|
app.use(vite.middlewares);
|
|
63
63
|
console.log(`[clawd-dev] vite middleware mounted (root=${viteRoot}, base=${viteBase}, apiPrefix=${apiPrefix}, allowedHosts=${allowedHosts.join(',')})`);
|
|
64
64
|
} else {
|
|
65
|
-
// prod / 脱离 clawd 跑:直接 serve
|
|
66
|
-
|
|
65
|
+
// prod / 脱离 clawd 跑:直接 serve 前端静态资源。
|
|
66
|
+
//
|
|
67
|
+
// 路径解析两条路(覆盖 FC 部署与本地 monorepo 启动两种场景):
|
|
68
|
+
// 1. FC(CODE_DIR=./server 只上传 server/,运行时 __dirname=dist/)
|
|
69
|
+
// publish.sh BUILD_CMD 末尾会跑 `mkdir -p dist/public && cp -R ../web/dist/. dist/public/`
|
|
70
|
+
// 把前端打包产物塞进 dist/public,跟着 server 一起上传到 FC。所以 prod 优先用
|
|
71
|
+
// __dirname/public 这条 FC 内可达的绝对路径。
|
|
72
|
+
// 2. 本地 monorepo `node dist/main.js`(极少用,但保留兼容):__dirname/public 不存在
|
|
73
|
+
// 时 fallback 到 ../../web/dist(monorepo 相对路径)。
|
|
74
|
+
//
|
|
75
|
+
// 历史坑:spec 2026-06-03 前只有路径 2,FC 上 404 整个前端 —— 因为 ../../web/dist 在 FC
|
|
76
|
+
// 容器里压根不存在(CODE_DIR 只上传了 server/)。dev 时靠 vite middleware 走内存编译没暴露。
|
|
77
|
+
const fs = await import('node:fs');
|
|
78
|
+
const fcStaticDir = path.resolve(__dirname, 'public');
|
|
79
|
+
const monorepoStaticDir = path.resolve(__dirname, '..', '..', 'web', 'dist');
|
|
80
|
+
const staticDir = fs.existsSync(fcStaticDir) ? fcStaticDir : monorepoStaticDir;
|
|
67
81
|
app.useStaticAssets(staticDir);
|
|
82
|
+
console.log(`[prod] serving static from ${staticDir}`);
|
|
68
83
|
}
|
|
69
84
|
|
|
70
85
|
await app.listen(port, '0.0.0.0');
|
|
@@ -34,7 +34,7 @@ cat > "$DEST/ext.conf" <<EOF
|
|
|
34
34
|
APP_NAME=$NAME
|
|
35
35
|
CODE_DIR=./server
|
|
36
36
|
FC_ENTRY=dist/main.js
|
|
37
|
-
BUILD_CMD="cd web &&
|
|
37
|
+
BUILD_CMD="cd web && pnpm install && pnpm build && cd ../server && pnpm install && pnpm build && mkdir -p dist/public && cp -R ../web/dist/. dist/public/"
|
|
38
38
|
# 本 extension 拥有的 Supabase 表(空格分隔,必须 ${NAME}_ 前缀);remove-extension.sh 据此清理
|
|
39
39
|
SUPABASE_TABLES=""
|
|
40
40
|
EOF
|
|
@@ -33,6 +33,10 @@ EOF
|
|
|
33
33
|
chmod 600 ~/.s/access.yaml
|
|
34
34
|
|
|
35
35
|
# 3) 构建产物(框架相关,由 ext.conf 的 BUILD_CMD 定义)
|
|
36
|
+
# 发布上线脚手架化 (spec 2026-06-03-app-builder-publish-scaffold-design §5.4):
|
|
37
|
+
# echo ::stage::build 在 if 外,BUILD_CMD 为空时也通知 daemon 进入 build 阶段(即使啥也没构建)。
|
|
38
|
+
# daemon 解析 stdout 命中此 marker 后 broadcast appBuilder:publish-progress 帧推 UI checklist。
|
|
39
|
+
echo "::stage::build"
|
|
36
40
|
if [ -n "$BUILD_CMD" ]; then
|
|
37
41
|
echo "==> build: $BUILD_CMD"
|
|
38
42
|
( cd "$EXT_DIR" && eval "$BUILD_CMD" )
|
|
@@ -57,10 +61,12 @@ sed -e "s|__APP_NAME__|$APP_NAME|g" \
|
|
|
57
61
|
"$KIT_DIR/contract/s.yaml.tmpl" > "$EXT_DIR/s.yaml"
|
|
58
62
|
|
|
59
63
|
# 6) 部署
|
|
64
|
+
echo "::stage::deploy"
|
|
60
65
|
echo "==> s deploy ($APP_NAME)"
|
|
61
66
|
( cd "$EXT_DIR" && s deploy -y )
|
|
62
67
|
|
|
63
68
|
# 7) 取自定义域名 + 验证
|
|
69
|
+
echo "::stage::verify"
|
|
64
70
|
DOM="$(aliyun fc GET /2023-03-30/custom-domains --region "$REGION" 2>/dev/null | python3 -c "
|
|
65
71
|
import sys,json
|
|
66
72
|
d=json.load(sys.stdin)
|
|
@@ -70,9 +76,19 @@ print(m[0] if m else '')")"
|
|
|
70
76
|
echo ""
|
|
71
77
|
echo "=================================================="
|
|
72
78
|
if [ -n "$DOM" ]; then
|
|
79
|
+
# daemon runner 优先解析这个 marker 作为 prodUrl(避免抠到 s deploy 中间的 FC system_url
|
|
80
|
+
# fcapp.run,阿里云对它强制 Content-Disposition: attachment,iframe / 浏览器直访都会变成下载)。
|
|
81
|
+
# 必须用 custom domain(<app>.fcv3.<accountId>.cn-hangzhou.fc.devsapp.net)。
|
|
82
|
+
echo "::prod-url::http://$DOM"
|
|
73
83
|
echo " ✅ 发布完成: http://$DOM"
|
|
74
84
|
echo "=================================================="
|
|
75
|
-
|
|
85
|
+
# verify.sh 失败(非 200 / Content-Disposition)→ exit 非 0,由 set -e 让 publish.sh
|
|
86
|
+
# 整体失败 → daemon runner 走 publish-failed 路径 + 回灌 chat 让 assistant 接管修复。
|
|
87
|
+
# 之前的 `|| true` 兜底已去掉,理由:线上挂了 prodUrl 仍写盘 = 老板看到"打开线上"按钮
|
|
88
|
+
# 但点开 404,不如 fail-loud。
|
|
89
|
+
"$KIT_DIR/scripts/verify.sh" "http://$DOM"
|
|
76
90
|
else
|
|
77
|
-
|
|
91
|
+
# 域名没拿到 = 部署本身有问题(fc3-domain 未成功),也算失败
|
|
92
|
+
echo "❌ 部署完成但未取到自定义域名,检查 fc3-domain 是否成功" >&2
|
|
93
|
+
exit 1
|
|
78
94
|
fi
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# 发布后健康检查:可达性 + Content-Type + 【是否被强制下载】
|
|
3
3
|
# 用法: verify.sh <url>
|
|
4
|
+
#
|
|
5
|
+
# 失败语义(spec 2026-06-03-app-builder-publish-scaffold-design follow-up):
|
|
6
|
+
# 首页非 200 / 检测到 Content-Disposition 强制下载 → exit 1。
|
|
7
|
+
# publish.sh 不加 `|| true` 兜底,verify 失败会让 publish.sh 整体 exit 非 0,
|
|
8
|
+
# 触发 daemon runner 的 publish-failed 路径:广播帧 + 回灌 chat user_text 让 assistant 接管修复。
|
|
9
|
+
#
|
|
10
|
+
# 信息原则:失败原因 echo 到 stderr(runner 的 errorSummary 抠 stderr 最后 20 行)。
|
|
4
11
|
set -euo pipefail
|
|
5
12
|
URL="${1:?用法: verify.sh <url>}"
|
|
6
13
|
|
|
@@ -11,10 +18,21 @@ echo "首页: HTTP $code ($ctype)"
|
|
|
11
18
|
|
|
12
19
|
# 关键检查: 有 Content-Disposition 说明会被浏览器当文件下载(没绑自定义域名的典型症状)
|
|
13
20
|
hdr=$(curl -s -D - -o /dev/null --max-time 30 "$URL/" || true)
|
|
21
|
+
has_cd=0
|
|
14
22
|
if echo "$hdr" | grep -qi 'content-disposition'; then
|
|
15
|
-
|
|
23
|
+
has_cd=1
|
|
24
|
+
echo "❌ 检测到 Content-Disposition —— 浏览器会下载而非渲染!确认走的是 fc3-domain 自定义域名,而不是 fcapp.run" >&2
|
|
16
25
|
else
|
|
17
26
|
echo "✓ 无 Content-Disposition,浏览器可正常渲染网页"
|
|
18
27
|
fi
|
|
19
28
|
|
|
20
|
-
[ "$code" = "200" ] &&
|
|
29
|
+
if [ "$code" = "200" ] && [ "$has_cd" = "0" ]; then
|
|
30
|
+
echo "✓ 全链路 OK"
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# 失败:原因写 stderr 供 runner 抠成 errorSummary,UI / assistant 都能看清楚
|
|
35
|
+
if [ "$code" != "200" ]; then
|
|
36
|
+
echo "❌ verify failed: 首页 HTTP $code (期望 200);查 s logs 找原因" >&2
|
|
37
|
+
fi
|
|
38
|
+
exit 1
|
package/package.json
CHANGED