@clawos-dev/clawd 0.2.625 → 0.2.627
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 +20 -89
- package/dist/app-builder-plugin/mcp-server.cjs +24 -1
- package/dist/cli.cjs +52 -8
- package/dist/cloud-persona-conversations.html +19 -19
- package/dist/dispatch/mcp-server.cjs +2 -1
- package/dist/persona-defaults/persona-app-builder/mcp/clawd-app-builder/mcp-server.cjs +24 -1
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-introspection/SKILL.md +4 -21
- package/dist/persona-defaults/persona-dataclaw-builder/mcp/clawd-app-builder/mcp-server.cjs +24 -1
- package/dist/share-ui/assets/{guest-DBwcqbLb.js → guest-CjFEd0FP.js} +116 -116
- package/dist/share-ui/guest.html +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,109 +1,40 @@
|
|
|
1
1
|
# @clawos-dev/clawd
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Clawd daemon CLI:管理 Claude Code、Codex、pi 会话,通过 WebSocket 与 HTTP RPC 提供会话、persona、权限、历史和远程接入能力。
|
|
4
4
|
|
|
5
5
|
## 安装与启动
|
|
6
6
|
|
|
7
|
-
推荐用 `npx`,每次自动拉最新版(无需全局安装):
|
|
8
|
-
|
|
9
7
|
```bash
|
|
10
|
-
npx @clawos-dev/clawd@latest
|
|
11
|
-
npx @clawos-dev/clawd@latest --port 28790
|
|
12
|
-
npx @clawos-dev/clawd@latest --data-dir /path/to/data
|
|
13
|
-
npx @clawos-dev/clawd@latest --tunnel
|
|
8
|
+
npx @clawos-dev/clawd@latest
|
|
9
|
+
npx @clawos-dev/clawd@latest --port 28790
|
|
10
|
+
npx @clawos-dev/clawd@latest --data-dir /path/to/data
|
|
11
|
+
npx @clawos-dev/clawd@latest --tunnel
|
|
14
12
|
```
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
启动成功 stdout 会打印 `Ready: ws://127.0.0.1:18790`,运行时元数据(`{url, pid, authToken?, tunnelUrl?, ...}`)写入 `~/.clawd/state.json`(0600 权限)。
|
|
19
|
-
|
|
20
|
-
> **本机模式无鉴权**:监听 `127.0.0.1`,所有连接直接放行;`--tunnel` 模式强制开启 first-message token 鉴权。
|
|
14
|
+
也可全局安装后运行 `clawd`。默认监听 `127.0.0.1:18790`,数据目录为 `~/.clawd`;参数与配置的当前定义见 [config.ts](./src/config.ts)。完整参数用 `clawd --help` 查看。
|
|
21
15
|
|
|
22
|
-
|
|
16
|
+
常用选项:`--port`、`--data-dir`、`--config`、`--log-level`、`--tunnel`、`--clawos-api`、`--auth-token`、`--no-log-shipping`。环境变量由 `resolveConfig` 解析,不根据旧示例猜测支持范围。
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|---|---|---|
|
|
26
|
-
| `--port <n>` | `18790` | WebSocket 监听端口 |
|
|
27
|
-
| `--data-dir <path>` | `~/.clawd` | 数据目录 |
|
|
28
|
-
| `--config <path>` | `<data-dir>/config.json` | 配置文件(存在则加载) |
|
|
29
|
-
| `--log-level <level>` | `info` | `debug` / `info` / `warn` / `error` |
|
|
30
|
-
| `--tunnel` | `false` | 启用 frp tunnel 把本地端口暴露到公网 |
|
|
31
|
-
| `--clawos-api <url>` | `https://api.clawos.chat` | tunnel register 接口 base url |
|
|
32
|
-
| `--auth-token <s>` | 自动生成 | 指定 daemon auth token;缺省时 tunnel 模式从 `~/.clawd/auth.json` 复用,不存在则生成 32 字节 base64url |
|
|
33
|
-
| `--help` / `-h` | — | 显示帮助 |
|
|
34
|
-
| `--version` / `-v` | — | 显示版本 |
|
|
18
|
+
## 鉴权与远程接入
|
|
35
19
|
|
|
36
|
-
|
|
20
|
+
- **WebSocket**:无 tunnel 时 loopback 连接可豁免首帧鉴权;启用 tunnel 后 loopback 也要求鉴权。需要鉴权的客户端发送 `{"type":"auth","token":"<token>"}` 并等待 `auth:ok` 后再发送业务帧。凭据决定 owner / guest 身份与权限,不由客户端自报身份。
|
|
21
|
+
- **HTTP RPC**:无论是否启用 tunnel 都使用已解析的 Bearer token。WebSocket 的本机豁免不适用于 HTTP。
|
|
22
|
+
- `--tunnel` 注册公网隧道并启动 frpc,使手机和授权的远端客户端能连接本机 daemon。连接串包含凭据,只交给授权客户端,不贴入诊断报告。
|
|
37
23
|
|
|
38
|
-
|
|
39
|
-
|---|---|
|
|
40
|
-
| `CLAWD_FRPC_BIN` | 自带 frpc 二进制路径(缺省时按需下载到 `~/.clawd/bin/frpc`) |
|
|
41
|
-
| `CLAWD_NO_TUNNEL_PERSIST` | `=1` 启动时不复用 `~/.clawd/tunnel.json`(dev only;`NODE_ENV=development` 自动开启) |
|
|
42
|
-
| `CLAWD_TUNNEL` | `=1` 等价于 `--tunnel` |
|
|
43
|
-
| `CLAWOS_API` | 等价于 `--clawos-api` |
|
|
44
|
-
| `CLAWD_AUTH_TOKEN` | 等价于 `--auth-token` |
|
|
24
|
+
本地 owner token、中心登录票 loginPass、云 gateway API key 各自有不同用途;当前边界见 [identity](../doc/glossary/identity.md) 和 [peer-mesh](../doc/glossary/peer-mesh.md)。
|
|
45
25
|
|
|
46
|
-
##
|
|
47
|
-
|
|
48
|
-
零参数即可启用:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
clawd --tunnel
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
启动后 stdout 会输出一段 banner,包含 tunnel URL 与一键连接串:
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
══════════════════════════════════════════════════════
|
|
58
|
-
Tunnel: wss://abcd1234.tunnel.clawos.chat
|
|
59
|
-
Connect: wss://abcd1234.tunnel.clawos.chat#token=kF3p...
|
|
60
|
-
Frpc config: ~/.clawd/frpc.toml
|
|
61
|
-
Frpc log: ~/.clawd/frpc.log
|
|
62
|
-
══════════════════════════════════════════════════════
|
|
63
|
-
```
|
|
26
|
+
## 查询状态与排障
|
|
64
27
|
|
|
65
|
-
|
|
28
|
+
persona / 会话 / 联系人 / 任务 / tunnel 的实际状态先通过 `clawd-rpc` 的 `list` + `call` 查询。会话列表走 `session:list`;历史读取用 `history:read` 并加 `slim:true`。不要按旧目录示例拼路径,也不直接读取 `auth.json` 或含 connectToken 的联系人记录。
|
|
66
29
|
|
|
67
|
-
|
|
30
|
+
默认日志在 `~/.clawd/log/`,daemon 主日志为 `clawd.log`。远端和云 persona 状态不能由本机文件判断;按 [日志排障手册](../doc/debug-with-logs.md) 查对应时间窗与 owner。
|
|
68
31
|
|
|
69
|
-
|
|
32
|
+
## 开发入口
|
|
70
33
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
5. 把 `tunnelUrl` 写进 `~/.clawd/state.json`
|
|
76
|
-
|
|
77
|
-
退出时 SIGTERM frpc 子进程,5 秒后 SIGKILL。
|
|
78
|
-
|
|
79
|
-
## Auth: first-message handshake
|
|
80
|
-
|
|
81
|
-
启用 tunnel 时,daemon 强制要求 first-message auth:
|
|
82
|
-
|
|
83
|
-
- 客户端连上后 5 秒内必须发送 `{"type":"auth","token":"<token>"}`
|
|
84
|
-
- 通过 → daemon 回 `{"type":"auth:ok"}`
|
|
85
|
-
- 失败 / 超时 / 越权 → close code 1008
|
|
86
|
-
|
|
87
|
-
token 来源(任选其一):
|
|
88
|
-
- 启动 banner 里 `Connect:` 整行(带 `#token=`),客户端一次粘贴即可
|
|
89
|
-
- 单独从 `Auth Token:` 行复制
|
|
90
|
-
- `~/.clawd/state.json` 的 `authToken` 字段(0600,仅本机用户可读)
|
|
91
|
-
|
|
92
|
-
非 tunnel 模式下,`127.0.0.1` / `::1` 来源连接默认豁免 auth;`--tunnel` 模式所有连接都要 auth。
|
|
93
|
-
|
|
94
|
-
## 目录结构
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
~/.clawd/
|
|
98
|
-
├── config.json # 可选配置文件
|
|
99
|
-
├── state.json # 运行时发现文件(启动写,退出删)
|
|
100
|
-
├── auth.json # tunnel auth token 持久化
|
|
101
|
-
├── tunnel.json # frps 凭证缓存
|
|
102
|
-
├── connect.txt # tunnel 连接串
|
|
103
|
-
├── frpc.toml / frpc.log # frpc 子进程配置 / 日志
|
|
104
|
-
├── clawd.log # daemon 运行日志
|
|
105
|
-
└── sessions/default/*.json # 会话持久化
|
|
106
|
-
```
|
|
34
|
+
- 工作规范:[CLAUDE.md](./CLAUDE.md)与[workspace 规范](../CLAUDE.md)。
|
|
35
|
+
- wire 字段与 schema:[protocol/src/](../protocol/src/);说明见 [wire-protocol](../doc/glossary/wire-protocol.md)。
|
|
36
|
+
- 模块边界和当前术语:[glossary](../doc/glossary/README.md)。
|
|
37
|
+
- 运行时持久化布局:[disk-layout](../doc/glossary/disk-layout.md),它是实现说明,不是状态查询接口。
|
|
107
38
|
|
|
108
39
|
## License
|
|
109
40
|
|
|
@@ -21714,7 +21714,8 @@ var DeploySecretPresenceSchema = external_exports.object({
|
|
|
21714
21714
|
}).strict();
|
|
21715
21715
|
var DEPLOY_STAGE_STATUSES = ["pending", "running", "done", "failed", "waiting", "skipped"];
|
|
21716
21716
|
var DeployStageStatusSchema = external_exports.enum(DEPLOY_STAGE_STATUSES);
|
|
21717
|
-
var
|
|
21717
|
+
var DEPLOY_VERIFY_STAGE = "verify";
|
|
21718
|
+
var DEPLOY_STAGE_KEYS = ["build", "smoke", "deploy", DEPLOY_VERIFY_STAGE];
|
|
21718
21719
|
var DeployStageKeySchema = external_exports.enum(DEPLOY_STAGE_KEYS);
|
|
21719
21720
|
var DeployJobSchema = external_exports.object({
|
|
21720
21721
|
key: DeployStageKeySchema,
|
|
@@ -24604,6 +24605,12 @@ var PackageFindingSchema = EnvPackageSchema.omit({ localVersion: true, artifact:
|
|
|
24604
24605
|
artifact: external_exports.object({ url: external_exports.string().url(), bin: external_exports.string() }).strict().optional()
|
|
24605
24606
|
});
|
|
24606
24607
|
|
|
24608
|
+
// src/feishu-auth/deploy-environments.ts
|
|
24609
|
+
var DEPLOY_TARGETS = {
|
|
24610
|
+
integration: { api: "https://api-int.clawos.chat", gateway: "https://persona-int.clawos.chat" },
|
|
24611
|
+
production: { api: "https://api.clawos.chat", gateway: "https://persona.clawos.chat" }
|
|
24612
|
+
};
|
|
24613
|
+
|
|
24607
24614
|
// src/deploy/release-workflow.ts
|
|
24608
24615
|
function renderDeployWorkflow(config2) {
|
|
24609
24616
|
const identity = [
|
|
@@ -24807,6 +24814,22 @@ function renderDeployWorkflow(config2) {
|
|
|
24807
24814
|
...download("${{ inputs.environment == 'production' && 'persona-candidate' || 'persona-smoked' }}"),
|
|
24808
24815
|
...contract,
|
|
24809
24816
|
...runtime("register"),
|
|
24817
|
+
...job(DEPLOY_VERIFY_STAGE),
|
|
24818
|
+
" needs: deploy",
|
|
24819
|
+
" if: inputs.environment != 'production'",
|
|
24820
|
+
" steps:",
|
|
24821
|
+
...download("persona-smoked"),
|
|
24822
|
+
...contract,
|
|
24823
|
+
" - name: Verify ordinary user conversation after deployment",
|
|
24824
|
+
" env:",
|
|
24825
|
+
` CLAWD_INT_API_URL: \${{ vars.CLAWD_INT_API_URL || '${DEPLOY_TARGETS.integration.api}' }}`,
|
|
24826
|
+
" CLAWD_INT_TEST_LOGIN_PASS: ${{ secrets.CLAWD_INT_TEST_LOGIN_PASS }}",
|
|
24827
|
+
" run: |",
|
|
24828
|
+
" node clawos/cloud-host/pipeline/persona-verify.mjs \\",
|
|
24829
|
+
" --file candidate-release.json \\",
|
|
24830
|
+
" --persona-id '${{ steps.plan.outputs.persona_id }}' \\",
|
|
24831
|
+
" --engine '${{ steps.plan.outputs.engine }}'",
|
|
24832
|
+
"",
|
|
24810
24833
|
...upload("persona-verified-${{ github.run_attempt }}")
|
|
24811
24834
|
].join("\n");
|
|
24812
24835
|
}
|
package/dist/cli.cjs
CHANGED
|
@@ -6260,7 +6260,7 @@ function cloudEngineOk(tool) {
|
|
|
6260
6260
|
function repoSlug(url) {
|
|
6261
6261
|
return url.trim().replace(/^git@[^:]+:/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/\.git$/, "");
|
|
6262
6262
|
}
|
|
6263
|
-
var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DEPLOY_PROMOTION_PHASES, DeployPromotionSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, ENGINE_AUTH_SECRETS, ENGINE_AUTH_PARTIAL_BLOCKER, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, CLOUD_ENGINES, DeployUnpublishRunSchema, DeployStateSchema, DeployUnpublishResultSchema, DeployPatchResultSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployGetArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployConfirmTestArgsSchema, DeployPromoteArgsSchema, DeployOpenTestArgsSchema, DeployEnvironmentArgsSchema, DeployConfirmTestResultSchema, DeployPromoteResultSchema, DeployOpenTestResultSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeploySetEngineAuthArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
|
|
6263
|
+
var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DEPLOY_PROMOTION_PHASES, DeployPromotionSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, ENGINE_AUTH_SECRETS, ENGINE_AUTH_PARTIAL_BLOCKER, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_VERIFY_STAGE, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, CLOUD_ENGINES, DeployUnpublishRunSchema, DeployStateSchema, DeployUnpublishResultSchema, DeployPatchResultSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployGetArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployConfirmTestArgsSchema, DeployPromoteArgsSchema, DeployOpenTestArgsSchema, DeployEnvironmentArgsSchema, DeployConfirmTestResultSchema, DeployPromoteResultSchema, DeployOpenTestResultSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeploySetEngineAuthArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
|
|
6264
6264
|
var init_deploy_schemas = __esm({
|
|
6265
6265
|
"../protocol/src/deploy-schemas.ts"() {
|
|
6266
6266
|
"use strict";
|
|
@@ -6350,7 +6350,8 @@ var init_deploy_schemas = __esm({
|
|
|
6350
6350
|
ENGINE_AUTH_PARTIAL_BLOCKER = "\u6A21\u578B\u8BA2\u9605\u53EA\u5199\u8FDB\u53BB\u4E00\u534A\u2014\u2014\u91CD\u586B\u6216\u6539\u56DE\u5E73\u53F0\u9ED8\u8BA4";
|
|
6351
6351
|
DEPLOY_STAGE_STATUSES = ["pending", "running", "done", "failed", "waiting", "skipped"];
|
|
6352
6352
|
DeployStageStatusSchema = external_exports.enum(DEPLOY_STAGE_STATUSES);
|
|
6353
|
-
|
|
6353
|
+
DEPLOY_VERIFY_STAGE = "verify";
|
|
6354
|
+
DEPLOY_STAGE_KEYS = ["build", "smoke", "deploy", DEPLOY_VERIFY_STAGE];
|
|
6354
6355
|
DeployStageKeySchema = external_exports.enum(DEPLOY_STAGE_KEYS);
|
|
6355
6356
|
DeployJobSchema = external_exports.object({
|
|
6356
6357
|
key: DeployStageKeySchema,
|
|
@@ -60940,6 +60941,7 @@ async function storeGithubAuth(args) {
|
|
|
60940
60941
|
}
|
|
60941
60942
|
|
|
60942
60943
|
// src/deploy/release-workflow.ts
|
|
60944
|
+
init_protocol();
|
|
60943
60945
|
function renderDeployWorkflow(config) {
|
|
60944
60946
|
const identity = [
|
|
60945
60947
|
" - name: Select pinned source identities",
|
|
@@ -61142,6 +61144,22 @@ function renderDeployWorkflow(config) {
|
|
|
61142
61144
|
...download("${{ inputs.environment == 'production' && 'persona-candidate' || 'persona-smoked' }}"),
|
|
61143
61145
|
...contract,
|
|
61144
61146
|
...runtime("register"),
|
|
61147
|
+
...job(DEPLOY_VERIFY_STAGE),
|
|
61148
|
+
" needs: deploy",
|
|
61149
|
+
" if: inputs.environment != 'production'",
|
|
61150
|
+
" steps:",
|
|
61151
|
+
...download("persona-smoked"),
|
|
61152
|
+
...contract,
|
|
61153
|
+
" - name: Verify ordinary user conversation after deployment",
|
|
61154
|
+
" env:",
|
|
61155
|
+
` CLAWD_INT_API_URL: \${{ vars.CLAWD_INT_API_URL || '${DEPLOY_TARGETS.integration.api}' }}`,
|
|
61156
|
+
" CLAWD_INT_TEST_LOGIN_PASS: ${{ secrets.CLAWD_INT_TEST_LOGIN_PASS }}",
|
|
61157
|
+
" run: |",
|
|
61158
|
+
" node clawos/cloud-host/pipeline/persona-verify.mjs \\",
|
|
61159
|
+
" --file candidate-release.json \\",
|
|
61160
|
+
" --persona-id '${{ steps.plan.outputs.persona_id }}' \\",
|
|
61161
|
+
" --engine '${{ steps.plan.outputs.engine }}'",
|
|
61162
|
+
"",
|
|
61145
61163
|
...upload("persona-verified-${{ github.run_attempt }}")
|
|
61146
61164
|
].join("\n");
|
|
61147
61165
|
}
|
|
@@ -61738,6 +61756,11 @@ async function readVerifiedRelease(api, slug, run) {
|
|
|
61738
61756
|
endpoint: DEPLOY_TARGETS.integration.gateway
|
|
61739
61757
|
}) };
|
|
61740
61758
|
}
|
|
61759
|
+
function requireDialogueVerification(release2, run) {
|
|
61760
|
+
if (!release2.verification.checks.includes("persona-dialogue") || !run.jobs.some((j2) => j2.key === DEPLOY_VERIFY_STAGE && j2.status === "done")) {
|
|
61761
|
+
throw new Error("\u8FD9\u6B21\u53D1\u5E03\u8FD8\u6CA1\u6709\u901A\u8FC7\u81EA\u52A8\u5BF9\u8BDD\u9A8C\u8BC1\uFF0C\u8BF7\u91CD\u65B0\u626B\u63CF\u5E76\u53D1\u5E03\u6D4B\u8BD5\u73AF\u5883");
|
|
61762
|
+
}
|
|
61763
|
+
}
|
|
61741
61764
|
function integrationPersonaForRelease(cloud, release2, releaseId) {
|
|
61742
61765
|
const cloudName = cloudPersonaIdOf("https://github.com/" + release2.repository);
|
|
61743
61766
|
if (cloud.personaId !== cloudName || cloud.image !== release2.image) return void 0;
|
|
@@ -62652,6 +62675,9 @@ function buildDeployHandlers(deps) {
|
|
|
62652
62675
|
}
|
|
62653
62676
|
return view(personaId2);
|
|
62654
62677
|
};
|
|
62678
|
+
const configureTestIdentity = async (api, slug) => {
|
|
62679
|
+
await api.putSecret(slug, "CLAWD_INT_TEST_LOGIN_PASS", await deps.testLoginPass(), "integration");
|
|
62680
|
+
};
|
|
62655
62681
|
const releaseHandler = async (frame, _client, ctx) => {
|
|
62656
62682
|
ensureOwner(ctx);
|
|
62657
62683
|
const { personaId: personaId2, scanId } = parseArgs2(DeployReleaseArgsSchema, frame, "deploy:release");
|
|
@@ -62667,6 +62693,7 @@ function buildDeployHandlers(deps) {
|
|
|
62667
62693
|
const pending = file.releases.find((r2) => r2.environment === "integration" && r2.scanId === scanId && !r2.pushed);
|
|
62668
62694
|
if (pending) {
|
|
62669
62695
|
try {
|
|
62696
|
+
await configureTestIdentity(api, repoSlug(repo2.url));
|
|
62670
62697
|
await pushRelease(deps.exec, dir, auth, pending.head);
|
|
62671
62698
|
await api.setDefaultBranch(repoSlug(repo2.url), "integration");
|
|
62672
62699
|
await writeScanFile(dir, { ...file, releases: file.releases.map((r2) => r2.id === pending.id ? { ...r2, pushed: true } : r2) });
|
|
@@ -62676,7 +62703,10 @@ function buildDeployHandlers(deps) {
|
|
|
62676
62703
|
}
|
|
62677
62704
|
}
|
|
62678
62705
|
const already = [...file.releases].reverse().find((r2) => r2.environment === "integration" && r2.scanId === scanId && r2.pushed && r2.head === repo2.head);
|
|
62679
|
-
if (already && !repo2.dirty)
|
|
62706
|
+
if (already && !repo2.dirty) {
|
|
62707
|
+
await configureTestIdentity(api, repoSlug(repo2.url));
|
|
62708
|
+
return { response: { type: "deploy:release", sha: already.head, actionsUrl: "https://github.com/" + repoSlug(repo2.url) + "/actions" } };
|
|
62709
|
+
}
|
|
62680
62710
|
if (entry.status !== "done") throw invalid(entry.status === "scanning" ? "\u8FD9\u6B21\u626B\u63CF\u8FD8\u5728\u8DD1\uFF0C\u7B49\u5B83\u626B\u5B8C" : "\u8FD9\u6B21\u626B\u63CF\u6CA1\u8DD1\u5B8C\uFF0C\u6E05\u5355\u4E0D\u5B8C\u6574\u2014\u2014\u91CD\u65B0\u626B\u63CF");
|
|
62681
62711
|
if (!isScanFresh(entry, repo2, file.releases.find((r2) => r2.head === repo2.head))) {
|
|
62682
62712
|
throw invalid(repo2.dirty ? "\u6709\u672A\u63D0\u4EA4\u7684\u6539\u52A8\uFF0C\u6E05\u5355\u662F\u6539\u52A8\u524D\u626B\u7684\u2014\u2014\u91CD\u65B0\u626B\u63CF" : "\u8FD9\u6B21\u626B\u63CF\u5BF9\u5E94\u7684\u4E0D\u662F\u5F53\u524D\u8FD9\u4E00\u7248 persona\u2014\u2014\u91CD\u65B0\u626B\u63CF");
|
|
@@ -62698,6 +62728,7 @@ function buildDeployHandlers(deps) {
|
|
|
62698
62728
|
blockers.push("\u8FD8\u6CA1\u9009\u6A21\u578B\uFF08\u5207\u5F15\u64CE\u65F6\u4F1A\u6E05\u7A7A\uFF09\u2014\u2014\u5728\u4E0A\u4E91\u9875\u300C\u5F15\u64CE\u4E0E\u6A21\u578B\u300D\u91CC\u9009\u4E00\u4E2A");
|
|
62699
62729
|
}
|
|
62700
62730
|
if (blockers.length > 0) throw invalid(`\u8FD8\u5DEE\uFF1A${blockers.join("\uFF1B")}`);
|
|
62731
|
+
await configureTestIdentity(api, repoSlug(repo2.url));
|
|
62701
62732
|
if (await deps.claimPublisher(cloudPersonaIdOf(repo2.url), "integration") === "taken") throw invalid("\u6D4B\u8BD5\u73AF\u5883\u91CC\u7684\u8FD9\u4E2A\u540D\u5B57\u5DF2\u7531\u522B\u4EBA\u53D1\u5E03");
|
|
62702
62733
|
const releaseId = (0, import_node_crypto14.randomUUID)();
|
|
62703
62734
|
try {
|
|
@@ -62734,6 +62765,7 @@ function buildDeployHandlers(deps) {
|
|
|
62734
62765
|
}
|
|
62735
62766
|
try {
|
|
62736
62767
|
if (record4?.environment === "integration") {
|
|
62768
|
+
await configureTestIdentity(api, slug);
|
|
62737
62769
|
await writeScanFile(dir, { ...file, releases: file.releases.map((r2) => r2.id === record4.id ? { ...r2, confirmation: void 0, verified: void 0, artifactId: void 0 } : r2) });
|
|
62738
62770
|
}
|
|
62739
62771
|
await rerunJob(api, slug, jobId);
|
|
@@ -62770,7 +62802,7 @@ function buildDeployHandlers(deps) {
|
|
|
62770
62802
|
const { type: _type, requestId: _requestId, ...args } = frame;
|
|
62771
62803
|
return parseArgs2({ safeParse: schema.safeParse.bind(schema) }, args, String(frame.type));
|
|
62772
62804
|
}
|
|
62773
|
-
async function testedRelease(personaId2, releaseId, checkOnline = true) {
|
|
62805
|
+
async function testedRelease(personaId2, releaseId, checkOnline = true, requireDialogue = false) {
|
|
62774
62806
|
const dir = mustPersona(personaId2);
|
|
62775
62807
|
const file = await readHistory(dir);
|
|
62776
62808
|
const record4 = file.releases.find((r2) => r2.id === releaseId);
|
|
@@ -62781,6 +62813,13 @@ function buildDeployHandlers(deps) {
|
|
|
62781
62813
|
const run = record4.runId ? await runById(api, repoSlug(repo2.url), record4.runId, "integration") : await findReleaseRun(api, repoSlug(repo2.url), { environment: "integration", head: record4.head });
|
|
62782
62814
|
if (!run || run.headSha !== record4.head) throw invalid("\u6682\u65F6\u67E5\u4E0D\u5230\u672C\u6B21\u6D4B\u8BD5\u6D41\u6C34\u7EBF\uFF0C\u8BF7\u5237\u65B0");
|
|
62783
62815
|
const { artifactId, release: verified } = await readVerifiedRelease(api, repoSlug(repo2.url), run);
|
|
62816
|
+
if (requireDialogue) {
|
|
62817
|
+
try {
|
|
62818
|
+
requireDialogueVerification(verified, run);
|
|
62819
|
+
} catch (e) {
|
|
62820
|
+
throw invalid(e.message);
|
|
62821
|
+
}
|
|
62822
|
+
}
|
|
62784
62823
|
if (checkOnline && (await deps.cloudState(cloudPersonaIdOf(repo2.url), "integration")).image !== verified.image) throw invalid("\u6D4B\u8BD5\u73AF\u5883\u7684\u7248\u672C\u5DF2\u7ECF\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u53D1\u5E03\u6D4B\u8BD5\u5E76\u786E\u8BA4");
|
|
62785
62824
|
const changed = record4.runId !== run.runId || record4.runAttempt !== run.runAttempt || record4.verified?.verification.fingerprint !== verified.verification.fingerprint;
|
|
62786
62825
|
const updated = { ...record4, artifactId, verified, runId: run.runId, runAttempt: run.runAttempt ?? 1, ...changed ? { confirmation: void 0 } : {} };
|
|
@@ -62813,7 +62852,7 @@ function buildDeployHandlers(deps) {
|
|
|
62813
62852
|
const confirmTest = async (frame, _client, ctx) => {
|
|
62814
62853
|
ensureOwner(ctx);
|
|
62815
62854
|
const { personaId: personaId2, releaseId } = releaseArgs(frame, DeployConfirmTestArgsSchema);
|
|
62816
|
-
const record4 = await testedRelease(personaId2, releaseId);
|
|
62855
|
+
const record4 = await testedRelease(personaId2, releaseId, true, true);
|
|
62817
62856
|
const confirmation = record4.confirmation ?? { fingerprint: record4.verified.verification.fingerprint, runId: record4.runId, runAttempt: record4.runAttempt, at: deps.now() };
|
|
62818
62857
|
const dir = mustPersona(personaId2), file = await readHistory(dir);
|
|
62819
62858
|
await writeScanFile(dir, { ...file, releases: file.releases.map((r2) => r2.id === releaseId ? { ...r2, confirmation } : r2) });
|
|
@@ -62829,8 +62868,7 @@ function buildDeployHandlers(deps) {
|
|
|
62829
62868
|
const stored = file.releases.find((r2) => r2.id === releaseId);
|
|
62830
62869
|
const snapshot = old?.verified ?? (stored?.confirmation?.fingerprint === stored?.verified?.verification.fingerprint ? stored?.verified : void 0);
|
|
62831
62870
|
if (recovering && (!snapshot || !stored)) throw invalid("\u539F\u4E0A\u7EBF\u4EFB\u52A1\u7684\u5DF2\u6D4B\u5236\u54C1\u8BB0\u5F55\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u5148\u6838\u5B9E\u539F\u6D41\u6C34\u7EBF\uFF1B\u4E0D\u4F1A\u6539\u7528\u65B0\u7684\u6D4B\u8BD5\u7248\u672C");
|
|
62832
|
-
const record4 = recovering ? { ...stored, verified: snapshot } : await testedRelease(personaId2, releaseId);
|
|
62833
|
-
if (!recovering && (!record4.confirmation || record4.confirmation.fingerprint !== record4.verified.verification.fingerprint || record4.confirmation.runId !== record4.runId || record4.confirmation.runAttempt !== record4.runAttempt)) throw invalid("\u8BF7\u5148\u5728\u6D4B\u8BD5\u73AF\u5883\u8BD5\u7528\uFF0C\u5E76\u786E\u8BA4\u8FD9\u6B21\u6D4B\u8BD5\u901A\u8FC7");
|
|
62871
|
+
const record4 = recovering ? { ...stored, verified: snapshot } : await testedRelease(personaId2, releaseId, true, true);
|
|
62834
62872
|
const repo2 = await repoInfo(deps.exec, mustPersona(personaId2));
|
|
62835
62873
|
if (!repo2) throw invalid("\u4ED3\u5E93\u4E0D\u5B58\u5728");
|
|
62836
62874
|
if (await deps.claimPublisher(cloudPersonaIdOf(repo2.url), "production") === "taken") throw invalid("\u7EBF\u4E0A\u73AF\u5883\u91CC\u7684\u8FD9\u4E2A\u540D\u5B57\u5DF2\u7531\u522B\u4EBA\u53D1\u5E03");
|
|
@@ -73562,7 +73600,7 @@ function computeMethodAccess(args) {
|
|
|
73562
73600
|
}
|
|
73563
73601
|
|
|
73564
73602
|
// src/version.ts
|
|
73565
|
-
var version = "0.2.
|
|
73603
|
+
var version = "0.2.627".length > 0 ? "0.2.627" : "dev";
|
|
73566
73604
|
|
|
73567
73605
|
// src/cli-probe/probe.ts
|
|
73568
73606
|
var fs84 = __toESM(require("fs"), 1);
|
|
@@ -77221,6 +77259,12 @@ async function startDaemon(config) {
|
|
|
77221
77259
|
const persona = list.find((p3) => p3.personaId === personaId2);
|
|
77222
77260
|
return { online: persona !== void 0, ...persona?.image ? { image: persona.image } : {} };
|
|
77223
77261
|
},
|
|
77262
|
+
testLoginPass: async () => {
|
|
77263
|
+
const loginPass = requireEnvironmentIdentity(environmentStores, "integration").loginPass;
|
|
77264
|
+
const credentials = await centralGetApiKey({ api: targetApi("integration"), loginPass });
|
|
77265
|
+
if (!credentials.apiKey) await centralIssueApiKey({ api: targetApi("integration"), loginPass });
|
|
77266
|
+
return loginPass;
|
|
77267
|
+
},
|
|
77224
77268
|
openTestPersona: async (_personaId, release2, releaseId) => {
|
|
77225
77269
|
const loginPass = requireEnvironmentIdentity(environmentStores, "integration").loginPass;
|
|
77226
77270
|
const credentials = await centralGetApiKey({ api: targetApi("integration"), loginPass });
|