@clawos-dev/clawd 0.2.549 → 0.2.551
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 +53 -21
- package/dist/persona-defaults/persona-app-builder/extension-kit/examples/nestjs-react/server/pnpm-workspace.yaml +7 -0
- package/dist/persona-defaults/persona-app-builder/extension-kit/examples/nestjs-react/web/pnpm-workspace.yaml +9 -0
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-persona-for-deploy/SKILL.md +6 -1
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/pnpm-workspace.yaml +7 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/pnpm-workspace.yaml +9 -0
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -59723,14 +59723,27 @@ function toClawdError(err) {
|
|
|
59723
59723
|
if (err instanceof RepoError || err instanceof GithubApiError) return new ClawdError(ERROR_CODES.INTERNAL, err.message);
|
|
59724
59724
|
return new ClawdError(ERROR_CODES.INTERNAL, err instanceof Error ? err.message : String(err));
|
|
59725
59725
|
}
|
|
59726
|
-
function
|
|
59727
|
-
if (
|
|
59728
|
-
|
|
59729
|
-
}
|
|
59730
|
-
return scan;
|
|
59726
|
+
function isLiveScan(live, scan) {
|
|
59727
|
+
if (!live) return false;
|
|
59728
|
+
return live.sessionId === void 0 || live.sessionId === scan.scanSessionId;
|
|
59731
59729
|
}
|
|
59732
59730
|
function buildDeployHandlers(deps) {
|
|
59733
59731
|
const scannableAssets = deps.scannableAssets ?? SCANNABLE_ASSETS;
|
|
59732
|
+
const liveScans = /* @__PURE__ */ new Map();
|
|
59733
|
+
const settleStale = async (dir, scan) => {
|
|
59734
|
+
const settled = { ...scan, status: "failed", finishedAt: deps.now(), error: "\u626B\u63CF\u8BB0\u5F55\u505C\u5728 scanning\uFF0C\u4F46\u6CA1\u6709\u6B63\u5728\u8DD1\u7684\u626B\u63CF\u4F1A\u8BDD" };
|
|
59735
|
+
await writeScan(dir, settled);
|
|
59736
|
+
return settled;
|
|
59737
|
+
};
|
|
59738
|
+
const mustBeLiveScan = (personaId2, scan, method) => {
|
|
59739
|
+
if (scan?.status !== "scanning") {
|
|
59740
|
+
throw invalid(`${method} \u53EA\u5728\u626B\u63CF\u671F\u53EF\u7528\uFF08\u5F53\u524D ${scan?.status ?? "\u6CA1\u6709\u626B\u63CF\u8BB0\u5F55"}\uFF09`);
|
|
59741
|
+
}
|
|
59742
|
+
if (!isLiveScan(liveScans.get(personaId2), scan)) {
|
|
59743
|
+
throw invalid(`${method} \u53EA\u5728\u626B\u63CF\u671F\u53EF\u7528\uFF08\u8BB0\u5F55\u505C\u5728 scanning\uFF0C\u4F46\u6CA1\u6709\u6B63\u5728\u8DD1\u7684\u626B\u63CF\u4F1A\u8BDD\uFF09`);
|
|
59744
|
+
}
|
|
59745
|
+
return scan;
|
|
59746
|
+
};
|
|
59734
59747
|
const cacheMs = deps.secretsCacheMs ?? SECRETS_CACHE_MS;
|
|
59735
59748
|
const secretsCache = /* @__PURE__ */ new Map();
|
|
59736
59749
|
const runCache = /* @__PURE__ */ new Map();
|
|
@@ -59767,6 +59780,7 @@ function buildDeployHandlers(deps) {
|
|
|
59767
59780
|
fileError = err instanceof Error ? err.message : String(err);
|
|
59768
59781
|
}
|
|
59769
59782
|
let scan = await readScan(dir);
|
|
59783
|
+
if (scan?.status === "scanning" && !isLiveScan(liveScans.get(personaId2), scan)) scan = await settleStale(dir, scan);
|
|
59770
59784
|
if (scan && scan.status === "done") {
|
|
59771
59785
|
const stale = describeStaleAssets(staleScannerAssets(scan, scannableAssets));
|
|
59772
59786
|
const kept = scan.notes.filter((n2) => !n2.startsWith(STALE_ASSETS_NOTE_PREFIX));
|
|
@@ -59803,6 +59817,7 @@ function buildDeployHandlers(deps) {
|
|
|
59803
59817
|
response: { type: "deploy:state", ...await stateOf(personaId2) }
|
|
59804
59818
|
});
|
|
59805
59819
|
async function beginScan(personaId2, dir, current, head, want) {
|
|
59820
|
+
liveScans.set(personaId2, {});
|
|
59806
59821
|
const prevManifest = await readDeployFile(dir).catch(() => void 0);
|
|
59807
59822
|
const scanBase = pickScanBase({
|
|
59808
59823
|
// **文件在 ≠ 清单能用**:硬扫一开头就写了一份空清单,那一轮没跑完(OTA 重启 / butler 崩,
|
|
@@ -59847,8 +59862,23 @@ function buildDeployHandlers(deps) {
|
|
|
59847
59862
|
};
|
|
59848
59863
|
const started = deps.startScan(personaId2, scanBase);
|
|
59849
59864
|
if ("sessionId" in started) {
|
|
59865
|
+
liveScans.set(personaId2, { sessionId: started.sessionId });
|
|
59850
59866
|
await writeScan(dir, { status: "scanning", scanSessionId: started.sessionId, ...withMcp });
|
|
59867
|
+
const mine = () => liveScans.get(personaId2)?.sessionId === started.sessionId;
|
|
59868
|
+
void started.ended.then(async (outcome) => {
|
|
59869
|
+
if (mine()) liveScans.delete(personaId2);
|
|
59870
|
+
const current2 = await readScan(dir).catch(() => void 0);
|
|
59871
|
+
if (liveScans.has(personaId2) || current2?.scanSessionId !== started.sessionId) return;
|
|
59872
|
+
const settled = settleEndedScan(outcome, current2, deps.now());
|
|
59873
|
+
if (!settled) return;
|
|
59874
|
+
await writeScan(dir, settled);
|
|
59875
|
+
deps.warn?.("deploy scan ended without finishScan", { personaId: personaId2, why: settled.error });
|
|
59876
|
+
}).catch((err) => {
|
|
59877
|
+
if (mine()) liveScans.delete(personaId2);
|
|
59878
|
+
deps.warn?.("deploy scan settle failed", { personaId: personaId2, error: String(err) });
|
|
59879
|
+
});
|
|
59851
59880
|
} else {
|
|
59881
|
+
liveScans.delete(personaId2);
|
|
59852
59882
|
await writeScan(dir, {
|
|
59853
59883
|
status: "failed",
|
|
59854
59884
|
...withMcp,
|
|
@@ -59901,7 +59931,7 @@ function buildDeployHandlers(deps) {
|
|
|
59901
59931
|
ensureOwner(ctx);
|
|
59902
59932
|
const args = parseArgs2(DeployReportFindingArgsSchema, frame, "deploy:reportFinding");
|
|
59903
59933
|
const dir = mustPersona(args.personaId);
|
|
59904
|
-
const scan =
|
|
59934
|
+
const scan = mustBeLiveScan(args.personaId, await readScan(dir), "deploy:reportFinding");
|
|
59905
59935
|
let item;
|
|
59906
59936
|
try {
|
|
59907
59937
|
item = parseFinding(args.kind, args.item);
|
|
@@ -59922,7 +59952,7 @@ function buildDeployHandlers(deps) {
|
|
|
59922
59952
|
ensureOwner(ctx);
|
|
59923
59953
|
const args = parseArgs2(DeployFinishScanArgsSchema, frame, "deploy:finishScan");
|
|
59924
59954
|
const dir = mustPersona(args.personaId);
|
|
59925
|
-
const scan =
|
|
59955
|
+
const scan = mustBeLiveScan(args.personaId, await readScan(dir), "deploy:finishScan");
|
|
59926
59956
|
await writeScan(dir, {
|
|
59927
59957
|
...scan,
|
|
59928
59958
|
status: "done",
|
|
@@ -59956,8 +59986,13 @@ function buildDeployHandlers(deps) {
|
|
|
59956
59986
|
if (!repo2) throw new ClawdError(ERROR_CODES.INTERNAL, "\u4ED3\u5E93\u5EFA\u597D\u4E86\u4F46\u8BFB\u4E0D\u5230 origin");
|
|
59957
59987
|
}
|
|
59958
59988
|
if (repo2.branch !== "main") throw invalid(`\u5F53\u524D\u5728\u5206\u652F ${repo2.branch}\uFF0C\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u53EA\u8BA4 main\uFF1B\u5207\u56DE main \u518D\u53D1\u5E03`);
|
|
59959
|
-
const
|
|
59960
|
-
if (
|
|
59989
|
+
const starting = liveScans.get(personaId2);
|
|
59990
|
+
if (starting && starting.sessionId === void 0) return { response: { type: "deploy:release", outcome: "scanning" } };
|
|
59991
|
+
let current = await readScan(dir);
|
|
59992
|
+
if (current?.status === "scanning") {
|
|
59993
|
+
if (isLiveScan(liveScans.get(personaId2), current)) return { response: { type: "deploy:release", outcome: "scanning" } };
|
|
59994
|
+
current = await settleStale(dir, current);
|
|
59995
|
+
}
|
|
59961
59996
|
const fileUsable = await readDeployFile(dir).then((f2) => f2 !== void 0).catch(() => false);
|
|
59962
59997
|
if (scanBase !== void 0 || !fileUsable || !isScanFresh(current, repo2)) {
|
|
59963
59998
|
let head;
|
|
@@ -59967,7 +60002,12 @@ function buildDeployHandlers(deps) {
|
|
|
59967
60002
|
throw toClawdError(err);
|
|
59968
60003
|
}
|
|
59969
60004
|
runCache.delete(personaId2);
|
|
59970
|
-
|
|
60005
|
+
try {
|
|
60006
|
+
await beginScan(personaId2, dir, current, head, scanBase);
|
|
60007
|
+
} catch (err) {
|
|
60008
|
+
liveScans.delete(personaId2);
|
|
60009
|
+
throw err;
|
|
60010
|
+
}
|
|
59971
60011
|
return { response: { type: "deploy:release", outcome: "scanning" } };
|
|
59972
60012
|
}
|
|
59973
60013
|
const file = await readDeployFile(dir);
|
|
@@ -70930,7 +70970,7 @@ function computeMethodAccess(args) {
|
|
|
70930
70970
|
}
|
|
70931
70971
|
|
|
70932
70972
|
// src/version.ts
|
|
70933
|
-
var version = "0.2.
|
|
70973
|
+
var version = "0.2.551".length > 0 ? "0.2.551" : "dev";
|
|
70934
70974
|
|
|
70935
70975
|
// src/cli-probe/probe.ts
|
|
70936
70976
|
var fs78 = __toESM(require("fs"), 1);
|
|
@@ -74592,6 +74632,7 @@ async function startDaemon(config) {
|
|
|
74592
74632
|
githubApi: (token) => createGithubApi({ token }),
|
|
74593
74633
|
org: PERSONA_REPO_ORG,
|
|
74594
74634
|
now: () => Date.now(),
|
|
74635
|
+
warn: (msg, meta) => logger.warn(msg, meta),
|
|
74595
74636
|
startScan: (personaId2, scanBase) => {
|
|
74596
74637
|
const assetLines = SCANNABLE_ASSETS.map(
|
|
74597
74638
|
(a2) => ` - ${a2.name}${a2.path ? `\uFF08${a2.path(config.dataDir)}\uFF09` : ""}\uFF1A${a2.what}`
|
|
@@ -74623,16 +74664,7 @@ async function startDaemon(config) {
|
|
|
74623
74664
|
logger.error("deploy scan session failed to start", { personaId: personaId2, error: String(err) });
|
|
74624
74665
|
return { error: String(err) };
|
|
74625
74666
|
}
|
|
74626
|
-
|
|
74627
|
-
const dir = personaStore.personaDirPath(personaId2);
|
|
74628
|
-
const settled = settleEndedScan(outcome, await readScan(dir).catch(() => void 0), Date.now());
|
|
74629
|
-
if (!settled) return;
|
|
74630
|
-
await writeScan(dir, settled);
|
|
74631
|
-
logger.warn("deploy scan ended without finishScan", { personaId: personaId2, why: settled.error });
|
|
74632
|
-
}).catch((err) => {
|
|
74633
|
-
logger.warn("deploy scan settle failed", { personaId: personaId2, error: String(err) });
|
|
74634
|
-
});
|
|
74635
|
-
return { sessionId: handle.sessionId };
|
|
74667
|
+
return { sessionId: handle.sessionId, ended: handle.ended };
|
|
74636
74668
|
}
|
|
74637
74669
|
});
|
|
74638
74670
|
Object.assign(handlers, deployHandlers);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# 本目录就是一个独立的 pnpm 项目(packages 只列自己:pnpm 10 没有这一段会报 "packages field missing",12 不强求;
|
|
2
|
+
# 同时也让 pnpm 在这里止步、不往上爬进 clawos 的 workspace)。
|
|
3
|
+
packages:
|
|
4
|
+
- '.'
|
|
5
|
+
# 同 web/pnpm-workspace.yaml:pnpm 12 起 build 脚本要显式允许,@nestjs/core 有 postinstall。
|
|
6
|
+
allowBuilds:
|
|
7
|
+
"@nestjs/core": true
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 本目录就是一个独立的 pnpm 项目(packages 只列自己:pnpm 10 没有这一段会报 "packages field missing",12 不强求;
|
|
2
|
+
# 同时也让 pnpm 在这里止步、不往上爬进 clawos 的 workspace)。
|
|
3
|
+
packages:
|
|
4
|
+
- '.'
|
|
5
|
+
# pnpm 12 起「依赖带 build 脚本但没被显式允许」= install 直接失败(ERR_PNPM_IGNORED_BUILDS),且 pnpm 11 起不再读 package.json 的 pnpm 字段,
|
|
6
|
+
# 允许名单只能写在这里(写法同 clawd/pnpm-workspace.yaml)。vite 拖的 esbuild 有 postinstall。
|
|
7
|
+
# 以后加依赖 install 又报这个错 = 把它点名进来(本机 pnpm 10 的 warning 会列出来)。
|
|
8
|
+
allowBuilds:
|
|
9
|
+
esbuild: true
|
package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-persona-for-deploy/SKILL.md
CHANGED
|
@@ -270,7 +270,12 @@ GitHub release / apt,你得告诉我它从哪装」。
|
|
|
270
270
|
|
|
271
271
|
## 纪律
|
|
272
272
|
|
|
273
|
-
- **只读不写**:不要修改被扫 persona
|
|
273
|
+
- **只读不写**:不要修改被扫 persona 目录里的任何文件,不要执行它的脚本。**`.clawd/deploy.json` 和
|
|
274
|
+
`.clawd/deploy-scan.json` 也在内**——它们只能经 `deploy:reportFinding` / `deploy:patch` / `deploy:finishScan` 改。
|
|
275
|
+
把扫描记录手改回 `scanning` 没有用:daemon 只认它自己起的、还活着的扫描,会话一结束记录就不归你了,
|
|
276
|
+
改回去只会被翻成 failed。
|
|
277
|
+
- **扫完之后老板在这个会话里让你「重新扫」「改成硬扫 / 软扫」:不要动。** 不改文件、不重跑流程、不再上报。
|
|
278
|
+
回一句让他去页面重新点「发布」——按钮右边的下拉能选硬扫 / 软扫,daemon 会起新的扫描会话。
|
|
274
279
|
- **宁缺毋滥**:拿不准的去查清,不要编一条依赖进清单;查清了、且过得了 `notes` 那三道门槛的才是 note。
|
|
275
280
|
多报一条假依赖会让镜像装一堆没用的东西;漏报一条真依赖,云上试跑和用起来会发现,补一行再发一次就行。
|
|
276
281
|
- **没调 `finishScan` 就等于没扫完**——中途卡住也要调,把卡在哪写进 `notes`,别让页面一直停在
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# 本目录就是一个独立的 pnpm 项目(packages 只列自己:pnpm 10 没有这一段会报 "packages field missing",12 不强求;
|
|
2
|
+
# 同时也让 pnpm 在这里止步、不往上爬进 clawos 的 workspace)。
|
|
3
|
+
packages:
|
|
4
|
+
- '.'
|
|
5
|
+
# 同 web/pnpm-workspace.yaml:pnpm 12 起 build 脚本要显式允许,@nestjs/core 有 postinstall。
|
|
6
|
+
allowBuilds:
|
|
7
|
+
"@nestjs/core": true
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 本目录就是一个独立的 pnpm 项目(packages 只列自己:pnpm 10 没有这一段会报 "packages field missing",12 不强求;
|
|
2
|
+
# 同时也让 pnpm 在这里止步、不往上爬进 clawos 的 workspace)。
|
|
3
|
+
packages:
|
|
4
|
+
- '.'
|
|
5
|
+
# pnpm 12 起「依赖带 build 脚本但没被显式允许」= install 直接失败(ERR_PNPM_IGNORED_BUILDS),且 pnpm 11 起不再读 package.json 的 pnpm 字段,
|
|
6
|
+
# 允许名单只能写在这里(写法同 clawd/pnpm-workspace.yaml)。vite 拖的 esbuild 有 postinstall。
|
|
7
|
+
# 以后加依赖 install 又报这个错 = 把它点名进来(本机 pnpm 10 的 warning 会列出来)。
|
|
8
|
+
allowBuilds:
|
|
9
|
+
esbuild: true
|