@clawos-dev/clawd 0.2.445 → 0.2.447
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 +1243 -541
- package/dist/dispatch/mcp-server.cjs +210 -0
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-persona-for-deploy/SKILL.md +134 -0
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/guest-7QsWRy9Q.css +32 -0
- package/dist/share-ui/assets/{guest-Cn0m2N_c.js → guest-CilettnR.js} +132 -132
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-DISx208T.css +0 -32
package/dist/cli.cjs
CHANGED
|
@@ -450,8 +450,8 @@ var init_parseUtil = __esm({
|
|
|
450
450
|
init_errors();
|
|
451
451
|
init_en();
|
|
452
452
|
makeIssue = (params) => {
|
|
453
|
-
const { data, path:
|
|
454
|
-
const fullPath = [...
|
|
453
|
+
const { data, path: path93, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path93, ...issueData.path || []];
|
|
455
455
|
const fullIssue = {
|
|
456
456
|
...issueData,
|
|
457
457
|
path: fullPath
|
|
@@ -762,11 +762,11 @@ var init_types = __esm({
|
|
|
762
762
|
init_parseUtil();
|
|
763
763
|
init_util();
|
|
764
764
|
ParseInputLazyPath = class {
|
|
765
|
-
constructor(parent, value,
|
|
765
|
+
constructor(parent, value, path93, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path93;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -5950,6 +5950,187 @@ var init_contact_handshake = __esm({
|
|
|
5950
5950
|
}
|
|
5951
5951
|
});
|
|
5952
5952
|
|
|
5953
|
+
// ../protocol/src/environment-schemas.ts
|
|
5954
|
+
var EnvCliSchema, EnvSecretSchema, EnvAssetSchema, MANIFEST_BODY, EnvManifestBodySchema, EnvironmentManifestSchema, EnvEvidenceSchema;
|
|
5955
|
+
var init_environment_schemas = __esm({
|
|
5956
|
+
"../protocol/src/environment-schemas.ts"() {
|
|
5957
|
+
"use strict";
|
|
5958
|
+
init_zod();
|
|
5959
|
+
EnvCliSchema = external_exports.object({
|
|
5960
|
+
// 可执行文件名,装配后要能在 PATH 里直接调到('aliyun' / 's' / 'pnpm' / 'python3')
|
|
5961
|
+
name: external_exports.string().min(1),
|
|
5962
|
+
/**
|
|
5963
|
+
* 从哪装,约定 `<kind>:<ref>`:`npm:@serverless-devs/s` / `github:aliyun/aliyun-cli` /
|
|
5964
|
+
* `apt:python3`。
|
|
5965
|
+
*
|
|
5966
|
+
* **不是装饰字段,是构建器的必需输入**:可执行名往往推不出安装源——Serverless Devs 的命令
|
|
5967
|
+
* 就叫单个字母 `s`,没人能从 's' 猜到要 `npm i -g @serverless-devs/s`;`aliyun` 也不在
|
|
5968
|
+
* apt 源里,得从 GitHub release 拉 tarball。扫描器读 ensure-toolchain.sh 的时候本来就看见
|
|
5969
|
+
* 了这些,顺手带出来即可。
|
|
5970
|
+
*
|
|
5971
|
+
* 它同时解决人的阅读问题:单据上只写一个 `s`,看的人不知道那是什么东西。
|
|
5972
|
+
*
|
|
5973
|
+
* 允许缺省:扫描器拿不准安装源时不该编一个(编错了构建期才炸,还查不出来源)。缺省时构建
|
|
5974
|
+
* 器会失败或猜错,试装当场暴露——这跟整体「宁可让试装发现,不要靠猜」的取向一致。
|
|
5975
|
+
*
|
|
5976
|
+
* 只给一个源,不给平台回落链:本地那套 brew → GitHub → npm 的三级兜底是
|
|
5977
|
+
* ensure-toolchain.sh 的事,云上只构一个镜像、一个基础环境,多给反而要求构建器做选择。
|
|
5978
|
+
*/
|
|
5979
|
+
from: external_exports.string().optional(),
|
|
5980
|
+
// 精确版本;缺省 = 不挑版本,装配器自选
|
|
5981
|
+
version: external_exports.string().optional(),
|
|
5982
|
+
// 版本下限('20.6' 这种)。与 version 的区别:version 是「就要这个」,min 是「不低于」。
|
|
5983
|
+
// 两者都缺省即完全不约束。
|
|
5984
|
+
min: external_exports.string().optional()
|
|
5985
|
+
});
|
|
5986
|
+
EnvSecretSchema = external_exports.object({
|
|
5987
|
+
// 凭据的命名引用('aliyun-ak' / 'supabase-shared')。部署时按这个名字去解析实际的值。
|
|
5988
|
+
name: external_exports.string().min(1),
|
|
5989
|
+
// 解析出的值注入到哪些环境变量。一份凭据可含多个字段(AK 是 id+secret 两个,
|
|
5990
|
+
// supabase 是 url/anon/service-role/jwt 四个),所以是数组不是单值。
|
|
5991
|
+
env: external_exports.array(external_exports.string().min(1)).min(1)
|
|
5992
|
+
});
|
|
5993
|
+
EnvAssetSchema = external_exports.object({
|
|
5994
|
+
name: external_exports.string().min(1)
|
|
5995
|
+
});
|
|
5996
|
+
MANIFEST_BODY = {
|
|
5997
|
+
clis: external_exports.array(EnvCliSchema),
|
|
5998
|
+
secrets: external_exports.array(EnvSecretSchema),
|
|
5999
|
+
assets: external_exports.array(EnvAssetSchema)
|
|
6000
|
+
};
|
|
6001
|
+
EnvManifestBodySchema = external_exports.object(MANIFEST_BODY);
|
|
6002
|
+
EnvironmentManifestSchema = external_exports.object({
|
|
6003
|
+
// 格式版本。manifest 要跨进程(daemon 扫 → 镜像构建器读)也跨时间(部署记录留档),
|
|
6004
|
+
// 加字段兼容但改语义不兼容,留一个显式版本位。
|
|
6005
|
+
version: external_exports.literal(1),
|
|
6006
|
+
...MANIFEST_BODY
|
|
6007
|
+
}).strict();
|
|
6008
|
+
EnvEvidenceSchema = external_exports.object({
|
|
6009
|
+
// 这条证据支持的是哪一项:`${kind}:${name}`,如 'cli:aliyun' / 'secret:aliyun-ak'
|
|
6010
|
+
target: external_exports.string().min(1),
|
|
6011
|
+
// 一句人话:为什么需要它 + 从哪看出来的。单据默认显示这句。
|
|
6012
|
+
reason: external_exports.string().min(1),
|
|
6013
|
+
// persona 目录内的相对路径('CLAUDE.md' / '.claude/skills/foo/SKILL.md')
|
|
6014
|
+
file: external_exports.string().min(1),
|
|
6015
|
+
// 原文摘录(一两句即可,不是整段)。默认收起,起疑时才看。
|
|
6016
|
+
//
|
|
6017
|
+
// **自由文本,schema 守不住凭据值**:这里只验得了非空,而 agent 被要求「引原文不要转述」,
|
|
6018
|
+
// 引到 `KEY=值` 那行是迟早的事。落盘前由 daemon 的 deploy/redact.ts 涂抹(reason 同理)。
|
|
6019
|
+
quote: external_exports.string().min(1)
|
|
6020
|
+
});
|
|
6021
|
+
}
|
|
6022
|
+
});
|
|
6023
|
+
|
|
6024
|
+
// ../protocol/src/deploy-schemas.ts
|
|
6025
|
+
var FulfillmentSchema, DeployStatusSchema, DeployGapSchema, DeployReceiptSchema, DeployStartArgsSchema, DeployIdArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, DeploySecretStatusSchema, DeployReceiptViewSchema, DeployListResultSchema;
|
|
6026
|
+
var init_deploy_schemas = __esm({
|
|
6027
|
+
"../protocol/src/deploy-schemas.ts"() {
|
|
6028
|
+
"use strict";
|
|
6029
|
+
init_zod();
|
|
6030
|
+
init_environment_schemas();
|
|
6031
|
+
FulfillmentSchema = external_exports.enum(["deployer", "user"]);
|
|
6032
|
+
DeployStatusSchema = external_exports.enum([
|
|
6033
|
+
"scanning",
|
|
6034
|
+
"scanFailed",
|
|
6035
|
+
"draft",
|
|
6036
|
+
"ready",
|
|
6037
|
+
"trialing",
|
|
6038
|
+
"failed",
|
|
6039
|
+
"deployed"
|
|
6040
|
+
]);
|
|
6041
|
+
DeployGapSchema = external_exports.object({
|
|
6042
|
+
// agent 的自然语言错因,如「我要解析 aliyun 的 JSON 输出,但容器里没有 python3」
|
|
6043
|
+
errorText: external_exports.string().min(1),
|
|
6044
|
+
// 原始输出片段,给人自己判断用
|
|
6045
|
+
raw: external_exports.string().optional(),
|
|
6046
|
+
// 建议补的依赖:`cli:python3` 这种。拿不准就不给,让人自己决定。
|
|
6047
|
+
suggest: external_exports.string().optional()
|
|
6048
|
+
}).strict();
|
|
6049
|
+
DeployReceiptSchema = external_exports.object({
|
|
6050
|
+
deployId: external_exports.string().min(1),
|
|
6051
|
+
personaId: external_exports.string().min(1),
|
|
6052
|
+
status: DeployStatusSchema,
|
|
6053
|
+
/**
|
|
6054
|
+
* 干这次扫描的 butler 会话 id。单据上「看它怎么干的」入口靠它把工作过程调出来。
|
|
6055
|
+
*
|
|
6056
|
+
* 扫描不是 daemon 里一个闷头跑的黑盒进程,是 persona-butler 的一次真实会话——用户能翻
|
|
6057
|
+
* 看它读了哪些文件、搜了什么。这条也顺带解决「它到底有没有上网查」这类问题:不用另造
|
|
6058
|
+
* 探针去抓证据,看一眼就知道。
|
|
6059
|
+
*/
|
|
6060
|
+
scanSessionId: external_exports.string().optional(),
|
|
6061
|
+
// 扫描产物;scanning / scanFailed 时还没有
|
|
6062
|
+
manifest: EnvironmentManifestSchema.optional(),
|
|
6063
|
+
evidence: external_exports.array(EnvEvidenceSchema).optional(),
|
|
6064
|
+
smokeTask: external_exports.string().optional(),
|
|
6065
|
+
notes: external_exports.array(external_exports.string()).default([]),
|
|
6066
|
+
/**
|
|
6067
|
+
* 每条凭据的履约选择:secret name → 'deployer' | 'user'。
|
|
6068
|
+
* **只记「谁出」,不记值。** 没做选择的凭据不在这个 map 里(缺席即未定),
|
|
6069
|
+
* 用缺席而不是 'unset' 枚举值表达未定,省掉一个下游要处处判的第三态。
|
|
6070
|
+
*/
|
|
6071
|
+
fulfillment: external_exports.record(external_exports.string(), FulfillmentSchema).default({}),
|
|
6072
|
+
/** 试装失败时的缺口清单;成功或没试装过是空数组 */
|
|
6073
|
+
gaps: external_exports.array(DeployGapSchema).default([]),
|
|
6074
|
+
// 扫描 / 试装失败的原因(status 是 scanFailed / failed 时才有意义)
|
|
6075
|
+
error: external_exports.string().optional(),
|
|
6076
|
+
createdAt: external_exports.number(),
|
|
6077
|
+
updatedAt: external_exports.number()
|
|
6078
|
+
}).strict();
|
|
6079
|
+
DeployStartArgsSchema = external_exports.object({
|
|
6080
|
+
personaId: external_exports.string().min(1)
|
|
6081
|
+
}).strict();
|
|
6082
|
+
DeployIdArgsSchema = external_exports.object({
|
|
6083
|
+
deployId: external_exports.string().min(1)
|
|
6084
|
+
}).strict();
|
|
6085
|
+
DeployPatchArgsSchema = external_exports.object({
|
|
6086
|
+
deployId: external_exports.string().min(1),
|
|
6087
|
+
patch: external_exports.object({
|
|
6088
|
+
fulfillment: external_exports.record(external_exports.string(), FulfillmentSchema).optional(),
|
|
6089
|
+
smokeTask: external_exports.string().min(1).optional(),
|
|
6090
|
+
// 人工补依赖(试装失败后补 python3 这种);整份替换 manifest
|
|
6091
|
+
manifest: EnvironmentManifestSchema.optional()
|
|
6092
|
+
}).strict()
|
|
6093
|
+
}).strict();
|
|
6094
|
+
DeployPutSecretArgsSchema = external_exports.object({
|
|
6095
|
+
deployId: external_exports.string().min(1),
|
|
6096
|
+
// 对应 manifest.secrets[].name
|
|
6097
|
+
name: external_exports.string().min(1),
|
|
6098
|
+
// 环境变量名 → 值。key 必须是该 secret 声明过的 env 之一,handler 校验。
|
|
6099
|
+
values: external_exports.record(external_exports.string(), external_exports.string())
|
|
6100
|
+
}).strict();
|
|
6101
|
+
DeployReportFindingArgsSchema = external_exports.object({
|
|
6102
|
+
deployId: external_exports.string().min(1),
|
|
6103
|
+
kind: external_exports.enum(["cli", "secret", "asset"]),
|
|
6104
|
+
// 该条目在 manifest 对应数组里的内容(形状随 kind 变,handler 按 kind 收窄校验)
|
|
6105
|
+
item: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
6106
|
+
// 这条发现的来历(一句人话 + 原文出处),形状同 EnvEvidence,target 由 handler 从 kind+name 派生
|
|
6107
|
+
evidence: external_exports.object({
|
|
6108
|
+
reason: external_exports.string().min(1),
|
|
6109
|
+
file: external_exports.string().min(1),
|
|
6110
|
+
quote: external_exports.string().min(1)
|
|
6111
|
+
})
|
|
6112
|
+
}).strict();
|
|
6113
|
+
DeployFinishScanArgsSchema = external_exports.object({
|
|
6114
|
+
deployId: external_exports.string().min(1),
|
|
6115
|
+
smokeTask: external_exports.string().min(1),
|
|
6116
|
+
notes: external_exports.array(external_exports.string()).default([])
|
|
6117
|
+
}).strict();
|
|
6118
|
+
DeploySecretStatusSchema = external_exports.object({
|
|
6119
|
+
name: external_exports.string(),
|
|
6120
|
+
// 该 secret 声明的 env 里已有值的个数
|
|
6121
|
+
filled: external_exports.number(),
|
|
6122
|
+
total: external_exports.number()
|
|
6123
|
+
}).strict();
|
|
6124
|
+
DeployReceiptViewSchema = external_exports.object({
|
|
6125
|
+
receipt: DeployReceiptSchema,
|
|
6126
|
+
secretStatus: external_exports.array(DeploySecretStatusSchema)
|
|
6127
|
+
}).strict();
|
|
6128
|
+
DeployListResultSchema = external_exports.object({
|
|
6129
|
+
receipts: external_exports.array(DeployReceiptSchema)
|
|
6130
|
+
}).strict();
|
|
6131
|
+
}
|
|
6132
|
+
});
|
|
6133
|
+
|
|
5953
6134
|
// ../protocol/src/contact-remote-access.ts
|
|
5954
6135
|
var ContactSetRemoteAccessArgsSchema, ContactSetRemoteAccessOkSchema, ContactRemoteAccessUpdatedFrameSchema;
|
|
5955
6136
|
var init_contact_remote_access = __esm({
|
|
@@ -7413,6 +7594,14 @@ var init_schemas = __esm({
|
|
|
7413
7594
|
// 快速问答临时会话标记(spec 2026-06-23-fork-quick-ask):true = 关闭抽屉即删、
|
|
7414
7595
|
// 不进 sidebar 树、daemon 启动清扫孤儿。普通会话缺省。
|
|
7415
7596
|
ephemeral: external_exports.boolean().optional(),
|
|
7597
|
+
/**
|
|
7598
|
+
* 这条会话属于哪张部署单(persona 上云的环境扫描会话)。
|
|
7599
|
+
*
|
|
7600
|
+
* 有值 = 它在单据页右栏里活着,**sidebar 不再列它**——同一条会话两处出现,和话题 worker
|
|
7601
|
+
* 会话不进「最近」是同一条规矩。不复用 `ephemeral`:那个标记会被 daemon 启动清扫**删掉**,
|
|
7602
|
+
* 而扫描会话要跟单据一样长期留着(人隔天回来还要翻管家当时是怎么判的、还要接着追问)。
|
|
7603
|
+
*/
|
|
7604
|
+
deployId: external_exports.string().min(1).optional(),
|
|
7416
7605
|
// owner-mode persona session 身份标识;UI 用它在 SessionList 过滤 + jump,
|
|
7417
7606
|
// daemon 用它做 idempotent dedupe + spawn 时派生 ctx.personaMode='owner'
|
|
7418
7607
|
ownerPersonaId: external_exports.string().min(1).optional(),
|
|
@@ -8410,6 +8599,7 @@ var init_methods = __esm({
|
|
|
8410
8599
|
init_esm();
|
|
8411
8600
|
init_attachment_schemas();
|
|
8412
8601
|
init_contact_handshake();
|
|
8602
|
+
init_deploy_schemas();
|
|
8413
8603
|
init_contact_remote_access();
|
|
8414
8604
|
init_contact();
|
|
8415
8605
|
init_feishu_auth();
|
|
@@ -8613,6 +8803,42 @@ var init_methods = __esm({
|
|
|
8613
8803
|
summary: "\u8BFB\u6587\u4EF6\u5185\u5BB9\uFF1Bguest \u8DEF\u5F84\u8FB9\u754C\u4E0E workspace:list \u540C",
|
|
8614
8804
|
args: WorkspaceReadArgs
|
|
8615
8805
|
},
|
|
8806
|
+
"deploy:start": {
|
|
8807
|
+
summary: "\u6253\u5F00\u67D0\u4E2A persona \u7684\u90E8\u7F72\u5355\uFF1A**\u5DF2\u6709\u5C31\u539F\u6837\u8FD4\u56DE\u90A3\u5F20**\uFF08\u8349\u7A3F\u7EED\u586B\uFF0C\u4E0D\u91CD\u626B\uFF0C\u4E5F\u4E0D\u65B0\u5EFA\uFF09\uFF0C\u6CA1\u6709\u624D\u5EFA\u4E00\u5F20\u5E76**\u5F02\u6B65**\u8D77\u73AF\u5883\u626B\u63CF\u3002\u4E00\u4E2A persona \u540C\u65F6\u53EA\u6709\u4E00\u5F20\u5355\uFF0C\u8981\u91CD\u626B\u8D70 deploy:rescan\uFF1Bowner-only",
|
|
8808
|
+
args: DeployStartArgsSchema
|
|
8809
|
+
},
|
|
8810
|
+
"deploy:rescan": {
|
|
8811
|
+
summary: "\u5C31\u5730\u91CD\u626B\u4E00\u5F20\u5DF2\u6709\u7684\u90E8\u7F72\u5355\uFF1A\u6E05\u6389\u4E0A\u6B21\u626B\u51FA\u6765\u7684\u6E05\u5355 / \u8BC1\u636E / \u5B58\u7591\u9879\uFF0C\u72B6\u6001\u56DE scanning\uFF0C\u8D77\u4E00\u4E2A\u65B0\u7684\u626B\u63CF\u4F1A\u8BDD\u3002**\u5DF2\u586B\u7684\u51ED\u636E\u503C\u548C\u5C65\u7EA6\u9009\u62E9\u539F\u6837\u4FDD\u7559**\uFF08\u5B83\u4EEC\u6309\u5355\u636E id \u5B58\uFF0C\u4E0D\u968F\u626B\u63CF\u7ED3\u679C\u8D70\uFF09\uFF0C\u6240\u4EE5\u91CD\u626B\u4E0D\u4F1A\u8BA9\u4EBA\u767D\u586B\u4E00\u904D\uFF1Bowner-only",
|
|
8812
|
+
args: DeployIdArgsSchema
|
|
8813
|
+
},
|
|
8814
|
+
"deploy:list": {
|
|
8815
|
+
summary: "\u5217\u51FA\u5168\u90E8\u90E8\u7F72\u5355\uFF08\u65B0\u7684\u5728\u524D\uFF09\uFF1Bowner-only\u3002\u65E0\u53C2\u6570",
|
|
8816
|
+
args: NO_ARGS
|
|
8817
|
+
},
|
|
8818
|
+
"deploy:get": {
|
|
8819
|
+
summary: "\u53D6\u4E00\u5F20\u90E8\u7F72\u5355 + \u6BCF\u6761\u51ED\u636E\u7684\u586B\u5199\u8FDB\u5EA6\u3002**\u8FDB\u5EA6\u53EA\u6709\u4E2A\u6570\u4E0D\u542B\u503C**\u2014\u2014\u51ED\u636E\u503C\u4E0D\u7ECF\u8FC7\u8FD9\u6761\u8DEF\uFF1Bowner-only",
|
|
8820
|
+
args: DeployIdArgsSchema
|
|
8821
|
+
},
|
|
8822
|
+
"deploy:patch": {
|
|
8823
|
+
summary: "\u7F16\u8F91\u90E8\u7F72\u5355\uFF1A\u9009\u5C65\u7EA6\uFF08\u8C01\u51FA\u8FD9\u6761\u51ED\u636E\uFF09/ \u6539\u5192\u70DF\u4EFB\u52A1 / \u624B\u5DE5\u8865\u4F9D\u8D56\u3002**\u4E0D\u80FD\u4ECE\u8FD9\u91CC\u4F20\u51ED\u636E\u7684\u503C**\uFF08\u503C\u8D70 deploy:putSecret\uFF09\uFF1B\u5C65\u7EA6\u540D\u5FC5\u987B\u662F\u6E05\u5355\u91CC\u58F0\u660E\u8FC7\u7684\u51ED\u636E\uFF1Bowner-only",
|
|
8824
|
+
args: DeployPatchArgsSchema
|
|
8825
|
+
},
|
|
8826
|
+
"deploy:putSecret": {
|
|
8827
|
+
summary: "\u5F55\u5165\u4E00\u6761\u51ED\u636E\u7684\u503C\u3002**\u8FD9\u662F\u503C\u552F\u4E00\u7684\u5165\u53E3**\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u53EA\u56DE\u586B\u5199\u8FDB\u5EA6\u4E0D\u56DE\u663E\u503C\u3002env \u540D\u5FC5\u987B\u662F\u8BE5\u51ED\u636E\u5728\u6E05\u5355\u91CC\u58F0\u660E\u8FC7\u7684\uFF0C\u5426\u5219\u503C\u5B58\u4E86\u4E5F\u6C38\u8FDC\u6CE8\u5165\u4E0D\u5230\uFF1Bowner-only",
|
|
8828
|
+
args: DeployPutSecretArgsSchema
|
|
8829
|
+
},
|
|
8830
|
+
"deploy:reportFinding": {
|
|
8831
|
+
summary: "\u626B\u63CF\u4E2D\u7684 butler \u9010\u6761\u4E0A\u62A5\u4E00\u4E2A\u53D1\u73B0\uFF08cli / secret / asset\uFF09\u3002**\u8FB9\u626B\u8FB9\u62A5**\uFF0C\u5355\u636E\u9875\u968F\u4E4B\u4E00\u70B9\u70B9\u586B\u5145\uFF1B\u540C (kind,name) \u91CD\u590D\u4E0A\u62A5\u5373\u8986\u76D6\u3002owner-only\u2014\u2014butler \u4F1A\u8BDD\u672C\u8EAB\u8DD1\u5728 owner \u6A21\u5F0F",
|
|
8832
|
+
args: DeployReportFindingArgsSchema
|
|
8833
|
+
},
|
|
8834
|
+
"deploy:finishScan": {
|
|
8835
|
+
summary: "butler \u6536\u5C3E\uFF1A\u7ED9\u51FA\u5192\u70DF\u4EFB\u52A1\u4E0E\u5B58\u7591\u9879\uFF0C\u5355\u636E\u4ECE scanning \u8F6C draft\u3002\u6CA1\u8C03\u5230\u5B83\u5C31\u7B49\u4E8E\u6CA1\u626B\u5B8C\u2014\u2014butler \u4F1A\u8BDD\u7ED3\u675F\u65F6\u5355\u636E\u8FD8\u505C\u5728 scanning\uFF0Cdaemon \u636E\u6B64\u5224 scanFailed\uFF1Bowner-only",
|
|
8836
|
+
args: DeployFinishScanArgsSchema
|
|
8837
|
+
},
|
|
8838
|
+
"deploy:remove": {
|
|
8839
|
+
summary: "\u5220\u6389\u4E00\u5F20\u90E8\u7F72\u5355\uFF0C\u8FDE\u5E26\u6E05\u6389\u5B83\u7684\u5168\u90E8\u51ED\u636E\u503C\uFF08\u503C\u4E0D\u8BE5\u6BD4\u5355\u636E\u6D3B\u5F97\u4E45\uFF09\uFF1Bowner-only",
|
|
8840
|
+
args: DeployIdArgsSchema
|
|
8841
|
+
},
|
|
8616
8842
|
"shift:list": {
|
|
8617
8843
|
summary: "\u5217\u51FA owner \u7684\u5168\u90E8 shift\uFF08\u6392\u73ED\uFF09\uFF0C\u7ED9 UI \u65E5\u5386\u6E32\u67D3\u7528\uFF1Bowner-only",
|
|
8618
8844
|
args: NO_ARGS
|
|
@@ -9119,7 +9345,9 @@ var init_errors2 = __esm({
|
|
|
9119
9345
|
DISPATCH_NOT_FOUND: "DISPATCH_NOT_FOUND",
|
|
9120
9346
|
// persona:get 查不到该 personaId,或 guest ctx 查非 public / 无 read grant 的 persona
|
|
9121
9347
|
// (与 DISPATCH_NOT_FOUND 同款:越权与未知 id 同码,不泄露存在性)。
|
|
9122
|
-
PERSONA_NOT_FOUND: "PERSONA_NOT_FOUND"
|
|
9348
|
+
PERSONA_NOT_FOUND: "PERSONA_NOT_FOUND",
|
|
9349
|
+
// deploy:* 查不到该部署单(persona 上云的单据)。同上口径:未知 id 与越权同码。
|
|
9350
|
+
DEPLOY_NOT_FOUND: "DEPLOY_NOT_FOUND"
|
|
9123
9351
|
};
|
|
9124
9352
|
ClawdError = class extends Error {
|
|
9125
9353
|
constructor(code, message) {
|
|
@@ -9295,6 +9523,8 @@ var init_runtime = __esm({
|
|
|
9295
9523
|
init_errors2();
|
|
9296
9524
|
init_schemas();
|
|
9297
9525
|
init_frames();
|
|
9526
|
+
init_environment_schemas();
|
|
9527
|
+
init_deploy_schemas();
|
|
9298
9528
|
init_persona_schemas();
|
|
9299
9529
|
init_persona_mode();
|
|
9300
9530
|
init_attachment_schemas();
|
|
@@ -9593,8 +9823,8 @@ var require_req = __commonJS({
|
|
|
9593
9823
|
if (req.originalUrl) {
|
|
9594
9824
|
_req.url = req.originalUrl;
|
|
9595
9825
|
} else {
|
|
9596
|
-
const
|
|
9597
|
-
_req.url = typeof
|
|
9826
|
+
const path93 = req.path;
|
|
9827
|
+
_req.url = typeof path93 === "string" ? path93 : req.url ? req.url.path || req.url : void 0;
|
|
9598
9828
|
}
|
|
9599
9829
|
if (req.query) {
|
|
9600
9830
|
_req.query = req.query;
|
|
@@ -9759,14 +9989,14 @@ var require_redact = __commonJS({
|
|
|
9759
9989
|
}
|
|
9760
9990
|
return obj;
|
|
9761
9991
|
}
|
|
9762
|
-
function parsePath(
|
|
9992
|
+
function parsePath(path93) {
|
|
9763
9993
|
const parts = [];
|
|
9764
9994
|
let current = "";
|
|
9765
9995
|
let inBrackets = false;
|
|
9766
9996
|
let inQuotes = false;
|
|
9767
9997
|
let quoteChar = "";
|
|
9768
|
-
for (let i = 0; i <
|
|
9769
|
-
const char =
|
|
9998
|
+
for (let i = 0; i < path93.length; i++) {
|
|
9999
|
+
const char = path93[i];
|
|
9770
10000
|
if (!inBrackets && char === ".") {
|
|
9771
10001
|
if (current) {
|
|
9772
10002
|
parts.push(current);
|
|
@@ -9897,10 +10127,10 @@ var require_redact = __commonJS({
|
|
|
9897
10127
|
return current;
|
|
9898
10128
|
}
|
|
9899
10129
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
9900
|
-
for (const
|
|
9901
|
-
const parts = parsePath(
|
|
10130
|
+
for (const path93 of paths) {
|
|
10131
|
+
const parts = parsePath(path93);
|
|
9902
10132
|
if (parts.includes("*")) {
|
|
9903
|
-
redactWildcardPath(obj, parts, censor,
|
|
10133
|
+
redactWildcardPath(obj, parts, censor, path93, remove);
|
|
9904
10134
|
} else {
|
|
9905
10135
|
if (remove) {
|
|
9906
10136
|
removeKey(obj, parts);
|
|
@@ -9985,8 +10215,8 @@ var require_redact = __commonJS({
|
|
|
9985
10215
|
}
|
|
9986
10216
|
} else {
|
|
9987
10217
|
if (afterWildcard.includes("*")) {
|
|
9988
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9989
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
10218
|
+
const wrappedCensor = typeof censor === "function" ? (value, path93) => {
|
|
10219
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path93];
|
|
9990
10220
|
return censor(value, fullPath);
|
|
9991
10221
|
} : censor;
|
|
9992
10222
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -10021,8 +10251,8 @@ var require_redact = __commonJS({
|
|
|
10021
10251
|
return null;
|
|
10022
10252
|
}
|
|
10023
10253
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
10024
|
-
for (const
|
|
10025
|
-
const parts = parsePath(
|
|
10254
|
+
for (const path93 of pathsToClone) {
|
|
10255
|
+
const parts = parsePath(path93);
|
|
10026
10256
|
let current = pathStructure;
|
|
10027
10257
|
for (let i = 0; i < parts.length; i++) {
|
|
10028
10258
|
const part = parts[i];
|
|
@@ -10074,24 +10304,24 @@ var require_redact = __commonJS({
|
|
|
10074
10304
|
}
|
|
10075
10305
|
return cloneSelectively(obj, pathStructure);
|
|
10076
10306
|
}
|
|
10077
|
-
function validatePath(
|
|
10078
|
-
if (typeof
|
|
10307
|
+
function validatePath(path93) {
|
|
10308
|
+
if (typeof path93 !== "string") {
|
|
10079
10309
|
throw new Error("Paths must be (non-empty) strings");
|
|
10080
10310
|
}
|
|
10081
|
-
if (
|
|
10311
|
+
if (path93 === "") {
|
|
10082
10312
|
throw new Error("Invalid redaction path ()");
|
|
10083
10313
|
}
|
|
10084
|
-
if (
|
|
10085
|
-
throw new Error(`Invalid redaction path (${
|
|
10314
|
+
if (path93.includes("..")) {
|
|
10315
|
+
throw new Error(`Invalid redaction path (${path93})`);
|
|
10086
10316
|
}
|
|
10087
|
-
if (
|
|
10088
|
-
throw new Error(`Invalid redaction path (${
|
|
10317
|
+
if (path93.includes(",")) {
|
|
10318
|
+
throw new Error(`Invalid redaction path (${path93})`);
|
|
10089
10319
|
}
|
|
10090
10320
|
let bracketCount = 0;
|
|
10091
10321
|
let inQuotes = false;
|
|
10092
10322
|
let quoteChar = "";
|
|
10093
|
-
for (let i = 0; i <
|
|
10094
|
-
const char =
|
|
10323
|
+
for (let i = 0; i < path93.length; i++) {
|
|
10324
|
+
const char = path93[i];
|
|
10095
10325
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
10096
10326
|
if (!inQuotes) {
|
|
10097
10327
|
inQuotes = true;
|
|
@@ -10105,20 +10335,20 @@ var require_redact = __commonJS({
|
|
|
10105
10335
|
} else if (char === "]" && !inQuotes) {
|
|
10106
10336
|
bracketCount--;
|
|
10107
10337
|
if (bracketCount < 0) {
|
|
10108
|
-
throw new Error(`Invalid redaction path (${
|
|
10338
|
+
throw new Error(`Invalid redaction path (${path93})`);
|
|
10109
10339
|
}
|
|
10110
10340
|
}
|
|
10111
10341
|
}
|
|
10112
10342
|
if (bracketCount !== 0) {
|
|
10113
|
-
throw new Error(`Invalid redaction path (${
|
|
10343
|
+
throw new Error(`Invalid redaction path (${path93})`);
|
|
10114
10344
|
}
|
|
10115
10345
|
}
|
|
10116
10346
|
function validatePaths(paths) {
|
|
10117
10347
|
if (!Array.isArray(paths)) {
|
|
10118
10348
|
throw new TypeError("paths must be an array");
|
|
10119
10349
|
}
|
|
10120
|
-
for (const
|
|
10121
|
-
validatePath(
|
|
10350
|
+
for (const path93 of paths) {
|
|
10351
|
+
validatePath(path93);
|
|
10122
10352
|
}
|
|
10123
10353
|
}
|
|
10124
10354
|
function slowRedact(options = {}) {
|
|
@@ -10286,8 +10516,8 @@ var require_redaction = __commonJS({
|
|
|
10286
10516
|
if (shape[k2] === null) {
|
|
10287
10517
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
10288
10518
|
} else {
|
|
10289
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10290
|
-
return censor(value, [k2, ...
|
|
10519
|
+
const wrappedCensor = typeof censor === "function" ? (value, path93) => {
|
|
10520
|
+
return censor(value, [k2, ...path93]);
|
|
10291
10521
|
} : censor;
|
|
10292
10522
|
o[k2] = Redact({
|
|
10293
10523
|
paths: shape[k2],
|
|
@@ -10505,10 +10735,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
10505
10735
|
var require_sonic_boom = __commonJS({
|
|
10506
10736
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
10507
10737
|
"use strict";
|
|
10508
|
-
var
|
|
10738
|
+
var fs82 = require("fs");
|
|
10509
10739
|
var EventEmitter3 = require("events");
|
|
10510
10740
|
var inherits = require("util").inherits;
|
|
10511
|
-
var
|
|
10741
|
+
var path93 = require("path");
|
|
10512
10742
|
var sleep2 = require_atomic_sleep();
|
|
10513
10743
|
var assert = require("assert");
|
|
10514
10744
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -10562,20 +10792,20 @@ var require_sonic_boom = __commonJS({
|
|
|
10562
10792
|
const mode = sonic.mode;
|
|
10563
10793
|
if (sonic.sync) {
|
|
10564
10794
|
try {
|
|
10565
|
-
if (sonic.mkdir)
|
|
10566
|
-
const fd =
|
|
10795
|
+
if (sonic.mkdir) fs82.mkdirSync(path93.dirname(file), { recursive: true });
|
|
10796
|
+
const fd = fs82.openSync(file, flags, mode);
|
|
10567
10797
|
fileOpened(null, fd);
|
|
10568
10798
|
} catch (err) {
|
|
10569
10799
|
fileOpened(err);
|
|
10570
10800
|
throw err;
|
|
10571
10801
|
}
|
|
10572
10802
|
} else if (sonic.mkdir) {
|
|
10573
|
-
|
|
10803
|
+
fs82.mkdir(path93.dirname(file), { recursive: true }, (err) => {
|
|
10574
10804
|
if (err) return fileOpened(err);
|
|
10575
|
-
|
|
10805
|
+
fs82.open(file, flags, mode, fileOpened);
|
|
10576
10806
|
});
|
|
10577
10807
|
} else {
|
|
10578
|
-
|
|
10808
|
+
fs82.open(file, flags, mode, fileOpened);
|
|
10579
10809
|
}
|
|
10580
10810
|
}
|
|
10581
10811
|
function SonicBoom(opts) {
|
|
@@ -10616,8 +10846,8 @@ var require_sonic_boom = __commonJS({
|
|
|
10616
10846
|
this.flush = flushBuffer;
|
|
10617
10847
|
this.flushSync = flushBufferSync;
|
|
10618
10848
|
this._actualWrite = actualWriteBuffer;
|
|
10619
|
-
fsWriteSync = () =>
|
|
10620
|
-
fsWrite = () =>
|
|
10849
|
+
fsWriteSync = () => fs82.writeSync(this.fd, this._writingBuf);
|
|
10850
|
+
fsWrite = () => fs82.write(this.fd, this._writingBuf, this.release);
|
|
10621
10851
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
10622
10852
|
this._writingBuf = "";
|
|
10623
10853
|
this.write = write;
|
|
@@ -10626,15 +10856,15 @@ var require_sonic_boom = __commonJS({
|
|
|
10626
10856
|
this._actualWrite = actualWrite;
|
|
10627
10857
|
fsWriteSync = () => {
|
|
10628
10858
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10629
|
-
return
|
|
10859
|
+
return fs82.writeSync(this.fd, this._writingBuf);
|
|
10630
10860
|
}
|
|
10631
|
-
return
|
|
10861
|
+
return fs82.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10632
10862
|
};
|
|
10633
10863
|
fsWrite = () => {
|
|
10634
10864
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10635
|
-
return
|
|
10865
|
+
return fs82.write(this.fd, this._writingBuf, this.release);
|
|
10636
10866
|
}
|
|
10637
|
-
return
|
|
10867
|
+
return fs82.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
10638
10868
|
};
|
|
10639
10869
|
} else {
|
|
10640
10870
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -10691,7 +10921,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10691
10921
|
}
|
|
10692
10922
|
}
|
|
10693
10923
|
if (this._fsync) {
|
|
10694
|
-
|
|
10924
|
+
fs82.fsyncSync(this.fd);
|
|
10695
10925
|
}
|
|
10696
10926
|
const len = this._len;
|
|
10697
10927
|
if (this._reopening) {
|
|
@@ -10805,7 +11035,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10805
11035
|
const onDrain = () => {
|
|
10806
11036
|
if (!this._fsync) {
|
|
10807
11037
|
try {
|
|
10808
|
-
|
|
11038
|
+
fs82.fsync(this.fd, (err) => {
|
|
10809
11039
|
this._flushPending = false;
|
|
10810
11040
|
cb(err);
|
|
10811
11041
|
});
|
|
@@ -10907,7 +11137,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10907
11137
|
const fd = this.fd;
|
|
10908
11138
|
this.once("ready", () => {
|
|
10909
11139
|
if (fd !== this.fd) {
|
|
10910
|
-
|
|
11140
|
+
fs82.close(fd, (err) => {
|
|
10911
11141
|
if (err) {
|
|
10912
11142
|
return this.emit("error", err);
|
|
10913
11143
|
}
|
|
@@ -10956,7 +11186,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10956
11186
|
buf = this._bufs[0];
|
|
10957
11187
|
}
|
|
10958
11188
|
try {
|
|
10959
|
-
const n = Buffer.isBuffer(buf) ?
|
|
11189
|
+
const n = Buffer.isBuffer(buf) ? fs82.writeSync(this.fd, buf) : fs82.writeSync(this.fd, buf, "utf8");
|
|
10960
11190
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
10961
11191
|
buf = releasedBufObj.writingBuf;
|
|
10962
11192
|
this._len = releasedBufObj.len;
|
|
@@ -10972,7 +11202,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10972
11202
|
}
|
|
10973
11203
|
}
|
|
10974
11204
|
try {
|
|
10975
|
-
|
|
11205
|
+
fs82.fsyncSync(this.fd);
|
|
10976
11206
|
} catch {
|
|
10977
11207
|
}
|
|
10978
11208
|
}
|
|
@@ -10993,7 +11223,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10993
11223
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
10994
11224
|
}
|
|
10995
11225
|
try {
|
|
10996
|
-
const n =
|
|
11226
|
+
const n = fs82.writeSync(this.fd, buf);
|
|
10997
11227
|
buf = buf.subarray(n);
|
|
10998
11228
|
this._len = Math.max(this._len - n, 0);
|
|
10999
11229
|
if (buf.length <= 0) {
|
|
@@ -11021,13 +11251,13 @@ var require_sonic_boom = __commonJS({
|
|
|
11021
11251
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
11022
11252
|
if (this.sync) {
|
|
11023
11253
|
try {
|
|
11024
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
11254
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs82.writeSync(this.fd, this._writingBuf) : fs82.writeSync(this.fd, this._writingBuf, "utf8");
|
|
11025
11255
|
release(null, written);
|
|
11026
11256
|
} catch (err) {
|
|
11027
11257
|
release(err);
|
|
11028
11258
|
}
|
|
11029
11259
|
} else {
|
|
11030
|
-
|
|
11260
|
+
fs82.write(this.fd, this._writingBuf, release);
|
|
11031
11261
|
}
|
|
11032
11262
|
}
|
|
11033
11263
|
function actualWriteBuffer() {
|
|
@@ -11036,7 +11266,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11036
11266
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
11037
11267
|
if (this.sync) {
|
|
11038
11268
|
try {
|
|
11039
|
-
const written =
|
|
11269
|
+
const written = fs82.writeSync(this.fd, this._writingBuf);
|
|
11040
11270
|
release(null, written);
|
|
11041
11271
|
} catch (err) {
|
|
11042
11272
|
release(err);
|
|
@@ -11045,7 +11275,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11045
11275
|
if (kCopyBuffer) {
|
|
11046
11276
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
11047
11277
|
}
|
|
11048
|
-
|
|
11278
|
+
fs82.write(this.fd, this._writingBuf, release);
|
|
11049
11279
|
}
|
|
11050
11280
|
}
|
|
11051
11281
|
function actualClose(sonic) {
|
|
@@ -11061,12 +11291,12 @@ var require_sonic_boom = __commonJS({
|
|
|
11061
11291
|
sonic._lens = [];
|
|
11062
11292
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
11063
11293
|
try {
|
|
11064
|
-
|
|
11294
|
+
fs82.fsync(sonic.fd, closeWrapped);
|
|
11065
11295
|
} catch {
|
|
11066
11296
|
}
|
|
11067
11297
|
function closeWrapped() {
|
|
11068
11298
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
11069
|
-
|
|
11299
|
+
fs82.close(sonic.fd, done);
|
|
11070
11300
|
} else {
|
|
11071
11301
|
done();
|
|
11072
11302
|
}
|
|
@@ -14201,11 +14431,11 @@ var init_lib = __esm({
|
|
|
14201
14431
|
}
|
|
14202
14432
|
}
|
|
14203
14433
|
},
|
|
14204
|
-
addToPath: function addToPath(
|
|
14205
|
-
var last =
|
|
14434
|
+
addToPath: function addToPath(path93, added, removed, oldPosInc, options) {
|
|
14435
|
+
var last = path93.lastComponent;
|
|
14206
14436
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14207
14437
|
return {
|
|
14208
|
-
oldPos:
|
|
14438
|
+
oldPos: path93.oldPos + oldPosInc,
|
|
14209
14439
|
lastComponent: {
|
|
14210
14440
|
count: last.count + 1,
|
|
14211
14441
|
added,
|
|
@@ -14215,7 +14445,7 @@ var init_lib = __esm({
|
|
|
14215
14445
|
};
|
|
14216
14446
|
} else {
|
|
14217
14447
|
return {
|
|
14218
|
-
oldPos:
|
|
14448
|
+
oldPos: path93.oldPos + oldPosInc,
|
|
14219
14449
|
lastComponent: {
|
|
14220
14450
|
count: 1,
|
|
14221
14451
|
added,
|
|
@@ -14797,10 +15027,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
14797
15027
|
const memories = raw.map((m2) => {
|
|
14798
15028
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14799
15029
|
const rec4 = m2;
|
|
14800
|
-
const
|
|
15030
|
+
const path93 = typeof rec4.path === "string" ? rec4.path : null;
|
|
14801
15031
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
14802
|
-
if (!
|
|
14803
|
-
const entry = { path:
|
|
15032
|
+
if (!path93 || content == null) return null;
|
|
15033
|
+
const entry = { path: path93, content };
|
|
14804
15034
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
14805
15035
|
return entry;
|
|
14806
15036
|
}).filter((m2) => m2 !== null);
|
|
@@ -15666,10 +15896,10 @@ function parseAttachment(obj) {
|
|
|
15666
15896
|
const memories = raw.map((m2) => {
|
|
15667
15897
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15668
15898
|
const rec4 = m2;
|
|
15669
|
-
const
|
|
15899
|
+
const path93 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15670
15900
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15671
|
-
if (!
|
|
15672
|
-
const out = { path:
|
|
15901
|
+
if (!path93 || content == null) return null;
|
|
15902
|
+
const out = { path: path93, content };
|
|
15673
15903
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
15674
15904
|
return out;
|
|
15675
15905
|
}).filter((m2) => m2 !== null);
|
|
@@ -36643,8 +36873,8 @@ var require_utils = __commonJS({
|
|
|
36643
36873
|
var result = transform[inputType][outputType](input);
|
|
36644
36874
|
return result;
|
|
36645
36875
|
};
|
|
36646
|
-
exports2.resolve = function(
|
|
36647
|
-
var parts =
|
|
36876
|
+
exports2.resolve = function(path93) {
|
|
36877
|
+
var parts = path93.split("/");
|
|
36648
36878
|
var result = [];
|
|
36649
36879
|
for (var index = 0; index < parts.length; index++) {
|
|
36650
36880
|
var part = parts[index];
|
|
@@ -42497,18 +42727,18 @@ var require_object = __commonJS({
|
|
|
42497
42727
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
42498
42728
|
this.files[name] = object;
|
|
42499
42729
|
};
|
|
42500
|
-
var parentFolder = function(
|
|
42501
|
-
if (
|
|
42502
|
-
|
|
42730
|
+
var parentFolder = function(path93) {
|
|
42731
|
+
if (path93.slice(-1) === "/") {
|
|
42732
|
+
path93 = path93.substring(0, path93.length - 1);
|
|
42503
42733
|
}
|
|
42504
|
-
var lastSlash =
|
|
42505
|
-
return lastSlash > 0 ?
|
|
42734
|
+
var lastSlash = path93.lastIndexOf("/");
|
|
42735
|
+
return lastSlash > 0 ? path93.substring(0, lastSlash) : "";
|
|
42506
42736
|
};
|
|
42507
|
-
var forceTrailingSlash = function(
|
|
42508
|
-
if (
|
|
42509
|
-
|
|
42737
|
+
var forceTrailingSlash = function(path93) {
|
|
42738
|
+
if (path93.slice(-1) !== "/") {
|
|
42739
|
+
path93 += "/";
|
|
42510
42740
|
}
|
|
42511
|
-
return
|
|
42741
|
+
return path93;
|
|
42512
42742
|
};
|
|
42513
42743
|
var folderAdd = function(name, createFolders) {
|
|
42514
42744
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -43510,7 +43740,7 @@ var require_lib3 = __commonJS({
|
|
|
43510
43740
|
// src/run-case/recorder.ts
|
|
43511
43741
|
function startRunCaseRecorder(opts) {
|
|
43512
43742
|
const now = opts.now ?? Date.now;
|
|
43513
|
-
const dir =
|
|
43743
|
+
const dir = import_node_path75.default.dirname(opts.recordPath);
|
|
43514
43744
|
let stream = null;
|
|
43515
43745
|
let closing = false;
|
|
43516
43746
|
let closedSettled = false;
|
|
@@ -43550,12 +43780,12 @@ function startRunCaseRecorder(opts) {
|
|
|
43550
43780
|
};
|
|
43551
43781
|
return { tap, close, closed };
|
|
43552
43782
|
}
|
|
43553
|
-
var import_node_fs54,
|
|
43783
|
+
var import_node_fs54, import_node_path75;
|
|
43554
43784
|
var init_recorder = __esm({
|
|
43555
43785
|
"src/run-case/recorder.ts"() {
|
|
43556
43786
|
"use strict";
|
|
43557
43787
|
import_node_fs54 = __toESM(require("fs"), 1);
|
|
43558
|
-
|
|
43788
|
+
import_node_path75 = __toESM(require("path"), 1);
|
|
43559
43789
|
}
|
|
43560
43790
|
});
|
|
43561
43791
|
|
|
@@ -43598,7 +43828,7 @@ var init_wire = __esm({
|
|
|
43598
43828
|
// src/run-case/controller.ts
|
|
43599
43829
|
async function runController(opts) {
|
|
43600
43830
|
const now = opts.now ?? Date.now;
|
|
43601
|
-
const cwd = opts.cwd ?? (0, import_node_fs55.mkdtempSync)(
|
|
43831
|
+
const cwd = opts.cwd ?? (0, import_node_fs55.mkdtempSync)(import_node_path76.default.join(import_node_os27.default.tmpdir(), "clawd-runcase-"));
|
|
43602
43832
|
const ownsCwd = opts.cwd === void 0;
|
|
43603
43833
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
43604
43834
|
const spawnCtx = { cwd };
|
|
@@ -43765,13 +43995,13 @@ async function runController(opts) {
|
|
|
43765
43995
|
}
|
|
43766
43996
|
return exitCode ?? 0;
|
|
43767
43997
|
}
|
|
43768
|
-
var import_node_fs55, import_node_os27,
|
|
43998
|
+
var import_node_fs55, import_node_os27, import_node_path76;
|
|
43769
43999
|
var init_controller = __esm({
|
|
43770
44000
|
"src/run-case/controller.ts"() {
|
|
43771
44001
|
"use strict";
|
|
43772
44002
|
import_node_fs55 = require("fs");
|
|
43773
44003
|
import_node_os27 = __toESM(require("os"), 1);
|
|
43774
|
-
|
|
44004
|
+
import_node_path76 = __toESM(require("path"), 1);
|
|
43775
44005
|
init_claude();
|
|
43776
44006
|
init_stdout_splitter();
|
|
43777
44007
|
init_permission_stdio();
|
|
@@ -44046,7 +44276,7 @@ Env (advanced):
|
|
|
44046
44276
|
`;
|
|
44047
44277
|
|
|
44048
44278
|
// src/index.ts
|
|
44049
|
-
var
|
|
44279
|
+
var import_node_path74 = __toESM(require("path"), 1);
|
|
44050
44280
|
var import_node_fs53 = __toESM(require("fs"), 1);
|
|
44051
44281
|
var import_node_os26 = __toESM(require("os"), 1);
|
|
44052
44282
|
var import_node_crypto22 = require("crypto");
|
|
@@ -48427,6 +48657,7 @@ var SessionManager = class {
|
|
|
48427
48657
|
// persona 绑定的 model / effort 快照进 SessionFile(spec 2026-08-12)
|
|
48428
48658
|
...personaDefaultFields(personaDefaults),
|
|
48429
48659
|
...args.sourceSessionId ? { shiftFiredFromSessionId: args.sourceSessionId } : {},
|
|
48660
|
+
...args.deployId ? { deployId: args.deployId } : {},
|
|
48430
48661
|
createdAt: now,
|
|
48431
48662
|
updatedAt: now
|
|
48432
48663
|
};
|
|
@@ -51189,8 +51420,8 @@ function turnStartInput(text) {
|
|
|
51189
51420
|
const items = [];
|
|
51190
51421
|
let leftover = text;
|
|
51191
51422
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
51192
|
-
const [marker, name,
|
|
51193
|
-
items.push({ type: "skill", name, path:
|
|
51423
|
+
const [marker, name, path93] = m2;
|
|
51424
|
+
items.push({ type: "skill", name, path: path93 });
|
|
51194
51425
|
leftover = leftover.replace(marker, "");
|
|
51195
51426
|
}
|
|
51196
51427
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -54110,6 +54341,412 @@ function buildShiftInternalHandlers(deps) {
|
|
|
54110
54341
|
};
|
|
54111
54342
|
}
|
|
54112
54343
|
|
|
54344
|
+
// src/handlers/deploy.ts
|
|
54345
|
+
init_protocol();
|
|
54346
|
+
|
|
54347
|
+
// src/deploy/redact.ts
|
|
54348
|
+
var SECRET_KEY_HINT = /(KEY|TOKEN|SECRET|PASSWORD|PASSWD|PWD|CREDENTIAL|AKID|ACCESS_?ID)/i;
|
|
54349
|
+
var KNOWN_SECRET_SHAPES = [
|
|
54350
|
+
/LTAI[A-Za-z0-9]{6,}/,
|
|
54351
|
+
/eyJ[A-Za-z0-9_-]{10,}/,
|
|
54352
|
+
/sk-[A-Za-z0-9_-]{16,}/,
|
|
54353
|
+
/gh[pousr]_[A-Za-z0-9]{20,}/,
|
|
54354
|
+
/AKIA[A-Z0-9]{12,}/
|
|
54355
|
+
];
|
|
54356
|
+
var BARE_SECRET = new RegExp(KNOWN_SECRET_SHAPES.map((re) => re.source).join("|"), "g");
|
|
54357
|
+
var REDACTED = "<\u5DF2\u7565\u53BB>";
|
|
54358
|
+
function isPlaceholder(value) {
|
|
54359
|
+
return value.length === 0 || value === REDACTED || /^\$\{?[A-Za-z_]/.test(value) || // ${VAR} / $VAR
|
|
54360
|
+
/^["']?[<(]/.test(value) || // <your-key> / (填这里)
|
|
54361
|
+
/^["']?(your|xxx+|todo|placeholder|change[-_]?me|填)/i.test(value);
|
|
54362
|
+
}
|
|
54363
|
+
var ASSIGNMENT = /((?:export\s+)?)(["']?)([A-Za-z_][A-Za-z0-9_.-]*)\2(\s*[:=]\s*)(["']?)([^\s"'`,;)\]}]+)/g;
|
|
54364
|
+
function redactSecretValues(text) {
|
|
54365
|
+
const byAssignment = text.replace(
|
|
54366
|
+
ASSIGNMENT,
|
|
54367
|
+
(whole, exp, kq, key, sep4, vq, value) => {
|
|
54368
|
+
if (isPlaceholder(value)) return whole;
|
|
54369
|
+
const looksSecret = SECRET_KEY_HINT.test(key) || KNOWN_SECRET_SHAPES.some((re) => re.test(value));
|
|
54370
|
+
return looksSecret ? `${exp}${kq}${key}${kq}${sep4}${vq}${REDACTED}` : whole;
|
|
54371
|
+
}
|
|
54372
|
+
);
|
|
54373
|
+
return byAssignment.replace(BARE_SECRET, REDACTED);
|
|
54374
|
+
}
|
|
54375
|
+
function redactEvidence(evidence) {
|
|
54376
|
+
return {
|
|
54377
|
+
...evidence,
|
|
54378
|
+
reason: redactSecretValues(evidence.reason),
|
|
54379
|
+
quote: redactSecretValues(evidence.quote)
|
|
54380
|
+
};
|
|
54381
|
+
}
|
|
54382
|
+
|
|
54383
|
+
// src/handlers/deploy.ts
|
|
54384
|
+
function ensureOwner(ctx) {
|
|
54385
|
+
if (!ctx || ctx.principal.kind !== "owner") {
|
|
54386
|
+
throw new ClawdError(ERROR_CODES.UNAUTHORIZED, "UNAUTHORIZED: deploy:* requires owner ctx");
|
|
54387
|
+
}
|
|
54388
|
+
}
|
|
54389
|
+
function mustGet(deps, deployId) {
|
|
54390
|
+
const receipt = deps.receipts.get(deployId);
|
|
54391
|
+
if (!receipt) throw new ClawdError(ERROR_CODES.DEPLOY_NOT_FOUND, `DEPLOY_NOT_FOUND: \u6CA1\u6709\u8FD9\u5F20\u90E8\u7F72\u5355\uFF08${deployId}\uFF09`);
|
|
54392
|
+
return receipt;
|
|
54393
|
+
}
|
|
54394
|
+
function mustBeScanning(receipt, method) {
|
|
54395
|
+
if (receipt.status !== "scanning") {
|
|
54396
|
+
throw new ClawdError(
|
|
54397
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54398
|
+
`VALIDATION_ERROR: ${method} \u53EA\u5728\u626B\u63CF\u671F\u53EF\u7528\uFF08\u5F53\u524D ${receipt.status}\uFF09`
|
|
54399
|
+
);
|
|
54400
|
+
}
|
|
54401
|
+
return receipt;
|
|
54402
|
+
}
|
|
54403
|
+
function secretStatusOf(deps, receipt) {
|
|
54404
|
+
const declared = receipt.manifest?.secrets ?? [];
|
|
54405
|
+
return declared.map((s) => ({
|
|
54406
|
+
name: s.name,
|
|
54407
|
+
// 只看部署级:使用者自带的那部分由使用者各自绑定,不在部署者这张单据的进度里
|
|
54408
|
+
filled: deps.secrets.filledKeys(receipt.deployId, s.name).length,
|
|
54409
|
+
total: s.env.length
|
|
54410
|
+
}));
|
|
54411
|
+
}
|
|
54412
|
+
function buildDeployHandlers(deps) {
|
|
54413
|
+
const view = (receipt) => ({
|
|
54414
|
+
response: { type: "deploy:receipt", receipt, secretStatus: secretStatusOf(deps, receipt) }
|
|
54415
|
+
});
|
|
54416
|
+
const start = async (frame, _client, ctx) => {
|
|
54417
|
+
ensureOwner(ctx);
|
|
54418
|
+
const args = parseArgs2(DeployStartArgsSchema, frame, "deploy:start");
|
|
54419
|
+
if (!deps.hasPersona(args.personaId)) {
|
|
54420
|
+
throw new ClawdError(ERROR_CODES.PERSONA_NOT_FOUND, `PERSONA_NOT_FOUND: \u6CA1\u6709\u8FD9\u4E2A persona\uFF08${args.personaId}\uFF09`);
|
|
54421
|
+
}
|
|
54422
|
+
const existing = deps.receipts.list().find((r) => r.personaId === args.personaId);
|
|
54423
|
+
if (existing) return view(existing);
|
|
54424
|
+
const receipt = deps.receipts.create({
|
|
54425
|
+
deployId: deps.genId(),
|
|
54426
|
+
personaId: args.personaId,
|
|
54427
|
+
status: "scanning"
|
|
54428
|
+
});
|
|
54429
|
+
const scanSessionId = deps.startScan(receipt.deployId, args.personaId);
|
|
54430
|
+
if (scanSessionId) deps.receipts.update(receipt.deployId, { scanSessionId });
|
|
54431
|
+
return view(deps.receipts.get(receipt.deployId) ?? receipt);
|
|
54432
|
+
};
|
|
54433
|
+
const rescan = async (frame, _client, ctx) => {
|
|
54434
|
+
ensureOwner(ctx);
|
|
54435
|
+
const args = parseArgs2(DeployIdArgsSchema, frame, "deploy:rescan");
|
|
54436
|
+
const receipt = mustGet(deps, args.deployId);
|
|
54437
|
+
if (receipt.status === "scanning") {
|
|
54438
|
+
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "VALIDATION_ERROR: \u8FD9\u5F20\u5355\u6B63\u5728\u626B\u63CF\u4E2D\uFF0C\u7B49\u5B83\u626B\u5B8C\u518D\u91CD\u626B");
|
|
54439
|
+
}
|
|
54440
|
+
deps.receipts.update(args.deployId, {
|
|
54441
|
+
status: "scanning",
|
|
54442
|
+
manifest: void 0,
|
|
54443
|
+
evidence: [],
|
|
54444
|
+
notes: [],
|
|
54445
|
+
smokeTask: void 0,
|
|
54446
|
+
error: void 0,
|
|
54447
|
+
scanSessionId: void 0
|
|
54448
|
+
});
|
|
54449
|
+
const scanSessionId = deps.startScan(args.deployId, receipt.personaId);
|
|
54450
|
+
if (scanSessionId) deps.receipts.update(args.deployId, { scanSessionId });
|
|
54451
|
+
return view(deps.receipts.get(args.deployId) ?? receipt);
|
|
54452
|
+
};
|
|
54453
|
+
const list = async (_frame, _client, ctx) => {
|
|
54454
|
+
ensureOwner(ctx);
|
|
54455
|
+
return { response: { type: "deploy:list", receipts: deps.receipts.list() } };
|
|
54456
|
+
};
|
|
54457
|
+
const get = async (frame, _client, ctx) => {
|
|
54458
|
+
ensureOwner(ctx);
|
|
54459
|
+
const args = parseArgs2(DeployIdArgsSchema, frame, "deploy:get");
|
|
54460
|
+
return view(mustGet(deps, args.deployId));
|
|
54461
|
+
};
|
|
54462
|
+
const patch = async (frame, _client, ctx) => {
|
|
54463
|
+
ensureOwner(ctx);
|
|
54464
|
+
const args = parseArgs2(DeployPatchArgsSchema, frame, "deploy:patch");
|
|
54465
|
+
const receipt = mustGet(deps, args.deployId);
|
|
54466
|
+
if (args.patch.fulfillment) {
|
|
54467
|
+
const declared = new Set((args.patch.manifest ?? receipt.manifest)?.secrets.map((s) => s.name) ?? []);
|
|
54468
|
+
for (const name of Object.keys(args.patch.fulfillment)) {
|
|
54469
|
+
if (!declared.has(name)) {
|
|
54470
|
+
throw new ClawdError(
|
|
54471
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54472
|
+
`VALIDATION_ERROR: \u6E05\u5355\u91CC\u6CA1\u6709\u53EB\u300C${name}\u300D\u7684\u51ED\u636E`
|
|
54473
|
+
);
|
|
54474
|
+
}
|
|
54475
|
+
}
|
|
54476
|
+
}
|
|
54477
|
+
const next = deps.receipts.update(args.deployId, args.patch);
|
|
54478
|
+
return view(next ?? receipt);
|
|
54479
|
+
};
|
|
54480
|
+
const putSecret = async (frame, _client, ctx) => {
|
|
54481
|
+
ensureOwner(ctx);
|
|
54482
|
+
const args = parseArgs2(DeployPutSecretArgsSchema, frame, "deploy:putSecret");
|
|
54483
|
+
const receipt = mustGet(deps, args.deployId);
|
|
54484
|
+
const declared = receipt.manifest?.secrets.find((s) => s.name === args.name);
|
|
54485
|
+
if (!declared) {
|
|
54486
|
+
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `VALIDATION_ERROR: \u6E05\u5355\u91CC\u6CA1\u6709\u53EB\u300C${args.name}\u300D\u7684\u51ED\u636E`);
|
|
54487
|
+
}
|
|
54488
|
+
const allowed = new Set(declared.env);
|
|
54489
|
+
for (const key of Object.keys(args.values)) {
|
|
54490
|
+
if (!allowed.has(key)) {
|
|
54491
|
+
throw new ClawdError(
|
|
54492
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54493
|
+
`VALIDATION_ERROR: \u300C${args.name}\u300D\u6CA1\u6709\u58F0\u660E\u73AF\u5883\u53D8\u91CF ${key}`
|
|
54494
|
+
);
|
|
54495
|
+
}
|
|
54496
|
+
}
|
|
54497
|
+
deps.secrets.put({ deployId: args.deployId, name: args.name, values: args.values });
|
|
54498
|
+
return view(receipt);
|
|
54499
|
+
};
|
|
54500
|
+
const reportFinding = async (frame, _client, ctx) => {
|
|
54501
|
+
ensureOwner(ctx);
|
|
54502
|
+
const args = parseArgs2(DeployReportFindingArgsSchema, frame, "deploy:reportFinding");
|
|
54503
|
+
const receipt = mustBeScanning(mustGet(deps, args.deployId), "deploy:reportFinding");
|
|
54504
|
+
const schema = args.kind === "cli" ? EnvCliSchema : args.kind === "secret" ? EnvSecretSchema : EnvAssetSchema;
|
|
54505
|
+
const parsed = schema.safeParse(args.item);
|
|
54506
|
+
if (!parsed.success) {
|
|
54507
|
+
const first = parsed.error.issues[0];
|
|
54508
|
+
throw new ClawdError(
|
|
54509
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54510
|
+
`VALIDATION_ERROR: ${args.kind} \u6761\u76EE\u4E0D\u5408\u6CD5\uFF1A${first ? `${first.path.join(".")} ${first.message}` : ""}`
|
|
54511
|
+
);
|
|
54512
|
+
}
|
|
54513
|
+
const item = parsed.data;
|
|
54514
|
+
const base = receipt.manifest ?? { version: 1, clis: [], secrets: [], assets: [] };
|
|
54515
|
+
const key = args.kind === "cli" ? "clis" : args.kind === "secret" ? "secrets" : "assets";
|
|
54516
|
+
const list2 = [...base[key]];
|
|
54517
|
+
const idx = list2.findIndex((x) => x.name === item.name);
|
|
54518
|
+
if (idx === -1) list2.push(item);
|
|
54519
|
+
else list2[idx] = item;
|
|
54520
|
+
const target = `${args.kind}:${item.name}`;
|
|
54521
|
+
const evidence = [
|
|
54522
|
+
...(receipt.evidence ?? []).filter((e) => e.target !== target),
|
|
54523
|
+
redactEvidence({ target, ...args.evidence })
|
|
54524
|
+
];
|
|
54525
|
+
const next = deps.receipts.update(args.deployId, {
|
|
54526
|
+
manifest: { ...base, [key]: list2 },
|
|
54527
|
+
evidence
|
|
54528
|
+
});
|
|
54529
|
+
return view(next ?? receipt);
|
|
54530
|
+
};
|
|
54531
|
+
const finishScan = async (frame, _client, ctx) => {
|
|
54532
|
+
ensureOwner(ctx);
|
|
54533
|
+
const args = parseArgs2(DeployFinishScanArgsSchema, frame, "deploy:finishScan");
|
|
54534
|
+
mustBeScanning(mustGet(deps, args.deployId), "deploy:finishScan");
|
|
54535
|
+
const next = deps.receipts.update(args.deployId, {
|
|
54536
|
+
status: "draft",
|
|
54537
|
+
smokeTask: args.smokeTask ? redactSecretValues(args.smokeTask) : args.smokeTask,
|
|
54538
|
+
notes: args.notes?.map(redactSecretValues),
|
|
54539
|
+
error: void 0
|
|
54540
|
+
});
|
|
54541
|
+
return view(next);
|
|
54542
|
+
};
|
|
54543
|
+
const remove = async (frame, _client, ctx) => {
|
|
54544
|
+
ensureOwner(ctx);
|
|
54545
|
+
const args = parseArgs2(DeployIdArgsSchema, frame, "deploy:remove");
|
|
54546
|
+
mustGet(deps, args.deployId);
|
|
54547
|
+
deps.receipts.remove(args.deployId);
|
|
54548
|
+
deps.secrets.removeDeploy(args.deployId);
|
|
54549
|
+
return { response: { type: "deploy:remove", deployId: args.deployId } };
|
|
54550
|
+
};
|
|
54551
|
+
return {
|
|
54552
|
+
"deploy:start": start,
|
|
54553
|
+
"deploy:rescan": rescan,
|
|
54554
|
+
"deploy:list": list,
|
|
54555
|
+
"deploy:get": get,
|
|
54556
|
+
"deploy:patch": patch,
|
|
54557
|
+
"deploy:putSecret": putSecret,
|
|
54558
|
+
"deploy:reportFinding": reportFinding,
|
|
54559
|
+
"deploy:finishScan": finishScan,
|
|
54560
|
+
"deploy:remove": remove
|
|
54561
|
+
};
|
|
54562
|
+
}
|
|
54563
|
+
|
|
54564
|
+
// src/deploy/receipt-store.ts
|
|
54565
|
+
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
54566
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
54567
|
+
init_protocol();
|
|
54568
|
+
function createReceiptStore(deps) {
|
|
54569
|
+
let receipts = [];
|
|
54570
|
+
let flushTimer = null;
|
|
54571
|
+
async function load() {
|
|
54572
|
+
let raw;
|
|
54573
|
+
try {
|
|
54574
|
+
raw = await import_promises4.default.readFile(deps.filePath, "utf8");
|
|
54575
|
+
} catch (err) {
|
|
54576
|
+
if (err.code === "ENOENT") {
|
|
54577
|
+
receipts = [];
|
|
54578
|
+
return;
|
|
54579
|
+
}
|
|
54580
|
+
throw err;
|
|
54581
|
+
}
|
|
54582
|
+
const parsed = JSON.parse(raw);
|
|
54583
|
+
if (parsed.version !== 1) throw new Error(`deploy.json: unsupported version ${parsed.version}`);
|
|
54584
|
+
receipts = (parsed.receipts ?? []).map((r) => DeployReceiptSchema.parse(r));
|
|
54585
|
+
}
|
|
54586
|
+
async function flushNow() {
|
|
54587
|
+
if (flushTimer) {
|
|
54588
|
+
clearTimeout(flushTimer);
|
|
54589
|
+
flushTimer = null;
|
|
54590
|
+
}
|
|
54591
|
+
const content = { version: 1, receipts };
|
|
54592
|
+
await import_promises4.default.mkdir(import_node_path28.default.dirname(deps.filePath), { recursive: true });
|
|
54593
|
+
const tmp = `${deps.filePath}.tmp-${process.pid}-${deps.now()}`;
|
|
54594
|
+
await import_promises4.default.writeFile(tmp, JSON.stringify(content, null, 2), { encoding: "utf8", mode: 384 });
|
|
54595
|
+
await import_promises4.default.rename(tmp, deps.filePath);
|
|
54596
|
+
}
|
|
54597
|
+
function scheduleFlush() {
|
|
54598
|
+
if (flushTimer) return;
|
|
54599
|
+
flushTimer = setTimeout(() => {
|
|
54600
|
+
flushTimer = null;
|
|
54601
|
+
flushNow().catch((err) => deps.onFlushError?.(err));
|
|
54602
|
+
}, STORE_FLUSH_DEBOUNCE_MS);
|
|
54603
|
+
}
|
|
54604
|
+
return {
|
|
54605
|
+
load,
|
|
54606
|
+
flushNow,
|
|
54607
|
+
create(input) {
|
|
54608
|
+
const ts = deps.now();
|
|
54609
|
+
const receipt = {
|
|
54610
|
+
deployId: input.deployId,
|
|
54611
|
+
personaId: input.personaId,
|
|
54612
|
+
status: input.status,
|
|
54613
|
+
notes: [],
|
|
54614
|
+
fulfillment: {},
|
|
54615
|
+
gaps: [],
|
|
54616
|
+
createdAt: ts,
|
|
54617
|
+
updatedAt: ts
|
|
54618
|
+
};
|
|
54619
|
+
receipts.push(receipt);
|
|
54620
|
+
scheduleFlush();
|
|
54621
|
+
return receipt;
|
|
54622
|
+
},
|
|
54623
|
+
update(deployId, patch) {
|
|
54624
|
+
const idx = receipts.findIndex((r) => r.deployId === deployId);
|
|
54625
|
+
if (idx === -1) return void 0;
|
|
54626
|
+
const next = DeployReceiptSchema.parse({ ...receipts[idx], ...patch, updatedAt: deps.now() });
|
|
54627
|
+
receipts[idx] = next;
|
|
54628
|
+
scheduleFlush();
|
|
54629
|
+
return next;
|
|
54630
|
+
},
|
|
54631
|
+
get(deployId) {
|
|
54632
|
+
return receipts.find((r) => r.deployId === deployId);
|
|
54633
|
+
},
|
|
54634
|
+
list() {
|
|
54635
|
+
return [...receipts].sort((a, b2) => b2.createdAt - a.createdAt);
|
|
54636
|
+
},
|
|
54637
|
+
remove(deployId) {
|
|
54638
|
+
const idx = receipts.findIndex((r) => r.deployId === deployId);
|
|
54639
|
+
if (idx === -1) return false;
|
|
54640
|
+
receipts.splice(idx, 1);
|
|
54641
|
+
scheduleFlush();
|
|
54642
|
+
return true;
|
|
54643
|
+
}
|
|
54644
|
+
};
|
|
54645
|
+
}
|
|
54646
|
+
|
|
54647
|
+
// src/deploy/secret-store.ts
|
|
54648
|
+
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
54649
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
54650
|
+
function createSecretStore(deps) {
|
|
54651
|
+
let entries = [];
|
|
54652
|
+
let flushTimer = null;
|
|
54653
|
+
const sameScope = (e, deployId, name, userId) => e.deployId === deployId && e.name === name && (e.userId ?? void 0) === (userId ?? void 0);
|
|
54654
|
+
async function load() {
|
|
54655
|
+
let raw;
|
|
54656
|
+
try {
|
|
54657
|
+
raw = await import_promises5.default.readFile(deps.filePath, "utf8");
|
|
54658
|
+
} catch (err) {
|
|
54659
|
+
if (err.code === "ENOENT") {
|
|
54660
|
+
entries = [];
|
|
54661
|
+
return;
|
|
54662
|
+
}
|
|
54663
|
+
throw err;
|
|
54664
|
+
}
|
|
54665
|
+
const parsed = JSON.parse(raw);
|
|
54666
|
+
if (parsed.version !== 1) throw new Error(`deploy-secrets.json: unsupported version ${parsed.version}`);
|
|
54667
|
+
entries = parsed.entries ?? [];
|
|
54668
|
+
}
|
|
54669
|
+
async function flushNow() {
|
|
54670
|
+
if (flushTimer) {
|
|
54671
|
+
clearTimeout(flushTimer);
|
|
54672
|
+
flushTimer = null;
|
|
54673
|
+
}
|
|
54674
|
+
const content = { version: 1, entries };
|
|
54675
|
+
await import_promises5.default.mkdir(import_node_path29.default.dirname(deps.filePath), { recursive: true });
|
|
54676
|
+
const tmp = `${deps.filePath}.tmp-${process.pid}-${deps.now()}`;
|
|
54677
|
+
await import_promises5.default.writeFile(tmp, JSON.stringify(content, null, 2), { encoding: "utf8", mode: 384 });
|
|
54678
|
+
await import_promises5.default.rename(tmp, deps.filePath);
|
|
54679
|
+
}
|
|
54680
|
+
function scheduleFlush() {
|
|
54681
|
+
if (flushTimer) return;
|
|
54682
|
+
flushTimer = setTimeout(() => {
|
|
54683
|
+
flushTimer = null;
|
|
54684
|
+
flushNow().catch((err) => deps.onFlushError?.(err));
|
|
54685
|
+
}, STORE_FLUSH_DEBOUNCE_MS);
|
|
54686
|
+
}
|
|
54687
|
+
return {
|
|
54688
|
+
load,
|
|
54689
|
+
flushNow,
|
|
54690
|
+
put(entry) {
|
|
54691
|
+
const idx = entries.findIndex((e) => sameScope(e, entry.deployId, entry.name, entry.userId));
|
|
54692
|
+
if (idx === -1) {
|
|
54693
|
+
entries.push({ ...entry, updatedAt: deps.now() });
|
|
54694
|
+
} else {
|
|
54695
|
+
entries[idx] = {
|
|
54696
|
+
...entries[idx],
|
|
54697
|
+
values: { ...entries[idx].values, ...entry.values },
|
|
54698
|
+
updatedAt: deps.now()
|
|
54699
|
+
};
|
|
54700
|
+
}
|
|
54701
|
+
scheduleFlush();
|
|
54702
|
+
},
|
|
54703
|
+
resolve(deployId, userId) {
|
|
54704
|
+
const out = {};
|
|
54705
|
+
for (const e of entries) {
|
|
54706
|
+
if (e.deployId !== deployId || e.userId !== void 0) continue;
|
|
54707
|
+
Object.assign(out, e.values);
|
|
54708
|
+
}
|
|
54709
|
+
if (userId !== void 0) {
|
|
54710
|
+
for (const e of entries) {
|
|
54711
|
+
if (e.deployId !== deployId || e.userId !== userId) continue;
|
|
54712
|
+
Object.assign(out, e.values);
|
|
54713
|
+
}
|
|
54714
|
+
}
|
|
54715
|
+
return out;
|
|
54716
|
+
},
|
|
54717
|
+
filledKeys(deployId, name, userId) {
|
|
54718
|
+
const e = entries.find((x) => sameScope(x, deployId, name, userId));
|
|
54719
|
+
if (!e) return [];
|
|
54720
|
+
return Object.keys(e.values).filter((k2) => e.values[k2].length > 0);
|
|
54721
|
+
},
|
|
54722
|
+
removeDeploy(deployId) {
|
|
54723
|
+
const before = entries.length;
|
|
54724
|
+
entries = entries.filter((e) => e.deployId !== deployId);
|
|
54725
|
+
const removed = before - entries.length;
|
|
54726
|
+
if (removed > 0) scheduleFlush();
|
|
54727
|
+
return removed;
|
|
54728
|
+
}
|
|
54729
|
+
};
|
|
54730
|
+
}
|
|
54731
|
+
|
|
54732
|
+
// src/deploy/scan-task.ts
|
|
54733
|
+
var BUTLER_PERSONA_ID = "persona-clawd-butler";
|
|
54734
|
+
var SCANNABLE_ASSETS = ["deploy-kit"];
|
|
54735
|
+
function settleEndedScan(outcome, current) {
|
|
54736
|
+
if (current?.status !== "scanning") return void 0;
|
|
54737
|
+
return {
|
|
54738
|
+
status: "scanFailed",
|
|
54739
|
+
error: "error" in outcome ? outcome.error : "butler \u4F1A\u8BDD\u7ED3\u675F\u4E86\u4F46\u6CA1\u6709\u8C03 finishScan"
|
|
54740
|
+
};
|
|
54741
|
+
}
|
|
54742
|
+
function reconcileInterruptedScans(deps) {
|
|
54743
|
+
const stale = deps.list().filter((r) => r.status === "scanning");
|
|
54744
|
+
for (const r of stale) {
|
|
54745
|
+
deps.update(r.deployId, { status: "scanFailed", error: "daemon \u91CD\u542F\uFF0C\u626B\u63CF\u4F1A\u8BDD\u5DF2\u4E2D\u65AD\u2014\u2014\u8BF7\u91CD\u65B0\u626B\u63CF" });
|
|
54746
|
+
}
|
|
54747
|
+
return stale.map((r) => r.deployId);
|
|
54748
|
+
}
|
|
54749
|
+
|
|
54113
54750
|
// src/handlers/lark-bot.ts
|
|
54114
54751
|
init_protocol();
|
|
54115
54752
|
var PROVISION_ERROR_SET = new Set(LARK_BOT_PROVISION_ERROR_REASONS);
|
|
@@ -54498,9 +55135,9 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
54498
55135
|
|
|
54499
55136
|
// src/lark-bot-connector/binding-store.ts
|
|
54500
55137
|
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
54501
|
-
var
|
|
55138
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
54502
55139
|
function createLarkBotBindingStore(personaRoot) {
|
|
54503
|
-
const filePath = (personaId2) =>
|
|
55140
|
+
const filePath = (personaId2) => import_node_path30.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
54504
55141
|
const read = (personaId2) => {
|
|
54505
55142
|
const file = filePath(personaId2);
|
|
54506
55143
|
if (!import_node_fs26.default.existsSync(file)) return null;
|
|
@@ -54514,7 +55151,7 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
54514
55151
|
};
|
|
54515
55152
|
const write = (personaId2, meta) => {
|
|
54516
55153
|
const file = filePath(personaId2);
|
|
54517
|
-
import_node_fs26.default.mkdirSync(
|
|
55154
|
+
import_node_fs26.default.mkdirSync(import_node_path30.default.dirname(file), { recursive: true });
|
|
54518
55155
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
54519
55156
|
import_node_fs26.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
54520
55157
|
import_node_fs26.default.renameSync(tmp, file);
|
|
@@ -54682,7 +55319,7 @@ function createLarkBotCloudClient(opts) {
|
|
|
54682
55319
|
|
|
54683
55320
|
// src/lark-bot-connector/chat-router.ts
|
|
54684
55321
|
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
54685
|
-
var
|
|
55322
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
54686
55323
|
init_protocol();
|
|
54687
55324
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
54688
55325
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -54749,7 +55386,7 @@ function createLarkChatRouter(deps) {
|
|
|
54749
55386
|
}
|
|
54750
55387
|
const dir = deps.mediaRootFor(env.chatId);
|
|
54751
55388
|
import_node_fs27.default.mkdirSync(dir, { recursive: true });
|
|
54752
|
-
const p2 =
|
|
55389
|
+
const p2 = import_node_path31.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
|
|
54753
55390
|
import_node_fs27.default.writeFileSync(p2, r.data);
|
|
54754
55391
|
lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
54755
55392
|
} catch (err) {
|
|
@@ -54772,7 +55409,7 @@ function createLarkChatRouter(deps) {
|
|
|
54772
55409
|
}
|
|
54773
55410
|
const dir = deps.mediaRootFor(env.chatId);
|
|
54774
55411
|
import_node_fs27.default.mkdirSync(dir, { recursive: true });
|
|
54775
|
-
const p2 =
|
|
55412
|
+
const p2 = import_node_path31.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
54776
55413
|
import_node_fs27.default.writeFileSync(p2, r.data);
|
|
54777
55414
|
lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
54778
55415
|
} catch (err) {
|
|
@@ -55862,7 +56499,7 @@ var CodexHistoryReader = class {
|
|
|
55862
56499
|
};
|
|
55863
56500
|
|
|
55864
56501
|
// src/tools/codex-skills.ts
|
|
55865
|
-
var
|
|
56502
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
55866
56503
|
function str3(v2) {
|
|
55867
56504
|
return typeof v2 === "string" ? v2 : void 0;
|
|
55868
56505
|
}
|
|
@@ -55877,13 +56514,13 @@ function mapSkillsListResponse(res) {
|
|
|
55877
56514
|
const r = s ?? {};
|
|
55878
56515
|
const name = str3(r.name);
|
|
55879
56516
|
if (!name) continue;
|
|
55880
|
-
const
|
|
56517
|
+
const path93 = str3(r.path);
|
|
55881
56518
|
const description = str3(r.description);
|
|
55882
56519
|
const isPlugin = name.includes(":");
|
|
55883
56520
|
out.push({
|
|
55884
56521
|
name,
|
|
55885
56522
|
source: isPlugin ? "plugin" : "project",
|
|
55886
|
-
...
|
|
56523
|
+
...path93 ? { path: path93 } : {},
|
|
55887
56524
|
...description ? { description } : {},
|
|
55888
56525
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
55889
56526
|
});
|
|
@@ -55899,14 +56536,14 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
55899
56536
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
55900
56537
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
55901
56538
|
beforeRequest: (client) => {
|
|
55902
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
56539
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path32.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
55903
56540
|
}
|
|
55904
56541
|
});
|
|
55905
56542
|
return mapSkillsListResponse(res);
|
|
55906
56543
|
}
|
|
55907
56544
|
|
|
55908
56545
|
// src/tools/codex-turn-context.ts
|
|
55909
|
-
var
|
|
56546
|
+
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
55910
56547
|
function parseTurnContextFromRollout(raw) {
|
|
55911
56548
|
const lines = raw.split("\n");
|
|
55912
56549
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -55941,7 +56578,7 @@ async function readCodexTurnContext(args, deps = {}) {
|
|
|
55941
56578
|
);
|
|
55942
56579
|
const rolloutPath = str4(rec3(res?.thread)?.path);
|
|
55943
56580
|
if (!rolloutPath) return null;
|
|
55944
|
-
return parseTurnContextFromRollout(await
|
|
56581
|
+
return parseTurnContextFromRollout(await import_promises6.default.readFile(rolloutPath, "utf8"));
|
|
55945
56582
|
}
|
|
55946
56583
|
function createCodexResolvedMetaHydrator(deps) {
|
|
55947
56584
|
const fetchedThreadIds = /* @__PURE__ */ new Set();
|
|
@@ -55986,14 +56623,14 @@ function str4(v2) {
|
|
|
55986
56623
|
// src/workspace/browser.ts
|
|
55987
56624
|
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
55988
56625
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
55989
|
-
var
|
|
56626
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
55990
56627
|
init_protocol();
|
|
55991
56628
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
55992
56629
|
function resolveInsideCwd(cwd, subpath) {
|
|
55993
|
-
const absCwd =
|
|
55994
|
-
const joined =
|
|
55995
|
-
const rel =
|
|
55996
|
-
if (rel.startsWith("..") ||
|
|
56630
|
+
const absCwd = import_node_path33.default.resolve(cwd);
|
|
56631
|
+
const joined = import_node_path33.default.resolve(absCwd, subpath ?? ".");
|
|
56632
|
+
const rel = import_node_path33.default.relative(absCwd, joined);
|
|
56633
|
+
if (rel.startsWith("..") || import_node_path33.default.isAbsolute(rel)) {
|
|
55997
56634
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
55998
56635
|
}
|
|
55999
56636
|
return joined;
|
|
@@ -56024,7 +56661,7 @@ var WorkspaceBrowser = class {
|
|
|
56024
56661
|
mtime: ""
|
|
56025
56662
|
};
|
|
56026
56663
|
try {
|
|
56027
|
-
const st = import_node_fs28.default.statSync(
|
|
56664
|
+
const st = import_node_fs28.default.statSync(import_node_path33.default.join(full, d.name));
|
|
56028
56665
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
56029
56666
|
if (d.isFile()) entry.size = st.size;
|
|
56030
56667
|
} catch {
|
|
@@ -56071,7 +56708,7 @@ var WorkspaceBrowser = class {
|
|
|
56071
56708
|
// src/skills/agents-scanner.ts
|
|
56072
56709
|
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
56073
56710
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
56074
|
-
var
|
|
56711
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
56075
56712
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
56076
56713
|
function isDirLikeSync2(p2) {
|
|
56077
56714
|
try {
|
|
@@ -56109,10 +56746,10 @@ function scanAgentsDir(dir, source, seen, out) {
|
|
|
56109
56746
|
}
|
|
56110
56747
|
for (const ent of entries) {
|
|
56111
56748
|
if (!ent.name.endsWith(".md")) continue;
|
|
56112
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
56749
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path34.default.join(dir, ent.name)))) {
|
|
56113
56750
|
continue;
|
|
56114
56751
|
}
|
|
56115
|
-
const filePath =
|
|
56752
|
+
const filePath = import_node_path34.default.join(dir, ent.name);
|
|
56116
56753
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
56117
56754
|
if (seen.has(baseName)) continue;
|
|
56118
56755
|
seen.add(baseName);
|
|
@@ -56135,7 +56772,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
56135
56772
|
return;
|
|
56136
56773
|
}
|
|
56137
56774
|
for (const ent of entries) {
|
|
56138
|
-
const childPath =
|
|
56775
|
+
const childPath = import_node_path34.default.join(dir, ent.name);
|
|
56139
56776
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
56140
56777
|
walk2(childPath, [...namespaces, ent.name]);
|
|
56141
56778
|
continue;
|
|
@@ -56160,9 +56797,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
56160
56797
|
walk2(root, []);
|
|
56161
56798
|
}
|
|
56162
56799
|
function readInstalledPlugins2(home) {
|
|
56163
|
-
const pluginsDir =
|
|
56164
|
-
const v2 =
|
|
56165
|
-
const v1 =
|
|
56800
|
+
const pluginsDir = import_node_path34.default.join(home, ".claude", "plugins");
|
|
56801
|
+
const v2 = import_node_path34.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
56802
|
+
const v1 = import_node_path34.default.join(pluginsDir, "installed_plugins.json");
|
|
56166
56803
|
let raw = null;
|
|
56167
56804
|
for (const candidate of [v2, v1]) {
|
|
56168
56805
|
try {
|
|
@@ -56191,19 +56828,19 @@ function readInstalledPlugins2(home) {
|
|
|
56191
56828
|
return out;
|
|
56192
56829
|
}
|
|
56193
56830
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
56194
|
-
let cur =
|
|
56195
|
-
const fsRoot =
|
|
56831
|
+
let cur = import_node_path34.default.resolve(startCwd);
|
|
56832
|
+
const fsRoot = import_node_path34.default.parse(cur).root;
|
|
56196
56833
|
while (true) {
|
|
56197
|
-
scanAgentsDir(
|
|
56834
|
+
scanAgentsDir(import_node_path34.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
56198
56835
|
let hasGit = false;
|
|
56199
56836
|
try {
|
|
56200
|
-
hasGit = import_node_fs29.default.existsSync(
|
|
56837
|
+
hasGit = import_node_fs29.default.existsSync(import_node_path34.default.join(cur, ".git"));
|
|
56201
56838
|
} catch {
|
|
56202
56839
|
}
|
|
56203
56840
|
if (hasGit) return;
|
|
56204
56841
|
if (cur === home) return;
|
|
56205
56842
|
if (cur === fsRoot) return;
|
|
56206
|
-
const parent =
|
|
56843
|
+
const parent = import_node_path34.default.dirname(cur);
|
|
56207
56844
|
if (parent === cur) return;
|
|
56208
56845
|
cur = parent;
|
|
56209
56846
|
}
|
|
@@ -56238,7 +56875,7 @@ var AgentsScanner = class {
|
|
|
56238
56875
|
}
|
|
56239
56876
|
const fsBlock = [];
|
|
56240
56877
|
scanAgentsDir(
|
|
56241
|
-
|
|
56878
|
+
import_node_path34.default.join(this.home, ".claude", "agents"),
|
|
56242
56879
|
"global",
|
|
56243
56880
|
seen,
|
|
56244
56881
|
fsBlock
|
|
@@ -56252,7 +56889,7 @@ var AgentsScanner = class {
|
|
|
56252
56889
|
...this.extraPluginRoots
|
|
56253
56890
|
];
|
|
56254
56891
|
for (const { name, root } of plugins) {
|
|
56255
|
-
const agentsRoot =
|
|
56892
|
+
const agentsRoot = import_node_path34.default.join(root, "agents");
|
|
56256
56893
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
56257
56894
|
}
|
|
56258
56895
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -56262,13 +56899,13 @@ var AgentsScanner = class {
|
|
|
56262
56899
|
// src/observer/session-observer.ts
|
|
56263
56900
|
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
56264
56901
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
56265
|
-
var
|
|
56902
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
56266
56903
|
init_claude_history();
|
|
56267
56904
|
|
|
56268
56905
|
// src/observer/subagent-meta-observer.ts
|
|
56269
56906
|
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
56270
56907
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
56271
|
-
var
|
|
56908
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
56272
56909
|
init_claude_history();
|
|
56273
56910
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
56274
56911
|
var SubagentMetaObserver = class {
|
|
@@ -56281,7 +56918,7 @@ var SubagentMetaObserver = class {
|
|
|
56281
56918
|
watches = /* @__PURE__ */ new Map();
|
|
56282
56919
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
56283
56920
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
56284
|
-
return
|
|
56921
|
+
return import_node_path35.default.join(
|
|
56285
56922
|
this.home,
|
|
56286
56923
|
".claude",
|
|
56287
56924
|
"projects",
|
|
@@ -56337,7 +56974,7 @@ var SubagentMetaObserver = class {
|
|
|
56337
56974
|
if (!m2) return;
|
|
56338
56975
|
const agentId = m2[1];
|
|
56339
56976
|
if (w2.emitted.has(agentId)) return;
|
|
56340
|
-
const file =
|
|
56977
|
+
const file = import_node_path35.default.join(w2.dirPath, name);
|
|
56341
56978
|
let raw;
|
|
56342
56979
|
try {
|
|
56343
56980
|
raw = import_node_fs30.default.readFileSync(file, "utf8");
|
|
@@ -56397,7 +57034,7 @@ var SessionObserver = class {
|
|
|
56397
57034
|
metaObserver;
|
|
56398
57035
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
56399
57036
|
if (override) return override;
|
|
56400
|
-
return
|
|
57037
|
+
return import_node_path36.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
56401
57038
|
}
|
|
56402
57039
|
start(args) {
|
|
56403
57040
|
this.stop(args.sessionId);
|
|
@@ -56423,10 +57060,10 @@ var SessionObserver = class {
|
|
|
56423
57060
|
lastDeriveMs: 0
|
|
56424
57061
|
};
|
|
56425
57062
|
try {
|
|
56426
|
-
import_node_fs31.default.mkdirSync(
|
|
57063
|
+
import_node_fs31.default.mkdirSync(import_node_path36.default.dirname(filePath), { recursive: true });
|
|
56427
57064
|
} catch {
|
|
56428
57065
|
}
|
|
56429
|
-
w2.watcher = import_node_fs31.default.watch(
|
|
57066
|
+
w2.watcher = import_node_fs31.default.watch(import_node_path36.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
56430
57067
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
56431
57068
|
this.poll(w2);
|
|
56432
57069
|
});
|
|
@@ -56523,7 +57160,7 @@ var SessionObserver = class {
|
|
|
56523
57160
|
const now = Date.now();
|
|
56524
57161
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
56525
57162
|
w2.lastRelocateScanMs = now;
|
|
56526
|
-
const projectsRoot =
|
|
57163
|
+
const projectsRoot = import_node_path36.default.join(this.home, ".claude", "projects");
|
|
56527
57164
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
56528
57165
|
if (!found || found === w2.filePath) return;
|
|
56529
57166
|
try {
|
|
@@ -56532,7 +57169,7 @@ var SessionObserver = class {
|
|
|
56532
57169
|
}
|
|
56533
57170
|
w2.filePath = found;
|
|
56534
57171
|
try {
|
|
56535
|
-
w2.watcher = import_node_fs31.default.watch(
|
|
57172
|
+
w2.watcher = import_node_fs31.default.watch(import_node_path36.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
56536
57173
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
56537
57174
|
this.poll(w2);
|
|
56538
57175
|
});
|
|
@@ -56655,7 +57292,7 @@ function listRegistered() {
|
|
|
56655
57292
|
var import_node_child_process8 = require("child_process");
|
|
56656
57293
|
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
56657
57294
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
56658
|
-
var
|
|
57295
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56659
57296
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
56660
57297
|
var TITLE_MODEL_BY_TOOL = {
|
|
56661
57298
|
claude: "haiku",
|
|
@@ -56726,7 +57363,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
56726
57363
|
if (!text) return null;
|
|
56727
57364
|
let workDir;
|
|
56728
57365
|
try {
|
|
56729
|
-
workDir = import_node_fs32.default.mkdtempSync(
|
|
57366
|
+
workDir = import_node_fs32.default.mkdtempSync(import_node_path37.default.join(import_node_os12.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
56730
57367
|
} catch {
|
|
56731
57368
|
return null;
|
|
56732
57369
|
}
|
|
@@ -56736,8 +57373,8 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
56736
57373
|
} catch {
|
|
56737
57374
|
}
|
|
56738
57375
|
};
|
|
56739
|
-
const outFile =
|
|
56740
|
-
const schemaFile =
|
|
57376
|
+
const outFile = import_node_path37.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
57377
|
+
const schemaFile = import_node_path37.default.join(workDir, "title-schema.json");
|
|
56741
57378
|
if (tool === "codex") {
|
|
56742
57379
|
try {
|
|
56743
57380
|
import_node_fs32.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
@@ -57491,8 +58128,8 @@ async function authenticate(token, deps) {
|
|
|
57491
58128
|
}
|
|
57492
58129
|
|
|
57493
58130
|
// src/legacy-cleanup.ts
|
|
57494
|
-
var
|
|
57495
|
-
var
|
|
58131
|
+
var fs43 = __toESM(require("fs/promises"), 1);
|
|
58132
|
+
var path45 = __toESM(require("path"), 1);
|
|
57496
58133
|
var LEGACY_FILES = [
|
|
57497
58134
|
"personal-capability.json",
|
|
57498
58135
|
"received-capabilities.json",
|
|
@@ -57501,9 +58138,9 @@ var LEGACY_FILES = [
|
|
|
57501
58138
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
57502
58139
|
const removed = [];
|
|
57503
58140
|
for (const name of LEGACY_FILES) {
|
|
57504
|
-
const p2 =
|
|
58141
|
+
const p2 = path45.join(dataDir, name);
|
|
57505
58142
|
try {
|
|
57506
|
-
await
|
|
58143
|
+
await fs43.unlink(p2);
|
|
57507
58144
|
removed.push(name);
|
|
57508
58145
|
logger.debug("legacy capability file removed", { file: name });
|
|
57509
58146
|
} catch (err) {
|
|
@@ -57515,13 +58152,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
57515
58152
|
}
|
|
57516
58153
|
|
|
57517
58154
|
// src/inbox/inbox-store.ts
|
|
57518
|
-
var
|
|
57519
|
-
var
|
|
58155
|
+
var fs44 = __toESM(require("fs"), 1);
|
|
58156
|
+
var path46 = __toESM(require("path"), 1);
|
|
57520
58157
|
var INBOX_SUBDIR = "inbox";
|
|
57521
58158
|
var InboxStore = class {
|
|
57522
58159
|
constructor(dataDir) {
|
|
57523
58160
|
this.dataDir = dataDir;
|
|
57524
|
-
|
|
58161
|
+
fs44.mkdirSync(this.dirPath(), { recursive: true });
|
|
57525
58162
|
}
|
|
57526
58163
|
dataDir;
|
|
57527
58164
|
/**
|
|
@@ -57533,7 +58170,7 @@ var InboxStore = class {
|
|
|
57533
58170
|
const file = this.filePath(peerDeviceId);
|
|
57534
58171
|
let raw;
|
|
57535
58172
|
try {
|
|
57536
|
-
raw =
|
|
58173
|
+
raw = fs44.readFileSync(file, "utf8");
|
|
57537
58174
|
} catch (err) {
|
|
57538
58175
|
if (err?.code === "ENOENT") return [];
|
|
57539
58176
|
return [];
|
|
@@ -57549,7 +58186,7 @@ var InboxStore = class {
|
|
|
57549
58186
|
const dir = this.dirPath();
|
|
57550
58187
|
let entries;
|
|
57551
58188
|
try {
|
|
57552
|
-
entries =
|
|
58189
|
+
entries = fs44.readdirSync(dir);
|
|
57553
58190
|
} catch (err) {
|
|
57554
58191
|
if (err?.code === "ENOENT") return [];
|
|
57555
58192
|
return [];
|
|
@@ -57565,9 +58202,9 @@ var InboxStore = class {
|
|
|
57565
58202
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
57566
58203
|
const file = this.filePath(message.peerDeviceId);
|
|
57567
58204
|
const line = JSON.stringify(message) + "\n";
|
|
57568
|
-
|
|
58205
|
+
fs44.appendFileSync(file, line, { mode: 384 });
|
|
57569
58206
|
try {
|
|
57570
|
-
|
|
58207
|
+
fs44.chmodSync(file, 384);
|
|
57571
58208
|
} catch {
|
|
57572
58209
|
}
|
|
57573
58210
|
}
|
|
@@ -57597,7 +58234,7 @@ var InboxStore = class {
|
|
|
57597
58234
|
removeByPeerDeviceId(peerDeviceId) {
|
|
57598
58235
|
const file = this.filePath(peerDeviceId);
|
|
57599
58236
|
try {
|
|
57600
|
-
|
|
58237
|
+
fs44.unlinkSync(file);
|
|
57601
58238
|
} catch (err) {
|
|
57602
58239
|
if (err?.code === "ENOENT") return;
|
|
57603
58240
|
}
|
|
@@ -57606,18 +58243,18 @@ var InboxStore = class {
|
|
|
57606
58243
|
const file = this.filePath(peerDeviceId);
|
|
57607
58244
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
57608
58245
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
57609
|
-
|
|
57610
|
-
|
|
58246
|
+
fs44.writeFileSync(tmp, content, { mode: 384 });
|
|
58247
|
+
fs44.renameSync(tmp, file);
|
|
57611
58248
|
try {
|
|
57612
|
-
|
|
58249
|
+
fs44.chmodSync(file, 384);
|
|
57613
58250
|
} catch {
|
|
57614
58251
|
}
|
|
57615
58252
|
}
|
|
57616
58253
|
dirPath() {
|
|
57617
|
-
return
|
|
58254
|
+
return path46.join(this.dataDir, INBOX_SUBDIR);
|
|
57618
58255
|
}
|
|
57619
58256
|
filePath(peerDeviceId) {
|
|
57620
|
-
return
|
|
58257
|
+
return path46.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
57621
58258
|
}
|
|
57622
58259
|
};
|
|
57623
58260
|
function parseAllLines(raw) {
|
|
@@ -57705,8 +58342,8 @@ var InboxManager = class {
|
|
|
57705
58342
|
};
|
|
57706
58343
|
|
|
57707
58344
|
// src/state/contact-store.ts
|
|
57708
|
-
var
|
|
57709
|
-
var
|
|
58345
|
+
var fs45 = __toESM(require("fs"), 1);
|
|
58346
|
+
var path47 = __toESM(require("path"), 1);
|
|
57710
58347
|
var FILE_NAME = "contacts.json";
|
|
57711
58348
|
var ContactStore = class {
|
|
57712
58349
|
constructor(dataDir) {
|
|
@@ -57716,10 +58353,10 @@ var ContactStore = class {
|
|
|
57716
58353
|
contacts = /* @__PURE__ */ new Map();
|
|
57717
58354
|
load() {
|
|
57718
58355
|
this.contacts.clear();
|
|
57719
|
-
const file =
|
|
58356
|
+
const file = path47.join(this.dataDir, FILE_NAME);
|
|
57720
58357
|
let raw;
|
|
57721
58358
|
try {
|
|
57722
|
-
raw =
|
|
58359
|
+
raw = fs45.readFileSync(file, "utf8");
|
|
57723
58360
|
} catch (err) {
|
|
57724
58361
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
57725
58362
|
return;
|
|
@@ -57800,20 +58437,20 @@ var ContactStore = class {
|
|
|
57800
58437
|
return true;
|
|
57801
58438
|
}
|
|
57802
58439
|
flush() {
|
|
57803
|
-
const file =
|
|
58440
|
+
const file = path47.join(this.dataDir, FILE_NAME);
|
|
57804
58441
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
57805
58442
|
const content = JSON.stringify(
|
|
57806
58443
|
{ contacts: Array.from(this.contacts.values()) },
|
|
57807
58444
|
null,
|
|
57808
58445
|
2
|
|
57809
58446
|
);
|
|
57810
|
-
|
|
57811
|
-
|
|
57812
|
-
|
|
58447
|
+
fs45.mkdirSync(this.dataDir, { recursive: true });
|
|
58448
|
+
fs45.writeFileSync(tmp, content, { mode: 384 });
|
|
58449
|
+
fs45.renameSync(tmp, file);
|
|
57813
58450
|
}
|
|
57814
58451
|
renameBak(file) {
|
|
57815
58452
|
try {
|
|
57816
|
-
|
|
58453
|
+
fs45.renameSync(file, `${file}.bak`);
|
|
57817
58454
|
} catch {
|
|
57818
58455
|
}
|
|
57819
58456
|
}
|
|
@@ -57921,61 +58558,61 @@ async function connectRemote(args) {
|
|
|
57921
58558
|
}
|
|
57922
58559
|
|
|
57923
58560
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
57924
|
-
var
|
|
57925
|
-
var
|
|
58561
|
+
var fs46 = __toESM(require("fs"), 1);
|
|
58562
|
+
var path48 = __toESM(require("path"), 1);
|
|
57926
58563
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
57927
58564
|
function migrateFlattenSessions(opts) {
|
|
57928
58565
|
const dataDir = opts.dataDir;
|
|
57929
58566
|
const now = opts.now ?? Date.now;
|
|
57930
|
-
const sessionsDir =
|
|
57931
|
-
const flagPath =
|
|
58567
|
+
const sessionsDir = path48.join(dataDir, "sessions");
|
|
58568
|
+
const flagPath = path48.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
57932
58569
|
if (existsSync3(flagPath)) {
|
|
57933
58570
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
57934
58571
|
}
|
|
57935
58572
|
let movedBare = 0;
|
|
57936
58573
|
let movedVmOwner = 0;
|
|
57937
58574
|
let archivedListener = 0;
|
|
57938
|
-
const defaultDir =
|
|
58575
|
+
const defaultDir = path48.join(sessionsDir, "default");
|
|
57939
58576
|
if (existsSync3(defaultDir)) {
|
|
57940
58577
|
for (const entry of readdirSafe(defaultDir)) {
|
|
57941
58578
|
if (!entry.endsWith(".json")) continue;
|
|
57942
|
-
const src =
|
|
57943
|
-
const dst =
|
|
57944
|
-
|
|
58579
|
+
const src = path48.join(defaultDir, entry);
|
|
58580
|
+
const dst = path48.join(sessionsDir, entry);
|
|
58581
|
+
fs46.renameSync(src, dst);
|
|
57945
58582
|
movedBare += 1;
|
|
57946
58583
|
}
|
|
57947
58584
|
rmdirIfEmpty(defaultDir);
|
|
57948
58585
|
}
|
|
57949
58586
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
57950
|
-
const personaDir =
|
|
58587
|
+
const personaDir = path48.join(sessionsDir, pid);
|
|
57951
58588
|
if (!isDir(personaDir)) continue;
|
|
57952
58589
|
if (pid === "default") continue;
|
|
57953
|
-
const ownerSrc =
|
|
58590
|
+
const ownerSrc = path48.join(personaDir, "owner");
|
|
57954
58591
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
57955
|
-
const ownerDst =
|
|
57956
|
-
|
|
58592
|
+
const ownerDst = path48.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
58593
|
+
fs46.mkdirSync(ownerDst, { recursive: true });
|
|
57957
58594
|
for (const file of readdirSafe(ownerSrc)) {
|
|
57958
58595
|
if (!file.endsWith(".json")) continue;
|
|
57959
|
-
|
|
58596
|
+
fs46.renameSync(path48.join(ownerSrc, file), path48.join(ownerDst, file));
|
|
57960
58597
|
movedVmOwner += 1;
|
|
57961
58598
|
}
|
|
57962
58599
|
rmdirIfEmpty(ownerSrc);
|
|
57963
58600
|
}
|
|
57964
|
-
const listenerSrc =
|
|
58601
|
+
const listenerSrc = path48.join(personaDir, "listener");
|
|
57965
58602
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
57966
|
-
const archiveDst =
|
|
57967
|
-
|
|
58603
|
+
const archiveDst = path48.join(dataDir, ".legacy", `listener-${pid}`);
|
|
58604
|
+
fs46.mkdirSync(archiveDst, { recursive: true });
|
|
57968
58605
|
for (const file of readdirSafe(listenerSrc)) {
|
|
57969
58606
|
if (!file.endsWith(".json")) continue;
|
|
57970
|
-
|
|
58607
|
+
fs46.renameSync(path48.join(listenerSrc, file), path48.join(archiveDst, file));
|
|
57971
58608
|
archivedListener += 1;
|
|
57972
58609
|
}
|
|
57973
58610
|
rmdirIfEmpty(listenerSrc);
|
|
57974
58611
|
}
|
|
57975
58612
|
rmdirIfEmpty(personaDir);
|
|
57976
58613
|
}
|
|
57977
|
-
|
|
57978
|
-
|
|
58614
|
+
fs46.mkdirSync(sessionsDir, { recursive: true });
|
|
58615
|
+
fs46.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
57979
58616
|
return {
|
|
57980
58617
|
skipped: false,
|
|
57981
58618
|
flagWritten: true,
|
|
@@ -57986,7 +58623,7 @@ function migrateFlattenSessions(opts) {
|
|
|
57986
58623
|
}
|
|
57987
58624
|
function existsSync3(p2) {
|
|
57988
58625
|
try {
|
|
57989
|
-
|
|
58626
|
+
fs46.statSync(p2);
|
|
57990
58627
|
return true;
|
|
57991
58628
|
} catch {
|
|
57992
58629
|
return false;
|
|
@@ -57994,61 +58631,61 @@ function existsSync3(p2) {
|
|
|
57994
58631
|
}
|
|
57995
58632
|
function isDir(p2) {
|
|
57996
58633
|
try {
|
|
57997
|
-
return
|
|
58634
|
+
return fs46.statSync(p2).isDirectory();
|
|
57998
58635
|
} catch {
|
|
57999
58636
|
return false;
|
|
58000
58637
|
}
|
|
58001
58638
|
}
|
|
58002
58639
|
function readdirSafe(p2) {
|
|
58003
58640
|
try {
|
|
58004
|
-
return
|
|
58641
|
+
return fs46.readdirSync(p2);
|
|
58005
58642
|
} catch {
|
|
58006
58643
|
return [];
|
|
58007
58644
|
}
|
|
58008
58645
|
}
|
|
58009
58646
|
function rmdirIfEmpty(p2) {
|
|
58010
58647
|
try {
|
|
58011
|
-
|
|
58648
|
+
fs46.rmdirSync(p2);
|
|
58012
58649
|
} catch {
|
|
58013
58650
|
}
|
|
58014
58651
|
}
|
|
58015
58652
|
|
|
58016
58653
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
58017
|
-
var
|
|
58018
|
-
var
|
|
58654
|
+
var fs47 = __toESM(require("fs"), 1);
|
|
58655
|
+
var path49 = __toESM(require("path"), 1);
|
|
58019
58656
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
58020
58657
|
function dropSeededProjects(opts) {
|
|
58021
|
-
|
|
58022
|
-
const flag =
|
|
58023
|
-
if (
|
|
58024
|
-
const file =
|
|
58658
|
+
fs47.mkdirSync(opts.dataDir, { recursive: true });
|
|
58659
|
+
const flag = path49.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
|
|
58660
|
+
if (fs47.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
|
|
58661
|
+
const file = path49.join(opts.dataDir, "projects.json");
|
|
58025
58662
|
let raw = null;
|
|
58026
58663
|
let dropped = 0;
|
|
58027
58664
|
try {
|
|
58028
|
-
raw =
|
|
58665
|
+
raw = fs47.readFileSync(file, "utf8");
|
|
58029
58666
|
dropped = JSON.parse(raw).projects?.length ?? 0;
|
|
58030
58667
|
} catch {
|
|
58031
58668
|
}
|
|
58032
58669
|
let backup = null;
|
|
58033
58670
|
if (raw != null && dropped > 0) {
|
|
58034
|
-
const dir =
|
|
58035
|
-
|
|
58036
|
-
backup =
|
|
58037
|
-
|
|
58671
|
+
const dir = path49.join(opts.dataDir, "backups");
|
|
58672
|
+
fs47.mkdirSync(dir, { recursive: true });
|
|
58673
|
+
backup = path49.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
|
|
58674
|
+
fs47.writeFileSync(backup, raw);
|
|
58038
58675
|
}
|
|
58039
58676
|
if (raw != null || dropped > 0) {
|
|
58040
|
-
|
|
58677
|
+
fs47.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
|
|
58041
58678
|
}
|
|
58042
|
-
|
|
58679
|
+
fs47.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
|
|
58043
58680
|
return { skipped: false, dropped, backup };
|
|
58044
58681
|
}
|
|
58045
58682
|
|
|
58046
58683
|
// src/transport/http-router.ts
|
|
58047
58684
|
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
58048
|
-
var
|
|
58685
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
58049
58686
|
|
|
58050
58687
|
// src/attachment/mime.ts
|
|
58051
|
-
var
|
|
58688
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
58052
58689
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
58053
58690
|
var EXT_TO_NATIVE_MIME = {
|
|
58054
58691
|
// 图片
|
|
@@ -58155,7 +58792,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
58155
58792
|
".mk"
|
|
58156
58793
|
]);
|
|
58157
58794
|
function lookupMime(filePathOrName) {
|
|
58158
|
-
const ext =
|
|
58795
|
+
const ext = import_node_path38.default.extname(filePathOrName).toLowerCase();
|
|
58159
58796
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
58160
58797
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
58161
58798
|
return "application/octet-stream";
|
|
@@ -58226,9 +58863,9 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
58226
58863
|
|
|
58227
58864
|
// src/attachment/upload.ts
|
|
58228
58865
|
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
58229
|
-
var
|
|
58866
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
58230
58867
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
58231
|
-
var
|
|
58868
|
+
var import_promises7 = require("stream/promises");
|
|
58232
58869
|
var UploadError = class extends Error {
|
|
58233
58870
|
constructor(code, message) {
|
|
58234
58871
|
super(message);
|
|
@@ -58238,14 +58875,14 @@ var UploadError = class extends Error {
|
|
|
58238
58875
|
code;
|
|
58239
58876
|
};
|
|
58240
58877
|
function assertValidFileName(fileName) {
|
|
58241
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
58878
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path39.default.basename(fileName)) {
|
|
58242
58879
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
58243
58880
|
}
|
|
58244
58881
|
}
|
|
58245
58882
|
var HASH_PREFIX_LEN = 16;
|
|
58246
58883
|
async function writeUploadedAttachment(args) {
|
|
58247
58884
|
assertValidFileName(args.fileName);
|
|
58248
|
-
const attachmentsRoot =
|
|
58885
|
+
const attachmentsRoot = import_node_path39.default.join(args.baseDir, ".attachments");
|
|
58249
58886
|
try {
|
|
58250
58887
|
import_node_fs33.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
58251
58888
|
} catch (err) {
|
|
@@ -58253,12 +58890,12 @@ async function writeUploadedAttachment(args) {
|
|
|
58253
58890
|
}
|
|
58254
58891
|
const hasher = import_node_crypto10.default.createHash("sha256");
|
|
58255
58892
|
let actualSize = 0;
|
|
58256
|
-
const tmpPath =
|
|
58893
|
+
const tmpPath = import_node_path39.default.join(
|
|
58257
58894
|
attachmentsRoot,
|
|
58258
58895
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto10.default.randomBytes(4).toString("hex")}`
|
|
58259
58896
|
);
|
|
58260
58897
|
try {
|
|
58261
|
-
await (0,
|
|
58898
|
+
await (0, import_promises7.pipeline)(
|
|
58262
58899
|
args.body,
|
|
58263
58900
|
async function* (source) {
|
|
58264
58901
|
for await (const chunk of source) {
|
|
@@ -58288,7 +58925,7 @@ async function writeUploadedAttachment(args) {
|
|
|
58288
58925
|
);
|
|
58289
58926
|
}
|
|
58290
58927
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
58291
|
-
const hashDir =
|
|
58928
|
+
const hashDir = import_node_path39.default.join(attachmentsRoot, attachmentId);
|
|
58292
58929
|
let finalFileName;
|
|
58293
58930
|
let hashDirExists = false;
|
|
58294
58931
|
try {
|
|
@@ -58306,7 +58943,7 @@ async function writeUploadedAttachment(args) {
|
|
|
58306
58943
|
try {
|
|
58307
58944
|
import_node_fs33.default.mkdirSync(hashDir, { recursive: true });
|
|
58308
58945
|
finalFileName = args.fileName;
|
|
58309
|
-
import_node_fs33.default.renameSync(tmpPath,
|
|
58946
|
+
import_node_fs33.default.renameSync(tmpPath, import_node_path39.default.join(hashDir, finalFileName));
|
|
58310
58947
|
} catch (err) {
|
|
58311
58948
|
try {
|
|
58312
58949
|
import_node_fs33.default.unlinkSync(tmpPath);
|
|
@@ -58315,7 +58952,7 @@ async function writeUploadedAttachment(args) {
|
|
|
58315
58952
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
58316
58953
|
}
|
|
58317
58954
|
}
|
|
58318
|
-
const absPath =
|
|
58955
|
+
const absPath = import_node_path39.default.join(hashDir, finalFileName);
|
|
58319
58956
|
const relPath = absPath;
|
|
58320
58957
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
58321
58958
|
relPath: absPath,
|
|
@@ -58329,8 +58966,8 @@ async function writeUploadedAttachment(args) {
|
|
|
58329
58966
|
}
|
|
58330
58967
|
|
|
58331
58968
|
// src/extension/import.ts
|
|
58332
|
-
var
|
|
58333
|
-
var
|
|
58969
|
+
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
58970
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
58334
58971
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
58335
58972
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
58336
58973
|
var ImportError = class extends Error {
|
|
@@ -58348,7 +58985,7 @@ async function importZip(buf, root) {
|
|
|
58348
58985
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
58349
58986
|
}
|
|
58350
58987
|
for (const name of Object.keys(zip.files)) {
|
|
58351
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
58988
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path40.default.isAbsolute(name)) {
|
|
58352
58989
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
58353
58990
|
}
|
|
58354
58991
|
}
|
|
@@ -58381,33 +59018,33 @@ async function importZip(buf, root) {
|
|
|
58381
59018
|
);
|
|
58382
59019
|
}
|
|
58383
59020
|
}
|
|
58384
|
-
const destDir =
|
|
59021
|
+
const destDir = import_node_path40.default.join(root, manifest.id);
|
|
58385
59022
|
let destExists = false;
|
|
58386
59023
|
try {
|
|
58387
|
-
await
|
|
59024
|
+
await import_promises8.default.access(destDir);
|
|
58388
59025
|
destExists = true;
|
|
58389
59026
|
} catch {
|
|
58390
59027
|
}
|
|
58391
59028
|
if (destExists) {
|
|
58392
59029
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
58393
59030
|
}
|
|
58394
|
-
const stage = await
|
|
59031
|
+
const stage = await import_promises8.default.mkdtemp(import_node_path40.default.join(import_node_os13.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
58395
59032
|
try {
|
|
58396
59033
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
58397
|
-
const dest =
|
|
59034
|
+
const dest = import_node_path40.default.join(stage, name);
|
|
58398
59035
|
if (entry.dir) {
|
|
58399
|
-
await
|
|
59036
|
+
await import_promises8.default.mkdir(dest, { recursive: true });
|
|
58400
59037
|
continue;
|
|
58401
59038
|
}
|
|
58402
|
-
await
|
|
59039
|
+
await import_promises8.default.mkdir(import_node_path40.default.dirname(dest), { recursive: true });
|
|
58403
59040
|
const content = await entry.async("nodebuffer");
|
|
58404
|
-
await
|
|
59041
|
+
await import_promises8.default.writeFile(dest, content);
|
|
58405
59042
|
}
|
|
58406
|
-
await
|
|
58407
|
-
await
|
|
59043
|
+
await import_promises8.default.mkdir(root, { recursive: true });
|
|
59044
|
+
await import_promises8.default.rename(stage, destDir);
|
|
58408
59045
|
return { extId: manifest.id };
|
|
58409
59046
|
} catch (e) {
|
|
58410
|
-
await
|
|
59047
|
+
await import_promises8.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
58411
59048
|
});
|
|
58412
59049
|
throw e;
|
|
58413
59050
|
}
|
|
@@ -58429,7 +59066,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
58429
59066
|
".wasm": "application/wasm"
|
|
58430
59067
|
};
|
|
58431
59068
|
function shareUiAssetMime(filePath) {
|
|
58432
|
-
const ext =
|
|
59069
|
+
const ext = import_node_path41.default.extname(filePath).toLowerCase();
|
|
58433
59070
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
58434
59071
|
}
|
|
58435
59072
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -58528,7 +59165,7 @@ function isValidUploadFileName(fileName) {
|
|
|
58528
59165
|
if (fileName === "." || fileName === "..") return false;
|
|
58529
59166
|
if (fileName.startsWith(".")) return false;
|
|
58530
59167
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
58531
|
-
return fileName ===
|
|
59168
|
+
return fileName === import_node_path41.default.basename(fileName);
|
|
58532
59169
|
}
|
|
58533
59170
|
function createHttpRouter(deps) {
|
|
58534
59171
|
return async (req, res) => {
|
|
@@ -58764,7 +59401,7 @@ function createHttpRouter(deps) {
|
|
|
58764
59401
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
58765
59402
|
return true;
|
|
58766
59403
|
}
|
|
58767
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
59404
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path41.default.basename(r.absPath)));
|
|
58768
59405
|
return true;
|
|
58769
59406
|
}
|
|
58770
59407
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -58885,7 +59522,7 @@ function createHttpRouter(deps) {
|
|
|
58885
59522
|
return true;
|
|
58886
59523
|
}
|
|
58887
59524
|
let absPath;
|
|
58888
|
-
if (
|
|
59525
|
+
if (import_node_path41.default.isAbsolute(pathParam)) {
|
|
58889
59526
|
absPath = pathParam;
|
|
58890
59527
|
} else if (deps.sessionStore) {
|
|
58891
59528
|
const file = deps.sessionStore.read(sid);
|
|
@@ -58893,7 +59530,7 @@ function createHttpRouter(deps) {
|
|
|
58893
59530
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
58894
59531
|
return true;
|
|
58895
59532
|
}
|
|
58896
|
-
absPath =
|
|
59533
|
+
absPath = import_node_path41.default.join(file.cwd, pathParam);
|
|
58897
59534
|
} else {
|
|
58898
59535
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
58899
59536
|
return true;
|
|
@@ -58995,7 +59632,7 @@ function streamFile(res, absPath, logger) {
|
|
|
58995
59632
|
return;
|
|
58996
59633
|
}
|
|
58997
59634
|
const mime = lookupMime(absPath);
|
|
58998
|
-
const basename2 =
|
|
59635
|
+
const basename2 = import_node_path41.default.basename(absPath);
|
|
58999
59636
|
res.writeHead(200, {
|
|
59000
59637
|
"Content-Type": mime,
|
|
59001
59638
|
"Content-Length": String(stat.size),
|
|
@@ -59013,7 +59650,7 @@ function streamFile(res, absPath, logger) {
|
|
|
59013
59650
|
|
|
59014
59651
|
// src/attachment/gc.ts
|
|
59015
59652
|
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
59016
|
-
var
|
|
59653
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
59017
59654
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
59018
59655
|
function runAttachmentGc(args) {
|
|
59019
59656
|
const now = (args.now ?? Date.now)();
|
|
@@ -59022,12 +59659,12 @@ function runAttachmentGc(args) {
|
|
|
59022
59659
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
59023
59660
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
59024
59661
|
if (entry.stale) continue;
|
|
59025
|
-
if (
|
|
59662
|
+
if (import_node_path42.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
59026
59663
|
}
|
|
59027
59664
|
}
|
|
59028
59665
|
const visited = /* @__PURE__ */ new Set();
|
|
59029
59666
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
59030
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
59667
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path42.default.join(
|
|
59031
59668
|
args.dataDir,
|
|
59032
59669
|
"sessions",
|
|
59033
59670
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -59040,7 +59677,7 @@ function runAttachmentGc(args) {
|
|
|
59040
59677
|
return true;
|
|
59041
59678
|
});
|
|
59042
59679
|
for (const rootDir of roots) {
|
|
59043
|
-
const attRoot =
|
|
59680
|
+
const attRoot = import_node_path42.default.join(rootDir, ".attachments");
|
|
59044
59681
|
let hashDirs;
|
|
59045
59682
|
try {
|
|
59046
59683
|
hashDirs = import_node_fs35.default.readdirSync(attRoot);
|
|
@@ -59050,7 +59687,7 @@ function runAttachmentGc(args) {
|
|
|
59050
59687
|
continue;
|
|
59051
59688
|
}
|
|
59052
59689
|
for (const hashDir of hashDirs) {
|
|
59053
|
-
const hashDirAbs =
|
|
59690
|
+
const hashDirAbs = import_node_path42.default.join(attRoot, hashDir);
|
|
59054
59691
|
let files;
|
|
59055
59692
|
try {
|
|
59056
59693
|
files = import_node_fs35.default.readdirSync(hashDirAbs);
|
|
@@ -59058,7 +59695,7 @@ function runAttachmentGc(args) {
|
|
|
59058
59695
|
continue;
|
|
59059
59696
|
}
|
|
59060
59697
|
for (const name of files) {
|
|
59061
|
-
const file =
|
|
59698
|
+
const file = import_node_path42.default.join(hashDirAbs, name);
|
|
59062
59699
|
let stat;
|
|
59063
59700
|
try {
|
|
59064
59701
|
stat = import_node_fs35.default.statSync(file);
|
|
@@ -59090,7 +59727,7 @@ function runAttachmentGc(args) {
|
|
|
59090
59727
|
|
|
59091
59728
|
// src/attachment/group.ts
|
|
59092
59729
|
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
59093
|
-
var
|
|
59730
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
59094
59731
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
59095
59732
|
init_protocol();
|
|
59096
59733
|
var GroupFileStore = class {
|
|
@@ -59102,11 +59739,11 @@ var GroupFileStore = class {
|
|
|
59102
59739
|
this.logger = opts.logger;
|
|
59103
59740
|
}
|
|
59104
59741
|
rootForScope(scope) {
|
|
59105
|
-
return
|
|
59742
|
+
return import_node_path43.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
59106
59743
|
}
|
|
59107
59744
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
59108
59745
|
filePath(scope, sessionId) {
|
|
59109
|
-
return
|
|
59746
|
+
return import_node_path43.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
59110
59747
|
}
|
|
59111
59748
|
cacheKey(scope, sessionId) {
|
|
59112
59749
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -59141,7 +59778,7 @@ var GroupFileStore = class {
|
|
|
59141
59778
|
}
|
|
59142
59779
|
writeFile(scope, sessionId, entries) {
|
|
59143
59780
|
const file = this.filePath(scope, sessionId);
|
|
59144
|
-
import_node_fs36.default.mkdirSync(
|
|
59781
|
+
import_node_fs36.default.mkdirSync(import_node_path43.default.dirname(file), { recursive: true });
|
|
59145
59782
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
59146
59783
|
import_node_fs36.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
59147
59784
|
import_node_fs36.default.renameSync(tmp, file);
|
|
@@ -59231,9 +59868,9 @@ var GroupFileStore = class {
|
|
|
59231
59868
|
|
|
59232
59869
|
// src/discovery/state-file.ts
|
|
59233
59870
|
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
59234
|
-
var
|
|
59871
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
59235
59872
|
function defaultStateFilePath(dataDir) {
|
|
59236
|
-
return
|
|
59873
|
+
return import_node_path44.default.join(dataDir, "state.json");
|
|
59237
59874
|
}
|
|
59238
59875
|
function isPidAlive(pid) {
|
|
59239
59876
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -59269,7 +59906,7 @@ var StateFileManager = class {
|
|
|
59269
59906
|
return { status: "stale", existing };
|
|
59270
59907
|
}
|
|
59271
59908
|
write(state) {
|
|
59272
|
-
import_node_fs37.default.mkdirSync(
|
|
59909
|
+
import_node_fs37.default.mkdirSync(import_node_path44.default.dirname(this.file), { recursive: true });
|
|
59273
59910
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
59274
59911
|
import_node_fs37.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
59275
59912
|
import_node_fs37.default.renameSync(tmp, this.file);
|
|
@@ -59297,13 +59934,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
59297
59934
|
|
|
59298
59935
|
// src/tunnel/tunnel-manager.ts
|
|
59299
59936
|
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
59300
|
-
var
|
|
59937
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
59301
59938
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
59302
59939
|
var import_node_child_process11 = require("child_process");
|
|
59303
59940
|
|
|
59304
59941
|
// src/tunnel/tunnel-store.ts
|
|
59305
59942
|
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
59306
|
-
var
|
|
59943
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
59307
59944
|
var TunnelStore = class {
|
|
59308
59945
|
constructor(filePath) {
|
|
59309
59946
|
this.filePath = filePath;
|
|
@@ -59322,7 +59959,7 @@ var TunnelStore = class {
|
|
|
59322
59959
|
}
|
|
59323
59960
|
}
|
|
59324
59961
|
async set(v2) {
|
|
59325
|
-
const dir =
|
|
59962
|
+
const dir = import_node_path45.default.dirname(this.filePath);
|
|
59326
59963
|
await import_node_fs38.default.promises.mkdir(dir, { recursive: true });
|
|
59327
59964
|
const data = JSON.stringify(v2, null, 2);
|
|
59328
59965
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
@@ -59434,10 +60071,10 @@ function escape(v2) {
|
|
|
59434
60071
|
// src/tunnel/frpc-binary.ts
|
|
59435
60072
|
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
59436
60073
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
59437
|
-
var
|
|
60074
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
59438
60075
|
var import_node_child_process9 = require("child_process");
|
|
59439
60076
|
var import_node_stream3 = require("stream");
|
|
59440
|
-
var
|
|
60077
|
+
var import_promises9 = require("stream/promises");
|
|
59441
60078
|
var FRPC_VERSION = "0.68.0";
|
|
59442
60079
|
var UnsupportedPlatformError = class extends Error {
|
|
59443
60080
|
constructor(platform, arch) {
|
|
@@ -59473,13 +60110,13 @@ async function ensureFrpcBinary(opts) {
|
|
|
59473
60110
|
}
|
|
59474
60111
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
59475
60112
|
const platform = opts.platform ?? detectPlatform();
|
|
59476
|
-
const binDir =
|
|
60113
|
+
const binDir = import_node_path46.default.join(opts.dataDir, "bin");
|
|
59477
60114
|
import_node_fs39.default.mkdirSync(binDir, { recursive: true });
|
|
59478
60115
|
cleanupStaleArtifacts(binDir);
|
|
59479
|
-
const stableBin =
|
|
60116
|
+
const stableBin = import_node_path46.default.join(binDir, "frpc");
|
|
59480
60117
|
if (import_node_fs39.default.existsSync(stableBin)) return stableBin;
|
|
59481
60118
|
const partialBin = `${stableBin}.partial`;
|
|
59482
|
-
const tarballPath =
|
|
60119
|
+
const tarballPath = import_node_path46.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
59483
60120
|
try {
|
|
59484
60121
|
const url = frpcDownloadUrl(version2, platform);
|
|
59485
60122
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -59505,7 +60142,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
59505
60142
|
}
|
|
59506
60143
|
for (const name of entries) {
|
|
59507
60144
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
59508
|
-
const full =
|
|
60145
|
+
const full = import_node_path46.default.join(binDir, name);
|
|
59509
60146
|
try {
|
|
59510
60147
|
import_node_fs39.default.rmSync(full, { recursive: true, force: true });
|
|
59511
60148
|
} catch {
|
|
@@ -59528,10 +60165,10 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
59528
60165
|
}
|
|
59529
60166
|
const out = import_node_fs39.default.createWriteStream(dest);
|
|
59530
60167
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
59531
|
-
await (0,
|
|
60168
|
+
await (0, import_promises9.pipeline)(nodeStream, out);
|
|
59532
60169
|
}
|
|
59533
60170
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
59534
|
-
const work =
|
|
60171
|
+
const work = import_node_path46.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
59535
60172
|
import_node_fs39.default.mkdirSync(work, { recursive: true });
|
|
59536
60173
|
try {
|
|
59537
60174
|
await new Promise((resolve9, reject) => {
|
|
@@ -59540,7 +60177,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
59540
60177
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
59541
60178
|
});
|
|
59542
60179
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
59543
|
-
const src =
|
|
60180
|
+
const src = import_node_path46.default.join(work, dirName, "frpc");
|
|
59544
60181
|
if (!import_node_fs39.default.existsSync(src)) {
|
|
59545
60182
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
59546
60183
|
}
|
|
@@ -59552,10 +60189,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
59552
60189
|
|
|
59553
60190
|
// src/tunnel/frpc-process.ts
|
|
59554
60191
|
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
59555
|
-
var
|
|
60192
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
59556
60193
|
var import_node_child_process10 = require("child_process");
|
|
59557
60194
|
function frpcPidFilePath(dataDir) {
|
|
59558
|
-
return
|
|
60195
|
+
return import_node_path47.default.join(dataDir, "frpc.pid");
|
|
59559
60196
|
}
|
|
59560
60197
|
function writeFrpcPid(dataDir, pid) {
|
|
59561
60198
|
try {
|
|
@@ -59597,7 +60234,7 @@ function defaultSleep2(ms) {
|
|
|
59597
60234
|
}
|
|
59598
60235
|
async function killStaleFrpc(deps) {
|
|
59599
60236
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
59600
|
-
const tomlPath =
|
|
60237
|
+
const tomlPath = import_node_path47.default.join(deps.dataDir, "frpc.toml");
|
|
59601
60238
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
59602
60239
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
59603
60240
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -59669,7 +60306,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
59669
60306
|
var TunnelManager = class {
|
|
59670
60307
|
constructor(deps) {
|
|
59671
60308
|
this.deps = deps;
|
|
59672
|
-
this.store = deps.store ?? new TunnelStore(
|
|
60309
|
+
this.store = deps.store ?? new TunnelStore(import_node_path48.default.join(deps.dataDir, "tunnel.json"));
|
|
59673
60310
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
59674
60311
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
59675
60312
|
}
|
|
@@ -59796,7 +60433,7 @@ var TunnelManager = class {
|
|
|
59796
60433
|
dataDir: this.deps.dataDir,
|
|
59797
60434
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
59798
60435
|
});
|
|
59799
|
-
const tomlPath =
|
|
60436
|
+
const tomlPath = import_node_path48.default.join(this.deps.dataDir, "frpc.toml");
|
|
59800
60437
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto12.default.randomBytes(3).toString("hex")}`;
|
|
59801
60438
|
const toml = buildFrpcToml({
|
|
59802
60439
|
serverAddr: t.frpsHost,
|
|
@@ -59811,9 +60448,9 @@ var TunnelManager = class {
|
|
|
59811
60448
|
const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(frpcBin, ["-c", tomlPath], {
|
|
59812
60449
|
stdio: ["ignore", "pipe", "pipe"]
|
|
59813
60450
|
});
|
|
59814
|
-
const logDir =
|
|
60451
|
+
const logDir = import_node_path48.default.join(this.deps.dataDir, "log");
|
|
59815
60452
|
import_node_fs41.default.mkdirSync(logDir, { recursive: true });
|
|
59816
|
-
const logFilePath =
|
|
60453
|
+
const logFilePath = import_node_path48.default.join(logDir, "frpc.log");
|
|
59817
60454
|
const logStream = import_node_fs41.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
59818
60455
|
logStream.on("error", () => {
|
|
59819
60456
|
});
|
|
@@ -59897,15 +60534,15 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
59897
60534
|
|
|
59898
60535
|
// src/tunnel/device-key.ts
|
|
59899
60536
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
59900
|
-
var
|
|
60537
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
59901
60538
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
59902
60539
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
59903
60540
|
function deriveStableDeviceKey(opts = {}) {
|
|
59904
60541
|
const hostname = opts.hostname ?? import_node_os15.default.hostname();
|
|
59905
60542
|
const uid = opts.uid ?? (typeof import_node_os15.default.userInfo === "function" ? import_node_os15.default.userInfo().uid : 0);
|
|
59906
60543
|
const home = opts.home ?? import_node_os15.default.homedir();
|
|
59907
|
-
const defaultDataDir =
|
|
59908
|
-
const normalizedDataDir = opts.dataDir ?
|
|
60544
|
+
const defaultDataDir = import_node_path49.default.resolve(import_node_path49.default.join(home, ".clawd"));
|
|
60545
|
+
const normalizedDataDir = opts.dataDir ? import_node_path49.default.resolve(opts.dataDir) : null;
|
|
59909
60546
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
59910
60547
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
59911
60548
|
return import_node_crypto13.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
@@ -59913,11 +60550,11 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
59913
60550
|
|
|
59914
60551
|
// src/auth-store.ts
|
|
59915
60552
|
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
59916
|
-
var
|
|
60553
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
59917
60554
|
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
59918
60555
|
var AUTH_FILE_NAME = "auth.json";
|
|
59919
60556
|
function authFilePath(dataDir) {
|
|
59920
|
-
return
|
|
60557
|
+
return import_node_path50.default.join(dataDir, AUTH_FILE_NAME);
|
|
59921
60558
|
}
|
|
59922
60559
|
function loadOrCreateAuthFile(opts) {
|
|
59923
60560
|
const file = authFilePath(opts.dataDir);
|
|
@@ -59969,7 +60606,7 @@ function readAuthFile(file) {
|
|
|
59969
60606
|
}
|
|
59970
60607
|
}
|
|
59971
60608
|
function writeAuthFile(file, content) {
|
|
59972
|
-
import_node_fs42.default.mkdirSync(
|
|
60609
|
+
import_node_fs42.default.mkdirSync(import_node_path50.default.dirname(file), { recursive: true });
|
|
59973
60610
|
import_node_fs42.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
59974
60611
|
try {
|
|
59975
60612
|
import_node_fs42.default.chmodSync(file, 384);
|
|
@@ -59980,10 +60617,10 @@ function writeAuthFile(file, content) {
|
|
|
59980
60617
|
// src/owner-profile.ts
|
|
59981
60618
|
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
59982
60619
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
59983
|
-
var
|
|
60620
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
59984
60621
|
var PROFILE_FILENAME = "profile.json";
|
|
59985
60622
|
function profilePath(dataDir) {
|
|
59986
|
-
return
|
|
60623
|
+
return import_node_path51.default.join(dataDir, PROFILE_FILENAME);
|
|
59987
60624
|
}
|
|
59988
60625
|
function loadOwnerProfile(dataDir) {
|
|
59989
60626
|
let raw;
|
|
@@ -60021,12 +60658,12 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
60021
60658
|
|
|
60022
60659
|
// src/feishu-auth/owner-identity-store.ts
|
|
60023
60660
|
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
60024
|
-
var
|
|
60661
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
60025
60662
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
60026
60663
|
var OwnerIdentityStore = class {
|
|
60027
60664
|
file;
|
|
60028
60665
|
constructor(dataDir) {
|
|
60029
|
-
this.file =
|
|
60666
|
+
this.file = import_node_path52.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
60030
60667
|
}
|
|
60031
60668
|
read() {
|
|
60032
60669
|
let raw;
|
|
@@ -60059,7 +60696,7 @@ var OwnerIdentityStore = class {
|
|
|
60059
60696
|
};
|
|
60060
60697
|
}
|
|
60061
60698
|
write(record3) {
|
|
60062
|
-
import_node_fs44.default.mkdirSync(
|
|
60699
|
+
import_node_fs44.default.mkdirSync(import_node_path52.default.dirname(this.file), { recursive: true });
|
|
60063
60700
|
import_node_fs44.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
|
|
60064
60701
|
try {
|
|
60065
60702
|
import_node_fs44.default.chmodSync(this.file, 384);
|
|
@@ -60205,9 +60842,9 @@ var CentralClientError = class extends Error {
|
|
|
60205
60842
|
code;
|
|
60206
60843
|
cause;
|
|
60207
60844
|
};
|
|
60208
|
-
async function centralRequest(opts,
|
|
60845
|
+
async function centralRequest(opts, path93, init) {
|
|
60209
60846
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
60210
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
60847
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path93}`;
|
|
60211
60848
|
const ctrl = new AbortController();
|
|
60212
60849
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
60213
60850
|
let res;
|
|
@@ -60461,7 +61098,7 @@ async function syncOrgMesh(deps) {
|
|
|
60461
61098
|
|
|
60462
61099
|
// src/handlers/device.ts
|
|
60463
61100
|
init_protocol();
|
|
60464
|
-
function
|
|
61101
|
+
function ensureOwner2(ctx) {
|
|
60465
61102
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
60466
61103
|
throw new ClawdError(ERROR_CODES.UNAUTHORIZED, "UNAUTHORIZED: device:* requires owner ctx");
|
|
60467
61104
|
}
|
|
@@ -60556,14 +61193,14 @@ function createConnectToDevice(deps) {
|
|
|
60556
61193
|
function buildDeviceHandlers(deps) {
|
|
60557
61194
|
const connectToDevice = createConnectToDevice(deps);
|
|
60558
61195
|
const list = async (_frame, _client, ctx) => {
|
|
60559
|
-
|
|
61196
|
+
ensureOwner2(ctx);
|
|
60560
61197
|
const devices = await deps.listDevices().catch(rethrowLoginExpired);
|
|
60561
61198
|
return {
|
|
60562
61199
|
response: { type: "device:list:ok", devices }
|
|
60563
61200
|
};
|
|
60564
61201
|
};
|
|
60565
61202
|
const connect = async (frame, _client, ctx) => {
|
|
60566
|
-
|
|
61203
|
+
ensureOwner2(ctx);
|
|
60567
61204
|
const { type: _t, requestId: _r, ...rest } = frame;
|
|
60568
61205
|
const args = DeviceConnectArgsSchema.parse(rest);
|
|
60569
61206
|
const contact = await connectToDevice(args);
|
|
@@ -60578,7 +61215,7 @@ function buildDeviceHandlers(deps) {
|
|
|
60578
61215
|
};
|
|
60579
61216
|
};
|
|
60580
61217
|
const connections = async (_frame, client, ctx) => {
|
|
60581
|
-
|
|
61218
|
+
ensureOwner2(ctx);
|
|
60582
61219
|
const entries = deps.listOwnerConnections();
|
|
60583
61220
|
return {
|
|
60584
61221
|
response: {
|
|
@@ -60644,8 +61281,8 @@ function verifyConnectToken(args) {
|
|
|
60644
61281
|
}
|
|
60645
61282
|
|
|
60646
61283
|
// src/feishu-auth/server-key.ts
|
|
60647
|
-
var
|
|
60648
|
-
var
|
|
61284
|
+
var fs61 = __toESM(require("fs"), 1);
|
|
61285
|
+
var path65 = __toESM(require("path"), 1);
|
|
60649
61286
|
var FILE_NAME2 = "server-signing-key.json";
|
|
60650
61287
|
var ServerKeyStore = class {
|
|
60651
61288
|
constructor(dataDir) {
|
|
@@ -60653,12 +61290,12 @@ var ServerKeyStore = class {
|
|
|
60653
61290
|
}
|
|
60654
61291
|
dataDir;
|
|
60655
61292
|
filePath() {
|
|
60656
|
-
return
|
|
61293
|
+
return path65.join(this.dataDir, FILE_NAME2);
|
|
60657
61294
|
}
|
|
60658
61295
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
60659
61296
|
read() {
|
|
60660
61297
|
try {
|
|
60661
|
-
const raw =
|
|
61298
|
+
const raw = fs61.readFileSync(this.filePath(), "utf8");
|
|
60662
61299
|
const parsed = JSON.parse(raw);
|
|
60663
61300
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
60664
61301
|
return parsed.publicKeyPem;
|
|
@@ -60673,12 +61310,12 @@ var ServerKeyStore = class {
|
|
|
60673
61310
|
publicKeyPem,
|
|
60674
61311
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
60675
61312
|
};
|
|
60676
|
-
|
|
60677
|
-
|
|
61313
|
+
fs61.mkdirSync(this.dataDir, { recursive: true });
|
|
61314
|
+
fs61.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
60678
61315
|
}
|
|
60679
61316
|
clear() {
|
|
60680
61317
|
try {
|
|
60681
|
-
|
|
61318
|
+
fs61.unlinkSync(this.filePath());
|
|
60682
61319
|
} catch {
|
|
60683
61320
|
}
|
|
60684
61321
|
}
|
|
@@ -60688,7 +61325,7 @@ var ServerKeyStore = class {
|
|
|
60688
61325
|
init_protocol();
|
|
60689
61326
|
|
|
60690
61327
|
// src/handlers/index.ts
|
|
60691
|
-
var
|
|
61328
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
60692
61329
|
|
|
60693
61330
|
// src/handlers/session.ts
|
|
60694
61331
|
init_protocol();
|
|
@@ -60696,7 +61333,7 @@ init_protocol();
|
|
|
60696
61333
|
// src/session/fork.ts
|
|
60697
61334
|
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
60698
61335
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
60699
|
-
var
|
|
61336
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
60700
61337
|
var import_node_crypto16 = require("crypto");
|
|
60701
61338
|
init_claude_history();
|
|
60702
61339
|
function readJsonlEntries(file) {
|
|
@@ -60713,19 +61350,19 @@ function readJsonlEntries(file) {
|
|
|
60713
61350
|
return out;
|
|
60714
61351
|
}
|
|
60715
61352
|
function forkSession(input) {
|
|
60716
|
-
const baseDir = input.baseDir ??
|
|
60717
|
-
let projectDir =
|
|
60718
|
-
let sourceFile =
|
|
61353
|
+
const baseDir = input.baseDir ?? import_node_path53.default.join(import_node_os17.default.homedir(), ".claude");
|
|
61354
|
+
let projectDir = import_node_path53.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
61355
|
+
let sourceFile = import_node_path53.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
60719
61356
|
if (!import_node_fs45.default.existsSync(sourceFile)) {
|
|
60720
61357
|
const found = findTranscriptByToolSessionId(
|
|
60721
|
-
|
|
61358
|
+
import_node_path53.default.join(baseDir, "projects"),
|
|
60722
61359
|
input.toolSessionId
|
|
60723
61360
|
);
|
|
60724
61361
|
if (!found) {
|
|
60725
61362
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
60726
61363
|
}
|
|
60727
61364
|
sourceFile = found;
|
|
60728
|
-
projectDir =
|
|
61365
|
+
projectDir = import_node_path53.default.dirname(found);
|
|
60729
61366
|
}
|
|
60730
61367
|
const entries = readJsonlEntries(sourceFile);
|
|
60731
61368
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -60754,8 +61391,8 @@ function forkSession(input) {
|
|
|
60754
61391
|
}
|
|
60755
61392
|
forkedLines.push(JSON.stringify(forked));
|
|
60756
61393
|
}
|
|
60757
|
-
const outDir = input.targetCwd ?
|
|
60758
|
-
const forkedFilePath =
|
|
61394
|
+
const outDir = input.targetCwd ? import_node_path53.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
61395
|
+
const forkedFilePath = import_node_path53.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
60759
61396
|
import_node_fs45.default.mkdirSync(outDir, { recursive: true });
|
|
60760
61397
|
import_node_fs45.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
60761
61398
|
return { forkedToolSessionId, forkedFilePath };
|
|
@@ -60763,18 +61400,18 @@ function forkSession(input) {
|
|
|
60763
61400
|
|
|
60764
61401
|
// src/session/external-scan.ts
|
|
60765
61402
|
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
60766
|
-
var
|
|
61403
|
+
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
60767
61404
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
60768
|
-
var
|
|
61405
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
60769
61406
|
var import_node_module = require("module");
|
|
60770
61407
|
var import_node_child_process12 = require("child_process");
|
|
60771
61408
|
var import_meta4 = {};
|
|
60772
61409
|
function defaultRoots() {
|
|
60773
61410
|
const home = import_node_os18.default.homedir();
|
|
60774
61411
|
return {
|
|
60775
|
-
claudeProjectsDir:
|
|
60776
|
-
codexDir:
|
|
60777
|
-
clawdDir:
|
|
61412
|
+
claudeProjectsDir: import_node_path54.default.join(home, ".claude", "projects"),
|
|
61413
|
+
codexDir: import_node_path54.default.join(home, ".codex"),
|
|
61414
|
+
clawdDir: import_node_path54.default.join(home, ".clawd")
|
|
60778
61415
|
};
|
|
60779
61416
|
}
|
|
60780
61417
|
function width(s) {
|
|
@@ -60802,7 +61439,7 @@ function toMs(v2) {
|
|
|
60802
61439
|
async function* jsonLines(file) {
|
|
60803
61440
|
let raw;
|
|
60804
61441
|
try {
|
|
60805
|
-
raw = await
|
|
61442
|
+
raw = await import_promises10.default.readFile(file, "utf8");
|
|
60806
61443
|
} catch {
|
|
60807
61444
|
return;
|
|
60808
61445
|
}
|
|
@@ -60842,13 +61479,13 @@ async function scanClaude(roots) {
|
|
|
60842
61479
|
if (!d.isDirectory()) continue;
|
|
60843
61480
|
let files;
|
|
60844
61481
|
try {
|
|
60845
|
-
files = import_node_fs46.default.readdirSync(
|
|
61482
|
+
files = import_node_fs46.default.readdirSync(import_node_path54.default.join(roots.claudeProjectsDir, d.name));
|
|
60846
61483
|
} catch {
|
|
60847
61484
|
continue;
|
|
60848
61485
|
}
|
|
60849
61486
|
for (const name of files) {
|
|
60850
61487
|
if (!name.endsWith(".jsonl")) continue;
|
|
60851
|
-
const file =
|
|
61488
|
+
const file = import_node_path54.default.join(roots.claudeProjectsDir, d.name, name);
|
|
60852
61489
|
let st;
|
|
60853
61490
|
try {
|
|
60854
61491
|
st = import_node_fs46.default.statSync(file);
|
|
@@ -60978,7 +61615,7 @@ async function codexFromRows(rows) {
|
|
|
60978
61615
|
async function scanCodex(roots) {
|
|
60979
61616
|
let dbs = [];
|
|
60980
61617
|
try {
|
|
60981
|
-
dbs = import_node_fs46.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) =>
|
|
61618
|
+
dbs = import_node_fs46.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path54.default.join(roots.codexDir, n));
|
|
60982
61619
|
} catch {
|
|
60983
61620
|
}
|
|
60984
61621
|
if (!dbs.length) return [];
|
|
@@ -60987,14 +61624,14 @@ async function scanCodex(roots) {
|
|
|
60987
61624
|
}
|
|
60988
61625
|
async function scanExternalSessions(rootsIn) {
|
|
60989
61626
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
60990
|
-
const personaRoot =
|
|
61627
|
+
const personaRoot = import_node_path54.default.join(roots.clawdDir, "personas");
|
|
60991
61628
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
60992
61629
|
const out = [];
|
|
60993
61630
|
for (const c of all) {
|
|
60994
61631
|
if (c.skip) continue;
|
|
60995
61632
|
if (c.turns < 1) continue;
|
|
60996
61633
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
60997
|
-
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot +
|
|
61634
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path54.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path54.default.sep)) {
|
|
60998
61635
|
continue;
|
|
60999
61636
|
}
|
|
61000
61637
|
out.push({
|
|
@@ -61012,12 +61649,12 @@ async function scanExternalSessions(rootsIn) {
|
|
|
61012
61649
|
|
|
61013
61650
|
// src/session/import-ledger.ts
|
|
61014
61651
|
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
61015
|
-
var
|
|
61652
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
61016
61653
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
61017
61654
|
function readImportLedger(dataDir) {
|
|
61018
61655
|
try {
|
|
61019
61656
|
const parsed = JSON.parse(
|
|
61020
|
-
import_node_fs47.default.readFileSync(
|
|
61657
|
+
import_node_fs47.default.readFileSync(import_node_path55.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
61021
61658
|
);
|
|
61022
61659
|
return Array.isArray(parsed) ? parsed : [];
|
|
61023
61660
|
} catch {
|
|
@@ -61025,7 +61662,7 @@ function readImportLedger(dataDir) {
|
|
|
61025
61662
|
}
|
|
61026
61663
|
}
|
|
61027
61664
|
function appendImportLedger(dataDir, entry) {
|
|
61028
|
-
const file =
|
|
61665
|
+
const file = import_node_path55.default.join(dataDir, LEDGER_FILENAME);
|
|
61029
61666
|
const entries = readImportLedger(dataDir);
|
|
61030
61667
|
entries.push(entry);
|
|
61031
61668
|
import_node_fs47.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
@@ -61033,7 +61670,7 @@ function appendImportLedger(dataDir, entry) {
|
|
|
61033
61670
|
|
|
61034
61671
|
// src/tools/transcript-search.ts
|
|
61035
61672
|
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
61036
|
-
var
|
|
61673
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
61037
61674
|
var SNIPPET_PAD = 60;
|
|
61038
61675
|
var INJECTED_ENVELOPE_RE = /^<(system-reminder|command-name|command-message|command-args|local-command-stdout|local-command-stderr|task-notification|user-prompt-submit-hook|environment_context|user_instructions)\b/;
|
|
61039
61676
|
var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
|
|
@@ -61126,7 +61763,7 @@ function createCodexRolloutLocator(roots) {
|
|
|
61126
61763
|
return;
|
|
61127
61764
|
}
|
|
61128
61765
|
for (const entry of entries) {
|
|
61129
|
-
const full =
|
|
61766
|
+
const full = import_node_path56.default.join(dir, entry.name);
|
|
61130
61767
|
if (entry.isDirectory()) {
|
|
61131
61768
|
walk2(full, into);
|
|
61132
61769
|
continue;
|
|
@@ -61147,15 +61784,15 @@ function createCodexRolloutLocator(roots) {
|
|
|
61147
61784
|
// src/handlers/session.ts
|
|
61148
61785
|
init_protocol();
|
|
61149
61786
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
61150
|
-
var
|
|
61787
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
61151
61788
|
function canReadSearchHit(ctx, file) {
|
|
61152
61789
|
if (!ctx || ctx.principal.kind === "owner") return true;
|
|
61153
61790
|
return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
|
|
61154
61791
|
}
|
|
61155
61792
|
var DEFAULT_SEARCH_LIMIT = 9;
|
|
61156
61793
|
function codexRolloutRoots(dataDir) {
|
|
61157
|
-
const roots = [
|
|
61158
|
-
if (dataDir) roots.push(
|
|
61794
|
+
const roots = [import_node_path57.default.join(import_node_os19.default.homedir(), ".codex", "sessions")];
|
|
61795
|
+
if (dataDir) roots.push(import_node_path57.default.join(dataDir, "codex-home", "sessions"));
|
|
61159
61796
|
return roots;
|
|
61160
61797
|
}
|
|
61161
61798
|
function buildSessionHandlers(deps) {
|
|
@@ -61697,7 +62334,7 @@ function buildPermissionHandlers(deps) {
|
|
|
61697
62334
|
}
|
|
61698
62335
|
|
|
61699
62336
|
// src/handlers/history.ts
|
|
61700
|
-
var
|
|
62337
|
+
var path72 = __toESM(require("path"), 1);
|
|
61701
62338
|
init_protocol();
|
|
61702
62339
|
|
|
61703
62340
|
// src/session/recent-dirs.ts
|
|
@@ -61715,7 +62352,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
61715
62352
|
}
|
|
61716
62353
|
|
|
61717
62354
|
// src/permission/persona-paths.ts
|
|
61718
|
-
var
|
|
62355
|
+
var path71 = __toESM(require("path"), 1);
|
|
61719
62356
|
function getAllowedPersonaIds(grants, action) {
|
|
61720
62357
|
const ids = /* @__PURE__ */ new Set();
|
|
61721
62358
|
for (const g2 of grants) {
|
|
@@ -61728,42 +62365,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
61728
62365
|
return ids;
|
|
61729
62366
|
}
|
|
61730
62367
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
61731
|
-
const target =
|
|
62368
|
+
const target = path71.resolve(absPath);
|
|
61732
62369
|
if (userWorkDir) {
|
|
61733
|
-
const u =
|
|
61734
|
-
const usep = u.endsWith(
|
|
62370
|
+
const u = path71.resolve(userWorkDir);
|
|
62371
|
+
const usep = u.endsWith(path71.sep) ? "" : path71.sep;
|
|
61735
62372
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
61736
62373
|
}
|
|
61737
|
-
const root =
|
|
61738
|
-
const sep4 = root.endsWith(
|
|
62374
|
+
const root = path71.resolve(personaRoot);
|
|
62375
|
+
const sep4 = root.endsWith(path71.sep) ? "" : path71.sep;
|
|
61739
62376
|
if (!target.startsWith(root + sep4)) return false;
|
|
61740
|
-
const rel =
|
|
62377
|
+
const rel = path71.relative(root, target);
|
|
61741
62378
|
if (!rel || rel.startsWith("..")) return false;
|
|
61742
|
-
const personaId2 = rel.split(
|
|
62379
|
+
const personaId2 = rel.split(path71.sep)[0];
|
|
61743
62380
|
if (!personaId2) return false;
|
|
61744
62381
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
61745
62382
|
if (allowed === "*") return true;
|
|
61746
62383
|
return allowed.has(personaId2);
|
|
61747
62384
|
}
|
|
61748
62385
|
function personaIdFromPath(absPath, personaRoot) {
|
|
61749
|
-
const root =
|
|
61750
|
-
const target =
|
|
61751
|
-
const sep4 = root.endsWith(
|
|
62386
|
+
const root = path71.resolve(personaRoot);
|
|
62387
|
+
const target = path71.resolve(absPath);
|
|
62388
|
+
const sep4 = root.endsWith(path71.sep) ? "" : path71.sep;
|
|
61752
62389
|
if (!target.startsWith(root + sep4)) return null;
|
|
61753
|
-
const rel =
|
|
62390
|
+
const rel = path71.relative(root, target);
|
|
61754
62391
|
if (!rel || rel.startsWith("..")) return null;
|
|
61755
|
-
const id = rel.split(
|
|
62392
|
+
const id = rel.split(path71.sep)[0];
|
|
61756
62393
|
return id || null;
|
|
61757
62394
|
}
|
|
61758
62395
|
function isPathWithin(dir, absPath) {
|
|
61759
|
-
const d =
|
|
61760
|
-
const t =
|
|
61761
|
-
const sep4 = d.endsWith(
|
|
62396
|
+
const d = path71.resolve(dir);
|
|
62397
|
+
const t = path71.resolve(absPath);
|
|
62398
|
+
const sep4 = d.endsWith(path71.sep) ? "" : path71.sep;
|
|
61762
62399
|
return t === d || t.startsWith(d + sep4);
|
|
61763
62400
|
}
|
|
61764
62401
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
61765
62402
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
61766
|
-
return personaIdFromPath(
|
|
62403
|
+
return personaIdFromPath(path71.resolve(absPath), personaRoot) === personaId2;
|
|
61767
62404
|
}
|
|
61768
62405
|
|
|
61769
62406
|
// src/handlers/history.ts
|
|
@@ -61816,7 +62453,7 @@ function buildHistoryHandlers(deps) {
|
|
|
61816
62453
|
if (!pid) return false;
|
|
61817
62454
|
return isGuestPathAllowed(
|
|
61818
62455
|
ctx.grants,
|
|
61819
|
-
|
|
62456
|
+
path72.join(personaRoot, pid),
|
|
61820
62457
|
personaRoot,
|
|
61821
62458
|
"read",
|
|
61822
62459
|
userWorkDir
|
|
@@ -61828,7 +62465,7 @@ function buildHistoryHandlers(deps) {
|
|
|
61828
62465
|
};
|
|
61829
62466
|
const list = async (frame, _client, ctx) => {
|
|
61830
62467
|
const args = HistoryListArgs.parse(frame);
|
|
61831
|
-
assertGuestPath(ctx,
|
|
62468
|
+
assertGuestPath(ctx, path72.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
61832
62469
|
const sessions = await history.listSessions(args);
|
|
61833
62470
|
return { response: { type: "history:list", sessions } };
|
|
61834
62471
|
};
|
|
@@ -61876,14 +62513,14 @@ function buildHistoryHandlers(deps) {
|
|
|
61876
62513
|
};
|
|
61877
62514
|
const subagents = async (frame, _client, ctx) => {
|
|
61878
62515
|
const args = HistorySubagentsArgs.parse(frame);
|
|
61879
|
-
assertGuestPath(ctx,
|
|
62516
|
+
assertGuestPath(ctx, path72.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
61880
62517
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
61881
62518
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
61882
62519
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
61883
62520
|
};
|
|
61884
62521
|
const subagentRead = async (frame, _client, ctx) => {
|
|
61885
62522
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
61886
|
-
assertGuestPath(ctx,
|
|
62523
|
+
assertGuestPath(ctx, path72.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
61887
62524
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
61888
62525
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
61889
62526
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -61893,7 +62530,7 @@ function buildHistoryHandlers(deps) {
|
|
|
61893
62530
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
61894
62531
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
61895
62532
|
const filtered = dirs.filter(
|
|
61896
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
62533
|
+
(d) => isGuestPathAllowed(ctx.grants, path72.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
61897
62534
|
);
|
|
61898
62535
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
61899
62536
|
}
|
|
@@ -61910,17 +62547,17 @@ function buildHistoryHandlers(deps) {
|
|
|
61910
62547
|
}
|
|
61911
62548
|
|
|
61912
62549
|
// src/handlers/projects.ts
|
|
61913
|
-
var
|
|
62550
|
+
var fs66 = __toESM(require("fs"), 1);
|
|
61914
62551
|
var os21 = __toESM(require("os"), 1);
|
|
61915
|
-
var
|
|
62552
|
+
var path73 = __toESM(require("path"), 1);
|
|
61916
62553
|
var import_node_child_process13 = require("child_process");
|
|
61917
62554
|
init_protocol();
|
|
61918
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
62555
|
+
var DEFAULT_PROJECTS_ROOT = path73.join(os21.homedir(), "Documents", "ChatGPT");
|
|
61919
62556
|
function allocateDir(root, name) {
|
|
61920
|
-
let candidate =
|
|
62557
|
+
let candidate = path73.join(root, name);
|
|
61921
62558
|
let n = 2;
|
|
61922
|
-
while (
|
|
61923
|
-
candidate =
|
|
62559
|
+
while (fs66.existsSync(candidate)) {
|
|
62560
|
+
candidate = path73.join(root, `${name} ${n}`);
|
|
61924
62561
|
n += 1;
|
|
61925
62562
|
}
|
|
61926
62563
|
return candidate;
|
|
@@ -61948,7 +62585,7 @@ function buildProjectHandlers(deps) {
|
|
|
61948
62585
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
61949
62586
|
}
|
|
61950
62587
|
try {
|
|
61951
|
-
if (!
|
|
62588
|
+
if (!fs66.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
61952
62589
|
} catch {
|
|
61953
62590
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
61954
62591
|
}
|
|
@@ -61964,7 +62601,7 @@ function buildProjectHandlers(deps) {
|
|
|
61964
62601
|
let target;
|
|
61965
62602
|
if (args.path) {
|
|
61966
62603
|
try {
|
|
61967
|
-
if (!
|
|
62604
|
+
if (!fs66.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
61968
62605
|
} catch {
|
|
61969
62606
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
61970
62607
|
}
|
|
@@ -61972,15 +62609,15 @@ function buildProjectHandlers(deps) {
|
|
|
61972
62609
|
} else {
|
|
61973
62610
|
const name = args.name;
|
|
61974
62611
|
try {
|
|
61975
|
-
|
|
62612
|
+
fs66.mkdirSync(root, { recursive: true });
|
|
61976
62613
|
target = allocateDir(root, name);
|
|
61977
|
-
|
|
62614
|
+
fs66.mkdirSync(target);
|
|
61978
62615
|
} catch (err) {
|
|
61979
62616
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
61980
62617
|
}
|
|
61981
62618
|
const git = (0, import_node_child_process13.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
61982
62619
|
if (git.status !== 0) {
|
|
61983
|
-
|
|
62620
|
+
fs66.rmSync(target, { recursive: true, force: true });
|
|
61984
62621
|
throw new ClawdError(
|
|
61985
62622
|
ERROR_CODES.INVALID_CWD,
|
|
61986
62623
|
`git init \u5931\u8D25\uFF08${git.error ? String(git.error) : `exit ${git.status}`}\uFF09: ${target}`
|
|
@@ -62005,7 +62642,7 @@ function buildProjectHandlers(deps) {
|
|
|
62005
62642
|
}
|
|
62006
62643
|
|
|
62007
62644
|
// src/handlers/workspace.ts
|
|
62008
|
-
var
|
|
62645
|
+
var path74 = __toESM(require("path"), 1);
|
|
62009
62646
|
var os22 = __toESM(require("os"), 1);
|
|
62010
62647
|
init_protocol();
|
|
62011
62648
|
init_protocol();
|
|
@@ -62047,22 +62684,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
62047
62684
|
const args = WorkspaceListArgs.parse(frame);
|
|
62048
62685
|
const isGuest = ctx?.principal.kind === "guest";
|
|
62049
62686
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os22.homedir();
|
|
62050
|
-
const resolvedCwd =
|
|
62051
|
-
const target = args.path ?
|
|
62687
|
+
const resolvedCwd = path74.resolve(args.cwd ?? fallbackCwd);
|
|
62688
|
+
const target = args.path ? path74.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
62052
62689
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
62053
62690
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
62054
62691
|
return { response: { type: "workspace:list", ...res } };
|
|
62055
62692
|
};
|
|
62056
62693
|
const read = async (frame, _client, ctx) => {
|
|
62057
62694
|
const args = WorkspaceReadArgs.parse(frame);
|
|
62058
|
-
const target =
|
|
62695
|
+
const target = path74.isAbsolute(args.path) ? path74.resolve(args.path) : path74.resolve(args.cwd, args.path);
|
|
62059
62696
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
62060
62697
|
const res = workspace.read(args);
|
|
62061
62698
|
return { response: { type: "workspace:read", ...res } };
|
|
62062
62699
|
};
|
|
62063
62700
|
const skillsList = async (frame, _client, ctx) => {
|
|
62064
62701
|
const args = SkillsListArgs.parse(frame);
|
|
62065
|
-
const cwdAbs =
|
|
62702
|
+
const cwdAbs = path74.resolve(args.cwd);
|
|
62066
62703
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
62067
62704
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
62068
62705
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -62074,7 +62711,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
62074
62711
|
};
|
|
62075
62712
|
const agentsList = async (frame, _client, ctx) => {
|
|
62076
62713
|
const args = AgentsListArgs.parse(frame);
|
|
62077
|
-
const cwdAbs =
|
|
62714
|
+
const cwdAbs = path74.resolve(args.cwd);
|
|
62078
62715
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
62079
62716
|
if (args.tool === "codex") {
|
|
62080
62717
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -62096,18 +62733,18 @@ function buildWorkspaceHandlers(deps) {
|
|
|
62096
62733
|
}
|
|
62097
62734
|
|
|
62098
62735
|
// src/handlers/git.ts
|
|
62099
|
-
var
|
|
62736
|
+
var path76 = __toESM(require("path"), 1);
|
|
62100
62737
|
init_protocol();
|
|
62101
62738
|
init_protocol();
|
|
62102
62739
|
|
|
62103
62740
|
// src/workspace/git.ts
|
|
62104
62741
|
var import_node_child_process14 = require("child_process");
|
|
62105
62742
|
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
62106
|
-
var
|
|
62743
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
62107
62744
|
var import_node_util = require("util");
|
|
62108
62745
|
var pexec = (0, import_node_util.promisify)(import_node_child_process14.execFile);
|
|
62109
62746
|
function normalizePath(p2) {
|
|
62110
|
-
const resolved =
|
|
62747
|
+
const resolved = import_node_path58.default.resolve(p2);
|
|
62111
62748
|
try {
|
|
62112
62749
|
return import_node_fs49.default.realpathSync(resolved);
|
|
62113
62750
|
} catch {
|
|
@@ -62183,7 +62820,7 @@ async function listGitBranches(cwd) {
|
|
|
62183
62820
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
62184
62821
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
62185
62822
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
62186
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
62823
|
+
if (!isGuestPathAllowed(ctx.grants, path76.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
62187
62824
|
throw new ClawdError(
|
|
62188
62825
|
ERROR_CODES.UNAUTHORIZED,
|
|
62189
62826
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -62438,7 +63075,7 @@ function upsertPeerContact(args) {
|
|
|
62438
63075
|
}
|
|
62439
63076
|
|
|
62440
63077
|
// src/handlers/contact.ts
|
|
62441
|
-
function
|
|
63078
|
+
function ensureOwner3(ctx) {
|
|
62442
63079
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
62443
63080
|
throw new ClawdError(
|
|
62444
63081
|
ERROR_CODES.UNAUTHORIZED,
|
|
@@ -62448,7 +63085,7 @@ function ensureOwner2(ctx) {
|
|
|
62448
63085
|
}
|
|
62449
63086
|
function buildContactHandlers(deps) {
|
|
62450
63087
|
const list = async (_frame, _client, ctx) => {
|
|
62451
|
-
|
|
63088
|
+
ensureOwner3(ctx);
|
|
62452
63089
|
return {
|
|
62453
63090
|
response: {
|
|
62454
63091
|
type: "contact:list:ok",
|
|
@@ -62457,7 +63094,7 @@ function buildContactHandlers(deps) {
|
|
|
62457
63094
|
};
|
|
62458
63095
|
};
|
|
62459
63096
|
const pin = async (frame, _client, ctx) => {
|
|
62460
|
-
|
|
63097
|
+
ensureOwner3(ctx);
|
|
62461
63098
|
const args = parseArgs2(ContactPinArgsSchema, frame, "contact:pin");
|
|
62462
63099
|
const pinnedAt = args.pinned ? deps.now() : null;
|
|
62463
63100
|
const hit = deps.store.setPin(args.deviceId, pinnedAt);
|
|
@@ -62481,7 +63118,7 @@ function buildContactHandlers(deps) {
|
|
|
62481
63118
|
};
|
|
62482
63119
|
};
|
|
62483
63120
|
const setNote = async (frame, _client, ctx) => {
|
|
62484
|
-
|
|
63121
|
+
ensureOwner3(ctx);
|
|
62485
63122
|
const args = parseArgs2(ContactSetNoteArgsSchema, frame, "contact:setNote");
|
|
62486
63123
|
const hit = deps.store.setNote(args.deviceId, args.note);
|
|
62487
63124
|
if (!hit) {
|
|
@@ -62504,13 +63141,13 @@ function buildContactHandlers(deps) {
|
|
|
62504
63141
|
};
|
|
62505
63142
|
};
|
|
62506
63143
|
const orgPeers = async (_frame, _client, ctx) => {
|
|
62507
|
-
|
|
63144
|
+
ensureOwner3(ctx);
|
|
62508
63145
|
return {
|
|
62509
63146
|
response: { type: "org:peers:ok", peers: getCachedOrgPeers() }
|
|
62510
63147
|
};
|
|
62511
63148
|
};
|
|
62512
63149
|
const remove = async (frame, _client, ctx) => {
|
|
62513
|
-
|
|
63150
|
+
ensureOwner3(ctx);
|
|
62514
63151
|
const args = parseArgs2(ContactRemoveArgsSchema, frame, "contact:remove");
|
|
62515
63152
|
deps.store.removeByDeviceId(args.deviceId);
|
|
62516
63153
|
deps.broadcast({
|
|
@@ -62584,7 +63221,7 @@ function buildContactHandlers(deps) {
|
|
|
62584
63221
|
|
|
62585
63222
|
// src/handlers/contact-remote-access.ts
|
|
62586
63223
|
init_protocol();
|
|
62587
|
-
function
|
|
63224
|
+
function ensureOwner4(ctx) {
|
|
62588
63225
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
62589
63226
|
throw new ClawdError(
|
|
62590
63227
|
ERROR_CODES.UNAUTHORIZED,
|
|
@@ -62594,7 +63231,7 @@ function ensureOwner3(ctx) {
|
|
|
62594
63231
|
}
|
|
62595
63232
|
function buildContactRemoteAccessHandlers(deps) {
|
|
62596
63233
|
const setRemoteAccess = async (frame, _client, ctx) => {
|
|
62597
|
-
|
|
63234
|
+
ensureOwner4(ctx);
|
|
62598
63235
|
const args = parseArgs2(ContactSetRemoteAccessArgsSchema, frame, "contact:setRemoteAccess");
|
|
62599
63236
|
const hit = deps.store.setRemoteAccess(args.deviceId, {
|
|
62600
63237
|
remoteAccessAllowed: args.remoteAccessAllowed
|
|
@@ -62773,6 +63410,17 @@ var METHOD_GRANT_MAP = {
|
|
|
62773
63410
|
// ---- visitor:* (访客名单,owner-only) ----
|
|
62774
63411
|
// owner 看完整访客名单(含没开会话的);guest 不可调(handler 内再 assertOwner 兜底)。
|
|
62775
63412
|
"visitor:list": ADMIN_ANY,
|
|
63413
|
+
// deploy:*(persona 上云的部署单):全部 owner-only。单据里有履约决策、凭据录入口,
|
|
63414
|
+
// guest 不该看见更不该动。
|
|
63415
|
+
"deploy:start": ADMIN_ANY,
|
|
63416
|
+
"deploy:rescan": ADMIN_ANY,
|
|
63417
|
+
"deploy:list": ADMIN_ANY,
|
|
63418
|
+
"deploy:get": ADMIN_ANY,
|
|
63419
|
+
"deploy:patch": ADMIN_ANY,
|
|
63420
|
+
"deploy:putSecret": ADMIN_ANY,
|
|
63421
|
+
"deploy:reportFinding": ADMIN_ANY,
|
|
63422
|
+
"deploy:finishScan": ADMIN_ANY,
|
|
63423
|
+
"deploy:remove": ADMIN_ANY,
|
|
62776
63424
|
// ---- session:* / chat:* 业务方法(v2 Phase 8 两层模型)----
|
|
62777
63425
|
// dispatcher 不验资源,handler 内按 ctx + frame.args 反查 ownerPersonaId 调 assertGrant。
|
|
62778
63426
|
// owner 自动通过(ctx 自带 '*':'admin' grant 一切 match);guest 在被授权 persona 内可调。
|
|
@@ -63018,21 +63666,21 @@ function computeMethodAccess(args) {
|
|
|
63018
63666
|
}
|
|
63019
63667
|
|
|
63020
63668
|
// src/version.ts
|
|
63021
|
-
var version = "0.2.
|
|
63669
|
+
var version = "0.2.447".length > 0 ? "0.2.447" : "dev";
|
|
63022
63670
|
|
|
63023
63671
|
// src/cli-probe/probe.ts
|
|
63024
|
-
var
|
|
63025
|
-
var
|
|
63672
|
+
var fs68 = __toESM(require("fs"), 1);
|
|
63673
|
+
var path77 = __toESM(require("path"), 1);
|
|
63026
63674
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
63027
63675
|
var BIN_NAME = "clawd";
|
|
63028
63676
|
var MAX_PARENT_HOPS = 5;
|
|
63029
63677
|
function probeGlobalCli(pathEnv) {
|
|
63030
63678
|
if (!pathEnv) return null;
|
|
63031
|
-
for (const dir of pathEnv.split(
|
|
63679
|
+
for (const dir of pathEnv.split(path77.delimiter)) {
|
|
63032
63680
|
if (!dir) continue;
|
|
63033
63681
|
let real;
|
|
63034
63682
|
try {
|
|
63035
|
-
real =
|
|
63683
|
+
real = fs68.realpathSync(path77.join(dir, BIN_NAME));
|
|
63036
63684
|
} catch {
|
|
63037
63685
|
continue;
|
|
63038
63686
|
}
|
|
@@ -63042,15 +63690,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
63042
63690
|
return null;
|
|
63043
63691
|
}
|
|
63044
63692
|
function readOwnPackageVersion(entryPath) {
|
|
63045
|
-
let dir =
|
|
63693
|
+
let dir = path77.dirname(entryPath);
|
|
63046
63694
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
63047
63695
|
try {
|
|
63048
|
-
const raw =
|
|
63696
|
+
const raw = fs68.readFileSync(path77.join(dir, "package.json"), "utf8");
|
|
63049
63697
|
const pkg = JSON.parse(raw);
|
|
63050
63698
|
if (pkg.name !== PKG_NAME) return null;
|
|
63051
63699
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
63052
63700
|
} catch {
|
|
63053
|
-
const parent =
|
|
63701
|
+
const parent = path77.dirname(dir);
|
|
63054
63702
|
if (parent === dir) return null;
|
|
63055
63703
|
dir = parent;
|
|
63056
63704
|
}
|
|
@@ -63222,7 +63870,7 @@ function buildPersonaHandlers(deps) {
|
|
|
63222
63870
|
}
|
|
63223
63871
|
|
|
63224
63872
|
// src/handlers/attachment.ts
|
|
63225
|
-
var
|
|
63873
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
63226
63874
|
init_protocol();
|
|
63227
63875
|
init_protocol();
|
|
63228
63876
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -63302,12 +63950,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
63302
63950
|
`session ${args.sessionId} scope unresolved`
|
|
63303
63951
|
);
|
|
63304
63952
|
}
|
|
63305
|
-
const cwdAbs =
|
|
63306
|
-
const candidateAbs =
|
|
63953
|
+
const cwdAbs = import_node_path59.default.resolve(sessionFile.cwd);
|
|
63954
|
+
const candidateAbs = import_node_path59.default.isAbsolute(args.relPath) ? import_node_path59.default.resolve(args.relPath) : import_node_path59.default.resolve(cwdAbs, args.relPath);
|
|
63307
63955
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
63308
63956
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
63309
63957
|
const entry = entries.find((e) => {
|
|
63310
|
-
const storedAbs =
|
|
63958
|
+
const storedAbs = import_node_path59.default.isAbsolute(e.relPath) ? import_node_path59.default.resolve(e.relPath) : import_node_path59.default.resolve(cwdAbs, e.relPath);
|
|
63311
63959
|
return storedAbs === candidateAbs && !e.stale;
|
|
63312
63960
|
});
|
|
63313
63961
|
if (!entry) {
|
|
@@ -63332,7 +63980,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
63332
63980
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
63333
63981
|
const f = deps.sessionStore.read(sessionId);
|
|
63334
63982
|
if (!f) return;
|
|
63335
|
-
assertGuestAttachmentPath(ctx,
|
|
63983
|
+
assertGuestAttachmentPath(ctx, import_node_path59.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
63336
63984
|
}
|
|
63337
63985
|
const groupAdd = async (frame, _client, ctx) => {
|
|
63338
63986
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -63347,8 +63995,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
63347
63995
|
if (!scope) {
|
|
63348
63996
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
63349
63997
|
}
|
|
63350
|
-
const cwdAbs =
|
|
63351
|
-
const candidateAbs =
|
|
63998
|
+
const cwdAbs = import_node_path59.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
63999
|
+
const candidateAbs = import_node_path59.default.isAbsolute(args.relPath) ? import_node_path59.default.resolve(args.relPath) : import_node_path59.default.resolve(cwdAbs, args.relPath);
|
|
63352
64000
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
63353
64001
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
63354
64002
|
const size = 0;
|
|
@@ -63406,21 +64054,21 @@ function buildAttachmentHandlers(deps) {
|
|
|
63406
64054
|
}
|
|
63407
64055
|
|
|
63408
64056
|
// src/handlers/extension.ts
|
|
63409
|
-
var
|
|
63410
|
-
var
|
|
64057
|
+
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
64058
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
63411
64059
|
init_protocol();
|
|
63412
64060
|
|
|
63413
64061
|
// src/extension/bundle-zip.ts
|
|
63414
|
-
var
|
|
63415
|
-
var
|
|
64062
|
+
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
64063
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
63416
64064
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
63417
64065
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
63418
64066
|
async function bundleExtensionDir(dir) {
|
|
63419
64067
|
const entries = await listFilesSorted(dir);
|
|
63420
64068
|
const zip = new import_jszip2.default();
|
|
63421
64069
|
for (const rel of entries) {
|
|
63422
|
-
const abs =
|
|
63423
|
-
const content = await
|
|
64070
|
+
const abs = import_node_path60.default.join(dir, rel);
|
|
64071
|
+
const content = await import_promises11.default.readFile(abs);
|
|
63424
64072
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
63425
64073
|
}
|
|
63426
64074
|
const buffer = await zip.generateAsync({
|
|
@@ -63440,8 +64088,8 @@ async function listFilesSorted(rootDir) {
|
|
|
63440
64088
|
return out;
|
|
63441
64089
|
}
|
|
63442
64090
|
async function walk(absRoot, relPrefix, out) {
|
|
63443
|
-
const dirAbs =
|
|
63444
|
-
const entries = await
|
|
64091
|
+
const dirAbs = import_node_path60.default.join(absRoot, relPrefix);
|
|
64092
|
+
const entries = await import_promises11.default.readdir(dirAbs, { withFileTypes: true });
|
|
63445
64093
|
for (const e of entries) {
|
|
63446
64094
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
63447
64095
|
const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
|
|
@@ -63493,26 +64141,26 @@ function computePublishCheck(args) {
|
|
|
63493
64141
|
}
|
|
63494
64142
|
|
|
63495
64143
|
// src/extension/install-flow.ts
|
|
63496
|
-
var
|
|
63497
|
-
var
|
|
64144
|
+
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
64145
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
63498
64146
|
var import_node_os22 = __toESM(require("os"), 1);
|
|
63499
64147
|
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
63500
64148
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
63501
64149
|
|
|
63502
64150
|
// src/extension/paths.ts
|
|
63503
64151
|
var import_node_os21 = __toESM(require("os"), 1);
|
|
63504
|
-
var
|
|
64152
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
63505
64153
|
function clawdHomeRoot(override) {
|
|
63506
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
64154
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path61.default.join(import_node_os21.default.homedir(), ".clawd");
|
|
63507
64155
|
}
|
|
63508
64156
|
function extensionsRoot(override) {
|
|
63509
|
-
return
|
|
64157
|
+
return import_node_path61.default.join(clawdHomeRoot(override), "extensions");
|
|
63510
64158
|
}
|
|
63511
64159
|
function publishedChannelsFile(override) {
|
|
63512
|
-
return
|
|
64160
|
+
return import_node_path61.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
63513
64161
|
}
|
|
63514
64162
|
function bundleCacheRoot(override) {
|
|
63515
|
-
return
|
|
64163
|
+
return import_node_path61.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
63516
64164
|
}
|
|
63517
64165
|
|
|
63518
64166
|
// src/extension/install-flow.ts
|
|
@@ -63539,7 +64187,7 @@ async function installFromChannel(args, deps) {
|
|
|
63539
64187
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
63540
64188
|
}
|
|
63541
64189
|
for (const name of Object.keys(zip.files)) {
|
|
63542
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
64190
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path62.default.isAbsolute(name)) {
|
|
63543
64191
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
63544
64192
|
}
|
|
63545
64193
|
}
|
|
@@ -63571,10 +64219,10 @@ async function installFromChannel(args, deps) {
|
|
|
63571
64219
|
);
|
|
63572
64220
|
}
|
|
63573
64221
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
63574
|
-
const destDir =
|
|
64222
|
+
const destDir = import_node_path62.default.join(deps.extensionsRoot, localExtId);
|
|
63575
64223
|
let destExists = false;
|
|
63576
64224
|
try {
|
|
63577
|
-
await
|
|
64225
|
+
await import_promises12.default.access(destDir);
|
|
63578
64226
|
destExists = true;
|
|
63579
64227
|
} catch {
|
|
63580
64228
|
}
|
|
@@ -63584,28 +64232,28 @@ async function installFromChannel(args, deps) {
|
|
|
63584
64232
|
`extension ${localExtId} already installed locally (from owner ${channelRef.ownerPrincipalId})`
|
|
63585
64233
|
);
|
|
63586
64234
|
}
|
|
63587
|
-
const stage = await
|
|
63588
|
-
|
|
64235
|
+
const stage = await import_promises12.default.mkdtemp(
|
|
64236
|
+
import_node_path62.default.join(import_node_os22.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
63589
64237
|
);
|
|
63590
64238
|
try {
|
|
63591
64239
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
63592
|
-
const dest =
|
|
64240
|
+
const dest = import_node_path62.default.join(stage, name);
|
|
63593
64241
|
if (entry.dir) {
|
|
63594
|
-
await
|
|
64242
|
+
await import_promises12.default.mkdir(dest, { recursive: true });
|
|
63595
64243
|
continue;
|
|
63596
64244
|
}
|
|
63597
|
-
await
|
|
64245
|
+
await import_promises12.default.mkdir(import_node_path62.default.dirname(dest), { recursive: true });
|
|
63598
64246
|
if (name === "manifest.json") {
|
|
63599
64247
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
63600
|
-
await
|
|
64248
|
+
await import_promises12.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
63601
64249
|
} else {
|
|
63602
|
-
await
|
|
64250
|
+
await import_promises12.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
63603
64251
|
}
|
|
63604
64252
|
}
|
|
63605
|
-
await
|
|
63606
|
-
await
|
|
64253
|
+
await import_promises12.default.mkdir(deps.extensionsRoot, { recursive: true });
|
|
64254
|
+
await import_promises12.default.rename(stage, destDir);
|
|
63607
64255
|
} catch (e) {
|
|
63608
|
-
await
|
|
64256
|
+
await import_promises12.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
63609
64257
|
});
|
|
63610
64258
|
throw e;
|
|
63611
64259
|
}
|
|
@@ -63614,8 +64262,8 @@ async function installFromChannel(args, deps) {
|
|
|
63614
64262
|
}
|
|
63615
64263
|
|
|
63616
64264
|
// src/extension/update-flow.ts
|
|
63617
|
-
var
|
|
63618
|
-
var
|
|
64265
|
+
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
64266
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
63619
64267
|
var import_node_os23 = __toESM(require("os"), 1);
|
|
63620
64268
|
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
63621
64269
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -63632,11 +64280,11 @@ async function updateFromChannel(args, deps) {
|
|
|
63632
64280
|
channelRef.extId,
|
|
63633
64281
|
channelRef.ownerPrincipalId
|
|
63634
64282
|
);
|
|
63635
|
-
const liveDir =
|
|
64283
|
+
const liveDir = import_node_path63.default.join(deps.extensionsRoot, localExtId);
|
|
63636
64284
|
const prevDir = `${liveDir}.prev`;
|
|
63637
64285
|
let existingVersion;
|
|
63638
64286
|
try {
|
|
63639
|
-
const raw = await
|
|
64287
|
+
const raw = await import_promises13.default.readFile(import_node_path63.default.join(liveDir, "manifest.json"), "utf8");
|
|
63640
64288
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
63641
64289
|
if (!parsed2.success) {
|
|
63642
64290
|
throw new UpdateError(
|
|
@@ -63669,7 +64317,7 @@ async function updateFromChannel(args, deps) {
|
|
|
63669
64317
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
63670
64318
|
}
|
|
63671
64319
|
for (const name of Object.keys(zip.files)) {
|
|
63672
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
64320
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path63.default.isAbsolute(name)) {
|
|
63673
64321
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
63674
64322
|
}
|
|
63675
64323
|
}
|
|
@@ -63701,31 +64349,31 @@ async function updateFromChannel(args, deps) {
|
|
|
63701
64349
|
);
|
|
63702
64350
|
}
|
|
63703
64351
|
await deps.runtime.close(localExtId);
|
|
63704
|
-
await
|
|
63705
|
-
await
|
|
63706
|
-
const stage = await
|
|
63707
|
-
|
|
64352
|
+
await import_promises13.default.rm(prevDir, { recursive: true, force: true });
|
|
64353
|
+
await import_promises13.default.rename(liveDir, prevDir);
|
|
64354
|
+
const stage = await import_promises13.default.mkdtemp(
|
|
64355
|
+
import_node_path63.default.join(import_node_os23.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
63708
64356
|
);
|
|
63709
64357
|
try {
|
|
63710
64358
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
63711
|
-
const dest =
|
|
64359
|
+
const dest = import_node_path63.default.join(stage, name);
|
|
63712
64360
|
if (entry.dir) {
|
|
63713
|
-
await
|
|
64361
|
+
await import_promises13.default.mkdir(dest, { recursive: true });
|
|
63714
64362
|
continue;
|
|
63715
64363
|
}
|
|
63716
|
-
await
|
|
64364
|
+
await import_promises13.default.mkdir(import_node_path63.default.dirname(dest), { recursive: true });
|
|
63717
64365
|
if (name === "manifest.json") {
|
|
63718
64366
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
63719
|
-
await
|
|
64367
|
+
await import_promises13.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
63720
64368
|
} else {
|
|
63721
|
-
await
|
|
64369
|
+
await import_promises13.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
63722
64370
|
}
|
|
63723
64371
|
}
|
|
63724
|
-
await
|
|
64372
|
+
await import_promises13.default.rename(stage, liveDir);
|
|
63725
64373
|
} catch (e) {
|
|
63726
|
-
await
|
|
64374
|
+
await import_promises13.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
63727
64375
|
});
|
|
63728
|
-
await
|
|
64376
|
+
await import_promises13.default.rename(prevDir, liveDir).catch(() => {
|
|
63729
64377
|
});
|
|
63730
64378
|
await deps.runtime.open(localExtId).catch(() => {
|
|
63731
64379
|
});
|
|
@@ -63747,7 +64395,7 @@ async function updateFromChannel(args, deps) {
|
|
|
63747
64395
|
reason: e.message
|
|
63748
64396
|
};
|
|
63749
64397
|
}
|
|
63750
|
-
await
|
|
64398
|
+
await import_promises13.default.rm(prevDir, { recursive: true, force: true });
|
|
63751
64399
|
return {
|
|
63752
64400
|
kind: "updated",
|
|
63753
64401
|
extId: localExtId,
|
|
@@ -63755,9 +64403,9 @@ async function updateFromChannel(args, deps) {
|
|
|
63755
64403
|
};
|
|
63756
64404
|
}
|
|
63757
64405
|
async function rollback(deps, localExtId, liveDir, prevDir) {
|
|
63758
|
-
await
|
|
64406
|
+
await import_promises13.default.rm(liveDir, { recursive: true, force: true }).catch(() => {
|
|
63759
64407
|
});
|
|
63760
|
-
await
|
|
64408
|
+
await import_promises13.default.rename(prevDir, liveDir).catch(() => {
|
|
63761
64409
|
});
|
|
63762
64410
|
await deps.runtime.open(localExtId).catch(() => {
|
|
63763
64411
|
});
|
|
@@ -63780,18 +64428,18 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
63780
64428
|
);
|
|
63781
64429
|
}
|
|
63782
64430
|
}
|
|
63783
|
-
const manifestPath =
|
|
64431
|
+
const manifestPath = import_node_path64.default.join(root, extId, "manifest.json");
|
|
63784
64432
|
const manifest = await readManifest(root, extId);
|
|
63785
64433
|
const next = { ...manifest, version: newVersion };
|
|
63786
64434
|
const tmp = `${manifestPath}.tmp`;
|
|
63787
|
-
await
|
|
63788
|
-
await
|
|
64435
|
+
await import_promises14.default.writeFile(tmp, JSON.stringify(next, null, 2));
|
|
64436
|
+
await import_promises14.default.rename(tmp, manifestPath);
|
|
63789
64437
|
}
|
|
63790
64438
|
async function readManifest(root, extId) {
|
|
63791
|
-
const file =
|
|
64439
|
+
const file = import_node_path64.default.join(root, extId, "manifest.json");
|
|
63792
64440
|
let raw;
|
|
63793
64441
|
try {
|
|
63794
|
-
raw = await
|
|
64442
|
+
raw = await import_promises14.default.readFile(file, "utf8");
|
|
63795
64443
|
} catch (e) {
|
|
63796
64444
|
if (e.code === "ENOENT") {
|
|
63797
64445
|
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `extension ${extId} not installed`);
|
|
@@ -63872,7 +64520,7 @@ function buildExtensionHandlers(deps) {
|
|
|
63872
64520
|
};
|
|
63873
64521
|
async function buildSnapshotMeta(extId) {
|
|
63874
64522
|
const manifest = await readManifest(deps.root, extId);
|
|
63875
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
64523
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path64.default.join(deps.root, extId));
|
|
63876
64524
|
return { manifest, contentHash: sha256, buffer };
|
|
63877
64525
|
}
|
|
63878
64526
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -64049,7 +64697,7 @@ function buildExtensionHandlers(deps) {
|
|
|
64049
64697
|
// src/app-builder/project-store.ts
|
|
64050
64698
|
var import_node_fs50 = require("fs");
|
|
64051
64699
|
var import_node_child_process15 = require("child_process");
|
|
64052
|
-
var
|
|
64700
|
+
var import_node_path65 = require("path");
|
|
64053
64701
|
init_protocol();
|
|
64054
64702
|
var PROJECTS_DIR = "projects";
|
|
64055
64703
|
var META_FILE = ".clawd-project.json";
|
|
@@ -64063,14 +64711,14 @@ var ProjectStore = class {
|
|
|
64063
64711
|
root;
|
|
64064
64712
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
64065
64713
|
metaPath(name) {
|
|
64066
|
-
return (0,
|
|
64714
|
+
return (0, import_node_path65.join)(this.projectsRoot(), name, META_FILE);
|
|
64067
64715
|
}
|
|
64068
64716
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
64069
64717
|
projectDir(name) {
|
|
64070
|
-
return (0,
|
|
64718
|
+
return (0, import_node_path65.join)(this.projectsRoot(), name);
|
|
64071
64719
|
}
|
|
64072
64720
|
projectsRoot() {
|
|
64073
|
-
return (0,
|
|
64721
|
+
return (0, import_node_path65.join)(this.root, PROJECTS_DIR);
|
|
64074
64722
|
}
|
|
64075
64723
|
async list() {
|
|
64076
64724
|
let entries;
|
|
@@ -64373,7 +65021,7 @@ var PublishJobRegistry = class {
|
|
|
64373
65021
|
// src/app-builder/publish-job-runner.ts
|
|
64374
65022
|
var import_node_child_process17 = require("child_process");
|
|
64375
65023
|
var import_node_fs51 = require("fs");
|
|
64376
|
-
var
|
|
65024
|
+
var import_node_path66 = require("path");
|
|
64377
65025
|
|
|
64378
65026
|
// src/app-builder/publish-stage-parser.ts
|
|
64379
65027
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -64405,7 +65053,7 @@ async function startPublishJob(deps, args) {
|
|
|
64405
65053
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
64406
65054
|
}
|
|
64407
65055
|
const projDir = projectDir(args.name);
|
|
64408
|
-
const logPath = (0,
|
|
65056
|
+
const logPath = (0, import_node_path66.join)(projDir, ".publish.log");
|
|
64409
65057
|
let logStream = null;
|
|
64410
65058
|
try {
|
|
64411
65059
|
logStream = (0, import_node_fs51.createWriteStream)(logPath, { flags: "w" });
|
|
@@ -64665,7 +65313,7 @@ async function recoverInterruptedJobs(deps) {
|
|
|
64665
65313
|
|
|
64666
65314
|
// src/handlers/app-builder.ts
|
|
64667
65315
|
init_protocol();
|
|
64668
|
-
var
|
|
65316
|
+
var import_node_path67 = require("path");
|
|
64669
65317
|
var import_node_fs52 = require("fs");
|
|
64670
65318
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
64671
65319
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
@@ -64816,8 +65464,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
64816
65464
|
const project = await userStore.create(f.name, reservedPorts);
|
|
64817
65465
|
try {
|
|
64818
65466
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
64819
|
-
const templateSrcDir = (0,
|
|
64820
|
-
const scaffoldScript = (0,
|
|
65467
|
+
const templateSrcDir = (0, import_node_path67.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
65468
|
+
const scaffoldScript = (0, import_node_path67.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
64821
65469
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
64822
65470
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
64823
65471
|
name: project.name,
|
|
@@ -65021,7 +65669,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
65021
65669
|
await userStore.clearPublishJob(args.name);
|
|
65022
65670
|
}
|
|
65023
65671
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
65024
|
-
const scriptPath = (0,
|
|
65672
|
+
const scriptPath = (0, import_node_path67.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
65025
65673
|
deps.logger?.info("app-builder.publish.start", {
|
|
65026
65674
|
name: args.name,
|
|
65027
65675
|
sessionId: boundSession.sessionId,
|
|
@@ -65250,7 +65898,7 @@ function joinLines(records, lineMeta) {
|
|
|
65250
65898
|
return out;
|
|
65251
65899
|
}
|
|
65252
65900
|
function buildTopicHandlers(deps) {
|
|
65253
|
-
const
|
|
65901
|
+
const mustGet2 = (topicId) => {
|
|
65254
65902
|
const t = deps.topicStore.get(topicId);
|
|
65255
65903
|
if (!t) throw new ClawdError(ERROR_CODES.INVALID_PARAM, `topic not found: ${topicId}`);
|
|
65256
65904
|
return t;
|
|
@@ -65283,7 +65931,7 @@ function buildTopicHandlers(deps) {
|
|
|
65283
65931
|
},
|
|
65284
65932
|
"topic:get": async (frame) => {
|
|
65285
65933
|
const args = TopicGetArgsSchema.parse(frame);
|
|
65286
|
-
const topic = args.topicId ?
|
|
65934
|
+
const topic = args.topicId ? mustGet2(args.topicId) : deps.topicStore.getByMasterSession(args.sessionId);
|
|
65287
65935
|
if (!topic) {
|
|
65288
65936
|
throw new ClawdError(
|
|
65289
65937
|
ERROR_CODES.INVALID_PARAM,
|
|
@@ -65314,7 +65962,7 @@ function buildTopicHandlers(deps) {
|
|
|
65314
65962
|
},
|
|
65315
65963
|
"topic:setPlan": async (frame) => {
|
|
65316
65964
|
const args = TopicSetPlanArgsSchema.parse(frame);
|
|
65317
|
-
|
|
65965
|
+
mustGet2(args.topicId);
|
|
65318
65966
|
const topic = deps.topicStore.setPlan(args.topicId, {
|
|
65319
65967
|
...args.title ? { title: args.title } : {},
|
|
65320
65968
|
goal: args.goal,
|
|
@@ -65326,7 +65974,7 @@ function buildTopicHandlers(deps) {
|
|
|
65326
65974
|
},
|
|
65327
65975
|
"topic:append": async (frame) => {
|
|
65328
65976
|
const args = TopicAppendArgsSchema.parse(frame);
|
|
65329
|
-
const topic =
|
|
65977
|
+
const topic = mustGet2(args.topicId);
|
|
65330
65978
|
deps.topicStore.appendActivity(args.topicId, {
|
|
65331
65979
|
actor: "master",
|
|
65332
65980
|
action: args.action,
|
|
@@ -65339,7 +65987,7 @@ function buildTopicHandlers(deps) {
|
|
|
65339
65987
|
},
|
|
65340
65988
|
"topic:reject": async (frame) => {
|
|
65341
65989
|
const args = TopicRejectArgsSchema.parse(frame);
|
|
65342
|
-
const topic =
|
|
65990
|
+
const topic = mustGet2(args.topicId);
|
|
65343
65991
|
const { rejectCount } = deps.topicStore.bumpReject(args.topicId, args.lineId);
|
|
65344
65992
|
if (topic.state === "done") deps.topicStore.setState(args.topicId, "running");
|
|
65345
65993
|
deps.topicStore.appendActivity(args.topicId, {
|
|
@@ -65358,7 +66006,7 @@ function buildTopicHandlers(deps) {
|
|
|
65358
66006
|
},
|
|
65359
66007
|
"topic:accept": async (frame) => {
|
|
65360
66008
|
const args = TopicAcceptArgsSchema.parse(frame);
|
|
65361
|
-
const topic =
|
|
66009
|
+
const topic = mustGet2(args.topicId);
|
|
65362
66010
|
if (!linesOf(topic).some((l) => l.lineId === args.lineId)) {
|
|
65363
66011
|
throw new ClawdError(
|
|
65364
66012
|
ERROR_CODES.INVALID_PARAM,
|
|
@@ -65382,11 +66030,11 @@ function buildTopicHandlers(deps) {
|
|
|
65382
66030
|
reason: args.reason,
|
|
65383
66031
|
...args.artifacts ? { artifacts: args.artifacts } : {}
|
|
65384
66032
|
});
|
|
65385
|
-
const lines = linesOf(
|
|
66033
|
+
const lines = linesOf(mustGet2(args.topicId));
|
|
65386
66034
|
const acceptedLines = lines.filter((l) => l.accepted).length;
|
|
65387
66035
|
const allAccepted = lines.length > 0 && acceptedLines === lines.length;
|
|
65388
66036
|
if (allAccepted) deps.topicStore.setState(args.topicId, "done");
|
|
65389
|
-
const overrides = Object.values(
|
|
66037
|
+
const overrides = Object.values(mustGet2(args.topicId).lineMeta).reduce(
|
|
65390
66038
|
(n, m2) => n + (m2.overrideCount ?? 0),
|
|
65391
66039
|
0
|
|
65392
66040
|
);
|
|
@@ -65403,21 +66051,21 @@ function buildTopicHandlers(deps) {
|
|
|
65403
66051
|
},
|
|
65404
66052
|
"topic:close": async (frame) => {
|
|
65405
66053
|
const args = TopicCloseArgsSchema.parse(frame);
|
|
65406
|
-
|
|
66054
|
+
mustGet2(args.topicId);
|
|
65407
66055
|
const topic = deps.topicStore.setState(args.topicId, args.state);
|
|
65408
66056
|
announceChanged(topic);
|
|
65409
66057
|
return { response: TopicResultSchema.parse({ topic }) };
|
|
65410
66058
|
},
|
|
65411
66059
|
"topic:rename": async (frame) => {
|
|
65412
66060
|
const args = TopicRenameArgsSchema.parse(frame);
|
|
65413
|
-
|
|
66061
|
+
mustGet2(args.topicId);
|
|
65414
66062
|
const topic = deps.topicStore.rename(args.topicId, args.title);
|
|
65415
66063
|
announceChanged(topic);
|
|
65416
66064
|
return { response: TopicResultSchema.parse({ topic }) };
|
|
65417
66065
|
},
|
|
65418
66066
|
"topic:delete": async (frame) => {
|
|
65419
66067
|
const { topicId } = TopicDeleteArgsSchema.parse(frame);
|
|
65420
|
-
const topic =
|
|
66068
|
+
const topic = mustGet2(topicId);
|
|
65421
66069
|
const { removed, broadcast } = deps.deleteSession(topic.masterSessionId);
|
|
65422
66070
|
const removedWorkerSessionIds = [];
|
|
65423
66071
|
const allBroadcast = [...broadcast];
|
|
@@ -65452,7 +66100,7 @@ function buildTopicHandlers(deps) {
|
|
|
65452
66100
|
init_protocol();
|
|
65453
66101
|
|
|
65454
66102
|
// src/channel/authority.ts
|
|
65455
|
-
var
|
|
66103
|
+
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
65456
66104
|
init_protocol();
|
|
65457
66105
|
var DEFAULT_AUTHORITY_RULES = [
|
|
65458
66106
|
{ id: "outbound-message", desc: "\u4EE5\u8001\u677F\u540D\u4E49\u7ED9\u5176\u4ED6\u4EBA\u53D1\u6D88\u606F\uFF08IM/\u90AE\u4EF6\uFF09", action: "ask" },
|
|
@@ -65470,7 +66118,7 @@ async function resolveAuthority(args) {
|
|
|
65470
66118
|
let source;
|
|
65471
66119
|
let raw = null;
|
|
65472
66120
|
try {
|
|
65473
|
-
raw = await
|
|
66121
|
+
raw = await import_promises15.default.readFile(args.tablePath, "utf8");
|
|
65474
66122
|
} catch (e) {
|
|
65475
66123
|
if (e.code !== "ENOENT") {
|
|
65476
66124
|
return askBecause(`\u6388\u6743\u8BBE\u5B9A\u8BFB\u4E0D\u51FA\u6765\uFF08${args.tablePath}\uFF09\uFF1A${e.message}`);
|
|
@@ -65755,7 +66403,7 @@ function buildGithubHandlers(deps) {
|
|
|
65755
66403
|
|
|
65756
66404
|
// src/handlers/visitor.ts
|
|
65757
66405
|
init_protocol();
|
|
65758
|
-
function
|
|
66406
|
+
function ensureOwner5(ctx) {
|
|
65759
66407
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
65760
66408
|
throw new ClawdError(
|
|
65761
66409
|
ERROR_CODES.UNAUTHORIZED,
|
|
@@ -65765,7 +66413,7 @@ function ensureOwner4(ctx) {
|
|
|
65765
66413
|
}
|
|
65766
66414
|
function buildVisitorHandlers(deps) {
|
|
65767
66415
|
const list = async (_frame, _client, ctx) => {
|
|
65768
|
-
|
|
66416
|
+
ensureOwner5(ctx);
|
|
65769
66417
|
return {
|
|
65770
66418
|
response: {
|
|
65771
66419
|
type: "visitor:list",
|
|
@@ -65779,12 +66427,12 @@ function buildVisitorHandlers(deps) {
|
|
|
65779
66427
|
}
|
|
65780
66428
|
|
|
65781
66429
|
// src/extension/registry.ts
|
|
65782
|
-
var
|
|
65783
|
-
var
|
|
66430
|
+
var import_promises16 = __toESM(require("fs/promises"), 1);
|
|
66431
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
65784
66432
|
async function loadAll(root) {
|
|
65785
66433
|
let entries;
|
|
65786
66434
|
try {
|
|
65787
|
-
entries = await
|
|
66435
|
+
entries = await import_promises16.default.readdir(root, { withFileTypes: true });
|
|
65788
66436
|
} catch (e) {
|
|
65789
66437
|
if (e.code === "ENOENT") return [];
|
|
65790
66438
|
throw e;
|
|
@@ -65793,16 +66441,16 @@ async function loadAll(root) {
|
|
|
65793
66441
|
for (const ent of entries) {
|
|
65794
66442
|
if (!ent.isDirectory()) continue;
|
|
65795
66443
|
if (ent.name.startsWith(".")) continue;
|
|
65796
|
-
records.push(await loadOne(
|
|
66444
|
+
records.push(await loadOne(import_node_path68.default.join(root, ent.name), ent.name));
|
|
65797
66445
|
}
|
|
65798
66446
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
65799
66447
|
return records;
|
|
65800
66448
|
}
|
|
65801
66449
|
async function loadOne(dir, dirName) {
|
|
65802
|
-
const manifestPath =
|
|
66450
|
+
const manifestPath = import_node_path68.default.join(dir, "manifest.json");
|
|
65803
66451
|
let raw;
|
|
65804
66452
|
try {
|
|
65805
|
-
raw = await
|
|
66453
|
+
raw = await import_promises16.default.readFile(manifestPath, "utf8");
|
|
65806
66454
|
} catch {
|
|
65807
66455
|
return {
|
|
65808
66456
|
extId: dirName,
|
|
@@ -65843,8 +66491,8 @@ async function loadOne(dir, dirName) {
|
|
|
65843
66491
|
}
|
|
65844
66492
|
|
|
65845
66493
|
// src/extension/uninstall.ts
|
|
65846
|
-
var
|
|
65847
|
-
var
|
|
66494
|
+
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
66495
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
65848
66496
|
var UninstallError = class extends Error {
|
|
65849
66497
|
constructor(code, message) {
|
|
65850
66498
|
super(message);
|
|
@@ -65853,14 +66501,14 @@ var UninstallError = class extends Error {
|
|
|
65853
66501
|
code;
|
|
65854
66502
|
};
|
|
65855
66503
|
async function uninstall(deps) {
|
|
65856
|
-
const dir =
|
|
66504
|
+
const dir = import_node_path69.default.join(deps.root, deps.extId);
|
|
65857
66505
|
try {
|
|
65858
|
-
await
|
|
66506
|
+
await import_promises17.default.access(dir);
|
|
65859
66507
|
} catch {
|
|
65860
66508
|
throw new UninstallError("NOT_FOUND", `extension ${deps.extId} not installed`);
|
|
65861
66509
|
}
|
|
65862
66510
|
await deps.runtime.close(deps.extId);
|
|
65863
|
-
await
|
|
66511
|
+
await import_promises17.default.rm(dir, { recursive: true, force: true });
|
|
65864
66512
|
}
|
|
65865
66513
|
|
|
65866
66514
|
// src/handlers/index.ts
|
|
@@ -66086,7 +66734,7 @@ function buildMethodHandlers(deps) {
|
|
|
66086
66734
|
broadcast: deps.broadcastToOwners
|
|
66087
66735
|
}),
|
|
66088
66736
|
...buildMasterHandlers({
|
|
66089
|
-
authorityTablePath:
|
|
66737
|
+
authorityTablePath: import_node_path70.default.join(deps.masterDataDir, "master-authority.json")
|
|
66090
66738
|
}),
|
|
66091
66739
|
...buildTopicHandlers({
|
|
66092
66740
|
topicStore: deps.topicStore,
|
|
@@ -66132,8 +66780,8 @@ function refreshPathFromLoginShell() {
|
|
|
66132
66780
|
timeout: 3e3,
|
|
66133
66781
|
stdio: ["ignore", "pipe", "ignore"]
|
|
66134
66782
|
});
|
|
66135
|
-
const
|
|
66136
|
-
if (
|
|
66783
|
+
const path93 = out.trim();
|
|
66784
|
+
if (path93) process.env.PATH = path93;
|
|
66137
66785
|
} catch {
|
|
66138
66786
|
}
|
|
66139
66787
|
}
|
|
@@ -66547,8 +67195,8 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
66547
67195
|
|
|
66548
67196
|
// src/extension/runtime.ts
|
|
66549
67197
|
var import_node_child_process22 = require("child_process");
|
|
66550
|
-
var
|
|
66551
|
-
var
|
|
67198
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
67199
|
+
var import_promises18 = require("timers/promises");
|
|
66552
67200
|
|
|
66553
67201
|
// src/extension/port-allocator.ts
|
|
66554
67202
|
var import_node_net2 = __toESM(require("net"), 1);
|
|
@@ -66648,7 +67296,7 @@ var Runtime = class {
|
|
|
66648
67296
|
/\$CLAWOS_EXT_PORT/g,
|
|
66649
67297
|
String(port)
|
|
66650
67298
|
);
|
|
66651
|
-
const dir =
|
|
67299
|
+
const dir = import_node_path71.default.join(this.root, extId);
|
|
66652
67300
|
const env = {
|
|
66653
67301
|
...process.env,
|
|
66654
67302
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -66724,7 +67372,7 @@ ${handle.stderrTail}`
|
|
|
66724
67372
|
if (res.ok) return;
|
|
66725
67373
|
} catch {
|
|
66726
67374
|
}
|
|
66727
|
-
await (0,
|
|
67375
|
+
await (0, import_promises18.setTimeout)(this.healthzIntervalMs);
|
|
66728
67376
|
}
|
|
66729
67377
|
throw new RuntimeError(
|
|
66730
67378
|
"HEALTHZ_FAILED",
|
|
@@ -66749,7 +67397,7 @@ ${handle.stderrTail}`
|
|
|
66749
67397
|
};
|
|
66750
67398
|
killGroup("SIGTERM");
|
|
66751
67399
|
const exited = new Promise((resolve9) => child.once("exit", () => resolve9()));
|
|
66752
|
-
const timed = (0,
|
|
67400
|
+
const timed = (0, import_promises18.setTimeout)(5e3).then(() => "timeout");
|
|
66753
67401
|
const winner = await Promise.race([exited.then(() => "exited"), timed]);
|
|
66754
67402
|
if (winner === "timeout" && child.exitCode === null) {
|
|
66755
67403
|
killGroup("SIGKILL");
|
|
@@ -66759,8 +67407,8 @@ ${handle.stderrTail}`
|
|
|
66759
67407
|
};
|
|
66760
67408
|
|
|
66761
67409
|
// src/extension/published-channels.ts
|
|
66762
|
-
var
|
|
66763
|
-
var
|
|
67410
|
+
var import_promises19 = __toESM(require("fs/promises"), 1);
|
|
67411
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
66764
67412
|
init_zod();
|
|
66765
67413
|
var PublishedChannelsError = class extends Error {
|
|
66766
67414
|
constructor(code, message) {
|
|
@@ -66790,7 +67438,7 @@ var PublishedChannelStore = class {
|
|
|
66790
67438
|
this.channels.clear();
|
|
66791
67439
|
let raw;
|
|
66792
67440
|
try {
|
|
66793
|
-
raw = await
|
|
67441
|
+
raw = await import_promises19.default.readFile(this.filePath, "utf8");
|
|
66794
67442
|
} catch (e) {
|
|
66795
67443
|
if (e.code === "ENOENT") {
|
|
66796
67444
|
this.loaded = true;
|
|
@@ -66859,15 +67507,15 @@ var PublishedChannelStore = class {
|
|
|
66859
67507
|
)
|
|
66860
67508
|
};
|
|
66861
67509
|
const tmp = `${this.filePath}.tmp`;
|
|
66862
|
-
await
|
|
66863
|
-
await
|
|
66864
|
-
await
|
|
67510
|
+
await import_promises19.default.mkdir(import_node_path72.default.dirname(this.filePath), { recursive: true });
|
|
67511
|
+
await import_promises19.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
67512
|
+
await import_promises19.default.rename(tmp, this.filePath);
|
|
66865
67513
|
}
|
|
66866
67514
|
};
|
|
66867
67515
|
|
|
66868
67516
|
// src/extension/bundle-cache.ts
|
|
66869
|
-
var
|
|
66870
|
-
var
|
|
67517
|
+
var import_promises20 = __toESM(require("fs/promises"), 1);
|
|
67518
|
+
var import_node_path73 = __toESM(require("path"), 1);
|
|
66871
67519
|
var BundleCache = class {
|
|
66872
67520
|
constructor(rootDir) {
|
|
66873
67521
|
this.rootDir = rootDir;
|
|
@@ -66875,17 +67523,17 @@ var BundleCache = class {
|
|
|
66875
67523
|
rootDir;
|
|
66876
67524
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
66877
67525
|
async write(snapshotHash, buffer) {
|
|
66878
|
-
await
|
|
66879
|
-
const file =
|
|
67526
|
+
await import_promises20.default.mkdir(this.rootDir, { recursive: true });
|
|
67527
|
+
const file = import_node_path73.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
66880
67528
|
const tmp = `${file}.tmp`;
|
|
66881
|
-
await
|
|
66882
|
-
await
|
|
67529
|
+
await import_promises20.default.writeFile(tmp, buffer, { mode: 384 });
|
|
67530
|
+
await import_promises20.default.rename(tmp, file);
|
|
66883
67531
|
}
|
|
66884
67532
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
66885
67533
|
async read(snapshotHash) {
|
|
66886
|
-
const file =
|
|
67534
|
+
const file = import_node_path73.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
66887
67535
|
try {
|
|
66888
|
-
return await
|
|
67536
|
+
return await import_promises20.default.readFile(file);
|
|
66889
67537
|
} catch (e) {
|
|
66890
67538
|
if (e.code === "ENOENT") return null;
|
|
66891
67539
|
throw e;
|
|
@@ -66893,8 +67541,8 @@ var BundleCache = class {
|
|
|
66893
67541
|
}
|
|
66894
67542
|
/** Idempotent — missing file is not an error. */
|
|
66895
67543
|
async delete(snapshotHash) {
|
|
66896
|
-
const file =
|
|
66897
|
-
await
|
|
67544
|
+
const file = import_node_path73.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
67545
|
+
await import_promises20.default.rm(file, { force: true });
|
|
66898
67546
|
}
|
|
66899
67547
|
};
|
|
66900
67548
|
|
|
@@ -66916,24 +67564,24 @@ async function startDaemon(config) {
|
|
|
66916
67564
|
sampling: logShippingCfg.sampling,
|
|
66917
67565
|
homeDir: import_node_os26.default.homedir()
|
|
66918
67566
|
});
|
|
66919
|
-
const logDir =
|
|
67567
|
+
const logDir = import_node_path74.default.join(config.dataDir, "log");
|
|
66920
67568
|
import_node_fs53.default.mkdirSync(logDir, { recursive: true });
|
|
66921
67569
|
const logger = createLogger({
|
|
66922
67570
|
level: config.logLevel,
|
|
66923
|
-
file:
|
|
67571
|
+
file: import_node_path74.default.join(logDir, "clawd.log"),
|
|
66924
67572
|
logClient
|
|
66925
67573
|
});
|
|
66926
67574
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
66927
67575
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
66928
|
-
file:
|
|
67576
|
+
file: import_node_path74.default.join(logDir, "screen-idle-probe.log"),
|
|
66929
67577
|
level: "debug"
|
|
66930
67578
|
});
|
|
66931
67579
|
logger.info("screen-idle probe logger enabled", {
|
|
66932
|
-
file:
|
|
67580
|
+
file: import_node_path74.default.join(logDir, "screen-idle-probe.log")
|
|
66933
67581
|
});
|
|
66934
67582
|
const CAP_TARGETS = [
|
|
66935
|
-
|
|
66936
|
-
|
|
67583
|
+
import_node_path74.default.join(logDir, "clawd.log"),
|
|
67584
|
+
import_node_path74.default.join(logDir, "screen-idle-probe.log")
|
|
66937
67585
|
];
|
|
66938
67586
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
66939
67587
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -67055,8 +67703,8 @@ async function startDaemon(config) {
|
|
|
67055
67703
|
const agents = new AgentsScanner();
|
|
67056
67704
|
const history = new ClaudeHistoryReader();
|
|
67057
67705
|
let transport = null;
|
|
67058
|
-
const personaStore = new PersonaStore(
|
|
67059
|
-
const usersRoot =
|
|
67706
|
+
const personaStore = new PersonaStore(import_node_path74.default.join(config.dataDir, "personas"));
|
|
67707
|
+
const usersRoot = import_node_path74.default.join(config.dataDir, "users");
|
|
67060
67708
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
67061
67709
|
if (defaultsRoot) {
|
|
67062
67710
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -67080,7 +67728,7 @@ async function startDaemon(config) {
|
|
|
67080
67728
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
67081
67729
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
67082
67730
|
const dispatchStore = createDispatchStore({
|
|
67083
|
-
filePath:
|
|
67731
|
+
filePath: import_node_path74.default.join(config.dataDir, "dispatch.json"),
|
|
67084
67732
|
now: () => Date.now(),
|
|
67085
67733
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
67086
67734
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -67089,7 +67737,7 @@ async function startDaemon(config) {
|
|
|
67089
67737
|
await dispatchStore.load();
|
|
67090
67738
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
67091
67739
|
const channelStore = createChannelStore({
|
|
67092
|
-
filePath:
|
|
67740
|
+
filePath: import_node_path74.default.join(config.dataDir, "channels.json"),
|
|
67093
67741
|
now: () => Date.now(),
|
|
67094
67742
|
genId: () => `ch-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
67095
67743
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
@@ -67098,7 +67746,7 @@ async function startDaemon(config) {
|
|
|
67098
67746
|
});
|
|
67099
67747
|
await channelStore.load();
|
|
67100
67748
|
const topicStore = createTopicStore({
|
|
67101
|
-
filePath:
|
|
67749
|
+
filePath: import_node_path74.default.join(config.dataDir, "topics.json"),
|
|
67102
67750
|
now: () => Date.now(),
|
|
67103
67751
|
genId: () => `tp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
67104
67752
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
@@ -67125,18 +67773,18 @@ async function startDaemon(config) {
|
|
|
67125
67773
|
});
|
|
67126
67774
|
}
|
|
67127
67775
|
});
|
|
67128
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
67776
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path74.default.dirname((0, import_node_url4.fileURLToPath)(import_meta7.url));
|
|
67129
67777
|
const mcpConfigs = [];
|
|
67130
67778
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
67131
67779
|
const dispatchServerCandidates = [
|
|
67132
|
-
|
|
67780
|
+
import_node_path74.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
67133
67781
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
67134
|
-
|
|
67782
|
+
import_node_path74.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
67135
67783
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
67136
67784
|
];
|
|
67137
67785
|
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67138
67786
|
if (dispatchServerScriptPath) {
|
|
67139
|
-
const dispatchLogPath =
|
|
67787
|
+
const dispatchLogPath = import_node_path74.default.join(logDir, "dispatch-mcp-server.log");
|
|
67140
67788
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
67141
67789
|
dataDir: config.dataDir,
|
|
67142
67790
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -67156,12 +67804,12 @@ async function startDaemon(config) {
|
|
|
67156
67804
|
});
|
|
67157
67805
|
}
|
|
67158
67806
|
const ticketServerCandidates = [
|
|
67159
|
-
|
|
67160
|
-
|
|
67807
|
+
import_node_path74.default.join(here, "ticket", "mcp-server.cjs"),
|
|
67808
|
+
import_node_path74.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
67161
67809
|
];
|
|
67162
67810
|
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67163
67811
|
if (ticketServerScriptPath) {
|
|
67164
|
-
const ticketLogPath =
|
|
67812
|
+
const ticketLogPath = import_node_path74.default.join(logDir, "ticket-mcp-server.log");
|
|
67165
67813
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
67166
67814
|
dataDir: config.dataDir,
|
|
67167
67815
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -67183,12 +67831,12 @@ async function startDaemon(config) {
|
|
|
67183
67831
|
});
|
|
67184
67832
|
}
|
|
67185
67833
|
const shiftServerCandidates = [
|
|
67186
|
-
|
|
67187
|
-
|
|
67834
|
+
import_node_path74.default.join(here, "shift", "mcp-server.cjs"),
|
|
67835
|
+
import_node_path74.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
67188
67836
|
];
|
|
67189
67837
|
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67190
67838
|
if (shiftServerScriptPath) {
|
|
67191
|
-
const shiftLogPath =
|
|
67839
|
+
const shiftLogPath = import_node_path74.default.join(logDir, "shift-mcp-server.log");
|
|
67192
67840
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
67193
67841
|
dataDir: config.dataDir,
|
|
67194
67842
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -67209,12 +67857,12 @@ async function startDaemon(config) {
|
|
|
67209
67857
|
);
|
|
67210
67858
|
}
|
|
67211
67859
|
const inboxServerCandidates = [
|
|
67212
|
-
|
|
67213
|
-
|
|
67860
|
+
import_node_path74.default.join(here, "inbox", "mcp-server.cjs"),
|
|
67861
|
+
import_node_path74.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
67214
67862
|
];
|
|
67215
67863
|
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67216
67864
|
if (inboxServerScriptPath) {
|
|
67217
|
-
const inboxLogPath =
|
|
67865
|
+
const inboxLogPath = import_node_path74.default.join(logDir, "inbox-mcp-server.log");
|
|
67218
67866
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
67219
67867
|
dataDir: config.dataDir,
|
|
67220
67868
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -67235,8 +67883,8 @@ async function startDaemon(config) {
|
|
|
67235
67883
|
);
|
|
67236
67884
|
}
|
|
67237
67885
|
const peerOpsServerCandidates = [
|
|
67238
|
-
|
|
67239
|
-
|
|
67886
|
+
import_node_path74.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
67887
|
+
import_node_path74.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
67240
67888
|
];
|
|
67241
67889
|
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67242
67890
|
if (peerOpsServerScriptPath) {
|
|
@@ -67258,12 +67906,12 @@ async function startDaemon(config) {
|
|
|
67258
67906
|
);
|
|
67259
67907
|
}
|
|
67260
67908
|
const rpcToolServerCandidates = [
|
|
67261
|
-
|
|
67262
|
-
|
|
67909
|
+
import_node_path74.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
67910
|
+
import_node_path74.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
67263
67911
|
];
|
|
67264
67912
|
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67265
67913
|
if (rpcToolServerScriptPath) {
|
|
67266
|
-
const rpcToolLogPath =
|
|
67914
|
+
const rpcToolLogPath = import_node_path74.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
67267
67915
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
67268
67916
|
dataDir: config.dataDir,
|
|
67269
67917
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -67284,7 +67932,7 @@ async function startDaemon(config) {
|
|
|
67284
67932
|
);
|
|
67285
67933
|
}
|
|
67286
67934
|
const shiftStore = createShiftStore({
|
|
67287
|
-
filePath:
|
|
67935
|
+
filePath: import_node_path74.default.join(config.dataDir, "shift.json"),
|
|
67288
67936
|
ownerIdProvider: () => ownerPrincipalId,
|
|
67289
67937
|
now: () => Date.now()
|
|
67290
67938
|
});
|
|
@@ -67306,7 +67954,7 @@ async function startDaemon(config) {
|
|
|
67306
67954
|
getAdapter,
|
|
67307
67955
|
historyReader: history,
|
|
67308
67956
|
dataDir: config.dataDir,
|
|
67309
|
-
personaRoot:
|
|
67957
|
+
personaRoot: import_node_path74.default.join(config.dataDir, "personas"),
|
|
67310
67958
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
67311
67959
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
67312
67960
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -67360,7 +68008,7 @@ async function startDaemon(config) {
|
|
|
67360
68008
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
67361
68009
|
attachmentGroup: {
|
|
67362
68010
|
onFileEdit: (input) => {
|
|
67363
|
-
const absPath =
|
|
68011
|
+
const absPath = import_node_path74.default.isAbsolute(input.relPath) ? input.relPath : import_node_path74.default.join(input.cwd, input.relPath);
|
|
67364
68012
|
let size = 0;
|
|
67365
68013
|
try {
|
|
67366
68014
|
size = import_node_fs53.default.statSync(absPath).size;
|
|
@@ -67393,9 +68041,9 @@ async function startDaemon(config) {
|
|
|
67393
68041
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
67394
68042
|
}
|
|
67395
68043
|
const projectsStore = new ProjectsStore({
|
|
67396
|
-
file:
|
|
68044
|
+
file: import_node_path74.default.join(config.dataDir, "projects.json"),
|
|
67397
68045
|
clawdDir: config.dataDir,
|
|
67398
|
-
codexStateFile:
|
|
68046
|
+
codexStateFile: import_node_path74.default.join(import_node_os26.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
67399
68047
|
logger
|
|
67400
68048
|
});
|
|
67401
68049
|
const observer = new SessionObserver({
|
|
@@ -67455,12 +68103,12 @@ async function startDaemon(config) {
|
|
|
67455
68103
|
screenIdleProbeLogger
|
|
67456
68104
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
67457
68105
|
registerAdapter("claude", claudeAdapter);
|
|
67458
|
-
const codexIsolatedHome =
|
|
68106
|
+
const codexIsolatedHome = import_node_path74.default.join(config.dataDir, "codex-home");
|
|
67459
68107
|
try {
|
|
67460
68108
|
import_node_fs53.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
67461
68109
|
for (const f of ["auth.json", "config.toml"]) {
|
|
67462
|
-
const link =
|
|
67463
|
-
const target =
|
|
68110
|
+
const link = import_node_path74.default.join(codexIsolatedHome, f);
|
|
68111
|
+
const target = import_node_path74.default.join(import_node_os26.default.homedir(), ".codex", f);
|
|
67464
68112
|
if (!import_node_fs53.default.existsSync(link) && import_node_fs53.default.existsSync(target)) import_node_fs53.default.symlinkSync(target, link);
|
|
67465
68113
|
}
|
|
67466
68114
|
} catch (err) {
|
|
@@ -67474,11 +68122,11 @@ async function startDaemon(config) {
|
|
|
67474
68122
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
67475
68123
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
67476
68124
|
cwd,
|
|
67477
|
-
personaRoot:
|
|
68125
|
+
personaRoot: import_node_path74.default.join(config.dataDir, "personas"),
|
|
67478
68126
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
67479
68127
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
67480
68128
|
projectPaths: projectsStore.listMerged().map((x) => x.path),
|
|
67481
|
-
sharedHome:
|
|
68129
|
+
sharedHome: import_node_path74.default.join(import_node_os26.default.homedir(), ".codex"),
|
|
67482
68130
|
isolatedHome: codexIsolatedHome
|
|
67483
68131
|
})
|
|
67484
68132
|
})
|
|
@@ -67762,11 +68410,11 @@ async function startDaemon(config) {
|
|
|
67762
68410
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
67763
68411
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
67764
68412
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
67765
|
-
personaRoot:
|
|
68413
|
+
personaRoot: import_node_path74.default.join(config.dataDir, "personas"),
|
|
67766
68414
|
usersRoot
|
|
67767
68415
|
},
|
|
67768
68416
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
67769
|
-
personaRoot:
|
|
68417
|
+
personaRoot: import_node_path74.default.join(config.dataDir, "personas"),
|
|
67770
68418
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
67771
68419
|
usersRoot,
|
|
67772
68420
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -67865,11 +68513,11 @@ async function startDaemon(config) {
|
|
|
67865
68513
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
67866
68514
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
67867
68515
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
67868
|
-
appBuilderPersonaRoot:
|
|
68516
|
+
appBuilderPersonaRoot: import_node_path74.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
67869
68517
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
67870
|
-
deployKitRoot:
|
|
68518
|
+
deployKitRoot: import_node_path74.default.join(config.dataDir, "deploy-kit"),
|
|
67871
68519
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
67872
|
-
resolvePersonaRoot: (personaId2) =>
|
|
68520
|
+
resolvePersonaRoot: (personaId2) => import_node_path74.default.join(config.dataDir, "personas", personaId2),
|
|
67873
68521
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
67874
68522
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
67875
68523
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -67981,6 +68629,58 @@ async function startDaemon(config) {
|
|
|
67981
68629
|
ownerIdProvider: () => ownerPrincipalId
|
|
67982
68630
|
});
|
|
67983
68631
|
Object.assign(handlers, shiftHandlers);
|
|
68632
|
+
const deployReceipts = createReceiptStore({
|
|
68633
|
+
filePath: import_node_path74.default.join(config.dataDir, "deploy.json"),
|
|
68634
|
+
now: () => Date.now(),
|
|
68635
|
+
onFlushError: (err) => logger.error("deploy receipts flush failed", { error: String(err) })
|
|
68636
|
+
});
|
|
68637
|
+
const deploySecrets = createSecretStore({
|
|
68638
|
+
filePath: import_node_path74.default.join(config.dataDir, "deploy-secrets.json"),
|
|
68639
|
+
now: () => Date.now(),
|
|
68640
|
+
onFlushError: (err) => logger.error("deploy secrets flush failed", { error: String(err) })
|
|
68641
|
+
});
|
|
68642
|
+
await deployReceipts.load();
|
|
68643
|
+
await deploySecrets.load();
|
|
68644
|
+
const interrupted = reconcileInterruptedScans(deployReceipts);
|
|
68645
|
+
if (interrupted.length > 0) logger.warn("deploy scans interrupted by restart", { deployIds: interrupted });
|
|
68646
|
+
const deployHandlers = buildDeployHandlers({
|
|
68647
|
+
receipts: deployReceipts,
|
|
68648
|
+
secrets: deploySecrets,
|
|
68649
|
+
hasPersona: (personaId2) => personaStore.has(personaId2),
|
|
68650
|
+
startScan: (deployId, personaId2) => {
|
|
68651
|
+
const assetLines = SCANNABLE_ASSETS.map(
|
|
68652
|
+
(name) => ` - ${name}\uFF1A${import_node_path74.default.join(config.dataDir, name)}`
|
|
68653
|
+
).join("\n");
|
|
68654
|
+
const prompt = [
|
|
68655
|
+
`\u626B\u63CF persona\u300C${personaId2}\u300D\u7684\u90E8\u7F72\u73AF\u5883\uFF0CdeployId=${deployId}\u3002`,
|
|
68656
|
+
"",
|
|
68657
|
+
`persona \u76EE\u5F55\uFF1A${personaStore.personaDirPath(personaId2)}`,
|
|
68658
|
+
"\u53EF\u4EE5\u8BFB\u5230\u7684 persona \u76EE\u5F55\u4E4B\u5916\u7684\u5171\u4EAB\u8D44\u4EA7\uFF1A",
|
|
68659
|
+
assetLines || " \uFF08\u65E0\uFF09",
|
|
68660
|
+
"",
|
|
68661
|
+
"\u6309 scan-persona-for-deploy skill \u5E72\u6D3B\uFF1A\u8FB9\u67E5\u8FB9\u7528 deploy:reportFinding \u4E0A\u62A5\uFF0C",
|
|
68662
|
+
"\u5168\u90E8\u67E5\u5B8C\u8C03 deploy:finishScan \u6536\u5C3E\u3002"
|
|
68663
|
+
].join("\n");
|
|
68664
|
+
let handle;
|
|
68665
|
+
try {
|
|
68666
|
+
handle = manager.createShiftSession({ targetPersona: BUTLER_PERSONA_ID, prompt, deployId });
|
|
68667
|
+
} catch (err) {
|
|
68668
|
+
deployReceipts.update(deployId, { status: "scanFailed", error: `\u8D77\u626B\u63CF\u4F1A\u8BDD\u5931\u8D25\uFF1A${String(err)}` });
|
|
68669
|
+
logger.error("deploy scan session failed to start", { deployId, personaId: personaId2, error: String(err) });
|
|
68670
|
+
return void 0;
|
|
68671
|
+
}
|
|
68672
|
+
void handle.ended.then((outcome) => {
|
|
68673
|
+
const patch = settleEndedScan(outcome, deployReceipts.get(deployId));
|
|
68674
|
+
if (!patch) return;
|
|
68675
|
+
deployReceipts.update(deployId, patch);
|
|
68676
|
+
logger.warn("deploy scan ended without finishScan", { deployId, personaId: personaId2, why: patch.error });
|
|
68677
|
+
});
|
|
68678
|
+
return handle.sessionId;
|
|
68679
|
+
},
|
|
68680
|
+
genId: () => `dp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
68681
|
+
now: () => Date.now()
|
|
68682
|
+
});
|
|
68683
|
+
Object.assign(handlers, deployHandlers);
|
|
67984
68684
|
const shiftSpawnFn = createShiftSpawnFn({ sessionManager: manager });
|
|
67985
68685
|
const shiftScheduler = createShiftScheduler({
|
|
67986
68686
|
store: shiftStore,
|
|
@@ -67990,7 +68690,7 @@ async function startDaemon(config) {
|
|
|
67990
68690
|
});
|
|
67991
68691
|
shiftScheduler.start();
|
|
67992
68692
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
67993
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
68693
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path74.default.join(config.dataDir, "personas"));
|
|
67994
68694
|
const larkBotCloud = createLarkBotCloudClient({
|
|
67995
68695
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
67996
68696
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -68004,7 +68704,7 @@ async function startDaemon(config) {
|
|
|
68004
68704
|
store: larkBotStore,
|
|
68005
68705
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
68006
68706
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
68007
|
-
mediaRootFor: (chatId) =>
|
|
68707
|
+
mediaRootFor: (chatId) => import_node_path74.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
68008
68708
|
isShuttingDown: () => larkDraining,
|
|
68009
68709
|
logger: {
|
|
68010
68710
|
warn: (msg) => logger.warn(msg),
|
|
@@ -68309,8 +69009,8 @@ async function startDaemon(config) {
|
|
|
68309
69009
|
const lines = [
|
|
68310
69010
|
`Tunnel: ${r.url}`,
|
|
68311
69011
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
68312
|
-
`Frpc config: ${
|
|
68313
|
-
`Frpc log: ${
|
|
69012
|
+
`Frpc config: ${import_node_path74.default.join(config.dataDir, "frpc.toml")}`,
|
|
69013
|
+
`Frpc log: ${import_node_path74.default.join(logDir, "frpc.log")}`
|
|
68314
69014
|
];
|
|
68315
69015
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
68316
69016
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -68323,7 +69023,7 @@ ${bar}
|
|
|
68323
69023
|
|
|
68324
69024
|
`);
|
|
68325
69025
|
try {
|
|
68326
|
-
const connectPath =
|
|
69026
|
+
const connectPath = import_node_path74.default.join(config.dataDir, "connect.txt");
|
|
68327
69027
|
import_node_fs53.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
68328
69028
|
} catch {
|
|
68329
69029
|
}
|
|
@@ -68390,7 +69090,9 @@ ${bar}
|
|
|
68390
69090
|
await wss.stop();
|
|
68391
69091
|
for (const [name, store2] of [
|
|
68392
69092
|
["channels", channelStore],
|
|
68393
|
-
["topics", topicStore]
|
|
69093
|
+
["topics", topicStore],
|
|
69094
|
+
["deploy-receipts", deployReceipts],
|
|
69095
|
+
["deploy-secrets", deploySecrets]
|
|
68394
69096
|
]) {
|
|
68395
69097
|
await store2.flushNow().catch((err) => {
|
|
68396
69098
|
logger.warn("shutdown.store-flush-failed", {
|
|
@@ -68411,7 +69113,7 @@ ${bar}
|
|
|
68411
69113
|
};
|
|
68412
69114
|
}
|
|
68413
69115
|
function migrateDropPersonsDir(dataDir) {
|
|
68414
|
-
const dir =
|
|
69116
|
+
const dir = import_node_path74.default.join(dataDir, "persons");
|
|
68415
69117
|
try {
|
|
68416
69118
|
import_node_fs53.default.rmSync(dir, { recursive: true, force: true });
|
|
68417
69119
|
} catch {
|