@clawos-dev/clawd 0.2.459 → 0.2.461
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/app-builder-plugin/mcp-server.cjs +130 -1
- package/dist/cli.cjs +1257 -608
- package/dist/dispatch/mcp-server.cjs +53 -0
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/{guest-BJvgzqPz.js → guest-0upTtqLX.js} +116 -116
- package/dist/share-ui/assets/guest-B3t_VaRM.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-Q6LcVR9h.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: path98, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path98, ...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, path98, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path98;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -6022,7 +6022,7 @@ var init_environment_schemas = __esm({
|
|
|
6022
6022
|
});
|
|
6023
6023
|
|
|
6024
6024
|
// ../protocol/src/deploy-schemas.ts
|
|
6025
|
-
var FulfillmentSchema, DeployStatusSchema, DeployGapSchema, DeployReceiptSchema, DeployStartArgsSchema, DeployIdArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, DeploySecretStatusSchema, DeployReceiptViewSchema, DeployListResultSchema;
|
|
6025
|
+
var FulfillmentSchema, DeployStatusSchema, TRIAL_ROUND_MAX, DeployGapSchema, DeployPlacementSchema, DeployReceiptSchema, DeployStartArgsSchema, DeployIdArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, DeploySecretStatusSchema, DeployReceiptViewSchema, DeployListResultSchema;
|
|
6026
6026
|
var init_deploy_schemas = __esm({
|
|
6027
6027
|
"../protocol/src/deploy-schemas.ts"() {
|
|
6028
6028
|
"use strict";
|
|
@@ -6038,6 +6038,7 @@ var init_deploy_schemas = __esm({
|
|
|
6038
6038
|
"failed",
|
|
6039
6039
|
"deployed"
|
|
6040
6040
|
]);
|
|
6041
|
+
TRIAL_ROUND_MAX = 5;
|
|
6041
6042
|
DeployGapSchema = external_exports.object({
|
|
6042
6043
|
// agent 的自然语言错因,如「我要解析 aliyun 的 JSON 输出,但容器里没有 python3」
|
|
6043
6044
|
errorText: external_exports.string().min(1),
|
|
@@ -6046,6 +6047,19 @@ var init_deploy_schemas = __esm({
|
|
|
6046
6047
|
// 建议补的依赖:`cli:python3` 这种。拿不准就不给,让人自己决定。
|
|
6047
6048
|
suggest: external_exports.string().optional()
|
|
6048
6049
|
}).strict();
|
|
6050
|
+
DeployPlacementSchema = external_exports.object({
|
|
6051
|
+
/** gateway 的公网地址(入口 A 直接 POST 它;入口 B 由设备目录下发 ws 地址) */
|
|
6052
|
+
gatewayUrl: external_exports.string().min(1),
|
|
6053
|
+
/** 服务设备 id:别人的 clawd 用 `device:connect { deviceId }` 就能连上,本机侧零改动 */
|
|
6054
|
+
serviceDeviceId: external_exports.string().min(1),
|
|
6055
|
+
/** 这次登记为正式的镜像 tag(= 试装通过的那个) */
|
|
6056
|
+
image: external_exports.string().min(1),
|
|
6057
|
+
/** 使用者自带的凭据名字(= 单据里 fulfillment 选了 'user' 的那些)。**只有名字** */
|
|
6058
|
+
userSecrets: external_exports.array(external_exports.string()).default([]),
|
|
6059
|
+
/** 是否进公共设备目录。false = 只有拿到 deviceId 的人连得上 */
|
|
6060
|
+
publicDirectory: external_exports.boolean(),
|
|
6061
|
+
deployedAt: external_exports.number()
|
|
6062
|
+
}).strict();
|
|
6049
6063
|
DeployReceiptSchema = external_exports.object({
|
|
6050
6064
|
deployId: external_exports.string().min(1),
|
|
6051
6065
|
personaId: external_exports.string().min(1),
|
|
@@ -6071,6 +6085,23 @@ var init_deploy_schemas = __esm({
|
|
|
6071
6085
|
fulfillment: external_exports.record(external_exports.string(), FulfillmentSchema).default({}),
|
|
6072
6086
|
/** 试装失败时的缺口清单;成功或没试装过是空数组 */
|
|
6073
6087
|
gaps: external_exports.array(DeployGapSchema).default([]),
|
|
6088
|
+
/** 试装跑到第几轮了(每次 deploy:trial +1,上限 TRIAL_ROUND_MAX)。重扫清零 */
|
|
6089
|
+
trialRound: external_exports.number().default(0),
|
|
6090
|
+
/**
|
|
6091
|
+
* 试装当前在哪一步的一句人话(「在构镜像」「冒烟任务跑起来了」)。
|
|
6092
|
+
* 单据页要的是「到哪一步了」,不是逐 token 的过程——过程在 gateway 的任务台账里。
|
|
6093
|
+
*/
|
|
6094
|
+
trialStage: external_exports.string().optional(),
|
|
6095
|
+
/**
|
|
6096
|
+
* 上一次试装通过的时刻。**deploy:deploy 的前置**——没试装过不让部署,那正是试装存在的理由。
|
|
6097
|
+
* 试装通过后单据回 `ready` 而不是直接 `deployed`:试装的产物是一个用完即弃的镜像,
|
|
6098
|
+
* 部署的产物是一个别人能派活的服务,中间那次决定得留给人。
|
|
6099
|
+
*/
|
|
6100
|
+
trialPassedAt: external_exports.number().optional(),
|
|
6101
|
+
/** 试装通过的那个镜像 tag;deploy:deploy 登记的就是它,不重新构一遍 */
|
|
6102
|
+
trialImage: external_exports.string().optional(),
|
|
6103
|
+
/** 部署落点(status 是 deployed 才有) */
|
|
6104
|
+
placement: DeployPlacementSchema.optional(),
|
|
6074
6105
|
// 扫描 / 试装失败的原因(status 是 scanFailed / failed 时才有意义)
|
|
6075
6106
|
error: external_exports.string().optional(),
|
|
6076
6107
|
createdAt: external_exports.number(),
|
|
@@ -6892,6 +6923,21 @@ var init_topic = __esm({
|
|
|
6892
6923
|
TopicDecisionTypeSchema = external_exports.enum(TOPIC_DECISION_TYPES);
|
|
6893
6924
|
TopicDecisionStatusSchema = external_exports.enum(TOPIC_DECISION_STATUSES);
|
|
6894
6925
|
TopicDecisionSchema = external_exports.object({
|
|
6926
|
+
/**
|
|
6927
|
+
* 这条决策的标识,供后来的答复回指。可选:存量记录一条都没有,**不迁移**。
|
|
6928
|
+
*
|
|
6929
|
+
* 之所以要它——提问和答复是**两条**流水(`open` 一条、`resolved` 一条,见 `resolves`),
|
|
6930
|
+
* 两条之间没有任何关联时,展示层只能逐条渲染,于是**已经拍板完的待办永远挂在那儿**。
|
|
6931
|
+
*/
|
|
6932
|
+
id: nonBlank2.optional(),
|
|
6933
|
+
/**
|
|
6934
|
+
* 本条解决的是哪条决策(填对方的 `id`)。展示层据此把提问与答复合并成一行。
|
|
6935
|
+
*
|
|
6936
|
+
* **只关联、不改写**:不去改动已落盘那条 `open` 记录的 status。原地改写会丢掉
|
|
6937
|
+
* 「什么时候提出 / 什么时候解决」的双时间戳,也丢掉「Master 建议了什么 vs
|
|
6938
|
+
* 老板最终定了什么」的差异——而老板事后要看的恰恰是这个差异。合并只发生在展示层。
|
|
6939
|
+
*/
|
|
6940
|
+
resolves: nonBlank2.optional(),
|
|
6895
6941
|
type: TopicDecisionTypeSchema,
|
|
6896
6942
|
status: TopicDecisionStatusSchema,
|
|
6897
6943
|
question: nonBlank2,
|
|
@@ -8863,6 +8909,14 @@ var init_methods = __esm({
|
|
|
8863
8909
|
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",
|
|
8864
8910
|
args: DeployFinishScanArgsSchema
|
|
8865
8911
|
},
|
|
8912
|
+
"deploy:trial": {
|
|
8913
|
+
summary: "\u8D77\u4E00\u6B21\u8BD5\u88C5\uFF1A**\u4E00\u6B21\u5E26\u81EA\u6BC1\u7684\u771F\u90E8\u7F72**\u2014\u2014\u6309\u5355\u636E\u7684\u6E05\u5355\u6784\u955C\u50CF \u2192 \u63A8\u8FDB k3s \u2192 \u7ECF gateway \u6295\u5582\u5355\u636E\u4E0A\u90A3\u6761\u5192\u70DF\u4EFB\u52A1 \u2192 \u8BA9 persona \u7528\u81EA\u5DF1\u7684\u65B9\u5F0F\u5E72 \u2192 \u8DD1\u5B8C\u8BA9\u5B83\u628A\u5EFA\u51FA\u6765\u7684\u4E1C\u897F\u62C6\u6389\u3002\u524D\u7F6E\u662F `ready`\uFF08\u5C65\u7EA6\u90FD\u9009\u4E86\u3001\u9009\u4E86\u300C\u6211\u6765\u63D0\u4F9B\u300D\u7684\u51ED\u636E\u90FD\u586B\u9F50\u4E86\uFF09\uFF0C\u7F3A\u54EA\u6761\u4F1A\u5728\u9519\u8BEF\u91CC\u70B9\u540D\uFF1B\u8DD1\u51E0\u5341\u5206\u949F\uFF0C\u6240\u4EE5 RPC \u79D2\u56DE `trialing` \u6001\u5355\u636E\uFF0C\u7ED3\u679C\u7531\u540E\u53F0\u56DE\u5199\uFF08UI \u8F6E\u8BE2\uFF09\u3002\u901A\u8FC7 \u2192 \u56DE `ready` \u5E76\u8BB0\u4E0B trialPassedAt\uFF08\u90E8\u7F72\u662F\u4EBA\u7684\u7B2C\u4E8C\u6B21\u51B3\u5B9A\uFF09\uFF1B\u6CA1\u8FC7 \u2192 `failed` + gaps\uFF08agent \u7684\u4EBA\u8BDD\u9519\u56E0\uFF09\uFF0C\u6539\u5B8C\u6E05\u5355\u518D\u8C03\u4E00\u6B21\u5373\u53EF\u3002\u8F6E\u6B21\u6709\u4E0A\u9650\uFF1Bowner-only",
|
|
8914
|
+
args: DeployIdArgsSchema
|
|
8915
|
+
},
|
|
8916
|
+
"deploy:deploy": {
|
|
8917
|
+
summary: "\u628A\u8BD5\u88C5\u901A\u8FC7\u7684\u90A3\u4E2A\u955C\u50CF\u5728 gateway \u767B\u8BB0\u4E3A**\u6B63\u5F0F**\u90E8\u7F72\uFF1A\u4E4B\u540E\u522B\u4EBA\u7684 clawd \u6D3E\u6D3B\u7ED9\u8FD9\u4E2A\u670D\u52A1\u8BBE\u5907\uFF0C\u8D77\u7684\u5C31\u662F\u5B83\u3002\u524D\u7F6E\u662F\u8BD5\u88C5\u901A\u8FC7\u8FC7\uFF08\u6CA1\u9A8C\u8FC7\u4E0D\u8BA9\u53D1\uFF0C\u90A3\u6B63\u662F\u8BD5\u88C5\u5B58\u5728\u7684\u7406\u7531\uFF09\u3002\u56DE\u6765\u7684\u5355\u636E\u5E26 placement\u2014\u2014\u4E91\u4E0A\u5730\u5740 / \u670D\u52A1\u8BBE\u5907 id / \u8C01\u53EF\u8C03\u7528 / \u4F7F\u7528\u8005\u9700\u81EA\u5E26\u54EA\u4E9B\u51ED\u636E\uFF1Bowner-only",
|
|
8918
|
+
args: DeployIdArgsSchema
|
|
8919
|
+
},
|
|
8866
8920
|
"deploy:remove": {
|
|
8867
8921
|
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",
|
|
8868
8922
|
args: DeployIdArgsSchema
|
|
@@ -9851,8 +9905,8 @@ var require_req = __commonJS({
|
|
|
9851
9905
|
if (req.originalUrl) {
|
|
9852
9906
|
_req.url = req.originalUrl;
|
|
9853
9907
|
} else {
|
|
9854
|
-
const
|
|
9855
|
-
_req.url = typeof
|
|
9908
|
+
const path98 = req.path;
|
|
9909
|
+
_req.url = typeof path98 === "string" ? path98 : req.url ? req.url.path || req.url : void 0;
|
|
9856
9910
|
}
|
|
9857
9911
|
if (req.query) {
|
|
9858
9912
|
_req.query = req.query;
|
|
@@ -10017,14 +10071,14 @@ var require_redact = __commonJS({
|
|
|
10017
10071
|
}
|
|
10018
10072
|
return obj;
|
|
10019
10073
|
}
|
|
10020
|
-
function parsePath(
|
|
10074
|
+
function parsePath(path98) {
|
|
10021
10075
|
const parts = [];
|
|
10022
10076
|
let current = "";
|
|
10023
10077
|
let inBrackets = false;
|
|
10024
10078
|
let inQuotes = false;
|
|
10025
10079
|
let quoteChar = "";
|
|
10026
|
-
for (let i = 0; i <
|
|
10027
|
-
const char =
|
|
10080
|
+
for (let i = 0; i < path98.length; i++) {
|
|
10081
|
+
const char = path98[i];
|
|
10028
10082
|
if (!inBrackets && char === ".") {
|
|
10029
10083
|
if (current) {
|
|
10030
10084
|
parts.push(current);
|
|
@@ -10155,10 +10209,10 @@ var require_redact = __commonJS({
|
|
|
10155
10209
|
return current;
|
|
10156
10210
|
}
|
|
10157
10211
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
10158
|
-
for (const
|
|
10159
|
-
const parts = parsePath(
|
|
10212
|
+
for (const path98 of paths) {
|
|
10213
|
+
const parts = parsePath(path98);
|
|
10160
10214
|
if (parts.includes("*")) {
|
|
10161
|
-
redactWildcardPath(obj, parts, censor,
|
|
10215
|
+
redactWildcardPath(obj, parts, censor, path98, remove);
|
|
10162
10216
|
} else {
|
|
10163
10217
|
if (remove) {
|
|
10164
10218
|
removeKey(obj, parts);
|
|
@@ -10243,8 +10297,8 @@ var require_redact = __commonJS({
|
|
|
10243
10297
|
}
|
|
10244
10298
|
} else {
|
|
10245
10299
|
if (afterWildcard.includes("*")) {
|
|
10246
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10247
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
10300
|
+
const wrappedCensor = typeof censor === "function" ? (value, path98) => {
|
|
10301
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path98];
|
|
10248
10302
|
return censor(value, fullPath);
|
|
10249
10303
|
} : censor;
|
|
10250
10304
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -10279,8 +10333,8 @@ var require_redact = __commonJS({
|
|
|
10279
10333
|
return null;
|
|
10280
10334
|
}
|
|
10281
10335
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
10282
|
-
for (const
|
|
10283
|
-
const parts = parsePath(
|
|
10336
|
+
for (const path98 of pathsToClone) {
|
|
10337
|
+
const parts = parsePath(path98);
|
|
10284
10338
|
let current = pathStructure;
|
|
10285
10339
|
for (let i = 0; i < parts.length; i++) {
|
|
10286
10340
|
const part = parts[i];
|
|
@@ -10332,24 +10386,24 @@ var require_redact = __commonJS({
|
|
|
10332
10386
|
}
|
|
10333
10387
|
return cloneSelectively(obj, pathStructure);
|
|
10334
10388
|
}
|
|
10335
|
-
function validatePath(
|
|
10336
|
-
if (typeof
|
|
10389
|
+
function validatePath(path98) {
|
|
10390
|
+
if (typeof path98 !== "string") {
|
|
10337
10391
|
throw new Error("Paths must be (non-empty) strings");
|
|
10338
10392
|
}
|
|
10339
|
-
if (
|
|
10393
|
+
if (path98 === "") {
|
|
10340
10394
|
throw new Error("Invalid redaction path ()");
|
|
10341
10395
|
}
|
|
10342
|
-
if (
|
|
10343
|
-
throw new Error(`Invalid redaction path (${
|
|
10396
|
+
if (path98.includes("..")) {
|
|
10397
|
+
throw new Error(`Invalid redaction path (${path98})`);
|
|
10344
10398
|
}
|
|
10345
|
-
if (
|
|
10346
|
-
throw new Error(`Invalid redaction path (${
|
|
10399
|
+
if (path98.includes(",")) {
|
|
10400
|
+
throw new Error(`Invalid redaction path (${path98})`);
|
|
10347
10401
|
}
|
|
10348
10402
|
let bracketCount = 0;
|
|
10349
10403
|
let inQuotes = false;
|
|
10350
10404
|
let quoteChar = "";
|
|
10351
|
-
for (let i = 0; i <
|
|
10352
|
-
const char =
|
|
10405
|
+
for (let i = 0; i < path98.length; i++) {
|
|
10406
|
+
const char = path98[i];
|
|
10353
10407
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
10354
10408
|
if (!inQuotes) {
|
|
10355
10409
|
inQuotes = true;
|
|
@@ -10363,20 +10417,20 @@ var require_redact = __commonJS({
|
|
|
10363
10417
|
} else if (char === "]" && !inQuotes) {
|
|
10364
10418
|
bracketCount--;
|
|
10365
10419
|
if (bracketCount < 0) {
|
|
10366
|
-
throw new Error(`Invalid redaction path (${
|
|
10420
|
+
throw new Error(`Invalid redaction path (${path98})`);
|
|
10367
10421
|
}
|
|
10368
10422
|
}
|
|
10369
10423
|
}
|
|
10370
10424
|
if (bracketCount !== 0) {
|
|
10371
|
-
throw new Error(`Invalid redaction path (${
|
|
10425
|
+
throw new Error(`Invalid redaction path (${path98})`);
|
|
10372
10426
|
}
|
|
10373
10427
|
}
|
|
10374
10428
|
function validatePaths(paths) {
|
|
10375
10429
|
if (!Array.isArray(paths)) {
|
|
10376
10430
|
throw new TypeError("paths must be an array");
|
|
10377
10431
|
}
|
|
10378
|
-
for (const
|
|
10379
|
-
validatePath(
|
|
10432
|
+
for (const path98 of paths) {
|
|
10433
|
+
validatePath(path98);
|
|
10380
10434
|
}
|
|
10381
10435
|
}
|
|
10382
10436
|
function slowRedact(options = {}) {
|
|
@@ -10544,8 +10598,8 @@ var require_redaction = __commonJS({
|
|
|
10544
10598
|
if (shape[k2] === null) {
|
|
10545
10599
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
10546
10600
|
} else {
|
|
10547
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10548
|
-
return censor(value, [k2, ...
|
|
10601
|
+
const wrappedCensor = typeof censor === "function" ? (value, path98) => {
|
|
10602
|
+
return censor(value, [k2, ...path98]);
|
|
10549
10603
|
} : censor;
|
|
10550
10604
|
o[k2] = Redact({
|
|
10551
10605
|
paths: shape[k2],
|
|
@@ -10763,10 +10817,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
10763
10817
|
var require_sonic_boom = __commonJS({
|
|
10764
10818
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
10765
10819
|
"use strict";
|
|
10766
|
-
var
|
|
10820
|
+
var fs87 = require("fs");
|
|
10767
10821
|
var EventEmitter3 = require("events");
|
|
10768
10822
|
var inherits = require("util").inherits;
|
|
10769
|
-
var
|
|
10823
|
+
var path98 = require("path");
|
|
10770
10824
|
var sleep2 = require_atomic_sleep();
|
|
10771
10825
|
var assert = require("assert");
|
|
10772
10826
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -10820,20 +10874,20 @@ var require_sonic_boom = __commonJS({
|
|
|
10820
10874
|
const mode = sonic.mode;
|
|
10821
10875
|
if (sonic.sync) {
|
|
10822
10876
|
try {
|
|
10823
|
-
if (sonic.mkdir)
|
|
10824
|
-
const fd =
|
|
10877
|
+
if (sonic.mkdir) fs87.mkdirSync(path98.dirname(file), { recursive: true });
|
|
10878
|
+
const fd = fs87.openSync(file, flags, mode);
|
|
10825
10879
|
fileOpened(null, fd);
|
|
10826
10880
|
} catch (err) {
|
|
10827
10881
|
fileOpened(err);
|
|
10828
10882
|
throw err;
|
|
10829
10883
|
}
|
|
10830
10884
|
} else if (sonic.mkdir) {
|
|
10831
|
-
|
|
10885
|
+
fs87.mkdir(path98.dirname(file), { recursive: true }, (err) => {
|
|
10832
10886
|
if (err) return fileOpened(err);
|
|
10833
|
-
|
|
10887
|
+
fs87.open(file, flags, mode, fileOpened);
|
|
10834
10888
|
});
|
|
10835
10889
|
} else {
|
|
10836
|
-
|
|
10890
|
+
fs87.open(file, flags, mode, fileOpened);
|
|
10837
10891
|
}
|
|
10838
10892
|
}
|
|
10839
10893
|
function SonicBoom(opts) {
|
|
@@ -10874,8 +10928,8 @@ var require_sonic_boom = __commonJS({
|
|
|
10874
10928
|
this.flush = flushBuffer;
|
|
10875
10929
|
this.flushSync = flushBufferSync;
|
|
10876
10930
|
this._actualWrite = actualWriteBuffer;
|
|
10877
|
-
fsWriteSync = () =>
|
|
10878
|
-
fsWrite = () =>
|
|
10931
|
+
fsWriteSync = () => fs87.writeSync(this.fd, this._writingBuf);
|
|
10932
|
+
fsWrite = () => fs87.write(this.fd, this._writingBuf, this.release);
|
|
10879
10933
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
10880
10934
|
this._writingBuf = "";
|
|
10881
10935
|
this.write = write;
|
|
@@ -10884,15 +10938,15 @@ var require_sonic_boom = __commonJS({
|
|
|
10884
10938
|
this._actualWrite = actualWrite;
|
|
10885
10939
|
fsWriteSync = () => {
|
|
10886
10940
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10887
|
-
return
|
|
10941
|
+
return fs87.writeSync(this.fd, this._writingBuf);
|
|
10888
10942
|
}
|
|
10889
|
-
return
|
|
10943
|
+
return fs87.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10890
10944
|
};
|
|
10891
10945
|
fsWrite = () => {
|
|
10892
10946
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10893
|
-
return
|
|
10947
|
+
return fs87.write(this.fd, this._writingBuf, this.release);
|
|
10894
10948
|
}
|
|
10895
|
-
return
|
|
10949
|
+
return fs87.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
10896
10950
|
};
|
|
10897
10951
|
} else {
|
|
10898
10952
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -10949,7 +11003,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10949
11003
|
}
|
|
10950
11004
|
}
|
|
10951
11005
|
if (this._fsync) {
|
|
10952
|
-
|
|
11006
|
+
fs87.fsyncSync(this.fd);
|
|
10953
11007
|
}
|
|
10954
11008
|
const len = this._len;
|
|
10955
11009
|
if (this._reopening) {
|
|
@@ -11063,7 +11117,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11063
11117
|
const onDrain = () => {
|
|
11064
11118
|
if (!this._fsync) {
|
|
11065
11119
|
try {
|
|
11066
|
-
|
|
11120
|
+
fs87.fsync(this.fd, (err) => {
|
|
11067
11121
|
this._flushPending = false;
|
|
11068
11122
|
cb(err);
|
|
11069
11123
|
});
|
|
@@ -11165,7 +11219,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11165
11219
|
const fd = this.fd;
|
|
11166
11220
|
this.once("ready", () => {
|
|
11167
11221
|
if (fd !== this.fd) {
|
|
11168
|
-
|
|
11222
|
+
fs87.close(fd, (err) => {
|
|
11169
11223
|
if (err) {
|
|
11170
11224
|
return this.emit("error", err);
|
|
11171
11225
|
}
|
|
@@ -11214,7 +11268,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11214
11268
|
buf = this._bufs[0];
|
|
11215
11269
|
}
|
|
11216
11270
|
try {
|
|
11217
|
-
const n = Buffer.isBuffer(buf) ?
|
|
11271
|
+
const n = Buffer.isBuffer(buf) ? fs87.writeSync(this.fd, buf) : fs87.writeSync(this.fd, buf, "utf8");
|
|
11218
11272
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
11219
11273
|
buf = releasedBufObj.writingBuf;
|
|
11220
11274
|
this._len = releasedBufObj.len;
|
|
@@ -11230,7 +11284,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11230
11284
|
}
|
|
11231
11285
|
}
|
|
11232
11286
|
try {
|
|
11233
|
-
|
|
11287
|
+
fs87.fsyncSync(this.fd);
|
|
11234
11288
|
} catch {
|
|
11235
11289
|
}
|
|
11236
11290
|
}
|
|
@@ -11251,7 +11305,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11251
11305
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
11252
11306
|
}
|
|
11253
11307
|
try {
|
|
11254
|
-
const n =
|
|
11308
|
+
const n = fs87.writeSync(this.fd, buf);
|
|
11255
11309
|
buf = buf.subarray(n);
|
|
11256
11310
|
this._len = Math.max(this._len - n, 0);
|
|
11257
11311
|
if (buf.length <= 0) {
|
|
@@ -11279,13 +11333,13 @@ var require_sonic_boom = __commonJS({
|
|
|
11279
11333
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
11280
11334
|
if (this.sync) {
|
|
11281
11335
|
try {
|
|
11282
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
11336
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs87.writeSync(this.fd, this._writingBuf) : fs87.writeSync(this.fd, this._writingBuf, "utf8");
|
|
11283
11337
|
release(null, written);
|
|
11284
11338
|
} catch (err) {
|
|
11285
11339
|
release(err);
|
|
11286
11340
|
}
|
|
11287
11341
|
} else {
|
|
11288
|
-
|
|
11342
|
+
fs87.write(this.fd, this._writingBuf, release);
|
|
11289
11343
|
}
|
|
11290
11344
|
}
|
|
11291
11345
|
function actualWriteBuffer() {
|
|
@@ -11294,7 +11348,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11294
11348
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
11295
11349
|
if (this.sync) {
|
|
11296
11350
|
try {
|
|
11297
|
-
const written =
|
|
11351
|
+
const written = fs87.writeSync(this.fd, this._writingBuf);
|
|
11298
11352
|
release(null, written);
|
|
11299
11353
|
} catch (err) {
|
|
11300
11354
|
release(err);
|
|
@@ -11303,7 +11357,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11303
11357
|
if (kCopyBuffer) {
|
|
11304
11358
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
11305
11359
|
}
|
|
11306
|
-
|
|
11360
|
+
fs87.write(this.fd, this._writingBuf, release);
|
|
11307
11361
|
}
|
|
11308
11362
|
}
|
|
11309
11363
|
function actualClose(sonic) {
|
|
@@ -11319,12 +11373,12 @@ var require_sonic_boom = __commonJS({
|
|
|
11319
11373
|
sonic._lens = [];
|
|
11320
11374
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
11321
11375
|
try {
|
|
11322
|
-
|
|
11376
|
+
fs87.fsync(sonic.fd, closeWrapped);
|
|
11323
11377
|
} catch {
|
|
11324
11378
|
}
|
|
11325
11379
|
function closeWrapped() {
|
|
11326
11380
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
11327
|
-
|
|
11381
|
+
fs87.close(sonic.fd, done);
|
|
11328
11382
|
} else {
|
|
11329
11383
|
done();
|
|
11330
11384
|
}
|
|
@@ -13688,7 +13742,7 @@ var require_multistream = __commonJS({
|
|
|
13688
13742
|
var require_pino = __commonJS({
|
|
13689
13743
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
13690
13744
|
"use strict";
|
|
13691
|
-
var
|
|
13745
|
+
var os32 = require("os");
|
|
13692
13746
|
var stdSerializers = require_pino_std_serializers();
|
|
13693
13747
|
var caller = require_caller();
|
|
13694
13748
|
var redaction = require_redaction();
|
|
@@ -13735,7 +13789,7 @@ var require_pino = __commonJS({
|
|
|
13735
13789
|
} = symbols;
|
|
13736
13790
|
var { epochTime, nullTime } = time;
|
|
13737
13791
|
var { pid } = process;
|
|
13738
|
-
var hostname =
|
|
13792
|
+
var hostname = os32.hostname();
|
|
13739
13793
|
var defaultErrorSerializer = stdSerializers.err;
|
|
13740
13794
|
var defaultOptions2 = {
|
|
13741
13795
|
level: "info",
|
|
@@ -14459,11 +14513,11 @@ var init_lib = __esm({
|
|
|
14459
14513
|
}
|
|
14460
14514
|
}
|
|
14461
14515
|
},
|
|
14462
|
-
addToPath: function addToPath(
|
|
14463
|
-
var last =
|
|
14516
|
+
addToPath: function addToPath(path98, added, removed, oldPosInc, options) {
|
|
14517
|
+
var last = path98.lastComponent;
|
|
14464
14518
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14465
14519
|
return {
|
|
14466
|
-
oldPos:
|
|
14520
|
+
oldPos: path98.oldPos + oldPosInc,
|
|
14467
14521
|
lastComponent: {
|
|
14468
14522
|
count: last.count + 1,
|
|
14469
14523
|
added,
|
|
@@ -14473,7 +14527,7 @@ var init_lib = __esm({
|
|
|
14473
14527
|
};
|
|
14474
14528
|
} else {
|
|
14475
14529
|
return {
|
|
14476
|
-
oldPos:
|
|
14530
|
+
oldPos: path98.oldPos + oldPosInc,
|
|
14477
14531
|
lastComponent: {
|
|
14478
14532
|
count: 1,
|
|
14479
14533
|
added,
|
|
@@ -15055,10 +15109,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
15055
15109
|
const memories = raw.map((m2) => {
|
|
15056
15110
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15057
15111
|
const rec4 = m2;
|
|
15058
|
-
const
|
|
15112
|
+
const path98 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15059
15113
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15060
|
-
if (!
|
|
15061
|
-
const entry = { path:
|
|
15114
|
+
if (!path98 || content == null) return null;
|
|
15115
|
+
const entry = { path: path98, content };
|
|
15062
15116
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
15063
15117
|
return entry;
|
|
15064
15118
|
}).filter((m2) => m2 !== null);
|
|
@@ -15924,10 +15978,10 @@ function parseAttachment(obj) {
|
|
|
15924
15978
|
const memories = raw.map((m2) => {
|
|
15925
15979
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15926
15980
|
const rec4 = m2;
|
|
15927
|
-
const
|
|
15981
|
+
const path98 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15928
15982
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15929
|
-
if (!
|
|
15930
|
-
const out = { path:
|
|
15983
|
+
if (!path98 || content == null) return null;
|
|
15984
|
+
const out = { path: path98, content };
|
|
15931
15985
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
15932
15986
|
return out;
|
|
15933
15987
|
}).filter((m2) => m2 !== null);
|
|
@@ -36901,8 +36955,8 @@ var require_utils = __commonJS({
|
|
|
36901
36955
|
var result = transform[inputType][outputType](input);
|
|
36902
36956
|
return result;
|
|
36903
36957
|
};
|
|
36904
|
-
exports2.resolve = function(
|
|
36905
|
-
var parts =
|
|
36958
|
+
exports2.resolve = function(path98) {
|
|
36959
|
+
var parts = path98.split("/");
|
|
36906
36960
|
var result = [];
|
|
36907
36961
|
for (var index = 0; index < parts.length; index++) {
|
|
36908
36962
|
var part = parts[index];
|
|
@@ -42755,18 +42809,18 @@ var require_object = __commonJS({
|
|
|
42755
42809
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
42756
42810
|
this.files[name] = object;
|
|
42757
42811
|
};
|
|
42758
|
-
var parentFolder = function(
|
|
42759
|
-
if (
|
|
42760
|
-
|
|
42812
|
+
var parentFolder = function(path98) {
|
|
42813
|
+
if (path98.slice(-1) === "/") {
|
|
42814
|
+
path98 = path98.substring(0, path98.length - 1);
|
|
42761
42815
|
}
|
|
42762
|
-
var lastSlash =
|
|
42763
|
-
return lastSlash > 0 ?
|
|
42816
|
+
var lastSlash = path98.lastIndexOf("/");
|
|
42817
|
+
return lastSlash > 0 ? path98.substring(0, lastSlash) : "";
|
|
42764
42818
|
};
|
|
42765
|
-
var forceTrailingSlash = function(
|
|
42766
|
-
if (
|
|
42767
|
-
|
|
42819
|
+
var forceTrailingSlash = function(path98) {
|
|
42820
|
+
if (path98.slice(-1) !== "/") {
|
|
42821
|
+
path98 += "/";
|
|
42768
42822
|
}
|
|
42769
|
-
return
|
|
42823
|
+
return path98;
|
|
42770
42824
|
};
|
|
42771
42825
|
var folderAdd = function(name, createFolders) {
|
|
42772
42826
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -43768,7 +43822,7 @@ var require_lib3 = __commonJS({
|
|
|
43768
43822
|
// src/run-case/recorder.ts
|
|
43769
43823
|
function startRunCaseRecorder(opts) {
|
|
43770
43824
|
const now = opts.now ?? Date.now;
|
|
43771
|
-
const dir =
|
|
43825
|
+
const dir = import_node_path80.default.dirname(opts.recordPath);
|
|
43772
43826
|
let stream = null;
|
|
43773
43827
|
let closing = false;
|
|
43774
43828
|
let closedSettled = false;
|
|
@@ -43808,12 +43862,12 @@ function startRunCaseRecorder(opts) {
|
|
|
43808
43862
|
};
|
|
43809
43863
|
return { tap, close, closed };
|
|
43810
43864
|
}
|
|
43811
|
-
var import_node_fs57,
|
|
43865
|
+
var import_node_fs57, import_node_path80;
|
|
43812
43866
|
var init_recorder = __esm({
|
|
43813
43867
|
"src/run-case/recorder.ts"() {
|
|
43814
43868
|
"use strict";
|
|
43815
43869
|
import_node_fs57 = __toESM(require("fs"), 1);
|
|
43816
|
-
|
|
43870
|
+
import_node_path80 = __toESM(require("path"), 1);
|
|
43817
43871
|
}
|
|
43818
43872
|
});
|
|
43819
43873
|
|
|
@@ -43856,7 +43910,7 @@ var init_wire = __esm({
|
|
|
43856
43910
|
// src/run-case/controller.ts
|
|
43857
43911
|
async function runController(opts) {
|
|
43858
43912
|
const now = opts.now ?? Date.now;
|
|
43859
|
-
const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(
|
|
43913
|
+
const cwd = opts.cwd ?? (0, import_node_fs58.mkdtempSync)(import_node_path81.default.join(import_node_os28.default.tmpdir(), "clawd-runcase-"));
|
|
43860
43914
|
const ownsCwd = opts.cwd === void 0;
|
|
43861
43915
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
43862
43916
|
const spawnCtx = { cwd };
|
|
@@ -44023,13 +44077,13 @@ async function runController(opts) {
|
|
|
44023
44077
|
}
|
|
44024
44078
|
return exitCode ?? 0;
|
|
44025
44079
|
}
|
|
44026
|
-
var import_node_fs58,
|
|
44080
|
+
var import_node_fs58, import_node_os28, import_node_path81;
|
|
44027
44081
|
var init_controller = __esm({
|
|
44028
44082
|
"src/run-case/controller.ts"() {
|
|
44029
44083
|
"use strict";
|
|
44030
44084
|
import_node_fs58 = require("fs");
|
|
44031
|
-
|
|
44032
|
-
|
|
44085
|
+
import_node_os28 = __toESM(require("os"), 1);
|
|
44086
|
+
import_node_path81 = __toESM(require("path"), 1);
|
|
44033
44087
|
init_claude();
|
|
44034
44088
|
init_stdout_splitter();
|
|
44035
44089
|
init_permission_stdio();
|
|
@@ -44304,9 +44358,9 @@ Env (advanced):
|
|
|
44304
44358
|
`;
|
|
44305
44359
|
|
|
44306
44360
|
// src/index.ts
|
|
44307
|
-
var
|
|
44361
|
+
var import_node_path79 = __toESM(require("path"), 1);
|
|
44308
44362
|
var import_node_fs56 = __toESM(require("fs"), 1);
|
|
44309
|
-
var
|
|
44363
|
+
var import_node_os27 = __toESM(require("os"), 1);
|
|
44310
44364
|
var import_node_crypto22 = require("crypto");
|
|
44311
44365
|
var import_node_url5 = require("url");
|
|
44312
44366
|
|
|
@@ -51562,8 +51616,8 @@ function turnStartInput(text) {
|
|
|
51562
51616
|
const items = [];
|
|
51563
51617
|
let leftover = text;
|
|
51564
51618
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
51565
|
-
const [marker, name,
|
|
51566
|
-
items.push({ type: "skill", name, path:
|
|
51619
|
+
const [marker, name, path98] = m2;
|
|
51620
|
+
items.push({ type: "skill", name, path: path98 });
|
|
51567
51621
|
leftover = leftover.replace(marker, "");
|
|
51568
51622
|
}
|
|
51569
51623
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -54626,6 +54680,38 @@ function redactEvidence(evidence) {
|
|
|
54626
54680
|
};
|
|
54627
54681
|
}
|
|
54628
54682
|
|
|
54683
|
+
// src/deploy/readiness.ts
|
|
54684
|
+
function secretShortfalls(receipt, filledEnv) {
|
|
54685
|
+
const declared = receipt.manifest?.secrets ?? [];
|
|
54686
|
+
const out = [];
|
|
54687
|
+
for (const sec of declared) {
|
|
54688
|
+
const f = receipt.fulfillment[sec.name];
|
|
54689
|
+
if (!f) {
|
|
54690
|
+
out.push({ name: sec.name, why: "fulfillment", missingEnv: [] });
|
|
54691
|
+
continue;
|
|
54692
|
+
}
|
|
54693
|
+
const filled = new Set(filledEnv(sec.name));
|
|
54694
|
+
const missing = sec.env.filter((e) => !filled.has(e));
|
|
54695
|
+
if (missing.length === 0) continue;
|
|
54696
|
+
out.push({ name: sec.name, why: f === "deployer" ? "values" : "trial", missingEnv: missing });
|
|
54697
|
+
}
|
|
54698
|
+
return out;
|
|
54699
|
+
}
|
|
54700
|
+
function describeShortfalls(items) {
|
|
54701
|
+
return items.map((s) => {
|
|
54702
|
+
if (s.why === "fulfillment") return `\u300C${s.name}\u300D\u8FD8\u6CA1\u9009\u8C01\u6765\u63D0\u4F9B`;
|
|
54703
|
+
if (s.why === "trial") return `\u300C${s.name}\u300D\u8BF4\u597D\u4F7F\u7528\u8005\u81EA\u5E26\uFF0C\u4F46\u8BD5\u88C5\u8981\u771F\u8DD1\u4E00\u6B21\uFF0C\u5F97\u4F60\u5148\u57AB\u4E00\u4EFD\uFF08\u8FD8\u5DEE ${s.missingEnv.join(" / ")}\uFF09`;
|
|
54704
|
+
return `\u300C${s.name}\u300D\u8FD8\u5DEE ${s.missingEnv.join(" / ")}`;
|
|
54705
|
+
}).join("\uFF1B");
|
|
54706
|
+
}
|
|
54707
|
+
function nextReadiness(receipt, filledEnv) {
|
|
54708
|
+
if (receipt.status !== "draft" && receipt.status !== "ready") return void 0;
|
|
54709
|
+
if (!receipt.manifest) return void 0;
|
|
54710
|
+
const ready = secretShortfalls(receipt, filledEnv).length === 0;
|
|
54711
|
+
const next = ready ? "ready" : "draft";
|
|
54712
|
+
return next === receipt.status ? void 0 : next;
|
|
54713
|
+
}
|
|
54714
|
+
|
|
54629
54715
|
// src/handlers/deploy.ts
|
|
54630
54716
|
function ensureOwner(ctx) {
|
|
54631
54717
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
@@ -54655,6 +54741,11 @@ function secretStatusOf(deps, receipt) {
|
|
|
54655
54741
|
total: s.env.length
|
|
54656
54742
|
}));
|
|
54657
54743
|
}
|
|
54744
|
+
function applyReadiness(deps, receipt) {
|
|
54745
|
+
const next = nextReadiness(receipt, (name) => deps.secrets.filledKeys(receipt.deployId, name));
|
|
54746
|
+
if (!next) return receipt;
|
|
54747
|
+
return deps.receipts.update(receipt.deployId, { status: next }) ?? receipt;
|
|
54748
|
+
}
|
|
54658
54749
|
function buildDeployHandlers(deps) {
|
|
54659
54750
|
const view = (receipt) => ({
|
|
54660
54751
|
response: { type: "deploy:receipt", receipt, secretStatus: secretStatusOf(deps, receipt) }
|
|
@@ -54690,6 +54781,12 @@ function buildDeployHandlers(deps) {
|
|
|
54690
54781
|
if (receipt.status === "scanning") {
|
|
54691
54782
|
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");
|
|
54692
54783
|
}
|
|
54784
|
+
if (receipt.status === "deployed") {
|
|
54785
|
+
throw new ClawdError(
|
|
54786
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54787
|
+
"VALIDATION_ERROR: \u8FD9\u5F20\u5355\u5DF2\u7ECF\u90E8\u7F72\u4E86\uFF0C\u4E0D\u80FD\u5C31\u5730\u91CD\u626B\u3002persona \u6539\u4E86\u8981\u91CD\u53D1\u7684\u8BDD\uFF0C\u56DE\u5361\u7247\u91CD\u65B0\u53D1\u8D77\u4E00\u6B21\u4E0A\u4E91\u2014\u2014\u90A3\u4F1A\u5F00\u4E00\u5F20\u65B0\u5355\u636E\uFF08\u51ED\u636E\u548C\u5C65\u7EA6\u4F1A\u7EE7\u627F\u8FC7\u6765\uFF09\uFF0C\u73B0\u5728\u8FD9\u4EFD\u90E8\u7F72\u5728\u65B0\u7684\u90E8\u7F72\u597D\u4E4B\u524D\u7167\u5E38\u670D\u52A1"
|
|
54788
|
+
);
|
|
54789
|
+
}
|
|
54693
54790
|
deps.receipts.update(args.deployId, {
|
|
54694
54791
|
status: "scanning",
|
|
54695
54792
|
manifest: void 0,
|
|
@@ -54697,7 +54794,12 @@ function buildDeployHandlers(deps) {
|
|
|
54697
54794
|
notes: [],
|
|
54698
54795
|
smokeTask: void 0,
|
|
54699
54796
|
error: void 0,
|
|
54700
|
-
scanSessionId: void 0
|
|
54797
|
+
scanSessionId: void 0,
|
|
54798
|
+
// 重扫 = 一次新的判断,试装轮次跟着清零(不是同一条路上的第 N 次撞墙)
|
|
54799
|
+
trialRound: 0,
|
|
54800
|
+
gaps: [],
|
|
54801
|
+
trialPassedAt: void 0,
|
|
54802
|
+
trialImage: void 0
|
|
54701
54803
|
});
|
|
54702
54804
|
const scanSessionId = deps.startScan(args.deployId, receipt.personaId);
|
|
54703
54805
|
if (scanSessionId) deps.receipts.update(args.deployId, { scanSessionId });
|
|
@@ -54727,8 +54829,9 @@ function buildDeployHandlers(deps) {
|
|
|
54727
54829
|
}
|
|
54728
54830
|
}
|
|
54729
54831
|
}
|
|
54730
|
-
const
|
|
54731
|
-
|
|
54832
|
+
const invalidates = args.patch.manifest ? { trialPassedAt: void 0, trialImage: void 0 } : {};
|
|
54833
|
+
const next = deps.receipts.update(args.deployId, { ...args.patch, ...invalidates });
|
|
54834
|
+
return view(applyReadiness(deps, next ?? receipt));
|
|
54732
54835
|
};
|
|
54733
54836
|
const putSecret = async (frame, _client, ctx) => {
|
|
54734
54837
|
ensureOwner(ctx);
|
|
@@ -54748,7 +54851,7 @@ function buildDeployHandlers(deps) {
|
|
|
54748
54851
|
}
|
|
54749
54852
|
}
|
|
54750
54853
|
deps.secrets.put({ deployId: args.deployId, name: args.name, values: args.values });
|
|
54751
|
-
return view(receipt);
|
|
54854
|
+
return view(applyReadiness(deps, receipt));
|
|
54752
54855
|
};
|
|
54753
54856
|
const reportFinding = async (frame, _client, ctx) => {
|
|
54754
54857
|
ensureOwner(ctx);
|
|
@@ -54791,12 +54894,77 @@ function buildDeployHandlers(deps) {
|
|
|
54791
54894
|
notes: args.notes?.map(redactSecretValues),
|
|
54792
54895
|
error: void 0
|
|
54793
54896
|
});
|
|
54794
|
-
return view(next);
|
|
54897
|
+
return view(applyReadiness(deps, next));
|
|
54898
|
+
};
|
|
54899
|
+
const trial = async (frame, _client, ctx) => {
|
|
54900
|
+
ensureOwner(ctx);
|
|
54901
|
+
const args = parseArgs2(DeployIdArgsSchema, frame, "deploy:trial");
|
|
54902
|
+
const receipt = mustGet(deps, args.deployId);
|
|
54903
|
+
if (receipt.status === "scanning" || receipt.status === "scanFailed") {
|
|
54904
|
+
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "VALIDATION_ERROR: \u8FD9\u5F20\u5355\u8FD8\u6CA1\u626B\u51FA\u6E05\u5355\uFF0C\u5148\u7B49\u626B\u63CF\u7ED3\u675F");
|
|
54905
|
+
}
|
|
54906
|
+
if (receipt.status === "trialing") {
|
|
54907
|
+
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "VALIDATION_ERROR: \u8FD9\u5F20\u5355\u6B63\u5728\u8BD5\u88C5\u4E2D");
|
|
54908
|
+
}
|
|
54909
|
+
if (receipt.status === "deployed") {
|
|
54910
|
+
throw new ClawdError(
|
|
54911
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54912
|
+
"VALIDATION_ERROR: \u8FD9\u5F20\u5355\u5DF2\u7ECF\u90E8\u7F72\u4E86\u3002\u6539\u4E86\u4E1C\u897F\u8981\u91CD\u53D1\u7684\u8BDD\uFF0C\u56DE persona \u5361\u7247\u91CD\u65B0\u53D1\u8D77\u4E00\u6B21\u4E0A\u4E91"
|
|
54913
|
+
);
|
|
54914
|
+
}
|
|
54915
|
+
if (!receipt.manifest) {
|
|
54916
|
+
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "VALIDATION_ERROR: \u8FD9\u5F20\u5355\u6CA1\u6709\u73AF\u5883\u6E05\u5355\uFF0C\u8BD5\u88C5\u65E0\u4ECE\u8C08\u8D77");
|
|
54917
|
+
}
|
|
54918
|
+
const short = secretShortfalls(receipt, (name) => deps.secrets.filledKeys(args.deployId, name));
|
|
54919
|
+
if (short.length > 0) {
|
|
54920
|
+
throw new ClawdError(
|
|
54921
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54922
|
+
`VALIDATION_ERROR: \u51ED\u636E\u8FD8\u6CA1\u9F50\uFF0C\u8BD5\u88C5\u8DD1\u4E0D\u8D77\u6765\uFF1A${describeShortfalls(short)}`
|
|
54923
|
+
);
|
|
54924
|
+
}
|
|
54925
|
+
if (receipt.trialRound >= TRIAL_ROUND_MAX) {
|
|
54926
|
+
throw new ClawdError(
|
|
54927
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54928
|
+
`VALIDATION_ERROR: \u5DF2\u7ECF\u8BD5\u88C5 ${receipt.trialRound} \u8F6E\u4E86\uFF08\u4E0A\u9650 ${TRIAL_ROUND_MAX}\uFF09\u3002\u4E00\u8F6E\u662F\u4E00\u6B21\u771F\u7684\u955C\u50CF\u6784\u5EFA\u52A0\u4E00\u6B21\u771F\u7684\u53D1\u5E03\uFF0C\u5230\u8FD9\u4E2A\u6570\u8BF4\u660E\u7F3A\u7684\u591A\u534A\u4E0D\u662F\u4E00\u6761\u4F9D\u8D56\u2014\u2014\u56DE\u53BB\u91CD\u626B\u4E00\u904D\uFF0C\u6216\u8005\u627E\u4EBA\u770B\u770B\u8FD9\u6761\u8DEF\u662F\u4E0D\u662F\u8D70\u4E0D\u901A`
|
|
54929
|
+
);
|
|
54930
|
+
}
|
|
54931
|
+
const next = deps.receipts.update(args.deployId, {
|
|
54932
|
+
status: "trialing",
|
|
54933
|
+
trialRound: receipt.trialRound + 1,
|
|
54934
|
+
trialStage: "\u6392\u961F\u51C6\u5907\u4E2D",
|
|
54935
|
+
// 上一轮的缺口不留到这一轮:人已经照着补过了,留着会让人以为没改动
|
|
54936
|
+
gaps: [],
|
|
54937
|
+
error: void 0
|
|
54938
|
+
});
|
|
54939
|
+
deps.startTrial(args.deployId);
|
|
54940
|
+
return view(next ?? receipt);
|
|
54941
|
+
};
|
|
54942
|
+
const deploy = async (frame, _client, ctx) => {
|
|
54943
|
+
ensureOwner(ctx);
|
|
54944
|
+
const args = parseArgs2(DeployIdArgsSchema, frame, "deploy:deploy");
|
|
54945
|
+
const receipt = mustGet(deps, args.deployId);
|
|
54946
|
+
if (receipt.status === "deployed") return view(receipt);
|
|
54947
|
+
if (!receipt.trialPassedAt || !receipt.trialImage) {
|
|
54948
|
+
throw new ClawdError(
|
|
54949
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54950
|
+
"VALIDATION_ERROR: \u8FD8\u6CA1\u8BD5\u88C5\u901A\u8FC7\u8FC7\u3002\u5148\u70B9\u300C\u786E\u8BA4\u5E76\u8BD5\u88C5\u300D\u2014\u2014\u90A3\u4E00\u6B65\u624D\u77E5\u9053\u8FD9\u4EFD\u6E05\u5355\u5728\u4E91\u4E0A\u88C5\u4E0D\u88C5\u5F97\u8D77\u6765"
|
|
54951
|
+
);
|
|
54952
|
+
}
|
|
54953
|
+
if (receipt.status !== "ready") {
|
|
54954
|
+
throw new ClawdError(
|
|
54955
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
54956
|
+
`VALIDATION_ERROR: \u5F53\u524D\u72B6\u6001\u662F ${receipt.status}\uFF0C\u4E0D\u80FD\u90E8\u7F72`
|
|
54957
|
+
);
|
|
54958
|
+
}
|
|
54959
|
+
const placement = await deps.registerOfficial(receipt);
|
|
54960
|
+
const next = deps.receipts.update(args.deployId, { status: "deployed", placement, error: void 0 });
|
|
54961
|
+
return view(next ?? receipt);
|
|
54795
54962
|
};
|
|
54796
54963
|
const remove = async (frame, _client, ctx) => {
|
|
54797
54964
|
ensureOwner(ctx);
|
|
54798
54965
|
const args = parseArgs2(DeployIdArgsSchema, frame, "deploy:remove");
|
|
54799
|
-
mustGet(deps, args.deployId);
|
|
54966
|
+
const receipt = mustGet(deps, args.deployId);
|
|
54967
|
+
if (receipt.placement) await deps.unregisterDeployment(receipt.deployId);
|
|
54800
54968
|
deps.receipts.remove(args.deployId);
|
|
54801
54969
|
deps.secrets.removeDeploy(args.deployId);
|
|
54802
54970
|
return { response: { type: "deploy:remove", deployId: args.deployId } };
|
|
@@ -54810,6 +54978,8 @@ function buildDeployHandlers(deps) {
|
|
|
54810
54978
|
"deploy:putSecret": putSecret,
|
|
54811
54979
|
"deploy:reportFinding": reportFinding,
|
|
54812
54980
|
"deploy:finishScan": finishScan,
|
|
54981
|
+
"deploy:trial": trial,
|
|
54982
|
+
"deploy:deploy": deploy,
|
|
54813
54983
|
"deploy:remove": remove
|
|
54814
54984
|
};
|
|
54815
54985
|
}
|
|
@@ -54866,6 +55036,7 @@ function createReceiptStore(deps) {
|
|
|
54866
55036
|
notes: [],
|
|
54867
55037
|
fulfillment: {},
|
|
54868
55038
|
gaps: [],
|
|
55039
|
+
trialRound: 0,
|
|
54869
55040
|
createdAt: ts,
|
|
54870
55041
|
updatedAt: ts
|
|
54871
55042
|
};
|
|
@@ -54994,6 +55165,384 @@ function createSecretStore(deps) {
|
|
|
54994
55165
|
};
|
|
54995
55166
|
}
|
|
54996
55167
|
|
|
55168
|
+
// src/deploy/cloud-host-config.ts
|
|
55169
|
+
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
55170
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
55171
|
+
var CLOUD_HOST_CONFIG_FILE = "cloud-host.json";
|
|
55172
|
+
var REQUIRED = ["provisionDir", "gatewayUrl", "gatewayAdminKey", "gatewayApiKey", "k3sHost", "k3sKeyPath"];
|
|
55173
|
+
var CloudHostConfigError = class extends Error {
|
|
55174
|
+
};
|
|
55175
|
+
async function loadCloudHostConfig(dataDir) {
|
|
55176
|
+
const file = import_node_path32.default.join(dataDir, CLOUD_HOST_CONFIG_FILE);
|
|
55177
|
+
let raw;
|
|
55178
|
+
try {
|
|
55179
|
+
raw = await import_promises6.default.readFile(file, "utf8");
|
|
55180
|
+
} catch (err) {
|
|
55181
|
+
if (err.code === "ENOENT") {
|
|
55182
|
+
throw new CloudHostConfigError(
|
|
55183
|
+
`\u8FD8\u6CA1\u914D ${file}\u3002\u8BD5\u88C5\u8981\u77E5\u9053\u5F80\u54EA\u53F0\u673A\u5668\u63A8\u955C\u50CF\u3001\u8DDF\u54EA\u4E2A gateway \u8BF4\u8BDD\uFF0C\u5B57\u6BB5\u89C1 specs/2026-09-03-persona-cloud-m1b-trial-design.md \u7B2C\u4E94\u8282\u3002`
|
|
55184
|
+
);
|
|
55185
|
+
}
|
|
55186
|
+
throw err;
|
|
55187
|
+
}
|
|
55188
|
+
let parsed;
|
|
55189
|
+
try {
|
|
55190
|
+
parsed = JSON.parse(raw);
|
|
55191
|
+
} catch (err) {
|
|
55192
|
+
throw new CloudHostConfigError(`${file} \u4E0D\u662F\u5408\u6CD5 JSON\uFF1A${String(err)}`);
|
|
55193
|
+
}
|
|
55194
|
+
const missing = REQUIRED.filter((k2) => !parsed[k2]);
|
|
55195
|
+
if (missing.length > 0) {
|
|
55196
|
+
throw new CloudHostConfigError(`${file} \u7F3A\u5B57\u6BB5\uFF1A${missing.join(" / ")}`);
|
|
55197
|
+
}
|
|
55198
|
+
return {
|
|
55199
|
+
provisionDir: parsed.provisionDir,
|
|
55200
|
+
gatewayUrl: parsed.gatewayUrl.replace(/\/+$/, ""),
|
|
55201
|
+
gatewayAdminKey: parsed.gatewayAdminKey,
|
|
55202
|
+
gatewayApiKey: parsed.gatewayApiKey,
|
|
55203
|
+
k3sHost: parsed.k3sHost,
|
|
55204
|
+
k3sKeyPath: parsed.k3sKeyPath,
|
|
55205
|
+
imageRepo: parsed.imageRepo ?? "clawd-persona-cloud",
|
|
55206
|
+
trialTimeoutMs: parsed.trialTimeoutMs ?? 45 * 6e4
|
|
55207
|
+
};
|
|
55208
|
+
}
|
|
55209
|
+
|
|
55210
|
+
// src/deploy/trial-runner.ts
|
|
55211
|
+
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
55212
|
+
var import_node_os8 = __toESM(require("os"), 1);
|
|
55213
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
55214
|
+
var RAW_TAIL_CHARS = 2e3;
|
|
55215
|
+
var GATEWAY_ADMIN_TIMEOUT_MS = 3e4;
|
|
55216
|
+
var trialStamp = (nowMs) => Math.floor(nowMs / 1e3).toString(36);
|
|
55217
|
+
var trialImageTag = (repo2, deployId, round, stamp) => `${repo2}:${trialDeployId(deployId, round, stamp)}`;
|
|
55218
|
+
var trialDeployId = (deployId, round, stamp) => `${deployId}-t${round}-${stamp}`;
|
|
55219
|
+
var trialAppName = (deployId) => `trial-${deployId}`;
|
|
55220
|
+
var trialConversation = (deployId, round, stamp) => `trial-${deployId}-r${round}-${stamp}`;
|
|
55221
|
+
function secretTableFor(receipt, all, scope) {
|
|
55222
|
+
const declared = receipt.manifest?.secrets ?? [];
|
|
55223
|
+
const wanted = new Set(
|
|
55224
|
+
declared.filter((s) => scope === "all" || receipt.fulfillment[s.name] === "deployer").flatMap((s) => s.env)
|
|
55225
|
+
);
|
|
55226
|
+
return Object.fromEntries(Object.entries(all).filter(([k2]) => wanted.has(k2)));
|
|
55227
|
+
}
|
|
55228
|
+
function userSecretsOf(receipt) {
|
|
55229
|
+
return (receipt.manifest?.secrets ?? []).filter((s) => receipt.fulfillment[s.name] === "user").map((s) => ({ name: s.name, env: [...s.env] }));
|
|
55230
|
+
}
|
|
55231
|
+
var MISSING_MARKER = "::missing::";
|
|
55232
|
+
function buildSmokePrompt(smokeTask, appName) {
|
|
55233
|
+
return [
|
|
55234
|
+
"\u3010\u8BD5\u88C5\u3011\u8FD9\u662F\u4E00\u6B21\u6027\u7684\u73AF\u5883\u9A8C\u8BC1\uFF1A\u4F60\u5728\u4E00\u4E2A\u521A\u6784\u51FA\u6765\u7684\u4E91\u4E0A\u5BB9\u5668\u91CC\uFF0C\u8DD1\u5B8C\u8FD9\u6B21\u4EFB\u52A1\u5B83\u5C31\u4F1A\u88AB\u62C6\u6389\u3002",
|
|
55235
|
+
"",
|
|
55236
|
+
smokeTask,
|
|
55237
|
+
"",
|
|
55238
|
+
"\u4E09\u6761\u786C\u7EA6\u675F\uFF1A",
|
|
55239
|
+
`1. \u9879\u76EE\u540D\u5FC5\u987B\u53EB \`${appName}\`\uFF08\u62C6\u9664\u9760\u8FD9\u4E2A\u540D\u5B57\u8BC6\u522B\uFF0C\u7528\u522B\u7684\u540D\u5B57\u5C31\u6E05\u4E0D\u6389\u4E86\uFF09\u3002`,
|
|
55240
|
+
"2. \u4E00\u6B65\u90FD\u522B\u8DF3\uFF1A\u771F\u7684\u5EFA\u3001\u771F\u7684\u88C5\u4F9D\u8D56\u3001\u771F\u7684\u53D1\u5E03\u4E0A\u7EBF\uFF0C\u628A\u516C\u7F51\u5730\u5740\u56DE\u7ED9\u6211\u3002",
|
|
55241
|
+
`3. **\u6700\u540E\u5355\u72EC\u8D77\u4E00\u884C**\uFF0C\u628A\u8FD9\u6B21\u81EA\u5DF1\u52A8\u624B\u88C5\u4E0A\u7684**\u547D\u4EE4**\u5217\u51FA\u6765\uFF1A\`${MISSING_MARKER} \u540D\u5B57, \u540D\u5B57\`\uFF1B`,
|
|
55242
|
+
` \u4E00\u6761\u90FD\u6CA1\u88C5\u5C31\u5199 \`${MISSING_MARKER} none\`\u3002`,
|
|
55243
|
+
"",
|
|
55244
|
+
"\u7B2C 3 \u6761\u662F\u8FD9\u6B21\u8DD1\u7684\u771F\u6B63\u76EE\u7684\u3002**\u4F60\u4E3A\u4E86\u8DD1\u901A\u81EA\u5DF1\u88C5\u7684\u547D\u4EE4\uFF0C\u6070\u6070\u5C31\u662F\u90E8\u7F72\u6E05\u5355\u6F0F\u6389\u7684\u90A3\u51E0\u6761**\u2014\u2014",
|
|
55245
|
+
"\u5178\u578B\u662F `command not found` \u4E4B\u540E\u4F60 apt / npm -g / curl \u88C5\u4E0A\u7684\u90A3\u4E9B\u3002\u4F60\u80FD\u81EA\u5DF1\u8865\u4E0A\u4E0D\u4EE3\u8868",
|
|
55246
|
+
"\u8FD9\u6B21\u8BD5\u88C5\u8FC7\u4E86\uFF1A\u5BB9\u5668\u6BCF\u6B21\u90FD\u662F\u65B0\u7684\uFF0C\u4E0B\u6B21\u7167\u6837\u7F3A\u3002",
|
|
55247
|
+
"",
|
|
55248
|
+
`**\u53EA\u5217\u547D\u4EE4\u540D**\uFF08\u88C5\u5B8C \`command -v <\u540D\u5B57>\` \u67E5\u5F97\u5230\u7684\u90A3\u79CD\uFF09\uFF0C\u4E00\u884C\u91CC\u7528\u9017\u53F7\u5206\u9694\uFF0C\u522B\u5199\u53E5\u5B50\u3002`,
|
|
55249
|
+
"\u8DD1\u7684\u65F6\u5019\u987A\u624B\u6539\u7684\u914D\u7F6E\u3001\u8981\u5148\u8DD1\u4E00\u6B21\u7684\u786E\u8BA4\u6B65\u9AA4\u3001\u52A0\u7684\u547D\u4EE4\u884C\u53C2\u6570\u2014\u2014\u8FD9\u4E9B\u90FD\u4E0D\u662F\u7F3A\u7684\u4F9D\u8D56\uFF0C",
|
|
55250
|
+
`**\u4E0D\u8981\u5199\u8FDB ${MISSING_MARKER}**\uFF0C\u653E\u6B63\u6587\u91CC\u8BF4\u5C31\u884C\u3002`,
|
|
55251
|
+
"",
|
|
55252
|
+
"\u7F3A\u51ED\u636E\u3001\u8DD1\u4E0D\u4E0B\u53BB\u7684\u65F6\u5019\u4E5F\u628A\u8BDD\u8BF4\u6E05\u695A\uFF1A\u7F3A\u7684\u662F\u54EA\u4E2A\u547D\u4EE4 / \u54EA\u4E2A\u51ED\u636E\u3001\u5728\u5E72\u54EA\u4E00\u6B65\u649E\u4E0A\u7684\u3002"
|
|
55253
|
+
].join("\n");
|
|
55254
|
+
}
|
|
55255
|
+
function buildTeardownPrompt(appName, workspace = "/workspace") {
|
|
55256
|
+
return [
|
|
55257
|
+
`\u3010\u8BD5\u88C5\u6536\u5C3E\u3011\u628A\u521A\u624D\u5EFA\u7684 \`${appName}\` \u62C6\u5E72\u51C0\u3002`,
|
|
55258
|
+
"",
|
|
55259
|
+
`1. \u7528 clawd-app-builder \u7684 removeProject \u5DE5\u5177\uFF08name=${appName}\uFF09\u2014\u2014\u4E91\u4E0A\u7684\u963F\u91CC\u4E91\u51ED\u636E\u53EA\u5728\u90A3\u4E2A`,
|
|
55260
|
+
" \u5DE5\u5177\u7684\u8FDB\u7A0B\u91CC\uFF0C\u4F60\u81EA\u5DF1\u6572 bash \u8DD1 remove-extension.sh \u4F1A\u62A5\u300C\u7F3A ALIBABA_CLOUD_ACCESS_KEY_ID\u300D\u3002",
|
|
55261
|
+
" \u811A\u672C\u5982\u679C\u8BA9\u4F60\u7528 supabase MCP \u8DD1\u51E0\u6761 DROP\uFF0C\u4E00\u8D77\u8DD1\u6389\u3002",
|
|
55262
|
+
// 工作区是持久卷(每「使用者 × 部署」一份),跨轮活着。留着上一轮的项目目录,
|
|
55263
|
+
// 下一轮的 createProject 会撞名、agent 会直接接着用它 —— 于是 scaffold 那一段
|
|
55264
|
+
// 根本不再跑,清单里漏掉的 scaffold 依赖(rsync 就是)永远暴露不出来。
|
|
55265
|
+
// 这条是真机第三轮跑出来的:那一轮「通过」了,而它压根没建过项目。
|
|
55266
|
+
`2. \u518D\u628A\u9879\u76EE\u76EE\u5F55\u5220\u6389\uFF1A\`rm -rf ${workspace}/projects/${appName}\`\u3002`,
|
|
55267
|
+
" \u5DE5\u4F5C\u533A\u662F\u6301\u4E45\u5377\u3001\u8DE8\u8F6E\u6D3B\u7740\uFF0C\u7559\u7740\u5B83\u4E0B\u4E00\u8F6E\u5C31\u4E0D\u4F1A\u91CD\u65B0\u5EFA\u9879\u76EE\uFF0C\u7B49\u4E8E\u5C11\u9A8C\u4E86\u4E00\u6574\u6BB5\u3002",
|
|
55268
|
+
"",
|
|
55269
|
+
"\u6700\u540E\u4E00\u53E5\u8BDD\u544A\u8BC9\u6211\uFF1A\u62C6\u5E72\u51C0\u4E86\u6CA1\u6709\uFF0C\u8FD8\u5269\u4EC0\u4E48\u3002"
|
|
55270
|
+
].join("\n");
|
|
55271
|
+
}
|
|
55272
|
+
var gap = (errorText, raw, suggest) => ({
|
|
55273
|
+
// 落单据的自由文本一律先过涂抹:这两段是 agent 的话和容器的原始输出,
|
|
55274
|
+
// 引到 `KEY=值` 那行是迟早的事(与扫描证据同一道,见 redact.ts)
|
|
55275
|
+
errorText: redactSecretValues(errorText),
|
|
55276
|
+
...raw ? { raw: redactSecretValues(raw.slice(-RAW_TAIL_CHARS)) } : {},
|
|
55277
|
+
...suggest ? { suggest } : {}
|
|
55278
|
+
});
|
|
55279
|
+
function missingFromAgentText(text) {
|
|
55280
|
+
const idx = text.lastIndexOf(MISSING_MARKER);
|
|
55281
|
+
if (idx === -1) return [];
|
|
55282
|
+
const line = text.slice(idx + MISSING_MARKER.length).split("\n")[0].trim();
|
|
55283
|
+
if (!line || /^(none|无|没有)[.。]?$/i.test(line)) return [];
|
|
55284
|
+
return line.replace(/[`*]/g, "").split(/[,,、]/).map((s) => s.trim()).filter((s) => s.length > 0 && s.length <= 40 && !/[\s((]/.test(s));
|
|
55285
|
+
}
|
|
55286
|
+
function gapsFromBuildOutput(r) {
|
|
55287
|
+
try {
|
|
55288
|
+
const parsed = JSON.parse(r.stdout.trim());
|
|
55289
|
+
if (parsed && parsed.ok === false && Array.isArray(parsed.gaps) && parsed.gaps.length > 0) {
|
|
55290
|
+
return parsed.gaps.map((g2) => gap(g2.errorText, g2.raw, g2.suggest));
|
|
55291
|
+
}
|
|
55292
|
+
} catch {
|
|
55293
|
+
}
|
|
55294
|
+
return [gap(
|
|
55295
|
+
`\u6784\u955C\u50CF\u6CA1\u6210\u529F\uFF08\u9000\u51FA\u7801 ${r.code}\uFF09\u3002`,
|
|
55296
|
+
`${r.stdout}
|
|
55297
|
+
${r.stderr}`
|
|
55298
|
+
)];
|
|
55299
|
+
}
|
|
55300
|
+
async function chat(deps, args) {
|
|
55301
|
+
const { cloudHost } = deps;
|
|
55302
|
+
const ctl = new AbortController();
|
|
55303
|
+
const timer = setTimeout(() => ctl.abort(), args.timeoutMs);
|
|
55304
|
+
const notes = [];
|
|
55305
|
+
let text = "";
|
|
55306
|
+
try {
|
|
55307
|
+
const res = await deps.fetchImpl(`${cloudHost.gatewayUrl}/v1/chat/completions`, {
|
|
55308
|
+
method: "POST",
|
|
55309
|
+
headers: {
|
|
55310
|
+
"content-type": "application/json",
|
|
55311
|
+
authorization: `Bearer ${cloudHost.gatewayApiKey}`
|
|
55312
|
+
},
|
|
55313
|
+
body: JSON.stringify({
|
|
55314
|
+
model: args.deployId,
|
|
55315
|
+
stream: true,
|
|
55316
|
+
user: args.conversation,
|
|
55317
|
+
messages: [{ role: "user", content: args.prompt }]
|
|
55318
|
+
}),
|
|
55319
|
+
signal: ctl.signal
|
|
55320
|
+
});
|
|
55321
|
+
if (!res.ok) {
|
|
55322
|
+
const body = await res.text().catch(() => "");
|
|
55323
|
+
return { ok: false, text: `gateway \u62D2\u4E86\u8FD9\u6B21\u6295\u5582\uFF08HTTP ${res.status}\uFF09\uFF1A${body.slice(0, 500)}`, notes };
|
|
55324
|
+
}
|
|
55325
|
+
for await (const line of sseLines(res)) {
|
|
55326
|
+
if (line.startsWith(":")) {
|
|
55327
|
+
const note = line.slice(1).trim();
|
|
55328
|
+
if (note && !note.startsWith("clawd-gateway heartbeat")) {
|
|
55329
|
+
notes.push(note);
|
|
55330
|
+
deps.onStage(redactSecretValues(`\u8BD5\u88C5\u4E2D\uFF1A${note}`));
|
|
55331
|
+
}
|
|
55332
|
+
continue;
|
|
55333
|
+
}
|
|
55334
|
+
if (!line.startsWith("data:")) continue;
|
|
55335
|
+
const payload = line.slice(5).trim();
|
|
55336
|
+
if (payload === "[DONE]") break;
|
|
55337
|
+
try {
|
|
55338
|
+
const frame = JSON.parse(payload);
|
|
55339
|
+
text += frame.choices?.[0]?.delta?.content ?? "";
|
|
55340
|
+
} catch {
|
|
55341
|
+
}
|
|
55342
|
+
}
|
|
55343
|
+
} catch (err) {
|
|
55344
|
+
const aborted = err.name === "AbortError";
|
|
55345
|
+
return {
|
|
55346
|
+
ok: false,
|
|
55347
|
+
notes,
|
|
55348
|
+
text: aborted ? `\u7B49\u4E86 ${Math.round(args.timeoutMs / 6e4)} \u5206\u949F\uFF0C\u5BB9\u5668\u90A3\u8FB9\u8FD8\u6CA1\u8DD1\u5B8C` : `\u8DDF gateway \u8BF4\u4E0D\u4E0A\u8BDD\uFF1A${String(err)}`
|
|
55349
|
+
};
|
|
55350
|
+
} finally {
|
|
55351
|
+
clearTimeout(timer);
|
|
55352
|
+
}
|
|
55353
|
+
const failed = /\[gateway\]/.test(text);
|
|
55354
|
+
return { ok: !failed, text, notes };
|
|
55355
|
+
}
|
|
55356
|
+
async function* sseLines(res) {
|
|
55357
|
+
const reader = res.body?.getReader();
|
|
55358
|
+
if (!reader) return;
|
|
55359
|
+
const decoder = new TextDecoder();
|
|
55360
|
+
let buf = "";
|
|
55361
|
+
for (; ; ) {
|
|
55362
|
+
const { done, value } = await reader.read();
|
|
55363
|
+
if (done) break;
|
|
55364
|
+
buf += decoder.decode(value, { stream: true });
|
|
55365
|
+
let idx = buf.indexOf("\n");
|
|
55366
|
+
while (idx >= 0) {
|
|
55367
|
+
yield buf.slice(0, idx).trimEnd();
|
|
55368
|
+
buf = buf.slice(idx + 1);
|
|
55369
|
+
idx = buf.indexOf("\n");
|
|
55370
|
+
}
|
|
55371
|
+
}
|
|
55372
|
+
if (buf.trim()) yield buf.trim();
|
|
55373
|
+
}
|
|
55374
|
+
async function gatewayAdmin(deps, path98, body) {
|
|
55375
|
+
const res = await deps.fetchImpl(`${deps.cloudHost.gatewayUrl}${path98}`, {
|
|
55376
|
+
method: "POST",
|
|
55377
|
+
headers: {
|
|
55378
|
+
"content-type": "application/json",
|
|
55379
|
+
authorization: `Bearer ${deps.cloudHost.gatewayAdminKey}`
|
|
55380
|
+
},
|
|
55381
|
+
body: JSON.stringify(body),
|
|
55382
|
+
// 流水线其余每一步都有界(构建/推送有 timer、投喂有 AbortController),
|
|
55383
|
+
// 只有这两个 fetch 裸 await 的话,gateway 那头 TCP 挂住就没人救得了它:
|
|
55384
|
+
// 单据永久停在 trialing(trial 拒 trialing、启动对账只在启动时跑),得重启 daemon 才出得来。
|
|
55385
|
+
signal: AbortSignal.timeout(GATEWAY_ADMIN_TIMEOUT_MS)
|
|
55386
|
+
});
|
|
55387
|
+
const text = await res.text();
|
|
55388
|
+
if (!res.ok) throw new Error(`gateway ${path98} \u56DE\u4E86 HTTP ${res.status}\uFF1A${text.slice(0, 300)}`);
|
|
55389
|
+
try {
|
|
55390
|
+
return JSON.parse(text);
|
|
55391
|
+
} catch {
|
|
55392
|
+
throw new Error(`gateway ${path98} \u56DE\u7684\u4E0D\u662F JSON\uFF1A${text.slice(0, 300)}`);
|
|
55393
|
+
}
|
|
55394
|
+
}
|
|
55395
|
+
async function registerOfficialDeployment(deps, receipt, deployerSecrets) {
|
|
55396
|
+
const res = await gatewayAdmin(deps, "/admin/deployments", {
|
|
55397
|
+
deployId: receipt.deployId,
|
|
55398
|
+
personaId: receipt.personaId,
|
|
55399
|
+
image: receipt.trialImage,
|
|
55400
|
+
kind: "official",
|
|
55401
|
+
secrets: deployerSecrets,
|
|
55402
|
+
userSecrets: userSecretsOf(receipt)
|
|
55403
|
+
});
|
|
55404
|
+
const service = res.service ?? {};
|
|
55405
|
+
if (!service.deviceId || !service.publicUrl) {
|
|
55406
|
+
throw new Error(`gateway \u767B\u8BB0\u6210\u529F\u4E86\uFF0C\u4F46\u6CA1\u56DE\u670D\u52A1\u8EAB\u4EFD\uFF08deviceId / publicUrl\uFF09\uFF1A${JSON.stringify(res).slice(0, 300)}`);
|
|
55407
|
+
}
|
|
55408
|
+
return {
|
|
55409
|
+
gatewayUrl: deps.cloudHost.gatewayUrl,
|
|
55410
|
+
serviceDeviceId: service.deviceId,
|
|
55411
|
+
publicDirectory: Boolean(service.isPublic),
|
|
55412
|
+
image: receipt.trialImage,
|
|
55413
|
+
userSecrets: userSecretsOf(receipt).map((s) => s.name),
|
|
55414
|
+
deployedAt: deps.now()
|
|
55415
|
+
};
|
|
55416
|
+
}
|
|
55417
|
+
async function runTrial(deps, args) {
|
|
55418
|
+
const { receipt, round } = args;
|
|
55419
|
+
const { cloudHost } = deps;
|
|
55420
|
+
const manifest = receipt.manifest;
|
|
55421
|
+
const stamp = trialStamp(deps.now());
|
|
55422
|
+
const trialId = trialDeployId(receipt.deployId, round, stamp);
|
|
55423
|
+
const image = trialImageTag(cloudHost.imageRepo, receipt.deployId, round, stamp);
|
|
55424
|
+
const appName = trialAppName(receipt.deployId);
|
|
55425
|
+
const deadline = deps.now() + cloudHost.trialTimeoutMs;
|
|
55426
|
+
const left = () => Math.max(3e4, deadline - deps.now());
|
|
55427
|
+
deps.onStage("\u5728\u6309\u6E05\u5355\u6784\u955C\u50CF");
|
|
55428
|
+
const manifestFile = import_node_path33.default.join(import_node_os8.default.tmpdir(), `clawd-trial-${receipt.deployId}-t${round}-${stamp}.json`);
|
|
55429
|
+
let built;
|
|
55430
|
+
try {
|
|
55431
|
+
await import_promises7.default.writeFile(manifestFile, JSON.stringify({ manifest }, null, 2), { mode: 384 });
|
|
55432
|
+
built = await deps.runNode(
|
|
55433
|
+
`${cloudHost.provisionDir}/build-image.mjs`,
|
|
55434
|
+
["--manifest", manifestFile, "--tag", image, "--platform", "linux/amd64"],
|
|
55435
|
+
{ timeoutMs: left() }
|
|
55436
|
+
);
|
|
55437
|
+
await import_promises7.default.rm(manifestFile, { force: true });
|
|
55438
|
+
} catch (err) {
|
|
55439
|
+
return { ok: false, spent: false, gaps: [gap(`\u6784\u955C\u50CF\u8FD9\u4E00\u6B65\u8D77\u4E0D\u6765\uFF1A${String(err)}`)] };
|
|
55440
|
+
}
|
|
55441
|
+
if (built.code !== 0) return { ok: false, spent: false, gaps: gapsFromBuildOutput(built) };
|
|
55442
|
+
deps.onStage("\u628A\u955C\u50CF\u63A8\u5230\u4E91\u4E0A\u90A3\u53F0\u673A\u5668");
|
|
55443
|
+
const pushed = await deps.runNode(
|
|
55444
|
+
`${cloudHost.provisionDir}/push-to-k3s.mjs`,
|
|
55445
|
+
["--host", cloudHost.k3sHost, "--key", cloudHost.k3sKeyPath, "--image", image],
|
|
55446
|
+
{ timeoutMs: left() }
|
|
55447
|
+
);
|
|
55448
|
+
if (pushed.code !== 0) {
|
|
55449
|
+
return { ok: false, spent: false, gaps: [gap(`\u955C\u50CF\u63A8\u4E0D\u4E0A\u53BB\uFF08\u9000\u51FA\u7801 ${pushed.code}\uFF09\u3002`, `${pushed.stdout}
|
|
55450
|
+
${pushed.stderr}`)] };
|
|
55451
|
+
}
|
|
55452
|
+
deps.onStage("\u5728\u4E91\u4E0A\u767B\u8BB0\u8FD9\u6B21\u8BD5\u88C5");
|
|
55453
|
+
try {
|
|
55454
|
+
await gatewayAdmin(deps, "/admin/deployments", {
|
|
55455
|
+
deployId: trialId,
|
|
55456
|
+
personaId: receipt.personaId,
|
|
55457
|
+
image,
|
|
55458
|
+
kind: "trial",
|
|
55459
|
+
secrets: args.secretTable,
|
|
55460
|
+
userSecrets: []
|
|
55461
|
+
});
|
|
55462
|
+
} catch (err) {
|
|
55463
|
+
return { ok: false, spent: false, gaps: [gap(`gateway \u4E0D\u6536\u8FD9\u4EFD\u8BD5\u88C5\u767B\u8BB0\uFF1A${String(err)}`)] };
|
|
55464
|
+
}
|
|
55465
|
+
try {
|
|
55466
|
+
deps.onStage("\u5192\u70DF\u4EFB\u52A1\u5DF2\u7ECF\u6295\u7ED9\u5B83\u4E86");
|
|
55467
|
+
const smoke = await chat(deps, {
|
|
55468
|
+
deployId: trialId,
|
|
55469
|
+
conversation: trialConversation(receipt.deployId, round, stamp),
|
|
55470
|
+
prompt: buildSmokePrompt(receipt.smokeTask ?? "\u5EFA\u4E00\u4E2A\u6700\u5C0F\u7684\u5E94\u7528\u5E76\u53D1\u5E03\u4E0A\u7EBF\uFF0C\u628A\u516C\u7F51\u5730\u5740\u56DE\u7ED9\u6211", appName),
|
|
55471
|
+
timeoutMs: left()
|
|
55472
|
+
});
|
|
55473
|
+
deps.onStage("\u8BA9\u5B83\u628A\u8BD5\u88C5\u5EFA\u51FA\u6765\u7684\u4E1C\u897F\u62C6\u6389");
|
|
55474
|
+
const teardown = await chat(deps, {
|
|
55475
|
+
deployId: trialId,
|
|
55476
|
+
conversation: trialConversation(receipt.deployId, round, stamp),
|
|
55477
|
+
prompt: buildTeardownPrompt(appName),
|
|
55478
|
+
timeoutMs: Math.min(left(), 15 * 6e4)
|
|
55479
|
+
});
|
|
55480
|
+
if (!smoke.ok) {
|
|
55481
|
+
return {
|
|
55482
|
+
ok: false,
|
|
55483
|
+
spent: true,
|
|
55484
|
+
gaps: [
|
|
55485
|
+
gap(smoke.text.trim() || "\u5BB9\u5668\u91CC\u90A3\u4E2A persona \u6CA1\u8BF4\u6E05\u695A\u4E3A\u4EC0\u4E48\u6CA1\u8DD1\u5B8C", smoke.notes.slice(-20).join("\n")),
|
|
55486
|
+
...teardown.ok ? [] : [gap(`\u987A\u5E26\uFF1A\u8BD5\u88C5\u4EA7\u7269\u6CA1\u62C6\u5E72\u51C0\u2014\u2014${teardown.text.trim()}`)]
|
|
55487
|
+
]
|
|
55488
|
+
};
|
|
55489
|
+
}
|
|
55490
|
+
if (!teardown.ok) {
|
|
55491
|
+
return { ok: false, spent: true, gaps: [gap(`\u5E94\u7528\u5EFA\u51FA\u6765\u5E76\u53D1\u5E03\u6210\u529F\u4E86\uFF0C\u4F46\u62C6\u4E0D\u5E72\u51C0\uFF1A${teardown.text.trim()}`, teardown.notes.slice(-20).join("\n"))] };
|
|
55492
|
+
}
|
|
55493
|
+
const missing = missingFromAgentText(smoke.text);
|
|
55494
|
+
if (missing.length > 0) {
|
|
55495
|
+
return {
|
|
55496
|
+
ok: false,
|
|
55497
|
+
spent: true,
|
|
55498
|
+
gaps: missing.map((name) => gap(
|
|
55499
|
+
`\u5BB9\u5668\u91CC\u6CA1\u6709 \`${name}\`\uFF0C\u662F\u5B83\u81EA\u5DF1\u52A8\u624B\u8865\u4E0A\u624D\u8DD1\u4E0B\u53BB\u7684\u2014\u2014\u6E05\u5355\u91CC\u6F0F\u4E86\u8FD9\u6761\uFF0C\u4E0B\u4E00\u4E2A\u5BB9\u5668\u7167\u6837\u7F3A\u3002`,
|
|
55500
|
+
smoke.text.slice(-RAW_TAIL_CHARS),
|
|
55501
|
+
`cli:${name}`
|
|
55502
|
+
))
|
|
55503
|
+
};
|
|
55504
|
+
}
|
|
55505
|
+
deps.logger?.info("deploy.trial.passed", { deployId: receipt.deployId, round, image });
|
|
55506
|
+
const url = /https?:\/\/[^\s)"',。]+/.exec(smoke.text)?.[0];
|
|
55507
|
+
return { ok: true, image, ...url ? { publicUrl: url } : {} };
|
|
55508
|
+
} finally {
|
|
55509
|
+
deps.onStage("\u6536\u5C3E\uFF1A\u64A4\u9500\u8FD9\u6B21\u8BD5\u88C5\u7684\u767B\u8BB0");
|
|
55510
|
+
await gatewayAdmin(deps, "/admin/deployments:remove", { deployId: trialId }).catch((err) => {
|
|
55511
|
+
deps.logger?.warn("deploy.trial.unregister-failed", { deployId: receipt.deployId, error: String(err) });
|
|
55512
|
+
});
|
|
55513
|
+
}
|
|
55514
|
+
}
|
|
55515
|
+
|
|
55516
|
+
// src/deploy/run-node.ts
|
|
55517
|
+
var import_node_child_process8 = require("child_process");
|
|
55518
|
+
async function runNodeScript(script, args, timeoutMs) {
|
|
55519
|
+
return await new Promise((resolve9, reject) => {
|
|
55520
|
+
const child = (0, import_node_child_process8.spawn)(process.execPath, [script, ...args], { stdio: ["ignore", "pipe", "pipe"] });
|
|
55521
|
+
let stdout = "";
|
|
55522
|
+
let stderr = "";
|
|
55523
|
+
child.stdout.on("data", (d) => {
|
|
55524
|
+
stdout += d.toString("utf8");
|
|
55525
|
+
});
|
|
55526
|
+
child.stderr.on("data", (d) => {
|
|
55527
|
+
stderr += d.toString("utf8");
|
|
55528
|
+
});
|
|
55529
|
+
const timer = setTimeout(() => {
|
|
55530
|
+
child.kill("SIGKILL");
|
|
55531
|
+
stderr += `
|
|
55532
|
+
[clawd] \u8D85\u65F6\uFF08>${Math.round(timeoutMs / 1e3)}s\uFF09\uFF0C\u5DF2\u7ECF\u628A\u5B83\u6390\u4E86
|
|
55533
|
+
`;
|
|
55534
|
+
}, timeoutMs);
|
|
55535
|
+
child.on("error", (err) => {
|
|
55536
|
+
clearTimeout(timer);
|
|
55537
|
+
reject(new Error(`\u8D77\u4E0D\u6765 ${script}\uFF1A${err.message}`));
|
|
55538
|
+
});
|
|
55539
|
+
child.on("close", (code) => {
|
|
55540
|
+
clearTimeout(timer);
|
|
55541
|
+
resolve9({ code, stdout, stderr });
|
|
55542
|
+
});
|
|
55543
|
+
});
|
|
55544
|
+
}
|
|
55545
|
+
|
|
54997
55546
|
// src/deploy/scan-task.ts
|
|
54998
55547
|
var BUTLER_PERSONA_ID = "persona-clawd-butler";
|
|
54999
55548
|
var SCANNABLE_ASSETS = ["deploy-kit"];
|
|
@@ -55011,6 +55560,17 @@ function reconcileInterruptedScans(deps) {
|
|
|
55011
55560
|
}
|
|
55012
55561
|
return stale.map((r) => r.deployId);
|
|
55013
55562
|
}
|
|
55563
|
+
function reconcileInterruptedTrials(deps) {
|
|
55564
|
+
const stale = deps.list().filter((r) => r.status === "trialing");
|
|
55565
|
+
for (const r of stale) {
|
|
55566
|
+
deps.update(r.deployId, {
|
|
55567
|
+
status: "failed",
|
|
55568
|
+
trialStage: void 0,
|
|
55569
|
+
gaps: [{ errorText: "daemon \u91CD\u542F\uFF0C\u8FD9\u4E00\u8F6E\u8BD5\u88C5\u88AB\u6253\u65AD\u4E86\u2014\u2014\u6CA1\u7ED3\u8BBA\uFF0C\u91CD\u8DD1\u4E00\u6B21\u5373\u53EF\u3002" }]
|
|
55570
|
+
});
|
|
55571
|
+
}
|
|
55572
|
+
return stale.map((r) => r.deployId);
|
|
55573
|
+
}
|
|
55014
55574
|
|
|
55015
55575
|
// src/handlers/lark-bot.ts
|
|
55016
55576
|
init_protocol();
|
|
@@ -55400,9 +55960,9 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
55400
55960
|
|
|
55401
55961
|
// src/lark-bot-connector/binding-store.ts
|
|
55402
55962
|
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
55403
|
-
var
|
|
55963
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
55404
55964
|
function createLarkBotBindingStore(personaRoot) {
|
|
55405
|
-
const filePath = (personaId2) =>
|
|
55965
|
+
const filePath = (personaId2) => import_node_path34.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
55406
55966
|
const read = (personaId2) => {
|
|
55407
55967
|
const file = filePath(personaId2);
|
|
55408
55968
|
if (!import_node_fs28.default.existsSync(file)) return null;
|
|
@@ -55416,7 +55976,7 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
55416
55976
|
};
|
|
55417
55977
|
const write = (personaId2, meta) => {
|
|
55418
55978
|
const file = filePath(personaId2);
|
|
55419
|
-
import_node_fs28.default.mkdirSync(
|
|
55979
|
+
import_node_fs28.default.mkdirSync(import_node_path34.default.dirname(file), { recursive: true });
|
|
55420
55980
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
55421
55981
|
import_node_fs28.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
55422
55982
|
import_node_fs28.default.renameSync(tmp, file);
|
|
@@ -55584,7 +56144,7 @@ function createLarkBotCloudClient(opts) {
|
|
|
55584
56144
|
|
|
55585
56145
|
// src/lark-bot-connector/chat-router.ts
|
|
55586
56146
|
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
55587
|
-
var
|
|
56147
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
55588
56148
|
init_protocol();
|
|
55589
56149
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
55590
56150
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -55651,7 +56211,7 @@ function createLarkChatRouter(deps) {
|
|
|
55651
56211
|
}
|
|
55652
56212
|
const dir = deps.mediaRootFor(env.chatId);
|
|
55653
56213
|
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
55654
|
-
const p2 =
|
|
56214
|
+
const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
|
|
55655
56215
|
import_node_fs29.default.writeFileSync(p2, r.data);
|
|
55656
56216
|
lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
55657
56217
|
} catch (err) {
|
|
@@ -55674,7 +56234,7 @@ function createLarkChatRouter(deps) {
|
|
|
55674
56234
|
}
|
|
55675
56235
|
const dir = deps.mediaRootFor(env.chatId);
|
|
55676
56236
|
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
55677
|
-
const p2 =
|
|
56237
|
+
const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
55678
56238
|
import_node_fs29.default.writeFileSync(p2, r.data);
|
|
55679
56239
|
lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
55680
56240
|
} catch (err) {
|
|
@@ -56764,7 +57324,7 @@ var CodexHistoryReader = class {
|
|
|
56764
57324
|
};
|
|
56765
57325
|
|
|
56766
57326
|
// src/tools/codex-skills.ts
|
|
56767
|
-
var
|
|
57327
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
56768
57328
|
function str3(v2) {
|
|
56769
57329
|
return typeof v2 === "string" ? v2 : void 0;
|
|
56770
57330
|
}
|
|
@@ -56779,13 +57339,13 @@ function mapSkillsListResponse(res) {
|
|
|
56779
57339
|
const r = s ?? {};
|
|
56780
57340
|
const name = str3(r.name);
|
|
56781
57341
|
if (!name) continue;
|
|
56782
|
-
const
|
|
57342
|
+
const path98 = str3(r.path);
|
|
56783
57343
|
const description = str3(r.description);
|
|
56784
57344
|
const isPlugin = name.includes(":");
|
|
56785
57345
|
out.push({
|
|
56786
57346
|
name,
|
|
56787
57347
|
source: isPlugin ? "plugin" : "project",
|
|
56788
|
-
...
|
|
57348
|
+
...path98 ? { path: path98 } : {},
|
|
56789
57349
|
...description ? { description } : {},
|
|
56790
57350
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
56791
57351
|
});
|
|
@@ -56801,14 +57361,14 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
56801
57361
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
56802
57362
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
56803
57363
|
beforeRequest: (client) => {
|
|
56804
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
57364
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path36.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
56805
57365
|
}
|
|
56806
57366
|
});
|
|
56807
57367
|
return mapSkillsListResponse(res);
|
|
56808
57368
|
}
|
|
56809
57369
|
|
|
56810
57370
|
// src/tools/codex-turn-context.ts
|
|
56811
|
-
var
|
|
57371
|
+
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
56812
57372
|
function parseTurnContextFromRollout(raw) {
|
|
56813
57373
|
const lines = raw.split("\n");
|
|
56814
57374
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -56843,7 +57403,7 @@ async function readCodexTurnContext(args, deps = {}) {
|
|
|
56843
57403
|
);
|
|
56844
57404
|
const rolloutPath = str4(rec3(res?.thread)?.path);
|
|
56845
57405
|
if (!rolloutPath) return null;
|
|
56846
|
-
return parseTurnContextFromRollout(await
|
|
57406
|
+
return parseTurnContextFromRollout(await import_promises8.default.readFile(rolloutPath, "utf8"));
|
|
56847
57407
|
}
|
|
56848
57408
|
function createCodexResolvedMetaHydrator(deps) {
|
|
56849
57409
|
const fetchedThreadIds = /* @__PURE__ */ new Set();
|
|
@@ -56887,15 +57447,15 @@ function str4(v2) {
|
|
|
56887
57447
|
|
|
56888
57448
|
// src/workspace/browser.ts
|
|
56889
57449
|
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
56890
|
-
var
|
|
56891
|
-
var
|
|
57450
|
+
var import_node_os9 = __toESM(require("os"), 1);
|
|
57451
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56892
57452
|
init_protocol();
|
|
56893
57453
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
56894
57454
|
function resolveInsideCwd(cwd, subpath) {
|
|
56895
|
-
const absCwd =
|
|
56896
|
-
const joined =
|
|
56897
|
-
const rel =
|
|
56898
|
-
if (rel.startsWith("..") ||
|
|
57455
|
+
const absCwd = import_node_path37.default.resolve(cwd);
|
|
57456
|
+
const joined = import_node_path37.default.resolve(absCwd, subpath ?? ".");
|
|
57457
|
+
const rel = import_node_path37.default.relative(absCwd, joined);
|
|
57458
|
+
if (rel.startsWith("..") || import_node_path37.default.isAbsolute(rel)) {
|
|
56899
57459
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
56900
57460
|
}
|
|
56901
57461
|
return joined;
|
|
@@ -56913,7 +57473,7 @@ function ensureCwd(cwd) {
|
|
|
56913
57473
|
}
|
|
56914
57474
|
var WorkspaceBrowser = class {
|
|
56915
57475
|
list(args) {
|
|
56916
|
-
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd :
|
|
57476
|
+
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os9.default.homedir();
|
|
56917
57477
|
ensureCwd(cwd);
|
|
56918
57478
|
const full = resolveInsideCwd(cwd, args.path);
|
|
56919
57479
|
const dirents = import_node_fs30.default.readdirSync(full, { withFileTypes: true });
|
|
@@ -56926,7 +57486,7 @@ var WorkspaceBrowser = class {
|
|
|
56926
57486
|
mtime: ""
|
|
56927
57487
|
};
|
|
56928
57488
|
try {
|
|
56929
|
-
const st = import_node_fs30.default.statSync(
|
|
57489
|
+
const st = import_node_fs30.default.statSync(import_node_path37.default.join(full, d.name));
|
|
56930
57490
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
56931
57491
|
if (d.isFile()) entry.size = st.size;
|
|
56932
57492
|
} catch {
|
|
@@ -56972,8 +57532,8 @@ var WorkspaceBrowser = class {
|
|
|
56972
57532
|
|
|
56973
57533
|
// src/skills/agents-scanner.ts
|
|
56974
57534
|
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
56975
|
-
var
|
|
56976
|
-
var
|
|
57535
|
+
var import_node_os10 = __toESM(require("os"), 1);
|
|
57536
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
56977
57537
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
56978
57538
|
function isDirLikeSync2(p2) {
|
|
56979
57539
|
try {
|
|
@@ -57011,10 +57571,10 @@ function scanAgentsDir(dir, source, seen, out) {
|
|
|
57011
57571
|
}
|
|
57012
57572
|
for (const ent of entries) {
|
|
57013
57573
|
if (!ent.name.endsWith(".md")) continue;
|
|
57014
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
57574
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path38.default.join(dir, ent.name)))) {
|
|
57015
57575
|
continue;
|
|
57016
57576
|
}
|
|
57017
|
-
const filePath =
|
|
57577
|
+
const filePath = import_node_path38.default.join(dir, ent.name);
|
|
57018
57578
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
57019
57579
|
if (seen.has(baseName)) continue;
|
|
57020
57580
|
seen.add(baseName);
|
|
@@ -57037,7 +57597,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
57037
57597
|
return;
|
|
57038
57598
|
}
|
|
57039
57599
|
for (const ent of entries) {
|
|
57040
|
-
const childPath =
|
|
57600
|
+
const childPath = import_node_path38.default.join(dir, ent.name);
|
|
57041
57601
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
57042
57602
|
walk2(childPath, [...namespaces, ent.name]);
|
|
57043
57603
|
continue;
|
|
@@ -57062,9 +57622,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
57062
57622
|
walk2(root, []);
|
|
57063
57623
|
}
|
|
57064
57624
|
function readInstalledPlugins2(home) {
|
|
57065
|
-
const pluginsDir =
|
|
57066
|
-
const v2 =
|
|
57067
|
-
const v1 =
|
|
57625
|
+
const pluginsDir = import_node_path38.default.join(home, ".claude", "plugins");
|
|
57626
|
+
const v2 = import_node_path38.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
57627
|
+
const v1 = import_node_path38.default.join(pluginsDir, "installed_plugins.json");
|
|
57068
57628
|
let raw = null;
|
|
57069
57629
|
for (const candidate of [v2, v1]) {
|
|
57070
57630
|
try {
|
|
@@ -57093,19 +57653,19 @@ function readInstalledPlugins2(home) {
|
|
|
57093
57653
|
return out;
|
|
57094
57654
|
}
|
|
57095
57655
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
57096
|
-
let cur =
|
|
57097
|
-
const fsRoot =
|
|
57656
|
+
let cur = import_node_path38.default.resolve(startCwd);
|
|
57657
|
+
const fsRoot = import_node_path38.default.parse(cur).root;
|
|
57098
57658
|
while (true) {
|
|
57099
|
-
scanAgentsDir(
|
|
57659
|
+
scanAgentsDir(import_node_path38.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
57100
57660
|
let hasGit = false;
|
|
57101
57661
|
try {
|
|
57102
|
-
hasGit = import_node_fs31.default.existsSync(
|
|
57662
|
+
hasGit = import_node_fs31.default.existsSync(import_node_path38.default.join(cur, ".git"));
|
|
57103
57663
|
} catch {
|
|
57104
57664
|
}
|
|
57105
57665
|
if (hasGit) return;
|
|
57106
57666
|
if (cur === home) return;
|
|
57107
57667
|
if (cur === fsRoot) return;
|
|
57108
|
-
const parent =
|
|
57668
|
+
const parent = import_node_path38.default.dirname(cur);
|
|
57109
57669
|
if (parent === cur) return;
|
|
57110
57670
|
cur = parent;
|
|
57111
57671
|
}
|
|
@@ -57115,7 +57675,7 @@ var AgentsScanner = class {
|
|
|
57115
57675
|
extraPluginRoots;
|
|
57116
57676
|
policyDir;
|
|
57117
57677
|
constructor(opts = {}) {
|
|
57118
|
-
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ??
|
|
57678
|
+
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os10.default.homedir();
|
|
57119
57679
|
this.extraPluginRoots = opts.extraPluginRoots ?? [];
|
|
57120
57680
|
if (opts.policyDir !== void 0) {
|
|
57121
57681
|
this.policyDir = opts.policyDir;
|
|
@@ -57140,7 +57700,7 @@ var AgentsScanner = class {
|
|
|
57140
57700
|
}
|
|
57141
57701
|
const fsBlock = [];
|
|
57142
57702
|
scanAgentsDir(
|
|
57143
|
-
|
|
57703
|
+
import_node_path38.default.join(this.home, ".claude", "agents"),
|
|
57144
57704
|
"global",
|
|
57145
57705
|
seen,
|
|
57146
57706
|
fsBlock
|
|
@@ -57154,7 +57714,7 @@ var AgentsScanner = class {
|
|
|
57154
57714
|
...this.extraPluginRoots
|
|
57155
57715
|
];
|
|
57156
57716
|
for (const { name, root } of plugins) {
|
|
57157
|
-
const agentsRoot =
|
|
57717
|
+
const agentsRoot = import_node_path38.default.join(root, "agents");
|
|
57158
57718
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
57159
57719
|
}
|
|
57160
57720
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -57163,27 +57723,27 @@ var AgentsScanner = class {
|
|
|
57163
57723
|
|
|
57164
57724
|
// src/observer/session-observer.ts
|
|
57165
57725
|
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
57166
|
-
var
|
|
57167
|
-
var
|
|
57726
|
+
var import_node_os12 = __toESM(require("os"), 1);
|
|
57727
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
57168
57728
|
init_claude_history();
|
|
57169
57729
|
|
|
57170
57730
|
// src/observer/subagent-meta-observer.ts
|
|
57171
57731
|
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
57172
|
-
var
|
|
57173
|
-
var
|
|
57732
|
+
var import_node_os11 = __toESM(require("os"), 1);
|
|
57733
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
57174
57734
|
init_claude_history();
|
|
57175
57735
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
57176
57736
|
var SubagentMetaObserver = class {
|
|
57177
57737
|
constructor(opts) {
|
|
57178
57738
|
this.opts = opts;
|
|
57179
|
-
this.home = opts.home ??
|
|
57739
|
+
this.home = opts.home ?? import_node_os11.default.homedir();
|
|
57180
57740
|
}
|
|
57181
57741
|
opts;
|
|
57182
57742
|
home;
|
|
57183
57743
|
watches = /* @__PURE__ */ new Map();
|
|
57184
57744
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
57185
57745
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
57186
|
-
return
|
|
57746
|
+
return import_node_path39.default.join(
|
|
57187
57747
|
this.home,
|
|
57188
57748
|
".claude",
|
|
57189
57749
|
"projects",
|
|
@@ -57239,7 +57799,7 @@ var SubagentMetaObserver = class {
|
|
|
57239
57799
|
if (!m2) return;
|
|
57240
57800
|
const agentId = m2[1];
|
|
57241
57801
|
if (w2.emitted.has(agentId)) return;
|
|
57242
|
-
const file =
|
|
57802
|
+
const file = import_node_path39.default.join(w2.dirPath, name);
|
|
57243
57803
|
let raw;
|
|
57244
57804
|
try {
|
|
57245
57805
|
raw = import_node_fs32.default.readFileSync(file, "utf8");
|
|
@@ -57287,7 +57847,7 @@ var SubagentMetaObserver = class {
|
|
|
57287
57847
|
var SessionObserver = class {
|
|
57288
57848
|
constructor(opts) {
|
|
57289
57849
|
this.opts = opts;
|
|
57290
|
-
this.home = opts.home ??
|
|
57850
|
+
this.home = opts.home ?? import_node_os12.default.homedir();
|
|
57291
57851
|
this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
|
|
57292
57852
|
}
|
|
57293
57853
|
opts;
|
|
@@ -57299,7 +57859,7 @@ var SessionObserver = class {
|
|
|
57299
57859
|
metaObserver;
|
|
57300
57860
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
57301
57861
|
if (override) return override;
|
|
57302
|
-
return
|
|
57862
|
+
return import_node_path40.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
57303
57863
|
}
|
|
57304
57864
|
start(args) {
|
|
57305
57865
|
this.stop(args.sessionId);
|
|
@@ -57325,10 +57885,10 @@ var SessionObserver = class {
|
|
|
57325
57885
|
lastDeriveMs: 0
|
|
57326
57886
|
};
|
|
57327
57887
|
try {
|
|
57328
|
-
import_node_fs33.default.mkdirSync(
|
|
57888
|
+
import_node_fs33.default.mkdirSync(import_node_path40.default.dirname(filePath), { recursive: true });
|
|
57329
57889
|
} catch {
|
|
57330
57890
|
}
|
|
57331
|
-
w2.watcher = import_node_fs33.default.watch(
|
|
57891
|
+
w2.watcher = import_node_fs33.default.watch(import_node_path40.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
57332
57892
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
57333
57893
|
this.poll(w2);
|
|
57334
57894
|
});
|
|
@@ -57425,7 +57985,7 @@ var SessionObserver = class {
|
|
|
57425
57985
|
const now = Date.now();
|
|
57426
57986
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
57427
57987
|
w2.lastRelocateScanMs = now;
|
|
57428
|
-
const projectsRoot =
|
|
57988
|
+
const projectsRoot = import_node_path40.default.join(this.home, ".claude", "projects");
|
|
57429
57989
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
57430
57990
|
if (!found || found === w2.filePath) return;
|
|
57431
57991
|
try {
|
|
@@ -57434,7 +57994,7 @@ var SessionObserver = class {
|
|
|
57434
57994
|
}
|
|
57435
57995
|
w2.filePath = found;
|
|
57436
57996
|
try {
|
|
57437
|
-
w2.watcher = import_node_fs33.default.watch(
|
|
57997
|
+
w2.watcher = import_node_fs33.default.watch(import_node_path40.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
57438
57998
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
57439
57999
|
this.poll(w2);
|
|
57440
58000
|
});
|
|
@@ -57554,10 +58114,10 @@ function listRegistered() {
|
|
|
57554
58114
|
}
|
|
57555
58115
|
|
|
57556
58116
|
// src/tools/title-generator.ts
|
|
57557
|
-
var
|
|
58117
|
+
var import_node_child_process9 = require("child_process");
|
|
57558
58118
|
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
57559
|
-
var
|
|
57560
|
-
var
|
|
58119
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
58120
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
57561
58121
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
57562
58122
|
var TITLE_MODEL_BY_TOOL = {
|
|
57563
58123
|
claude: "haiku",
|
|
@@ -57628,7 +58188,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
57628
58188
|
if (!text) return null;
|
|
57629
58189
|
let workDir;
|
|
57630
58190
|
try {
|
|
57631
|
-
workDir = import_node_fs34.default.mkdtempSync(
|
|
58191
|
+
workDir = import_node_fs34.default.mkdtempSync(import_node_path41.default.join(import_node_os13.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
57632
58192
|
} catch {
|
|
57633
58193
|
return null;
|
|
57634
58194
|
}
|
|
@@ -57638,8 +58198,8 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
57638
58198
|
} catch {
|
|
57639
58199
|
}
|
|
57640
58200
|
};
|
|
57641
|
-
const outFile =
|
|
57642
|
-
const schemaFile =
|
|
58201
|
+
const outFile = import_node_path41.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
58202
|
+
const schemaFile = import_node_path41.default.join(workDir, "title-schema.json");
|
|
57643
58203
|
if (tool === "codex") {
|
|
57644
58204
|
try {
|
|
57645
58205
|
import_node_fs34.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
@@ -57650,7 +58210,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
57650
58210
|
}
|
|
57651
58211
|
const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
|
|
57652
58212
|
const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text)) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile);
|
|
57653
|
-
const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0,
|
|
58213
|
+
const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0, import_node_child_process9.spawn)(c, a, { ...o, stdio: ["ignore", "pipe", "pipe"] }));
|
|
57654
58214
|
const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
|
|
57655
58215
|
return await new Promise((resolve9) => {
|
|
57656
58216
|
let proc;
|
|
@@ -58393,8 +58953,8 @@ async function authenticate(token, deps) {
|
|
|
58393
58953
|
}
|
|
58394
58954
|
|
|
58395
58955
|
// src/legacy-cleanup.ts
|
|
58396
|
-
var
|
|
58397
|
-
var
|
|
58956
|
+
var fs47 = __toESM(require("fs/promises"), 1);
|
|
58957
|
+
var path49 = __toESM(require("path"), 1);
|
|
58398
58958
|
var LEGACY_FILES = [
|
|
58399
58959
|
"personal-capability.json",
|
|
58400
58960
|
"received-capabilities.json",
|
|
@@ -58403,9 +58963,9 @@ var LEGACY_FILES = [
|
|
|
58403
58963
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
58404
58964
|
const removed = [];
|
|
58405
58965
|
for (const name of LEGACY_FILES) {
|
|
58406
|
-
const p2 =
|
|
58966
|
+
const p2 = path49.join(dataDir, name);
|
|
58407
58967
|
try {
|
|
58408
|
-
await
|
|
58968
|
+
await fs47.unlink(p2);
|
|
58409
58969
|
removed.push(name);
|
|
58410
58970
|
logger.debug("legacy capability file removed", { file: name });
|
|
58411
58971
|
} catch (err) {
|
|
@@ -58417,13 +58977,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
58417
58977
|
}
|
|
58418
58978
|
|
|
58419
58979
|
// src/inbox/inbox-store.ts
|
|
58420
|
-
var
|
|
58421
|
-
var
|
|
58980
|
+
var fs48 = __toESM(require("fs"), 1);
|
|
58981
|
+
var path50 = __toESM(require("path"), 1);
|
|
58422
58982
|
var INBOX_SUBDIR = "inbox";
|
|
58423
58983
|
var InboxStore = class {
|
|
58424
58984
|
constructor(dataDir) {
|
|
58425
58985
|
this.dataDir = dataDir;
|
|
58426
|
-
|
|
58986
|
+
fs48.mkdirSync(this.dirPath(), { recursive: true });
|
|
58427
58987
|
}
|
|
58428
58988
|
dataDir;
|
|
58429
58989
|
/**
|
|
@@ -58435,7 +58995,7 @@ var InboxStore = class {
|
|
|
58435
58995
|
const file = this.filePath(peerDeviceId);
|
|
58436
58996
|
let raw;
|
|
58437
58997
|
try {
|
|
58438
|
-
raw =
|
|
58998
|
+
raw = fs48.readFileSync(file, "utf8");
|
|
58439
58999
|
} catch (err) {
|
|
58440
59000
|
if (err?.code === "ENOENT") return [];
|
|
58441
59001
|
return [];
|
|
@@ -58451,7 +59011,7 @@ var InboxStore = class {
|
|
|
58451
59011
|
const dir = this.dirPath();
|
|
58452
59012
|
let entries;
|
|
58453
59013
|
try {
|
|
58454
|
-
entries =
|
|
59014
|
+
entries = fs48.readdirSync(dir);
|
|
58455
59015
|
} catch (err) {
|
|
58456
59016
|
if (err?.code === "ENOENT") return [];
|
|
58457
59017
|
return [];
|
|
@@ -58467,9 +59027,9 @@ var InboxStore = class {
|
|
|
58467
59027
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
58468
59028
|
const file = this.filePath(message.peerDeviceId);
|
|
58469
59029
|
const line = JSON.stringify(message) + "\n";
|
|
58470
|
-
|
|
59030
|
+
fs48.appendFileSync(file, line, { mode: 384 });
|
|
58471
59031
|
try {
|
|
58472
|
-
|
|
59032
|
+
fs48.chmodSync(file, 384);
|
|
58473
59033
|
} catch {
|
|
58474
59034
|
}
|
|
58475
59035
|
}
|
|
@@ -58499,7 +59059,7 @@ var InboxStore = class {
|
|
|
58499
59059
|
removeByPeerDeviceId(peerDeviceId) {
|
|
58500
59060
|
const file = this.filePath(peerDeviceId);
|
|
58501
59061
|
try {
|
|
58502
|
-
|
|
59062
|
+
fs48.unlinkSync(file);
|
|
58503
59063
|
} catch (err) {
|
|
58504
59064
|
if (err?.code === "ENOENT") return;
|
|
58505
59065
|
}
|
|
@@ -58508,18 +59068,18 @@ var InboxStore = class {
|
|
|
58508
59068
|
const file = this.filePath(peerDeviceId);
|
|
58509
59069
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
58510
59070
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
58511
|
-
|
|
58512
|
-
|
|
59071
|
+
fs48.writeFileSync(tmp, content, { mode: 384 });
|
|
59072
|
+
fs48.renameSync(tmp, file);
|
|
58513
59073
|
try {
|
|
58514
|
-
|
|
59074
|
+
fs48.chmodSync(file, 384);
|
|
58515
59075
|
} catch {
|
|
58516
59076
|
}
|
|
58517
59077
|
}
|
|
58518
59078
|
dirPath() {
|
|
58519
|
-
return
|
|
59079
|
+
return path50.join(this.dataDir, INBOX_SUBDIR);
|
|
58520
59080
|
}
|
|
58521
59081
|
filePath(peerDeviceId) {
|
|
58522
|
-
return
|
|
59082
|
+
return path50.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
58523
59083
|
}
|
|
58524
59084
|
};
|
|
58525
59085
|
function parseAllLines(raw) {
|
|
@@ -58607,8 +59167,8 @@ var InboxManager = class {
|
|
|
58607
59167
|
};
|
|
58608
59168
|
|
|
58609
59169
|
// src/state/contact-store.ts
|
|
58610
|
-
var
|
|
58611
|
-
var
|
|
59170
|
+
var fs49 = __toESM(require("fs"), 1);
|
|
59171
|
+
var path51 = __toESM(require("path"), 1);
|
|
58612
59172
|
var FILE_NAME = "contacts.json";
|
|
58613
59173
|
var ContactStore = class {
|
|
58614
59174
|
constructor(dataDir) {
|
|
@@ -58618,10 +59178,10 @@ var ContactStore = class {
|
|
|
58618
59178
|
contacts = /* @__PURE__ */ new Map();
|
|
58619
59179
|
load() {
|
|
58620
59180
|
this.contacts.clear();
|
|
58621
|
-
const file =
|
|
59181
|
+
const file = path51.join(this.dataDir, FILE_NAME);
|
|
58622
59182
|
let raw;
|
|
58623
59183
|
try {
|
|
58624
|
-
raw =
|
|
59184
|
+
raw = fs49.readFileSync(file, "utf8");
|
|
58625
59185
|
} catch (err) {
|
|
58626
59186
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
58627
59187
|
return;
|
|
@@ -58702,20 +59262,20 @@ var ContactStore = class {
|
|
|
58702
59262
|
return true;
|
|
58703
59263
|
}
|
|
58704
59264
|
flush() {
|
|
58705
|
-
const file =
|
|
59265
|
+
const file = path51.join(this.dataDir, FILE_NAME);
|
|
58706
59266
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
58707
59267
|
const content = JSON.stringify(
|
|
58708
59268
|
{ contacts: Array.from(this.contacts.values()) },
|
|
58709
59269
|
null,
|
|
58710
59270
|
2
|
|
58711
59271
|
);
|
|
58712
|
-
|
|
58713
|
-
|
|
58714
|
-
|
|
59272
|
+
fs49.mkdirSync(this.dataDir, { recursive: true });
|
|
59273
|
+
fs49.writeFileSync(tmp, content, { mode: 384 });
|
|
59274
|
+
fs49.renameSync(tmp, file);
|
|
58715
59275
|
}
|
|
58716
59276
|
renameBak(file) {
|
|
58717
59277
|
try {
|
|
58718
|
-
|
|
59278
|
+
fs49.renameSync(file, `${file}.bak`);
|
|
58719
59279
|
} catch {
|
|
58720
59280
|
}
|
|
58721
59281
|
}
|
|
@@ -58823,61 +59383,61 @@ async function connectRemote(args) {
|
|
|
58823
59383
|
}
|
|
58824
59384
|
|
|
58825
59385
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
58826
|
-
var
|
|
58827
|
-
var
|
|
59386
|
+
var fs50 = __toESM(require("fs"), 1);
|
|
59387
|
+
var path52 = __toESM(require("path"), 1);
|
|
58828
59388
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
58829
59389
|
function migrateFlattenSessions(opts) {
|
|
58830
59390
|
const dataDir = opts.dataDir;
|
|
58831
59391
|
const now = opts.now ?? Date.now;
|
|
58832
|
-
const sessionsDir =
|
|
58833
|
-
const flagPath =
|
|
59392
|
+
const sessionsDir = path52.join(dataDir, "sessions");
|
|
59393
|
+
const flagPath = path52.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
58834
59394
|
if (existsSync3(flagPath)) {
|
|
58835
59395
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
58836
59396
|
}
|
|
58837
59397
|
let movedBare = 0;
|
|
58838
59398
|
let movedVmOwner = 0;
|
|
58839
59399
|
let archivedListener = 0;
|
|
58840
|
-
const defaultDir =
|
|
59400
|
+
const defaultDir = path52.join(sessionsDir, "default");
|
|
58841
59401
|
if (existsSync3(defaultDir)) {
|
|
58842
59402
|
for (const entry of readdirSafe(defaultDir)) {
|
|
58843
59403
|
if (!entry.endsWith(".json")) continue;
|
|
58844
|
-
const src =
|
|
58845
|
-
const dst =
|
|
58846
|
-
|
|
59404
|
+
const src = path52.join(defaultDir, entry);
|
|
59405
|
+
const dst = path52.join(sessionsDir, entry);
|
|
59406
|
+
fs50.renameSync(src, dst);
|
|
58847
59407
|
movedBare += 1;
|
|
58848
59408
|
}
|
|
58849
59409
|
rmdirIfEmpty(defaultDir);
|
|
58850
59410
|
}
|
|
58851
59411
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
58852
|
-
const personaDir =
|
|
59412
|
+
const personaDir = path52.join(sessionsDir, pid);
|
|
58853
59413
|
if (!isDir(personaDir)) continue;
|
|
58854
59414
|
if (pid === "default") continue;
|
|
58855
|
-
const ownerSrc =
|
|
59415
|
+
const ownerSrc = path52.join(personaDir, "owner");
|
|
58856
59416
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
58857
|
-
const ownerDst =
|
|
58858
|
-
|
|
59417
|
+
const ownerDst = path52.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
59418
|
+
fs50.mkdirSync(ownerDst, { recursive: true });
|
|
58859
59419
|
for (const file of readdirSafe(ownerSrc)) {
|
|
58860
59420
|
if (!file.endsWith(".json")) continue;
|
|
58861
|
-
|
|
59421
|
+
fs50.renameSync(path52.join(ownerSrc, file), path52.join(ownerDst, file));
|
|
58862
59422
|
movedVmOwner += 1;
|
|
58863
59423
|
}
|
|
58864
59424
|
rmdirIfEmpty(ownerSrc);
|
|
58865
59425
|
}
|
|
58866
|
-
const listenerSrc =
|
|
59426
|
+
const listenerSrc = path52.join(personaDir, "listener");
|
|
58867
59427
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
58868
|
-
const archiveDst =
|
|
58869
|
-
|
|
59428
|
+
const archiveDst = path52.join(dataDir, ".legacy", `listener-${pid}`);
|
|
59429
|
+
fs50.mkdirSync(archiveDst, { recursive: true });
|
|
58870
59430
|
for (const file of readdirSafe(listenerSrc)) {
|
|
58871
59431
|
if (!file.endsWith(".json")) continue;
|
|
58872
|
-
|
|
59432
|
+
fs50.renameSync(path52.join(listenerSrc, file), path52.join(archiveDst, file));
|
|
58873
59433
|
archivedListener += 1;
|
|
58874
59434
|
}
|
|
58875
59435
|
rmdirIfEmpty(listenerSrc);
|
|
58876
59436
|
}
|
|
58877
59437
|
rmdirIfEmpty(personaDir);
|
|
58878
59438
|
}
|
|
58879
|
-
|
|
58880
|
-
|
|
59439
|
+
fs50.mkdirSync(sessionsDir, { recursive: true });
|
|
59440
|
+
fs50.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
58881
59441
|
return {
|
|
58882
59442
|
skipped: false,
|
|
58883
59443
|
flagWritten: true,
|
|
@@ -58888,7 +59448,7 @@ function migrateFlattenSessions(opts) {
|
|
|
58888
59448
|
}
|
|
58889
59449
|
function existsSync3(p2) {
|
|
58890
59450
|
try {
|
|
58891
|
-
|
|
59451
|
+
fs50.statSync(p2);
|
|
58892
59452
|
return true;
|
|
58893
59453
|
} catch {
|
|
58894
59454
|
return false;
|
|
@@ -58896,61 +59456,61 @@ function existsSync3(p2) {
|
|
|
58896
59456
|
}
|
|
58897
59457
|
function isDir(p2) {
|
|
58898
59458
|
try {
|
|
58899
|
-
return
|
|
59459
|
+
return fs50.statSync(p2).isDirectory();
|
|
58900
59460
|
} catch {
|
|
58901
59461
|
return false;
|
|
58902
59462
|
}
|
|
58903
59463
|
}
|
|
58904
59464
|
function readdirSafe(p2) {
|
|
58905
59465
|
try {
|
|
58906
|
-
return
|
|
59466
|
+
return fs50.readdirSync(p2);
|
|
58907
59467
|
} catch {
|
|
58908
59468
|
return [];
|
|
58909
59469
|
}
|
|
58910
59470
|
}
|
|
58911
59471
|
function rmdirIfEmpty(p2) {
|
|
58912
59472
|
try {
|
|
58913
|
-
|
|
59473
|
+
fs50.rmdirSync(p2);
|
|
58914
59474
|
} catch {
|
|
58915
59475
|
}
|
|
58916
59476
|
}
|
|
58917
59477
|
|
|
58918
59478
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
58919
|
-
var
|
|
58920
|
-
var
|
|
59479
|
+
var fs51 = __toESM(require("fs"), 1);
|
|
59480
|
+
var path53 = __toESM(require("path"), 1);
|
|
58921
59481
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
58922
59482
|
function dropSeededProjects(opts) {
|
|
58923
|
-
|
|
58924
|
-
const flag =
|
|
58925
|
-
if (
|
|
58926
|
-
const file =
|
|
59483
|
+
fs51.mkdirSync(opts.dataDir, { recursive: true });
|
|
59484
|
+
const flag = path53.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
|
|
59485
|
+
if (fs51.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
|
|
59486
|
+
const file = path53.join(opts.dataDir, "projects.json");
|
|
58927
59487
|
let raw = null;
|
|
58928
59488
|
let dropped = 0;
|
|
58929
59489
|
try {
|
|
58930
|
-
raw =
|
|
59490
|
+
raw = fs51.readFileSync(file, "utf8");
|
|
58931
59491
|
dropped = JSON.parse(raw).projects?.length ?? 0;
|
|
58932
59492
|
} catch {
|
|
58933
59493
|
}
|
|
58934
59494
|
let backup = null;
|
|
58935
59495
|
if (raw != null && dropped > 0) {
|
|
58936
|
-
const dir =
|
|
58937
|
-
|
|
58938
|
-
backup =
|
|
58939
|
-
|
|
59496
|
+
const dir = path53.join(opts.dataDir, "backups");
|
|
59497
|
+
fs51.mkdirSync(dir, { recursive: true });
|
|
59498
|
+
backup = path53.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
|
|
59499
|
+
fs51.writeFileSync(backup, raw);
|
|
58940
59500
|
}
|
|
58941
59501
|
if (raw != null || dropped > 0) {
|
|
58942
|
-
|
|
59502
|
+
fs51.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
|
|
58943
59503
|
}
|
|
58944
|
-
|
|
59504
|
+
fs51.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
|
|
58945
59505
|
return { skipped: false, dropped, backup };
|
|
58946
59506
|
}
|
|
58947
59507
|
|
|
58948
59508
|
// src/transport/http-router.ts
|
|
58949
59509
|
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
58950
|
-
var
|
|
59510
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
58951
59511
|
|
|
58952
59512
|
// src/attachment/mime.ts
|
|
58953
|
-
var
|
|
59513
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
58954
59514
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
58955
59515
|
var EXT_TO_NATIVE_MIME = {
|
|
58956
59516
|
// 图片
|
|
@@ -59057,7 +59617,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
59057
59617
|
".mk"
|
|
59058
59618
|
]);
|
|
59059
59619
|
function lookupMime(filePathOrName) {
|
|
59060
|
-
const ext =
|
|
59620
|
+
const ext = import_node_path42.default.extname(filePathOrName).toLowerCase();
|
|
59061
59621
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
59062
59622
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
59063
59623
|
return "application/octet-stream";
|
|
@@ -59128,9 +59688,9 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
59128
59688
|
|
|
59129
59689
|
// src/attachment/upload.ts
|
|
59130
59690
|
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
59131
|
-
var
|
|
59691
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
59132
59692
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
59133
|
-
var
|
|
59693
|
+
var import_promises9 = require("stream/promises");
|
|
59134
59694
|
var UploadError = class extends Error {
|
|
59135
59695
|
constructor(code, message) {
|
|
59136
59696
|
super(message);
|
|
@@ -59140,14 +59700,14 @@ var UploadError = class extends Error {
|
|
|
59140
59700
|
code;
|
|
59141
59701
|
};
|
|
59142
59702
|
function assertValidFileName(fileName) {
|
|
59143
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
59703
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path43.default.basename(fileName)) {
|
|
59144
59704
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
59145
59705
|
}
|
|
59146
59706
|
}
|
|
59147
59707
|
var HASH_PREFIX_LEN = 16;
|
|
59148
59708
|
async function writeUploadedAttachment(args) {
|
|
59149
59709
|
assertValidFileName(args.fileName);
|
|
59150
|
-
const attachmentsRoot =
|
|
59710
|
+
const attachmentsRoot = import_node_path43.default.join(args.baseDir, ".attachments");
|
|
59151
59711
|
try {
|
|
59152
59712
|
import_node_fs35.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
59153
59713
|
} catch (err) {
|
|
@@ -59155,12 +59715,12 @@ async function writeUploadedAttachment(args) {
|
|
|
59155
59715
|
}
|
|
59156
59716
|
const hasher = import_node_crypto10.default.createHash("sha256");
|
|
59157
59717
|
let actualSize = 0;
|
|
59158
|
-
const tmpPath =
|
|
59718
|
+
const tmpPath = import_node_path43.default.join(
|
|
59159
59719
|
attachmentsRoot,
|
|
59160
59720
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto10.default.randomBytes(4).toString("hex")}`
|
|
59161
59721
|
);
|
|
59162
59722
|
try {
|
|
59163
|
-
await (0,
|
|
59723
|
+
await (0, import_promises9.pipeline)(
|
|
59164
59724
|
args.body,
|
|
59165
59725
|
async function* (source) {
|
|
59166
59726
|
for await (const chunk of source) {
|
|
@@ -59190,7 +59750,7 @@ async function writeUploadedAttachment(args) {
|
|
|
59190
59750
|
);
|
|
59191
59751
|
}
|
|
59192
59752
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
59193
|
-
const hashDir =
|
|
59753
|
+
const hashDir = import_node_path43.default.join(attachmentsRoot, attachmentId);
|
|
59194
59754
|
let finalFileName;
|
|
59195
59755
|
let hashDirExists = false;
|
|
59196
59756
|
try {
|
|
@@ -59208,7 +59768,7 @@ async function writeUploadedAttachment(args) {
|
|
|
59208
59768
|
try {
|
|
59209
59769
|
import_node_fs35.default.mkdirSync(hashDir, { recursive: true });
|
|
59210
59770
|
finalFileName = args.fileName;
|
|
59211
|
-
import_node_fs35.default.renameSync(tmpPath,
|
|
59771
|
+
import_node_fs35.default.renameSync(tmpPath, import_node_path43.default.join(hashDir, finalFileName));
|
|
59212
59772
|
} catch (err) {
|
|
59213
59773
|
try {
|
|
59214
59774
|
import_node_fs35.default.unlinkSync(tmpPath);
|
|
@@ -59217,7 +59777,7 @@ async function writeUploadedAttachment(args) {
|
|
|
59217
59777
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
59218
59778
|
}
|
|
59219
59779
|
}
|
|
59220
|
-
const absPath =
|
|
59780
|
+
const absPath = import_node_path43.default.join(hashDir, finalFileName);
|
|
59221
59781
|
const relPath = absPath;
|
|
59222
59782
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
59223
59783
|
relPath: absPath,
|
|
@@ -59231,9 +59791,9 @@ async function writeUploadedAttachment(args) {
|
|
|
59231
59791
|
}
|
|
59232
59792
|
|
|
59233
59793
|
// src/extension/import.ts
|
|
59234
|
-
var
|
|
59235
|
-
var
|
|
59236
|
-
var
|
|
59794
|
+
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
59795
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
59796
|
+
var import_node_os14 = __toESM(require("os"), 1);
|
|
59237
59797
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
59238
59798
|
var ImportError = class extends Error {
|
|
59239
59799
|
constructor(code, message) {
|
|
@@ -59250,7 +59810,7 @@ async function importZip(buf, root) {
|
|
|
59250
59810
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
59251
59811
|
}
|
|
59252
59812
|
for (const name of Object.keys(zip.files)) {
|
|
59253
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
59813
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path44.default.isAbsolute(name)) {
|
|
59254
59814
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
59255
59815
|
}
|
|
59256
59816
|
}
|
|
@@ -59283,33 +59843,33 @@ async function importZip(buf, root) {
|
|
|
59283
59843
|
);
|
|
59284
59844
|
}
|
|
59285
59845
|
}
|
|
59286
|
-
const destDir =
|
|
59846
|
+
const destDir = import_node_path44.default.join(root, manifest.id);
|
|
59287
59847
|
let destExists = false;
|
|
59288
59848
|
try {
|
|
59289
|
-
await
|
|
59849
|
+
await import_promises10.default.access(destDir);
|
|
59290
59850
|
destExists = true;
|
|
59291
59851
|
} catch {
|
|
59292
59852
|
}
|
|
59293
59853
|
if (destExists) {
|
|
59294
59854
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
59295
59855
|
}
|
|
59296
|
-
const stage = await
|
|
59856
|
+
const stage = await import_promises10.default.mkdtemp(import_node_path44.default.join(import_node_os14.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
59297
59857
|
try {
|
|
59298
59858
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
59299
|
-
const dest =
|
|
59859
|
+
const dest = import_node_path44.default.join(stage, name);
|
|
59300
59860
|
if (entry.dir) {
|
|
59301
|
-
await
|
|
59861
|
+
await import_promises10.default.mkdir(dest, { recursive: true });
|
|
59302
59862
|
continue;
|
|
59303
59863
|
}
|
|
59304
|
-
await
|
|
59864
|
+
await import_promises10.default.mkdir(import_node_path44.default.dirname(dest), { recursive: true });
|
|
59305
59865
|
const content = await entry.async("nodebuffer");
|
|
59306
|
-
await
|
|
59866
|
+
await import_promises10.default.writeFile(dest, content);
|
|
59307
59867
|
}
|
|
59308
|
-
await
|
|
59309
|
-
await
|
|
59868
|
+
await import_promises10.default.mkdir(root, { recursive: true });
|
|
59869
|
+
await import_promises10.default.rename(stage, destDir);
|
|
59310
59870
|
return { extId: manifest.id };
|
|
59311
59871
|
} catch (e) {
|
|
59312
|
-
await
|
|
59872
|
+
await import_promises10.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
59313
59873
|
});
|
|
59314
59874
|
throw e;
|
|
59315
59875
|
}
|
|
@@ -59331,7 +59891,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
59331
59891
|
".wasm": "application/wasm"
|
|
59332
59892
|
};
|
|
59333
59893
|
function shareUiAssetMime(filePath) {
|
|
59334
|
-
const ext =
|
|
59894
|
+
const ext = import_node_path45.default.extname(filePath).toLowerCase();
|
|
59335
59895
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
59336
59896
|
}
|
|
59337
59897
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -59430,7 +59990,7 @@ function isValidUploadFileName(fileName) {
|
|
|
59430
59990
|
if (fileName === "." || fileName === "..") return false;
|
|
59431
59991
|
if (fileName.startsWith(".")) return false;
|
|
59432
59992
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
59433
|
-
return fileName ===
|
|
59993
|
+
return fileName === import_node_path45.default.basename(fileName);
|
|
59434
59994
|
}
|
|
59435
59995
|
function createHttpRouter(deps) {
|
|
59436
59996
|
return async (req, res) => {
|
|
@@ -59666,7 +60226,7 @@ function createHttpRouter(deps) {
|
|
|
59666
60226
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
59667
60227
|
return true;
|
|
59668
60228
|
}
|
|
59669
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
60229
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path45.default.basename(r.absPath)));
|
|
59670
60230
|
return true;
|
|
59671
60231
|
}
|
|
59672
60232
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -59787,7 +60347,7 @@ function createHttpRouter(deps) {
|
|
|
59787
60347
|
return true;
|
|
59788
60348
|
}
|
|
59789
60349
|
let absPath;
|
|
59790
|
-
if (
|
|
60350
|
+
if (import_node_path45.default.isAbsolute(pathParam)) {
|
|
59791
60351
|
absPath = pathParam;
|
|
59792
60352
|
} else if (deps.sessionStore) {
|
|
59793
60353
|
const file = deps.sessionStore.read(sid);
|
|
@@ -59795,7 +60355,7 @@ function createHttpRouter(deps) {
|
|
|
59795
60355
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
59796
60356
|
return true;
|
|
59797
60357
|
}
|
|
59798
|
-
absPath =
|
|
60358
|
+
absPath = import_node_path45.default.join(file.cwd, pathParam);
|
|
59799
60359
|
} else {
|
|
59800
60360
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
59801
60361
|
return true;
|
|
@@ -59897,7 +60457,7 @@ function streamFile(res, absPath, logger) {
|
|
|
59897
60457
|
return;
|
|
59898
60458
|
}
|
|
59899
60459
|
const mime = lookupMime(absPath);
|
|
59900
|
-
const basename2 =
|
|
60460
|
+
const basename2 = import_node_path45.default.basename(absPath);
|
|
59901
60461
|
res.writeHead(200, {
|
|
59902
60462
|
"Content-Type": mime,
|
|
59903
60463
|
"Content-Length": String(stat.size),
|
|
@@ -59915,7 +60475,7 @@ function streamFile(res, absPath, logger) {
|
|
|
59915
60475
|
|
|
59916
60476
|
// src/attachment/gc.ts
|
|
59917
60477
|
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
59918
|
-
var
|
|
60478
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
59919
60479
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
59920
60480
|
function runAttachmentGc(args) {
|
|
59921
60481
|
const now = (args.now ?? Date.now)();
|
|
@@ -59924,12 +60484,12 @@ function runAttachmentGc(args) {
|
|
|
59924
60484
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
59925
60485
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
59926
60486
|
if (entry.stale) continue;
|
|
59927
|
-
if (
|
|
60487
|
+
if (import_node_path46.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
59928
60488
|
}
|
|
59929
60489
|
}
|
|
59930
60490
|
const visited = /* @__PURE__ */ new Set();
|
|
59931
60491
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
59932
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
60492
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path46.default.join(
|
|
59933
60493
|
args.dataDir,
|
|
59934
60494
|
"sessions",
|
|
59935
60495
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -59942,7 +60502,7 @@ function runAttachmentGc(args) {
|
|
|
59942
60502
|
return true;
|
|
59943
60503
|
});
|
|
59944
60504
|
for (const rootDir of roots) {
|
|
59945
|
-
const attRoot =
|
|
60505
|
+
const attRoot = import_node_path46.default.join(rootDir, ".attachments");
|
|
59946
60506
|
let hashDirs;
|
|
59947
60507
|
try {
|
|
59948
60508
|
hashDirs = import_node_fs37.default.readdirSync(attRoot);
|
|
@@ -59952,7 +60512,7 @@ function runAttachmentGc(args) {
|
|
|
59952
60512
|
continue;
|
|
59953
60513
|
}
|
|
59954
60514
|
for (const hashDir of hashDirs) {
|
|
59955
|
-
const hashDirAbs =
|
|
60515
|
+
const hashDirAbs = import_node_path46.default.join(attRoot, hashDir);
|
|
59956
60516
|
let files;
|
|
59957
60517
|
try {
|
|
59958
60518
|
files = import_node_fs37.default.readdirSync(hashDirAbs);
|
|
@@ -59960,7 +60520,7 @@ function runAttachmentGc(args) {
|
|
|
59960
60520
|
continue;
|
|
59961
60521
|
}
|
|
59962
60522
|
for (const name of files) {
|
|
59963
|
-
const file =
|
|
60523
|
+
const file = import_node_path46.default.join(hashDirAbs, name);
|
|
59964
60524
|
let stat;
|
|
59965
60525
|
try {
|
|
59966
60526
|
stat = import_node_fs37.default.statSync(file);
|
|
@@ -59992,7 +60552,7 @@ function runAttachmentGc(args) {
|
|
|
59992
60552
|
|
|
59993
60553
|
// src/attachment/group.ts
|
|
59994
60554
|
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
59995
|
-
var
|
|
60555
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
59996
60556
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
59997
60557
|
init_protocol();
|
|
59998
60558
|
var GroupFileStore = class {
|
|
@@ -60004,11 +60564,11 @@ var GroupFileStore = class {
|
|
|
60004
60564
|
this.logger = opts.logger;
|
|
60005
60565
|
}
|
|
60006
60566
|
rootForScope(scope) {
|
|
60007
|
-
return
|
|
60567
|
+
return import_node_path47.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
60008
60568
|
}
|
|
60009
60569
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
60010
60570
|
filePath(scope, sessionId) {
|
|
60011
|
-
return
|
|
60571
|
+
return import_node_path47.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
60012
60572
|
}
|
|
60013
60573
|
cacheKey(scope, sessionId) {
|
|
60014
60574
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -60043,7 +60603,7 @@ var GroupFileStore = class {
|
|
|
60043
60603
|
}
|
|
60044
60604
|
writeFile(scope, sessionId, entries) {
|
|
60045
60605
|
const file = this.filePath(scope, sessionId);
|
|
60046
|
-
import_node_fs38.default.mkdirSync(
|
|
60606
|
+
import_node_fs38.default.mkdirSync(import_node_path47.default.dirname(file), { recursive: true });
|
|
60047
60607
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
60048
60608
|
import_node_fs38.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
60049
60609
|
import_node_fs38.default.renameSync(tmp, file);
|
|
@@ -60133,9 +60693,9 @@ var GroupFileStore = class {
|
|
|
60133
60693
|
|
|
60134
60694
|
// src/discovery/state-file.ts
|
|
60135
60695
|
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
60136
|
-
var
|
|
60696
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
60137
60697
|
function defaultStateFilePath(dataDir) {
|
|
60138
|
-
return
|
|
60698
|
+
return import_node_path48.default.join(dataDir, "state.json");
|
|
60139
60699
|
}
|
|
60140
60700
|
function isPidAlive(pid) {
|
|
60141
60701
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -60171,7 +60731,7 @@ var StateFileManager = class {
|
|
|
60171
60731
|
return { status: "stale", existing };
|
|
60172
60732
|
}
|
|
60173
60733
|
write(state) {
|
|
60174
|
-
import_node_fs39.default.mkdirSync(
|
|
60734
|
+
import_node_fs39.default.mkdirSync(import_node_path48.default.dirname(this.file), { recursive: true });
|
|
60175
60735
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
60176
60736
|
import_node_fs39.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
60177
60737
|
import_node_fs39.default.renameSync(tmp, this.file);
|
|
@@ -60199,13 +60759,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
60199
60759
|
|
|
60200
60760
|
// src/tunnel/tunnel-manager.ts
|
|
60201
60761
|
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
60202
|
-
var
|
|
60762
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
60203
60763
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
60204
|
-
var
|
|
60764
|
+
var import_node_child_process12 = require("child_process");
|
|
60205
60765
|
|
|
60206
60766
|
// src/tunnel/tunnel-store.ts
|
|
60207
60767
|
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
60208
|
-
var
|
|
60768
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
60209
60769
|
var TunnelStore = class {
|
|
60210
60770
|
constructor(filePath) {
|
|
60211
60771
|
this.filePath = filePath;
|
|
@@ -60224,7 +60784,7 @@ var TunnelStore = class {
|
|
|
60224
60784
|
}
|
|
60225
60785
|
}
|
|
60226
60786
|
async set(v2) {
|
|
60227
|
-
const dir =
|
|
60787
|
+
const dir = import_node_path49.default.dirname(this.filePath);
|
|
60228
60788
|
await import_node_fs40.default.promises.mkdir(dir, { recursive: true });
|
|
60229
60789
|
const data = JSON.stringify(v2, null, 2);
|
|
60230
60790
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
@@ -60335,11 +60895,11 @@ function escape(v2) {
|
|
|
60335
60895
|
|
|
60336
60896
|
// src/tunnel/frpc-binary.ts
|
|
60337
60897
|
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
60338
|
-
var
|
|
60339
|
-
var
|
|
60340
|
-
var
|
|
60898
|
+
var import_node_os15 = __toESM(require("os"), 1);
|
|
60899
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
60900
|
+
var import_node_child_process10 = require("child_process");
|
|
60341
60901
|
var import_node_stream3 = require("stream");
|
|
60342
|
-
var
|
|
60902
|
+
var import_promises11 = require("stream/promises");
|
|
60343
60903
|
var FRPC_VERSION = "0.68.0";
|
|
60344
60904
|
var UnsupportedPlatformError = class extends Error {
|
|
60345
60905
|
constructor(platform, arch) {
|
|
@@ -60375,13 +60935,13 @@ async function ensureFrpcBinary(opts) {
|
|
|
60375
60935
|
}
|
|
60376
60936
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
60377
60937
|
const platform = opts.platform ?? detectPlatform();
|
|
60378
|
-
const binDir =
|
|
60938
|
+
const binDir = import_node_path50.default.join(opts.dataDir, "bin");
|
|
60379
60939
|
import_node_fs41.default.mkdirSync(binDir, { recursive: true });
|
|
60380
60940
|
cleanupStaleArtifacts(binDir);
|
|
60381
|
-
const stableBin =
|
|
60941
|
+
const stableBin = import_node_path50.default.join(binDir, "frpc");
|
|
60382
60942
|
if (import_node_fs41.default.existsSync(stableBin)) return stableBin;
|
|
60383
60943
|
const partialBin = `${stableBin}.partial`;
|
|
60384
|
-
const tarballPath =
|
|
60944
|
+
const tarballPath = import_node_path50.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
60385
60945
|
try {
|
|
60386
60946
|
const url = frpcDownloadUrl(version2, platform);
|
|
60387
60947
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -60407,7 +60967,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
60407
60967
|
}
|
|
60408
60968
|
for (const name of entries) {
|
|
60409
60969
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
60410
|
-
const full =
|
|
60970
|
+
const full = import_node_path50.default.join(binDir, name);
|
|
60411
60971
|
try {
|
|
60412
60972
|
import_node_fs41.default.rmSync(full, { recursive: true, force: true });
|
|
60413
60973
|
} catch {
|
|
@@ -60430,19 +60990,19 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
60430
60990
|
}
|
|
60431
60991
|
const out = import_node_fs41.default.createWriteStream(dest);
|
|
60432
60992
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
60433
|
-
await (0,
|
|
60993
|
+
await (0, import_promises11.pipeline)(nodeStream, out);
|
|
60434
60994
|
}
|
|
60435
60995
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
60436
|
-
const work =
|
|
60996
|
+
const work = import_node_path50.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
60437
60997
|
import_node_fs41.default.mkdirSync(work, { recursive: true });
|
|
60438
60998
|
try {
|
|
60439
60999
|
await new Promise((resolve9, reject) => {
|
|
60440
|
-
const proc = (0,
|
|
61000
|
+
const proc = (0, import_node_child_process10.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
60441
61001
|
proc.on("error", reject);
|
|
60442
61002
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
60443
61003
|
});
|
|
60444
61004
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
60445
|
-
const src =
|
|
61005
|
+
const src = import_node_path50.default.join(work, dirName, "frpc");
|
|
60446
61006
|
if (!import_node_fs41.default.existsSync(src)) {
|
|
60447
61007
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
60448
61008
|
}
|
|
@@ -60454,10 +61014,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
60454
61014
|
|
|
60455
61015
|
// src/tunnel/frpc-process.ts
|
|
60456
61016
|
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
60457
|
-
var
|
|
60458
|
-
var
|
|
61017
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
61018
|
+
var import_node_child_process11 = require("child_process");
|
|
60459
61019
|
function frpcPidFilePath(dataDir) {
|
|
60460
|
-
return
|
|
61020
|
+
return import_node_path51.default.join(dataDir, "frpc.pid");
|
|
60461
61021
|
}
|
|
60462
61022
|
function writeFrpcPid(dataDir, pid) {
|
|
60463
61023
|
try {
|
|
@@ -60499,7 +61059,7 @@ function defaultSleep2(ms) {
|
|
|
60499
61059
|
}
|
|
60500
61060
|
async function killStaleFrpc(deps) {
|
|
60501
61061
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
60502
|
-
const tomlPath =
|
|
61062
|
+
const tomlPath = import_node_path51.default.join(deps.dataDir, "frpc.toml");
|
|
60503
61063
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
60504
61064
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
60505
61065
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -60541,7 +61101,7 @@ async function killStaleFrpc(deps) {
|
|
|
60541
61101
|
async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
|
|
60542
61102
|
if (process.platform === "win32") return [];
|
|
60543
61103
|
return new Promise((resolve9) => {
|
|
60544
|
-
const ps = (0,
|
|
61104
|
+
const ps = (0, import_node_child_process11.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
|
|
60545
61105
|
let buf = "";
|
|
60546
61106
|
ps.stdout.on("data", (c) => {
|
|
60547
61107
|
buf += c.toString();
|
|
@@ -60571,7 +61131,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
60571
61131
|
var TunnelManager = class {
|
|
60572
61132
|
constructor(deps) {
|
|
60573
61133
|
this.deps = deps;
|
|
60574
|
-
this.store = deps.store ?? new TunnelStore(
|
|
61134
|
+
this.store = deps.store ?? new TunnelStore(import_node_path52.default.join(deps.dataDir, "tunnel.json"));
|
|
60575
61135
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
60576
61136
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
60577
61137
|
}
|
|
@@ -60698,7 +61258,7 @@ var TunnelManager = class {
|
|
|
60698
61258
|
dataDir: this.deps.dataDir,
|
|
60699
61259
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
60700
61260
|
});
|
|
60701
|
-
const tomlPath =
|
|
61261
|
+
const tomlPath = import_node_path52.default.join(this.deps.dataDir, "frpc.toml");
|
|
60702
61262
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto12.default.randomBytes(3).toString("hex")}`;
|
|
60703
61263
|
const toml = buildFrpcToml({
|
|
60704
61264
|
serverAddr: t.frpsHost,
|
|
@@ -60710,12 +61270,12 @@ var TunnelManager = class {
|
|
|
60710
61270
|
logLevel: "info"
|
|
60711
61271
|
});
|
|
60712
61272
|
await import_node_fs43.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
60713
|
-
const proc = (this.deps.spawnImpl ??
|
|
61273
|
+
const proc = (this.deps.spawnImpl ?? import_node_child_process12.spawn)(frpcBin, ["-c", tomlPath], {
|
|
60714
61274
|
stdio: ["ignore", "pipe", "pipe"]
|
|
60715
61275
|
});
|
|
60716
|
-
const logDir =
|
|
61276
|
+
const logDir = import_node_path52.default.join(this.deps.dataDir, "log");
|
|
60717
61277
|
import_node_fs43.default.mkdirSync(logDir, { recursive: true });
|
|
60718
|
-
const logFilePath =
|
|
61278
|
+
const logFilePath = import_node_path52.default.join(logDir, "frpc.log");
|
|
60719
61279
|
const logStream = import_node_fs43.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
60720
61280
|
logStream.on("error", () => {
|
|
60721
61281
|
});
|
|
@@ -60798,16 +61358,16 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
60798
61358
|
}
|
|
60799
61359
|
|
|
60800
61360
|
// src/tunnel/device-key.ts
|
|
60801
|
-
var
|
|
60802
|
-
var
|
|
61361
|
+
var import_node_os16 = __toESM(require("os"), 1);
|
|
61362
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
60803
61363
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
60804
61364
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
60805
61365
|
function deriveStableDeviceKey(opts = {}) {
|
|
60806
|
-
const hostname = opts.hostname ??
|
|
60807
|
-
const uid = opts.uid ?? (typeof
|
|
60808
|
-
const home = opts.home ??
|
|
60809
|
-
const defaultDataDir =
|
|
60810
|
-
const normalizedDataDir = opts.dataDir ?
|
|
61366
|
+
const hostname = opts.hostname ?? import_node_os16.default.hostname();
|
|
61367
|
+
const uid = opts.uid ?? (typeof import_node_os16.default.userInfo === "function" ? import_node_os16.default.userInfo().uid : 0);
|
|
61368
|
+
const home = opts.home ?? import_node_os16.default.homedir();
|
|
61369
|
+
const defaultDataDir = import_node_path53.default.resolve(import_node_path53.default.join(home, ".clawd"));
|
|
61370
|
+
const normalizedDataDir = opts.dataDir ? import_node_path53.default.resolve(opts.dataDir) : null;
|
|
60811
61371
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
60812
61372
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
60813
61373
|
return import_node_crypto13.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
@@ -60815,11 +61375,11 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
60815
61375
|
|
|
60816
61376
|
// src/auth-store.ts
|
|
60817
61377
|
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
60818
|
-
var
|
|
61378
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
60819
61379
|
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
60820
61380
|
var AUTH_FILE_NAME = "auth.json";
|
|
60821
61381
|
function authFilePath(dataDir) {
|
|
60822
|
-
return
|
|
61382
|
+
return import_node_path54.default.join(dataDir, AUTH_FILE_NAME);
|
|
60823
61383
|
}
|
|
60824
61384
|
function loadOrCreateAuthFile(opts) {
|
|
60825
61385
|
const file = authFilePath(opts.dataDir);
|
|
@@ -60871,7 +61431,7 @@ function readAuthFile(file) {
|
|
|
60871
61431
|
}
|
|
60872
61432
|
}
|
|
60873
61433
|
function writeAuthFile(file, content) {
|
|
60874
|
-
import_node_fs44.default.mkdirSync(
|
|
61434
|
+
import_node_fs44.default.mkdirSync(import_node_path54.default.dirname(file), { recursive: true });
|
|
60875
61435
|
import_node_fs44.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
60876
61436
|
try {
|
|
60877
61437
|
import_node_fs44.default.chmodSync(file, 384);
|
|
@@ -60881,11 +61441,11 @@ function writeAuthFile(file, content) {
|
|
|
60881
61441
|
|
|
60882
61442
|
// src/owner-profile.ts
|
|
60883
61443
|
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
60884
|
-
var
|
|
60885
|
-
var
|
|
61444
|
+
var import_node_os17 = __toESM(require("os"), 1);
|
|
61445
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
60886
61446
|
var PROFILE_FILENAME = "profile.json";
|
|
60887
61447
|
function profilePath(dataDir) {
|
|
60888
|
-
return
|
|
61448
|
+
return import_node_path55.default.join(dataDir, PROFILE_FILENAME);
|
|
60889
61449
|
}
|
|
60890
61450
|
function loadOwnerProfile(dataDir) {
|
|
60891
61451
|
let raw;
|
|
@@ -60910,7 +61470,7 @@ function patchOwnerProfile(dataDir, patch) {
|
|
|
60910
61470
|
return merged;
|
|
60911
61471
|
}
|
|
60912
61472
|
function loadOwnerDisplayName(dataDir) {
|
|
60913
|
-
const fallback =
|
|
61473
|
+
const fallback = import_node_os17.default.userInfo().username;
|
|
60914
61474
|
const displayName = loadOwnerProfile(dataDir).displayName;
|
|
60915
61475
|
if (typeof displayName !== "string" || displayName.length === 0) {
|
|
60916
61476
|
if (displayName !== void 0) {
|
|
@@ -60923,12 +61483,12 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
60923
61483
|
|
|
60924
61484
|
// src/feishu-auth/owner-identity-store.ts
|
|
60925
61485
|
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
60926
|
-
var
|
|
61486
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
60927
61487
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
60928
61488
|
var OwnerIdentityStore = class {
|
|
60929
61489
|
file;
|
|
60930
61490
|
constructor(dataDir) {
|
|
60931
|
-
this.file =
|
|
61491
|
+
this.file = import_node_path56.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
60932
61492
|
}
|
|
60933
61493
|
read() {
|
|
60934
61494
|
let raw;
|
|
@@ -60961,7 +61521,7 @@ var OwnerIdentityStore = class {
|
|
|
60961
61521
|
};
|
|
60962
61522
|
}
|
|
60963
61523
|
write(record3) {
|
|
60964
|
-
import_node_fs46.default.mkdirSync(
|
|
61524
|
+
import_node_fs46.default.mkdirSync(import_node_path56.default.dirname(this.file), { recursive: true });
|
|
60965
61525
|
import_node_fs46.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
|
|
60966
61526
|
try {
|
|
60967
61527
|
import_node_fs46.default.chmodSync(this.file, 384);
|
|
@@ -61107,9 +61667,9 @@ var CentralClientError = class extends Error {
|
|
|
61107
61667
|
code;
|
|
61108
61668
|
cause;
|
|
61109
61669
|
};
|
|
61110
|
-
async function centralRequest(opts,
|
|
61670
|
+
async function centralRequest(opts, path98, init) {
|
|
61111
61671
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
61112
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
61672
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path98}`;
|
|
61113
61673
|
const ctrl = new AbortController();
|
|
61114
61674
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
61115
61675
|
let res;
|
|
@@ -61546,8 +62106,8 @@ function verifyConnectToken(args) {
|
|
|
61546
62106
|
}
|
|
61547
62107
|
|
|
61548
62108
|
// src/feishu-auth/server-key.ts
|
|
61549
|
-
var
|
|
61550
|
-
var
|
|
62109
|
+
var fs65 = __toESM(require("fs"), 1);
|
|
62110
|
+
var path69 = __toESM(require("path"), 1);
|
|
61551
62111
|
var FILE_NAME2 = "server-signing-key.json";
|
|
61552
62112
|
var ServerKeyStore = class {
|
|
61553
62113
|
constructor(dataDir) {
|
|
@@ -61555,12 +62115,12 @@ var ServerKeyStore = class {
|
|
|
61555
62115
|
}
|
|
61556
62116
|
dataDir;
|
|
61557
62117
|
filePath() {
|
|
61558
|
-
return
|
|
62118
|
+
return path69.join(this.dataDir, FILE_NAME2);
|
|
61559
62119
|
}
|
|
61560
62120
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
61561
62121
|
read() {
|
|
61562
62122
|
try {
|
|
61563
|
-
const raw =
|
|
62123
|
+
const raw = fs65.readFileSync(this.filePath(), "utf8");
|
|
61564
62124
|
const parsed = JSON.parse(raw);
|
|
61565
62125
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
61566
62126
|
return parsed.publicKeyPem;
|
|
@@ -61575,12 +62135,12 @@ var ServerKeyStore = class {
|
|
|
61575
62135
|
publicKeyPem,
|
|
61576
62136
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
61577
62137
|
};
|
|
61578
|
-
|
|
61579
|
-
|
|
62138
|
+
fs65.mkdirSync(this.dataDir, { recursive: true });
|
|
62139
|
+
fs65.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
61580
62140
|
}
|
|
61581
62141
|
clear() {
|
|
61582
62142
|
try {
|
|
61583
|
-
|
|
62143
|
+
fs65.unlinkSync(this.filePath());
|
|
61584
62144
|
} catch {
|
|
61585
62145
|
}
|
|
61586
62146
|
}
|
|
@@ -61590,15 +62150,15 @@ var ServerKeyStore = class {
|
|
|
61590
62150
|
init_protocol();
|
|
61591
62151
|
|
|
61592
62152
|
// src/handlers/index.ts
|
|
61593
|
-
var
|
|
62153
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
61594
62154
|
|
|
61595
62155
|
// src/handlers/session.ts
|
|
61596
62156
|
init_protocol();
|
|
61597
62157
|
|
|
61598
62158
|
// src/session/fork.ts
|
|
61599
62159
|
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
61600
|
-
var
|
|
61601
|
-
var
|
|
62160
|
+
var import_node_os18 = __toESM(require("os"), 1);
|
|
62161
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
61602
62162
|
var import_node_crypto16 = require("crypto");
|
|
61603
62163
|
init_claude_history();
|
|
61604
62164
|
function readJsonlEntries(file) {
|
|
@@ -61615,19 +62175,19 @@ function readJsonlEntries(file) {
|
|
|
61615
62175
|
return out;
|
|
61616
62176
|
}
|
|
61617
62177
|
function forkSession(input) {
|
|
61618
|
-
const baseDir = input.baseDir ??
|
|
61619
|
-
let projectDir =
|
|
61620
|
-
let sourceFile =
|
|
62178
|
+
const baseDir = input.baseDir ?? import_node_path57.default.join(import_node_os18.default.homedir(), ".claude");
|
|
62179
|
+
let projectDir = import_node_path57.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
62180
|
+
let sourceFile = import_node_path57.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
61621
62181
|
if (!import_node_fs47.default.existsSync(sourceFile)) {
|
|
61622
62182
|
const found = findTranscriptByToolSessionId(
|
|
61623
|
-
|
|
62183
|
+
import_node_path57.default.join(baseDir, "projects"),
|
|
61624
62184
|
input.toolSessionId
|
|
61625
62185
|
);
|
|
61626
62186
|
if (!found) {
|
|
61627
62187
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
61628
62188
|
}
|
|
61629
62189
|
sourceFile = found;
|
|
61630
|
-
projectDir =
|
|
62190
|
+
projectDir = import_node_path57.default.dirname(found);
|
|
61631
62191
|
}
|
|
61632
62192
|
const entries = readJsonlEntries(sourceFile);
|
|
61633
62193
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -61656,8 +62216,8 @@ function forkSession(input) {
|
|
|
61656
62216
|
}
|
|
61657
62217
|
forkedLines.push(JSON.stringify(forked));
|
|
61658
62218
|
}
|
|
61659
|
-
const outDir = input.targetCwd ?
|
|
61660
|
-
const forkedFilePath =
|
|
62219
|
+
const outDir = input.targetCwd ? import_node_path57.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
62220
|
+
const forkedFilePath = import_node_path57.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
61661
62221
|
import_node_fs47.default.mkdirSync(outDir, { recursive: true });
|
|
61662
62222
|
import_node_fs47.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
61663
62223
|
return { forkedToolSessionId, forkedFilePath };
|
|
@@ -61665,18 +62225,18 @@ function forkSession(input) {
|
|
|
61665
62225
|
|
|
61666
62226
|
// src/session/external-scan.ts
|
|
61667
62227
|
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
61668
|
-
var
|
|
61669
|
-
var
|
|
61670
|
-
var
|
|
62228
|
+
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
62229
|
+
var import_node_os19 = __toESM(require("os"), 1);
|
|
62230
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
61671
62231
|
var import_node_module = require("module");
|
|
61672
|
-
var
|
|
62232
|
+
var import_node_child_process13 = require("child_process");
|
|
61673
62233
|
var import_meta5 = {};
|
|
61674
62234
|
function defaultRoots() {
|
|
61675
|
-
const home =
|
|
62235
|
+
const home = import_node_os19.default.homedir();
|
|
61676
62236
|
return {
|
|
61677
|
-
claudeProjectsDir:
|
|
61678
|
-
codexDir:
|
|
61679
|
-
clawdDir:
|
|
62237
|
+
claudeProjectsDir: import_node_path58.default.join(home, ".claude", "projects"),
|
|
62238
|
+
codexDir: import_node_path58.default.join(home, ".codex"),
|
|
62239
|
+
clawdDir: import_node_path58.default.join(home, ".clawd")
|
|
61680
62240
|
};
|
|
61681
62241
|
}
|
|
61682
62242
|
function width(s) {
|
|
@@ -61704,7 +62264,7 @@ function toMs(v2) {
|
|
|
61704
62264
|
async function* jsonLines(file) {
|
|
61705
62265
|
let raw;
|
|
61706
62266
|
try {
|
|
61707
|
-
raw = await
|
|
62267
|
+
raw = await import_promises12.default.readFile(file, "utf8");
|
|
61708
62268
|
} catch {
|
|
61709
62269
|
return;
|
|
61710
62270
|
}
|
|
@@ -61744,13 +62304,13 @@ async function scanClaude(roots) {
|
|
|
61744
62304
|
if (!d.isDirectory()) continue;
|
|
61745
62305
|
let files;
|
|
61746
62306
|
try {
|
|
61747
|
-
files = import_node_fs48.default.readdirSync(
|
|
62307
|
+
files = import_node_fs48.default.readdirSync(import_node_path58.default.join(roots.claudeProjectsDir, d.name));
|
|
61748
62308
|
} catch {
|
|
61749
62309
|
continue;
|
|
61750
62310
|
}
|
|
61751
62311
|
for (const name of files) {
|
|
61752
62312
|
if (!name.endsWith(".jsonl")) continue;
|
|
61753
|
-
const file =
|
|
62313
|
+
const file = import_node_path58.default.join(roots.claudeProjectsDir, d.name, name);
|
|
61754
62314
|
let st;
|
|
61755
62315
|
try {
|
|
61756
62316
|
st = import_node_fs48.default.statSync(file);
|
|
@@ -61837,14 +62397,14 @@ function readCodexThreads(db) {
|
|
|
61837
62397
|
} catch {
|
|
61838
62398
|
}
|
|
61839
62399
|
try {
|
|
61840
|
-
const info = (0,
|
|
62400
|
+
const info = (0, import_node_child_process13.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
|
|
61841
62401
|
if (info.status !== 0) return null;
|
|
61842
62402
|
const have = new Set(
|
|
61843
62403
|
info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
|
|
61844
62404
|
);
|
|
61845
62405
|
if (!["id", "cwd", "updated_at", "thread_source"].every((c) => have.has(c))) return null;
|
|
61846
62406
|
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
61847
|
-
const res = (0,
|
|
62407
|
+
const res = (0, import_node_child_process13.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
|
|
61848
62408
|
encoding: "utf8",
|
|
61849
62409
|
maxBuffer: 64 * 1024 * 1024
|
|
61850
62410
|
});
|
|
@@ -61880,7 +62440,7 @@ async function codexFromRows(rows) {
|
|
|
61880
62440
|
async function scanCodex(roots) {
|
|
61881
62441
|
let dbs = [];
|
|
61882
62442
|
try {
|
|
61883
|
-
dbs = import_node_fs48.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) =>
|
|
62443
|
+
dbs = import_node_fs48.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path58.default.join(roots.codexDir, n));
|
|
61884
62444
|
} catch {
|
|
61885
62445
|
}
|
|
61886
62446
|
if (!dbs.length) return [];
|
|
@@ -61889,14 +62449,14 @@ async function scanCodex(roots) {
|
|
|
61889
62449
|
}
|
|
61890
62450
|
async function scanExternalSessions(rootsIn) {
|
|
61891
62451
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
61892
|
-
const personaRoot =
|
|
62452
|
+
const personaRoot = import_node_path58.default.join(roots.clawdDir, "personas");
|
|
61893
62453
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
61894
62454
|
const out = [];
|
|
61895
62455
|
for (const c of all) {
|
|
61896
62456
|
if (c.skip) continue;
|
|
61897
62457
|
if (c.turns < 1) continue;
|
|
61898
62458
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
61899
|
-
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot +
|
|
62459
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path58.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path58.default.sep)) {
|
|
61900
62460
|
continue;
|
|
61901
62461
|
}
|
|
61902
62462
|
out.push({
|
|
@@ -61914,12 +62474,12 @@ async function scanExternalSessions(rootsIn) {
|
|
|
61914
62474
|
|
|
61915
62475
|
// src/session/import-ledger.ts
|
|
61916
62476
|
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
61917
|
-
var
|
|
62477
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
61918
62478
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
61919
62479
|
function readImportLedger(dataDir) {
|
|
61920
62480
|
try {
|
|
61921
62481
|
const parsed = JSON.parse(
|
|
61922
|
-
import_node_fs49.default.readFileSync(
|
|
62482
|
+
import_node_fs49.default.readFileSync(import_node_path59.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
61923
62483
|
);
|
|
61924
62484
|
return Array.isArray(parsed) ? parsed : [];
|
|
61925
62485
|
} catch {
|
|
@@ -61927,7 +62487,7 @@ function readImportLedger(dataDir) {
|
|
|
61927
62487
|
}
|
|
61928
62488
|
}
|
|
61929
62489
|
function appendImportLedger(dataDir, entry) {
|
|
61930
|
-
const file =
|
|
62490
|
+
const file = import_node_path59.default.join(dataDir, LEDGER_FILENAME);
|
|
61931
62491
|
const entries = readImportLedger(dataDir);
|
|
61932
62492
|
entries.push(entry);
|
|
61933
62493
|
import_node_fs49.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
@@ -61935,7 +62495,7 @@ function appendImportLedger(dataDir, entry) {
|
|
|
61935
62495
|
|
|
61936
62496
|
// src/tools/transcript-search.ts
|
|
61937
62497
|
var import_node_fs50 = __toESM(require("fs"), 1);
|
|
61938
|
-
var
|
|
62498
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
61939
62499
|
var SNIPPET_PAD = 60;
|
|
61940
62500
|
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/;
|
|
61941
62501
|
var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
|
|
@@ -62028,7 +62588,7 @@ function createCodexRolloutLocator(roots) {
|
|
|
62028
62588
|
return;
|
|
62029
62589
|
}
|
|
62030
62590
|
for (const entry of entries) {
|
|
62031
|
-
const full =
|
|
62591
|
+
const full = import_node_path60.default.join(dir, entry.name);
|
|
62032
62592
|
if (entry.isDirectory()) {
|
|
62033
62593
|
walk2(full, into);
|
|
62034
62594
|
continue;
|
|
@@ -62048,16 +62608,16 @@ function createCodexRolloutLocator(roots) {
|
|
|
62048
62608
|
|
|
62049
62609
|
// src/handlers/session.ts
|
|
62050
62610
|
init_protocol();
|
|
62051
|
-
var
|
|
62052
|
-
var
|
|
62611
|
+
var import_node_os20 = __toESM(require("os"), 1);
|
|
62612
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
62053
62613
|
function canReadSearchHit(ctx, file) {
|
|
62054
62614
|
if (!ctx || ctx.principal.kind === "owner") return true;
|
|
62055
62615
|
return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
|
|
62056
62616
|
}
|
|
62057
62617
|
var DEFAULT_SEARCH_LIMIT = 9;
|
|
62058
62618
|
function codexRolloutRoots(dataDir) {
|
|
62059
|
-
const roots = [
|
|
62060
|
-
if (dataDir) roots.push(
|
|
62619
|
+
const roots = [import_node_path61.default.join(import_node_os20.default.homedir(), ".codex", "sessions")];
|
|
62620
|
+
if (dataDir) roots.push(import_node_path61.default.join(dataDir, "codex-home", "sessions"));
|
|
62061
62621
|
return roots;
|
|
62062
62622
|
}
|
|
62063
62623
|
function buildSessionHandlers(deps) {
|
|
@@ -62599,7 +63159,7 @@ function buildPermissionHandlers(deps) {
|
|
|
62599
63159
|
}
|
|
62600
63160
|
|
|
62601
63161
|
// src/handlers/history.ts
|
|
62602
|
-
var
|
|
63162
|
+
var path76 = __toESM(require("path"), 1);
|
|
62603
63163
|
init_protocol();
|
|
62604
63164
|
|
|
62605
63165
|
// src/session/recent-dirs.ts
|
|
@@ -62617,7 +63177,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
62617
63177
|
}
|
|
62618
63178
|
|
|
62619
63179
|
// src/permission/persona-paths.ts
|
|
62620
|
-
var
|
|
63180
|
+
var path75 = __toESM(require("path"), 1);
|
|
62621
63181
|
function getAllowedPersonaIds(grants, action) {
|
|
62622
63182
|
const ids = /* @__PURE__ */ new Set();
|
|
62623
63183
|
for (const g2 of grants) {
|
|
@@ -62630,42 +63190,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
62630
63190
|
return ids;
|
|
62631
63191
|
}
|
|
62632
63192
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
62633
|
-
const target =
|
|
63193
|
+
const target = path75.resolve(absPath);
|
|
62634
63194
|
if (userWorkDir) {
|
|
62635
|
-
const u =
|
|
62636
|
-
const usep = u.endsWith(
|
|
63195
|
+
const u = path75.resolve(userWorkDir);
|
|
63196
|
+
const usep = u.endsWith(path75.sep) ? "" : path75.sep;
|
|
62637
63197
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
62638
63198
|
}
|
|
62639
|
-
const root =
|
|
62640
|
-
const sep4 = root.endsWith(
|
|
63199
|
+
const root = path75.resolve(personaRoot);
|
|
63200
|
+
const sep4 = root.endsWith(path75.sep) ? "" : path75.sep;
|
|
62641
63201
|
if (!target.startsWith(root + sep4)) return false;
|
|
62642
|
-
const rel =
|
|
63202
|
+
const rel = path75.relative(root, target);
|
|
62643
63203
|
if (!rel || rel.startsWith("..")) return false;
|
|
62644
|
-
const personaId2 = rel.split(
|
|
63204
|
+
const personaId2 = rel.split(path75.sep)[0];
|
|
62645
63205
|
if (!personaId2) return false;
|
|
62646
63206
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
62647
63207
|
if (allowed === "*") return true;
|
|
62648
63208
|
return allowed.has(personaId2);
|
|
62649
63209
|
}
|
|
62650
63210
|
function personaIdFromPath(absPath, personaRoot) {
|
|
62651
|
-
const root =
|
|
62652
|
-
const target =
|
|
62653
|
-
const sep4 = root.endsWith(
|
|
63211
|
+
const root = path75.resolve(personaRoot);
|
|
63212
|
+
const target = path75.resolve(absPath);
|
|
63213
|
+
const sep4 = root.endsWith(path75.sep) ? "" : path75.sep;
|
|
62654
63214
|
if (!target.startsWith(root + sep4)) return null;
|
|
62655
|
-
const rel =
|
|
63215
|
+
const rel = path75.relative(root, target);
|
|
62656
63216
|
if (!rel || rel.startsWith("..")) return null;
|
|
62657
|
-
const id = rel.split(
|
|
63217
|
+
const id = rel.split(path75.sep)[0];
|
|
62658
63218
|
return id || null;
|
|
62659
63219
|
}
|
|
62660
63220
|
function isPathWithin(dir, absPath) {
|
|
62661
|
-
const d =
|
|
62662
|
-
const t =
|
|
62663
|
-
const sep4 = d.endsWith(
|
|
63221
|
+
const d = path75.resolve(dir);
|
|
63222
|
+
const t = path75.resolve(absPath);
|
|
63223
|
+
const sep4 = d.endsWith(path75.sep) ? "" : path75.sep;
|
|
62664
63224
|
return t === d || t.startsWith(d + sep4);
|
|
62665
63225
|
}
|
|
62666
63226
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
62667
63227
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
62668
|
-
return personaIdFromPath(
|
|
63228
|
+
return personaIdFromPath(path75.resolve(absPath), personaRoot) === personaId2;
|
|
62669
63229
|
}
|
|
62670
63230
|
|
|
62671
63231
|
// src/handlers/history.ts
|
|
@@ -62718,7 +63278,7 @@ function buildHistoryHandlers(deps) {
|
|
|
62718
63278
|
if (!pid) return false;
|
|
62719
63279
|
return isGuestPathAllowed(
|
|
62720
63280
|
ctx.grants,
|
|
62721
|
-
|
|
63281
|
+
path76.join(personaRoot, pid),
|
|
62722
63282
|
personaRoot,
|
|
62723
63283
|
"read",
|
|
62724
63284
|
userWorkDir
|
|
@@ -62730,7 +63290,7 @@ function buildHistoryHandlers(deps) {
|
|
|
62730
63290
|
};
|
|
62731
63291
|
const list = async (frame, _client, ctx) => {
|
|
62732
63292
|
const args = HistoryListArgs.parse(frame);
|
|
62733
|
-
assertGuestPath(ctx,
|
|
63293
|
+
assertGuestPath(ctx, path76.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
62734
63294
|
const sessions = await history.listSessions(args);
|
|
62735
63295
|
return { response: { type: "history:list", sessions } };
|
|
62736
63296
|
};
|
|
@@ -62778,14 +63338,14 @@ function buildHistoryHandlers(deps) {
|
|
|
62778
63338
|
};
|
|
62779
63339
|
const subagents = async (frame, _client, ctx) => {
|
|
62780
63340
|
const args = HistorySubagentsArgs.parse(frame);
|
|
62781
|
-
assertGuestPath(ctx,
|
|
63341
|
+
assertGuestPath(ctx, path76.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
62782
63342
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
62783
63343
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
62784
63344
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
62785
63345
|
};
|
|
62786
63346
|
const subagentRead = async (frame, _client, ctx) => {
|
|
62787
63347
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
62788
|
-
assertGuestPath(ctx,
|
|
63348
|
+
assertGuestPath(ctx, path76.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
62789
63349
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
62790
63350
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
62791
63351
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -62795,7 +63355,7 @@ function buildHistoryHandlers(deps) {
|
|
|
62795
63355
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
62796
63356
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
62797
63357
|
const filtered = dirs.filter(
|
|
62798
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
63358
|
+
(d) => isGuestPathAllowed(ctx.grants, path76.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
62799
63359
|
);
|
|
62800
63360
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
62801
63361
|
}
|
|
@@ -62812,17 +63372,17 @@ function buildHistoryHandlers(deps) {
|
|
|
62812
63372
|
}
|
|
62813
63373
|
|
|
62814
63374
|
// src/handlers/projects.ts
|
|
62815
|
-
var
|
|
62816
|
-
var
|
|
62817
|
-
var
|
|
62818
|
-
var
|
|
63375
|
+
var fs70 = __toESM(require("fs"), 1);
|
|
63376
|
+
var os22 = __toESM(require("os"), 1);
|
|
63377
|
+
var path77 = __toESM(require("path"), 1);
|
|
63378
|
+
var import_node_child_process14 = require("child_process");
|
|
62819
63379
|
init_protocol();
|
|
62820
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
63380
|
+
var DEFAULT_PROJECTS_ROOT = path77.join(os22.homedir(), "Documents", "ChatGPT");
|
|
62821
63381
|
function allocateDir(root, name) {
|
|
62822
|
-
let candidate =
|
|
63382
|
+
let candidate = path77.join(root, name);
|
|
62823
63383
|
let n = 2;
|
|
62824
|
-
while (
|
|
62825
|
-
candidate =
|
|
63384
|
+
while (fs70.existsSync(candidate)) {
|
|
63385
|
+
candidate = path77.join(root, `${name} ${n}`);
|
|
62826
63386
|
n += 1;
|
|
62827
63387
|
}
|
|
62828
63388
|
return candidate;
|
|
@@ -62850,11 +63410,11 @@ function buildProjectHandlers(deps) {
|
|
|
62850
63410
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
62851
63411
|
}
|
|
62852
63412
|
try {
|
|
62853
|
-
if (!
|
|
63413
|
+
if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
62854
63414
|
} catch {
|
|
62855
63415
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
62856
63416
|
}
|
|
62857
|
-
const r = (0,
|
|
63417
|
+
const r = (0, import_node_child_process14.spawnSync)("open", ["-R", args.path], { stdio: "ignore" });
|
|
62858
63418
|
if (r.status !== 0) {
|
|
62859
63419
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `open -R \u5931\u8D25: exit ${r.status}`);
|
|
62860
63420
|
}
|
|
@@ -62866,7 +63426,7 @@ function buildProjectHandlers(deps) {
|
|
|
62866
63426
|
let target;
|
|
62867
63427
|
if (args.path) {
|
|
62868
63428
|
try {
|
|
62869
|
-
if (!
|
|
63429
|
+
if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
62870
63430
|
} catch {
|
|
62871
63431
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
62872
63432
|
}
|
|
@@ -62874,15 +63434,15 @@ function buildProjectHandlers(deps) {
|
|
|
62874
63434
|
} else {
|
|
62875
63435
|
const name = args.name;
|
|
62876
63436
|
try {
|
|
62877
|
-
|
|
63437
|
+
fs70.mkdirSync(root, { recursive: true });
|
|
62878
63438
|
target = allocateDir(root, name);
|
|
62879
|
-
|
|
63439
|
+
fs70.mkdirSync(target);
|
|
62880
63440
|
} catch (err) {
|
|
62881
63441
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
62882
63442
|
}
|
|
62883
|
-
const git = (0,
|
|
63443
|
+
const git = (0, import_node_child_process14.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
62884
63444
|
if (git.status !== 0) {
|
|
62885
|
-
|
|
63445
|
+
fs70.rmSync(target, { recursive: true, force: true });
|
|
62886
63446
|
throw new ClawdError(
|
|
62887
63447
|
ERROR_CODES.INVALID_CWD,
|
|
62888
63448
|
`git init \u5931\u8D25\uFF08${git.error ? String(git.error) : `exit ${git.status}`}\uFF09: ${target}`
|
|
@@ -62907,8 +63467,8 @@ function buildProjectHandlers(deps) {
|
|
|
62907
63467
|
}
|
|
62908
63468
|
|
|
62909
63469
|
// src/handlers/workspace.ts
|
|
62910
|
-
var
|
|
62911
|
-
var
|
|
63470
|
+
var path78 = __toESM(require("path"), 1);
|
|
63471
|
+
var os23 = __toESM(require("os"), 1);
|
|
62912
63472
|
init_protocol();
|
|
62913
63473
|
init_protocol();
|
|
62914
63474
|
function buildEnabledPluginNames(personaManager, personaId2) {
|
|
@@ -62948,23 +63508,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
62948
63508
|
const list = async (frame, _client, ctx) => {
|
|
62949
63509
|
const args = WorkspaceListArgs.parse(frame);
|
|
62950
63510
|
const isGuest = ctx?.principal.kind === "guest";
|
|
62951
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
62952
|
-
const resolvedCwd =
|
|
62953
|
-
const target = args.path ?
|
|
63511
|
+
const fallbackCwd = isGuest && personaRoot ? personaRoot : os23.homedir();
|
|
63512
|
+
const resolvedCwd = path78.resolve(args.cwd ?? fallbackCwd);
|
|
63513
|
+
const target = args.path ? path78.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
62954
63514
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
62955
63515
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
62956
63516
|
return { response: { type: "workspace:list", ...res } };
|
|
62957
63517
|
};
|
|
62958
63518
|
const read = async (frame, _client, ctx) => {
|
|
62959
63519
|
const args = WorkspaceReadArgs.parse(frame);
|
|
62960
|
-
const target =
|
|
63520
|
+
const target = path78.isAbsolute(args.path) ? path78.resolve(args.path) : path78.resolve(args.cwd, args.path);
|
|
62961
63521
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
62962
63522
|
const res = workspace.read(args);
|
|
62963
63523
|
return { response: { type: "workspace:read", ...res } };
|
|
62964
63524
|
};
|
|
62965
63525
|
const skillsList = async (frame, _client, ctx) => {
|
|
62966
63526
|
const args = SkillsListArgs.parse(frame);
|
|
62967
|
-
const cwdAbs =
|
|
63527
|
+
const cwdAbs = path78.resolve(args.cwd);
|
|
62968
63528
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
62969
63529
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
62970
63530
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -62976,7 +63536,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
62976
63536
|
};
|
|
62977
63537
|
const agentsList = async (frame, _client, ctx) => {
|
|
62978
63538
|
const args = AgentsListArgs.parse(frame);
|
|
62979
|
-
const cwdAbs =
|
|
63539
|
+
const cwdAbs = path78.resolve(args.cwd);
|
|
62980
63540
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
62981
63541
|
if (args.tool === "codex") {
|
|
62982
63542
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -62998,18 +63558,18 @@ function buildWorkspaceHandlers(deps) {
|
|
|
62998
63558
|
}
|
|
62999
63559
|
|
|
63000
63560
|
// src/handlers/git.ts
|
|
63001
|
-
var
|
|
63561
|
+
var path80 = __toESM(require("path"), 1);
|
|
63002
63562
|
init_protocol();
|
|
63003
63563
|
init_protocol();
|
|
63004
63564
|
|
|
63005
63565
|
// src/workspace/git.ts
|
|
63006
|
-
var
|
|
63566
|
+
var import_node_child_process15 = require("child_process");
|
|
63007
63567
|
var import_node_fs51 = __toESM(require("fs"), 1);
|
|
63008
|
-
var
|
|
63568
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
63009
63569
|
var import_node_util = require("util");
|
|
63010
|
-
var pexec = (0, import_node_util.promisify)(
|
|
63570
|
+
var pexec = (0, import_node_util.promisify)(import_node_child_process15.execFile);
|
|
63011
63571
|
function normalizePath(p2) {
|
|
63012
|
-
const resolved =
|
|
63572
|
+
const resolved = import_node_path62.default.resolve(p2);
|
|
63013
63573
|
try {
|
|
63014
63574
|
return import_node_fs51.default.realpathSync(resolved);
|
|
63015
63575
|
} catch {
|
|
@@ -63085,7 +63645,7 @@ async function listGitBranches(cwd) {
|
|
|
63085
63645
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
63086
63646
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
63087
63647
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
63088
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
63648
|
+
if (!isGuestPathAllowed(ctx.grants, path80.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
63089
63649
|
throw new ClawdError(
|
|
63090
63650
|
ERROR_CODES.UNAUTHORIZED,
|
|
63091
63651
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -63630,7 +64190,7 @@ function buildFeishuAuthHandlers(deps) {
|
|
|
63630
64190
|
}
|
|
63631
64191
|
|
|
63632
64192
|
// src/handlers/meta.ts
|
|
63633
|
-
var
|
|
64193
|
+
var import_node_os21 = __toESM(require("os"), 1);
|
|
63634
64194
|
init_protocol();
|
|
63635
64195
|
|
|
63636
64196
|
// src/handlers/method-grants.ts
|
|
@@ -63685,6 +64245,8 @@ var METHOD_GRANT_MAP = {
|
|
|
63685
64245
|
"deploy:putSecret": ADMIN_ANY,
|
|
63686
64246
|
"deploy:reportFinding": ADMIN_ANY,
|
|
63687
64247
|
"deploy:finishScan": ADMIN_ANY,
|
|
64248
|
+
"deploy:trial": ADMIN_ANY,
|
|
64249
|
+
"deploy:deploy": ADMIN_ANY,
|
|
63688
64250
|
"deploy:remove": ADMIN_ANY,
|
|
63689
64251
|
// ---- session:* / chat:* 业务方法(v2 Phase 8 两层模型)----
|
|
63690
64252
|
// dispatcher 不验资源,handler 内按 ctx + frame.args 反查 ownerPersonaId 调 assertGrant。
|
|
@@ -63931,21 +64493,21 @@ function computeMethodAccess(args) {
|
|
|
63931
64493
|
}
|
|
63932
64494
|
|
|
63933
64495
|
// src/version.ts
|
|
63934
|
-
var version = "0.2.
|
|
64496
|
+
var version = "0.2.461".length > 0 ? "0.2.461" : "dev";
|
|
63935
64497
|
|
|
63936
64498
|
// src/cli-probe/probe.ts
|
|
63937
|
-
var
|
|
63938
|
-
var
|
|
64499
|
+
var fs72 = __toESM(require("fs"), 1);
|
|
64500
|
+
var path81 = __toESM(require("path"), 1);
|
|
63939
64501
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
63940
64502
|
var BIN_NAME = "clawd";
|
|
63941
64503
|
var MAX_PARENT_HOPS = 5;
|
|
63942
64504
|
function probeGlobalCli(pathEnv) {
|
|
63943
64505
|
if (!pathEnv) return null;
|
|
63944
|
-
for (const dir of pathEnv.split(
|
|
64506
|
+
for (const dir of pathEnv.split(path81.delimiter)) {
|
|
63945
64507
|
if (!dir) continue;
|
|
63946
64508
|
let real;
|
|
63947
64509
|
try {
|
|
63948
|
-
real =
|
|
64510
|
+
real = fs72.realpathSync(path81.join(dir, BIN_NAME));
|
|
63949
64511
|
} catch {
|
|
63950
64512
|
continue;
|
|
63951
64513
|
}
|
|
@@ -63955,15 +64517,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
63955
64517
|
return null;
|
|
63956
64518
|
}
|
|
63957
64519
|
function readOwnPackageVersion(entryPath) {
|
|
63958
|
-
let dir =
|
|
64520
|
+
let dir = path81.dirname(entryPath);
|
|
63959
64521
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
63960
64522
|
try {
|
|
63961
|
-
const raw =
|
|
64523
|
+
const raw = fs72.readFileSync(path81.join(dir, "package.json"), "utf8");
|
|
63962
64524
|
const pkg = JSON.parse(raw);
|
|
63963
64525
|
if (pkg.name !== PKG_NAME) return null;
|
|
63964
64526
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
63965
64527
|
} catch {
|
|
63966
|
-
const parent =
|
|
64528
|
+
const parent = path81.dirname(dir);
|
|
63967
64529
|
if (parent === dir) return null;
|
|
63968
64530
|
dir = parent;
|
|
63969
64531
|
}
|
|
@@ -63999,7 +64561,7 @@ function buildReadyFrame(deps, client) {
|
|
|
63999
64561
|
return {
|
|
64000
64562
|
version,
|
|
64001
64563
|
protocolVersion: PROTOCOL_VERSION,
|
|
64002
|
-
hostname:
|
|
64564
|
+
hostname: import_node_os21.default.hostname(),
|
|
64003
64565
|
os: process.platform,
|
|
64004
64566
|
tools,
|
|
64005
64567
|
runningSessions: info.runningSessions,
|
|
@@ -64135,7 +64697,7 @@ function buildPersonaHandlers(deps) {
|
|
|
64135
64697
|
}
|
|
64136
64698
|
|
|
64137
64699
|
// src/handlers/attachment.ts
|
|
64138
|
-
var
|
|
64700
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
64139
64701
|
init_protocol();
|
|
64140
64702
|
init_protocol();
|
|
64141
64703
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -64215,12 +64777,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
64215
64777
|
`session ${args.sessionId} scope unresolved`
|
|
64216
64778
|
);
|
|
64217
64779
|
}
|
|
64218
|
-
const cwdAbs =
|
|
64219
|
-
const candidateAbs =
|
|
64780
|
+
const cwdAbs = import_node_path63.default.resolve(sessionFile.cwd);
|
|
64781
|
+
const candidateAbs = import_node_path63.default.isAbsolute(args.relPath) ? import_node_path63.default.resolve(args.relPath) : import_node_path63.default.resolve(cwdAbs, args.relPath);
|
|
64220
64782
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
64221
64783
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
64222
64784
|
const entry = entries.find((e) => {
|
|
64223
|
-
const storedAbs =
|
|
64785
|
+
const storedAbs = import_node_path63.default.isAbsolute(e.relPath) ? import_node_path63.default.resolve(e.relPath) : import_node_path63.default.resolve(cwdAbs, e.relPath);
|
|
64224
64786
|
return storedAbs === candidateAbs && !e.stale;
|
|
64225
64787
|
});
|
|
64226
64788
|
if (!entry) {
|
|
@@ -64245,7 +64807,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
64245
64807
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
64246
64808
|
const f = deps.sessionStore.read(sessionId);
|
|
64247
64809
|
if (!f) return;
|
|
64248
|
-
assertGuestAttachmentPath(ctx,
|
|
64810
|
+
assertGuestAttachmentPath(ctx, import_node_path63.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
64249
64811
|
}
|
|
64250
64812
|
const groupAdd = async (frame, _client, ctx) => {
|
|
64251
64813
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -64260,8 +64822,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
64260
64822
|
if (!scope) {
|
|
64261
64823
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
64262
64824
|
}
|
|
64263
|
-
const cwdAbs =
|
|
64264
|
-
const candidateAbs =
|
|
64825
|
+
const cwdAbs = import_node_path63.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
64826
|
+
const candidateAbs = import_node_path63.default.isAbsolute(args.relPath) ? import_node_path63.default.resolve(args.relPath) : import_node_path63.default.resolve(cwdAbs, args.relPath);
|
|
64265
64827
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
64266
64828
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
64267
64829
|
const size = 0;
|
|
@@ -64319,21 +64881,21 @@ function buildAttachmentHandlers(deps) {
|
|
|
64319
64881
|
}
|
|
64320
64882
|
|
|
64321
64883
|
// src/handlers/extension.ts
|
|
64322
|
-
var
|
|
64323
|
-
var
|
|
64884
|
+
var import_promises16 = __toESM(require("fs/promises"), 1);
|
|
64885
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
64324
64886
|
init_protocol();
|
|
64325
64887
|
|
|
64326
64888
|
// src/extension/bundle-zip.ts
|
|
64327
|
-
var
|
|
64328
|
-
var
|
|
64889
|
+
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
64890
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
64329
64891
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
64330
64892
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
64331
64893
|
async function bundleExtensionDir(dir) {
|
|
64332
64894
|
const entries = await listFilesSorted(dir);
|
|
64333
64895
|
const zip = new import_jszip2.default();
|
|
64334
64896
|
for (const rel of entries) {
|
|
64335
|
-
const abs =
|
|
64336
|
-
const content = await
|
|
64897
|
+
const abs = import_node_path64.default.join(dir, rel);
|
|
64898
|
+
const content = await import_promises13.default.readFile(abs);
|
|
64337
64899
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
64338
64900
|
}
|
|
64339
64901
|
const buffer = await zip.generateAsync({
|
|
@@ -64353,8 +64915,8 @@ async function listFilesSorted(rootDir) {
|
|
|
64353
64915
|
return out;
|
|
64354
64916
|
}
|
|
64355
64917
|
async function walk(absRoot, relPrefix, out) {
|
|
64356
|
-
const dirAbs =
|
|
64357
|
-
const entries = await
|
|
64918
|
+
const dirAbs = import_node_path64.default.join(absRoot, relPrefix);
|
|
64919
|
+
const entries = await import_promises13.default.readdir(dirAbs, { withFileTypes: true });
|
|
64358
64920
|
for (const e of entries) {
|
|
64359
64921
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
64360
64922
|
const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
|
|
@@ -64406,26 +64968,26 @@ function computePublishCheck(args) {
|
|
|
64406
64968
|
}
|
|
64407
64969
|
|
|
64408
64970
|
// src/extension/install-flow.ts
|
|
64409
|
-
var
|
|
64410
|
-
var
|
|
64411
|
-
var
|
|
64971
|
+
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
64972
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
64973
|
+
var import_node_os23 = __toESM(require("os"), 1);
|
|
64412
64974
|
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
64413
64975
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
64414
64976
|
|
|
64415
64977
|
// src/extension/paths.ts
|
|
64416
|
-
var
|
|
64417
|
-
var
|
|
64978
|
+
var import_node_os22 = __toESM(require("os"), 1);
|
|
64979
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
64418
64980
|
function clawdHomeRoot(override) {
|
|
64419
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
64981
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path65.default.join(import_node_os22.default.homedir(), ".clawd");
|
|
64420
64982
|
}
|
|
64421
64983
|
function extensionsRoot(override) {
|
|
64422
|
-
return
|
|
64984
|
+
return import_node_path65.default.join(clawdHomeRoot(override), "extensions");
|
|
64423
64985
|
}
|
|
64424
64986
|
function publishedChannelsFile(override) {
|
|
64425
|
-
return
|
|
64987
|
+
return import_node_path65.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
64426
64988
|
}
|
|
64427
64989
|
function bundleCacheRoot(override) {
|
|
64428
|
-
return
|
|
64990
|
+
return import_node_path65.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
64429
64991
|
}
|
|
64430
64992
|
|
|
64431
64993
|
// src/extension/install-flow.ts
|
|
@@ -64452,7 +65014,7 @@ async function installFromChannel(args, deps) {
|
|
|
64452
65014
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
64453
65015
|
}
|
|
64454
65016
|
for (const name of Object.keys(zip.files)) {
|
|
64455
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
65017
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path66.default.isAbsolute(name)) {
|
|
64456
65018
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
64457
65019
|
}
|
|
64458
65020
|
}
|
|
@@ -64484,10 +65046,10 @@ async function installFromChannel(args, deps) {
|
|
|
64484
65046
|
);
|
|
64485
65047
|
}
|
|
64486
65048
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
64487
|
-
const destDir =
|
|
65049
|
+
const destDir = import_node_path66.default.join(deps.extensionsRoot, localExtId);
|
|
64488
65050
|
let destExists = false;
|
|
64489
65051
|
try {
|
|
64490
|
-
await
|
|
65052
|
+
await import_promises14.default.access(destDir);
|
|
64491
65053
|
destExists = true;
|
|
64492
65054
|
} catch {
|
|
64493
65055
|
}
|
|
@@ -64497,28 +65059,28 @@ async function installFromChannel(args, deps) {
|
|
|
64497
65059
|
`extension ${localExtId} already installed locally (from owner ${channelRef.ownerPrincipalId})`
|
|
64498
65060
|
);
|
|
64499
65061
|
}
|
|
64500
|
-
const stage = await
|
|
64501
|
-
|
|
65062
|
+
const stage = await import_promises14.default.mkdtemp(
|
|
65063
|
+
import_node_path66.default.join(import_node_os23.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
64502
65064
|
);
|
|
64503
65065
|
try {
|
|
64504
65066
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
64505
|
-
const dest =
|
|
65067
|
+
const dest = import_node_path66.default.join(stage, name);
|
|
64506
65068
|
if (entry.dir) {
|
|
64507
|
-
await
|
|
65069
|
+
await import_promises14.default.mkdir(dest, { recursive: true });
|
|
64508
65070
|
continue;
|
|
64509
65071
|
}
|
|
64510
|
-
await
|
|
65072
|
+
await import_promises14.default.mkdir(import_node_path66.default.dirname(dest), { recursive: true });
|
|
64511
65073
|
if (name === "manifest.json") {
|
|
64512
65074
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
64513
|
-
await
|
|
65075
|
+
await import_promises14.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
64514
65076
|
} else {
|
|
64515
|
-
await
|
|
65077
|
+
await import_promises14.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
64516
65078
|
}
|
|
64517
65079
|
}
|
|
64518
|
-
await
|
|
64519
|
-
await
|
|
65080
|
+
await import_promises14.default.mkdir(deps.extensionsRoot, { recursive: true });
|
|
65081
|
+
await import_promises14.default.rename(stage, destDir);
|
|
64520
65082
|
} catch (e) {
|
|
64521
|
-
await
|
|
65083
|
+
await import_promises14.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
64522
65084
|
});
|
|
64523
65085
|
throw e;
|
|
64524
65086
|
}
|
|
@@ -64527,9 +65089,9 @@ async function installFromChannel(args, deps) {
|
|
|
64527
65089
|
}
|
|
64528
65090
|
|
|
64529
65091
|
// src/extension/update-flow.ts
|
|
64530
|
-
var
|
|
64531
|
-
var
|
|
64532
|
-
var
|
|
65092
|
+
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
65093
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
65094
|
+
var import_node_os24 = __toESM(require("os"), 1);
|
|
64533
65095
|
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
64534
65096
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
64535
65097
|
var UpdateError = class extends Error {
|
|
@@ -64545,11 +65107,11 @@ async function updateFromChannel(args, deps) {
|
|
|
64545
65107
|
channelRef.extId,
|
|
64546
65108
|
channelRef.ownerPrincipalId
|
|
64547
65109
|
);
|
|
64548
|
-
const liveDir =
|
|
65110
|
+
const liveDir = import_node_path67.default.join(deps.extensionsRoot, localExtId);
|
|
64549
65111
|
const prevDir = `${liveDir}.prev`;
|
|
64550
65112
|
let existingVersion;
|
|
64551
65113
|
try {
|
|
64552
|
-
const raw = await
|
|
65114
|
+
const raw = await import_promises15.default.readFile(import_node_path67.default.join(liveDir, "manifest.json"), "utf8");
|
|
64553
65115
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
64554
65116
|
if (!parsed2.success) {
|
|
64555
65117
|
throw new UpdateError(
|
|
@@ -64582,7 +65144,7 @@ async function updateFromChannel(args, deps) {
|
|
|
64582
65144
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
64583
65145
|
}
|
|
64584
65146
|
for (const name of Object.keys(zip.files)) {
|
|
64585
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
65147
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path67.default.isAbsolute(name)) {
|
|
64586
65148
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
64587
65149
|
}
|
|
64588
65150
|
}
|
|
@@ -64614,31 +65176,31 @@ async function updateFromChannel(args, deps) {
|
|
|
64614
65176
|
);
|
|
64615
65177
|
}
|
|
64616
65178
|
await deps.runtime.close(localExtId);
|
|
64617
|
-
await
|
|
64618
|
-
await
|
|
64619
|
-
const stage = await
|
|
64620
|
-
|
|
65179
|
+
await import_promises15.default.rm(prevDir, { recursive: true, force: true });
|
|
65180
|
+
await import_promises15.default.rename(liveDir, prevDir);
|
|
65181
|
+
const stage = await import_promises15.default.mkdtemp(
|
|
65182
|
+
import_node_path67.default.join(import_node_os24.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
64621
65183
|
);
|
|
64622
65184
|
try {
|
|
64623
65185
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
64624
|
-
const dest =
|
|
65186
|
+
const dest = import_node_path67.default.join(stage, name);
|
|
64625
65187
|
if (entry.dir) {
|
|
64626
|
-
await
|
|
65188
|
+
await import_promises15.default.mkdir(dest, { recursive: true });
|
|
64627
65189
|
continue;
|
|
64628
65190
|
}
|
|
64629
|
-
await
|
|
65191
|
+
await import_promises15.default.mkdir(import_node_path67.default.dirname(dest), { recursive: true });
|
|
64630
65192
|
if (name === "manifest.json") {
|
|
64631
65193
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
64632
|
-
await
|
|
65194
|
+
await import_promises15.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
64633
65195
|
} else {
|
|
64634
|
-
await
|
|
65196
|
+
await import_promises15.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
64635
65197
|
}
|
|
64636
65198
|
}
|
|
64637
|
-
await
|
|
65199
|
+
await import_promises15.default.rename(stage, liveDir);
|
|
64638
65200
|
} catch (e) {
|
|
64639
|
-
await
|
|
65201
|
+
await import_promises15.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
64640
65202
|
});
|
|
64641
|
-
await
|
|
65203
|
+
await import_promises15.default.rename(prevDir, liveDir).catch(() => {
|
|
64642
65204
|
});
|
|
64643
65205
|
await deps.runtime.open(localExtId).catch(() => {
|
|
64644
65206
|
});
|
|
@@ -64660,7 +65222,7 @@ async function updateFromChannel(args, deps) {
|
|
|
64660
65222
|
reason: e.message
|
|
64661
65223
|
};
|
|
64662
65224
|
}
|
|
64663
|
-
await
|
|
65225
|
+
await import_promises15.default.rm(prevDir, { recursive: true, force: true });
|
|
64664
65226
|
return {
|
|
64665
65227
|
kind: "updated",
|
|
64666
65228
|
extId: localExtId,
|
|
@@ -64668,9 +65230,9 @@ async function updateFromChannel(args, deps) {
|
|
|
64668
65230
|
};
|
|
64669
65231
|
}
|
|
64670
65232
|
async function rollback(deps, localExtId, liveDir, prevDir) {
|
|
64671
|
-
await
|
|
65233
|
+
await import_promises15.default.rm(liveDir, { recursive: true, force: true }).catch(() => {
|
|
64672
65234
|
});
|
|
64673
|
-
await
|
|
65235
|
+
await import_promises15.default.rename(prevDir, liveDir).catch(() => {
|
|
64674
65236
|
});
|
|
64675
65237
|
await deps.runtime.open(localExtId).catch(() => {
|
|
64676
65238
|
});
|
|
@@ -64693,18 +65255,18 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
64693
65255
|
);
|
|
64694
65256
|
}
|
|
64695
65257
|
}
|
|
64696
|
-
const manifestPath =
|
|
65258
|
+
const manifestPath = import_node_path68.default.join(root, extId, "manifest.json");
|
|
64697
65259
|
const manifest = await readManifest(root, extId);
|
|
64698
65260
|
const next = { ...manifest, version: newVersion };
|
|
64699
65261
|
const tmp = `${manifestPath}.tmp`;
|
|
64700
|
-
await
|
|
64701
|
-
await
|
|
65262
|
+
await import_promises16.default.writeFile(tmp, JSON.stringify(next, null, 2));
|
|
65263
|
+
await import_promises16.default.rename(tmp, manifestPath);
|
|
64702
65264
|
}
|
|
64703
65265
|
async function readManifest(root, extId) {
|
|
64704
|
-
const file =
|
|
65266
|
+
const file = import_node_path68.default.join(root, extId, "manifest.json");
|
|
64705
65267
|
let raw;
|
|
64706
65268
|
try {
|
|
64707
|
-
raw = await
|
|
65269
|
+
raw = await import_promises16.default.readFile(file, "utf8");
|
|
64708
65270
|
} catch (e) {
|
|
64709
65271
|
if (e.code === "ENOENT") {
|
|
64710
65272
|
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `extension ${extId} not installed`);
|
|
@@ -64785,7 +65347,7 @@ function buildExtensionHandlers(deps) {
|
|
|
64785
65347
|
};
|
|
64786
65348
|
async function buildSnapshotMeta(extId) {
|
|
64787
65349
|
const manifest = await readManifest(deps.root, extId);
|
|
64788
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
65350
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path68.default.join(deps.root, extId));
|
|
64789
65351
|
return { manifest, contentHash: sha256, buffer };
|
|
64790
65352
|
}
|
|
64791
65353
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -64960,7 +65522,7 @@ function buildExtensionHandlers(deps) {
|
|
|
64960
65522
|
}
|
|
64961
65523
|
|
|
64962
65524
|
// src/app-builder/kill-port.ts
|
|
64963
|
-
var
|
|
65525
|
+
var import_node_child_process16 = require("child_process");
|
|
64964
65526
|
async function killPortOccupants(port, ownedPids, logger) {
|
|
64965
65527
|
let pids;
|
|
64966
65528
|
try {
|
|
@@ -65002,7 +65564,7 @@ async function killPortOccupants(port, ownedPids, logger) {
|
|
|
65002
65564
|
}
|
|
65003
65565
|
function listPidsOnPort(port) {
|
|
65004
65566
|
return new Promise((resolve9, reject) => {
|
|
65005
|
-
(0,
|
|
65567
|
+
(0, import_node_child_process16.execFile)(
|
|
65006
65568
|
"lsof",
|
|
65007
65569
|
["-ti", `:${port}`],
|
|
65008
65570
|
{ timeout: 3e3 },
|
|
@@ -65028,7 +65590,7 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
|
65028
65590
|
|
|
65029
65591
|
// src/handlers/app-builder.ts
|
|
65030
65592
|
init_protocol();
|
|
65031
|
-
var
|
|
65593
|
+
var import_node_path69 = require("path");
|
|
65032
65594
|
var import_node_fs52 = require("fs");
|
|
65033
65595
|
var DEFAULT_TEMPLATE = "nestjs-react";
|
|
65034
65596
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
@@ -65175,13 +65737,13 @@ function buildAppBuilderHandlers(deps) {
|
|
|
65175
65737
|
const created = await deps.createProjectOnDisk({
|
|
65176
65738
|
store: userStore,
|
|
65177
65739
|
name: f.name,
|
|
65178
|
-
templateSrcDir: (0,
|
|
65179
|
-
scaffoldScript: (0,
|
|
65740
|
+
templateSrcDir: (0, import_node_path69.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
|
|
65741
|
+
scaffoldScript: (0, import_node_path69.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
|
|
65180
65742
|
reservedPorts,
|
|
65181
65743
|
// 凭据只进 scaffold 子进程的 env,且**只给这个 persona 的 kit 模板声明要的那几个变量**
|
|
65182
65744
|
// (M1b Step 5)。整表塞进去粒度只到「进程」——那会把 service-role key 交给一个用不到
|
|
65183
65745
|
// 它的脚本。new-extension.sh 用它把模板的 `${VAR}` 渲成项目可跑的 server/.env。
|
|
65184
|
-
extraEnv: secretsForKit(deps.readSecrets?.(), (0,
|
|
65746
|
+
extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path69.join)(personaRoot, "extension-kit")),
|
|
65185
65747
|
...deps.logger ? { logger: deps.logger } : {}
|
|
65186
65748
|
});
|
|
65187
65749
|
project = created.project;
|
|
@@ -65380,7 +65942,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
65380
65942
|
await userStore.clearPublishJob(args.name);
|
|
65381
65943
|
}
|
|
65382
65944
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
65383
|
-
const scriptPath = (0,
|
|
65945
|
+
const scriptPath = (0, import_node_path69.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
65384
65946
|
deps.logger?.info("app-builder.publish.start", {
|
|
65385
65947
|
name: args.name,
|
|
65386
65948
|
sessionId: boundSession.sessionId,
|
|
@@ -65396,7 +65958,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
65396
65958
|
// 凭据只进 publish.sh 这个子进程的 env,且只给它的 kit 模板声明要的那几个变量
|
|
65397
65959
|
// (M1b Step 5)。那个进程里跑着 `eval "$BUILD_CMD"`——项目自带的构建命令会继承这份
|
|
65398
65960
|
// env,多给一个变量就是多交一个凭据给它。personaRoot 上面已按绑定 session 的 persona 解析。
|
|
65399
|
-
extraEnv: secretsForKit(deps.readSecrets?.(), (0,
|
|
65961
|
+
extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path69.join)(personaRoot, "extension-kit")),
|
|
65400
65962
|
hooks: {
|
|
65401
65963
|
// 元数据每次写盘(publishJob 起落 / prodUrl 回填)后重推一帧:UI 渲染 PublishProgress
|
|
65402
65964
|
// 三段 checklist 依赖 project.publishJob.status==='in-flight',而 publishJob 字段只有
|
|
@@ -65804,7 +66366,7 @@ function buildTopicHandlers(deps) {
|
|
|
65804
66366
|
init_protocol();
|
|
65805
66367
|
|
|
65806
66368
|
// src/channel/authority.ts
|
|
65807
|
-
var
|
|
66369
|
+
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
65808
66370
|
init_protocol();
|
|
65809
66371
|
var DEFAULT_AUTHORITY_RULES = [
|
|
65810
66372
|
{ id: "outbound-message", desc: "\u4EE5\u8001\u677F\u540D\u4E49\u7ED9\u5176\u4ED6\u4EBA\u53D1\u6D88\u606F\uFF08IM/\u90AE\u4EF6\uFF09", action: "ask" },
|
|
@@ -65822,7 +66384,7 @@ async function resolveAuthority(args) {
|
|
|
65822
66384
|
let source;
|
|
65823
66385
|
let raw = null;
|
|
65824
66386
|
try {
|
|
65825
|
-
raw = await
|
|
66387
|
+
raw = await import_promises17.default.readFile(args.tablePath, "utf8");
|
|
65826
66388
|
} catch (e) {
|
|
65827
66389
|
if (e.code !== "ENOENT") {
|
|
65828
66390
|
return askBecause(`\u6388\u6743\u8BBE\u5B9A\u8BFB\u4E0D\u51FA\u6765\uFF08${args.tablePath}\uFF09\uFF1A${e.message}`);
|
|
@@ -66131,12 +66693,12 @@ function buildVisitorHandlers(deps) {
|
|
|
66131
66693
|
}
|
|
66132
66694
|
|
|
66133
66695
|
// src/extension/registry.ts
|
|
66134
|
-
var
|
|
66135
|
-
var
|
|
66696
|
+
var import_promises18 = __toESM(require("fs/promises"), 1);
|
|
66697
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
66136
66698
|
async function loadAll(root) {
|
|
66137
66699
|
let entries;
|
|
66138
66700
|
try {
|
|
66139
|
-
entries = await
|
|
66701
|
+
entries = await import_promises18.default.readdir(root, { withFileTypes: true });
|
|
66140
66702
|
} catch (e) {
|
|
66141
66703
|
if (e.code === "ENOENT") return [];
|
|
66142
66704
|
throw e;
|
|
@@ -66145,16 +66707,16 @@ async function loadAll(root) {
|
|
|
66145
66707
|
for (const ent of entries) {
|
|
66146
66708
|
if (!ent.isDirectory()) continue;
|
|
66147
66709
|
if (ent.name.startsWith(".")) continue;
|
|
66148
|
-
records.push(await loadOne(
|
|
66710
|
+
records.push(await loadOne(import_node_path70.default.join(root, ent.name), ent.name));
|
|
66149
66711
|
}
|
|
66150
66712
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
66151
66713
|
return records;
|
|
66152
66714
|
}
|
|
66153
66715
|
async function loadOne(dir, dirName) {
|
|
66154
|
-
const manifestPath =
|
|
66716
|
+
const manifestPath = import_node_path70.default.join(dir, "manifest.json");
|
|
66155
66717
|
let raw;
|
|
66156
66718
|
try {
|
|
66157
|
-
raw = await
|
|
66719
|
+
raw = await import_promises18.default.readFile(manifestPath, "utf8");
|
|
66158
66720
|
} catch {
|
|
66159
66721
|
return {
|
|
66160
66722
|
extId: dirName,
|
|
@@ -66195,8 +66757,8 @@ async function loadOne(dir, dirName) {
|
|
|
66195
66757
|
}
|
|
66196
66758
|
|
|
66197
66759
|
// src/extension/uninstall.ts
|
|
66198
|
-
var
|
|
66199
|
-
var
|
|
66760
|
+
var import_promises19 = __toESM(require("fs/promises"), 1);
|
|
66761
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
66200
66762
|
var UninstallError = class extends Error {
|
|
66201
66763
|
constructor(code, message) {
|
|
66202
66764
|
super(message);
|
|
@@ -66205,14 +66767,14 @@ var UninstallError = class extends Error {
|
|
|
66205
66767
|
code;
|
|
66206
66768
|
};
|
|
66207
66769
|
async function uninstall(deps) {
|
|
66208
|
-
const dir =
|
|
66770
|
+
const dir = import_node_path71.default.join(deps.root, deps.extId);
|
|
66209
66771
|
try {
|
|
66210
|
-
await
|
|
66772
|
+
await import_promises19.default.access(dir);
|
|
66211
66773
|
} catch {
|
|
66212
66774
|
throw new UninstallError("NOT_FOUND", `extension ${deps.extId} not installed`);
|
|
66213
66775
|
}
|
|
66214
66776
|
await deps.runtime.close(deps.extId);
|
|
66215
|
-
await
|
|
66777
|
+
await import_promises19.default.rm(dir, { recursive: true, force: true });
|
|
66216
66778
|
}
|
|
66217
66779
|
|
|
66218
66780
|
// src/handlers/index.ts
|
|
@@ -66222,15 +66784,15 @@ var import_node_crypto20 = require("crypto");
|
|
|
66222
66784
|
init_protocol();
|
|
66223
66785
|
|
|
66224
66786
|
// src/peer-ops/run-command.ts
|
|
66225
|
-
var
|
|
66226
|
-
var
|
|
66787
|
+
var import_node_child_process17 = require("child_process");
|
|
66788
|
+
var import_node_os25 = __toESM(require("os"), 1);
|
|
66227
66789
|
var DEFAULT_TIMEOUT_MS5 = 3e4;
|
|
66228
66790
|
var MAX_TIMEOUT_MS = 3e5;
|
|
66229
66791
|
var MAX_OUTPUT_BYTES = 1048576;
|
|
66230
66792
|
function runCommand(command, opts = {}) {
|
|
66231
66793
|
const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5, MAX_TIMEOUT_MS);
|
|
66232
66794
|
return new Promise((resolve9) => {
|
|
66233
|
-
const child = (0,
|
|
66795
|
+
const child = (0, import_node_child_process17.spawn)("bash", ["-c", command], { cwd: import_node_os25.default.homedir() });
|
|
66234
66796
|
const out = [];
|
|
66235
66797
|
const err = [];
|
|
66236
66798
|
let outBytes = 0;
|
|
@@ -66441,7 +67003,7 @@ function buildMethodHandlers(deps) {
|
|
|
66441
67003
|
broadcast: deps.broadcastToOwners
|
|
66442
67004
|
}),
|
|
66443
67005
|
...buildMasterHandlers({
|
|
66444
|
-
authorityTablePath:
|
|
67006
|
+
authorityTablePath: import_node_path72.default.join(deps.masterDataDir, "master-authority.json")
|
|
66445
67007
|
}),
|
|
66446
67008
|
...buildTopicHandlers({
|
|
66447
67009
|
topicStore: deps.topicStore,
|
|
@@ -66472,23 +67034,23 @@ function buildMethodHandlers(deps) {
|
|
|
66472
67034
|
init_protocol();
|
|
66473
67035
|
|
|
66474
67036
|
// src/tools/version-probe.ts
|
|
66475
|
-
var
|
|
67037
|
+
var import_node_child_process19 = require("child_process");
|
|
66476
67038
|
init_claude();
|
|
66477
67039
|
|
|
66478
67040
|
// src/tools/shell-path.ts
|
|
66479
|
-
var
|
|
66480
|
-
var
|
|
67041
|
+
var import_node_child_process18 = require("child_process");
|
|
67042
|
+
var import_node_os26 = __toESM(require("os"), 1);
|
|
66481
67043
|
function refreshPathFromLoginShell() {
|
|
66482
67044
|
if (process.platform === "win32") return;
|
|
66483
|
-
const shell = process.env.SHELL ??
|
|
67045
|
+
const shell = process.env.SHELL ?? import_node_os26.default.userInfo().shell ?? "/bin/zsh";
|
|
66484
67046
|
try {
|
|
66485
|
-
const out = (0,
|
|
67047
|
+
const out = (0, import_node_child_process18.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
|
|
66486
67048
|
encoding: "utf8",
|
|
66487
67049
|
timeout: 3e3,
|
|
66488
67050
|
stdio: ["ignore", "pipe", "ignore"]
|
|
66489
67051
|
});
|
|
66490
|
-
const
|
|
66491
|
-
if (
|
|
67052
|
+
const path98 = out.trim();
|
|
67053
|
+
if (path98) process.env.PATH = path98;
|
|
66492
67054
|
} catch {
|
|
66493
67055
|
}
|
|
66494
67056
|
}
|
|
@@ -66499,7 +67061,7 @@ function parseVersionOutput(out) {
|
|
|
66499
67061
|
}
|
|
66500
67062
|
function execVersion(bin) {
|
|
66501
67063
|
return new Promise((resolve9, reject) => {
|
|
66502
|
-
(0,
|
|
67064
|
+
(0, import_node_child_process19.execFile)(bin, ["--version"], { timeout: 5e3 }, (err, stdout) => {
|
|
66503
67065
|
if (err) reject(err);
|
|
66504
67066
|
else resolve9(String(stdout));
|
|
66505
67067
|
});
|
|
@@ -66613,8 +67175,8 @@ function buildOnboardingHandlers(deps) {
|
|
|
66613
67175
|
|
|
66614
67176
|
// src/app-builder-plugin/project-store.ts
|
|
66615
67177
|
var import_node_fs53 = require("fs");
|
|
66616
|
-
var
|
|
66617
|
-
var
|
|
67178
|
+
var import_node_child_process20 = require("child_process");
|
|
67179
|
+
var import_node_path73 = require("path");
|
|
66618
67180
|
init_protocol();
|
|
66619
67181
|
var PROJECTS_DIR = "projects";
|
|
66620
67182
|
var META_FILE = ".clawd-project.json";
|
|
@@ -66644,14 +67206,14 @@ var ProjectStore = class {
|
|
|
66644
67206
|
}
|
|
66645
67207
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
66646
67208
|
metaPath(name) {
|
|
66647
|
-
return (0,
|
|
67209
|
+
return (0, import_node_path73.join)(this.projectsRoot(), name, META_FILE);
|
|
66648
67210
|
}
|
|
66649
67211
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
66650
67212
|
projectDir(name) {
|
|
66651
|
-
return (0,
|
|
67213
|
+
return (0, import_node_path73.join)(this.projectsRoot(), name);
|
|
66652
67214
|
}
|
|
66653
67215
|
projectsRoot() {
|
|
66654
|
-
return (0,
|
|
67216
|
+
return (0, import_node_path73.join)(this.root, PROJECTS_DIR);
|
|
66655
67217
|
}
|
|
66656
67218
|
async list() {
|
|
66657
67219
|
let entries;
|
|
@@ -66734,7 +67296,7 @@ var ProjectStore = class {
|
|
|
66734
67296
|
async scaffold(name, templateSrcDir, scaffoldScriptPath, extraEnv) {
|
|
66735
67297
|
const destDir = this.projectDir(name);
|
|
66736
67298
|
return await new Promise((resolve9, reject) => {
|
|
66737
|
-
const child = (0,
|
|
67299
|
+
const child = (0, import_node_child_process20.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
|
|
66738
67300
|
// extraEnv 排在 PATH **之前**:凭据表里若混进一条名叫 PATH 的条目,顶掉 PATH 会让
|
|
66739
67301
|
// 脚本以「命令找不到」的形态崩在离现场很远的地方。
|
|
66740
67302
|
env: { ...process.env, ...extraEnv ?? {}, PATH: process.env.PATH ?? "" },
|
|
@@ -66848,7 +67410,7 @@ var ProjectStore = class {
|
|
|
66848
67410
|
};
|
|
66849
67411
|
|
|
66850
67412
|
// src/app-builder/dev-server-supervisor.ts
|
|
66851
|
-
var
|
|
67413
|
+
var import_node_child_process21 = require("child_process");
|
|
66852
67414
|
var import_node_events2 = require("events");
|
|
66853
67415
|
var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
|
|
66854
67416
|
var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
@@ -66885,7 +67447,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
66885
67447
|
tunnelHost: args.tunnelHost,
|
|
66886
67448
|
devCommand: cmd
|
|
66887
67449
|
});
|
|
66888
|
-
const child = (0,
|
|
67450
|
+
const child = (0, import_node_child_process21.spawn)("sh", ["-c", cmd], {
|
|
66889
67451
|
cwd: args.cwd,
|
|
66890
67452
|
env,
|
|
66891
67453
|
stdio: "pipe",
|
|
@@ -67101,6 +67663,9 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
67101
67663
|
}
|
|
67102
67664
|
};
|
|
67103
67665
|
|
|
67666
|
+
// src/app-builder-plugin/core.ts
|
|
67667
|
+
var import_node_child_process23 = require("child_process");
|
|
67668
|
+
|
|
67104
67669
|
// src/app-builder-plugin/publish-registry.ts
|
|
67105
67670
|
var import_node_crypto21 = require("crypto");
|
|
67106
67671
|
var PublishJobRegistry = class {
|
|
@@ -67152,9 +67717,9 @@ var PublishJobRegistry = class {
|
|
|
67152
67717
|
};
|
|
67153
67718
|
|
|
67154
67719
|
// src/app-builder-plugin/publish-job-runner.ts
|
|
67155
|
-
var
|
|
67720
|
+
var import_node_child_process22 = require("child_process");
|
|
67156
67721
|
var import_node_fs54 = require("fs");
|
|
67157
|
-
var
|
|
67722
|
+
var import_node_path74 = require("path");
|
|
67158
67723
|
|
|
67159
67724
|
// src/app-builder-plugin/publish-stage-parser.ts
|
|
67160
67725
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -67181,19 +67746,19 @@ function tailStderrLines(buf, n) {
|
|
|
67181
67746
|
// src/app-builder-plugin/publish-job-runner.ts
|
|
67182
67747
|
async function startPublishJob(deps, args) {
|
|
67183
67748
|
const { registry: registry2, projectDir } = deps;
|
|
67184
|
-
const
|
|
67749
|
+
const spawn14 = deps.spawnImpl ?? import_node_child_process22.spawn;
|
|
67185
67750
|
if (registry2.has(args.name)) {
|
|
67186
67751
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
67187
67752
|
}
|
|
67188
67753
|
const projDir = projectDir(args.name);
|
|
67189
|
-
const logPath = (0,
|
|
67754
|
+
const logPath = (0, import_node_path74.join)(projDir, ".publish.log");
|
|
67190
67755
|
let logStream = null;
|
|
67191
67756
|
try {
|
|
67192
67757
|
logStream = (0, import_node_fs54.createWriteStream)(logPath, { flags: "w" });
|
|
67193
67758
|
} catch {
|
|
67194
67759
|
logStream = null;
|
|
67195
67760
|
}
|
|
67196
|
-
const child =
|
|
67761
|
+
const child = spawn14("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
|
|
67197
67762
|
cwd: projDir,
|
|
67198
67763
|
// 宿主给的 env 覆盖在 process.env 之上:daemon 进程本身没有这些变量(它们只在这一个
|
|
67199
67764
|
// 子进程里活着)。云上宿主不传 extraEnv,凭据本来就在容器 env 里。
|
|
@@ -67523,6 +68088,7 @@ async function createProjectOnDisk(args) {
|
|
|
67523
68088
|
}
|
|
67524
68089
|
return { project, projectDir: store.projectDir(name) };
|
|
67525
68090
|
}
|
|
68091
|
+
var REMOVE_TIMEOUT_MS = 10 * 6e4;
|
|
67526
68092
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
67527
68093
|
await recoverInterruptedJobs({
|
|
67528
68094
|
listAllProjects: async () => store.list(),
|
|
@@ -67532,9 +68098,9 @@ async function recoverInterruptedPublishJobs(store, logger) {
|
|
|
67532
68098
|
|
|
67533
68099
|
// src/app-builder-plugin/mcp-config.ts
|
|
67534
68100
|
var import_node_fs55 = __toESM(require("fs"), 1);
|
|
67535
|
-
var
|
|
68101
|
+
var import_node_path75 = __toESM(require("path"), 1);
|
|
67536
68102
|
function appBuilderMcpConfigPath(dataDir) {
|
|
67537
|
-
return
|
|
68103
|
+
return import_node_path75.default.join(dataDir, "app-builder.mcp.json");
|
|
67538
68104
|
}
|
|
67539
68105
|
function writeAppBuilderMcpConfig(args) {
|
|
67540
68106
|
const cfgPath = appBuilderMcpConfigPath(args.dataDir);
|
|
@@ -67548,8 +68114,8 @@ function writeAppBuilderMcpConfig(args) {
|
|
|
67548
68114
|
env: {
|
|
67549
68115
|
CLAWD_DAEMON_TOKEN: args.daemonToken,
|
|
67550
68116
|
CLAWD_DAEMON_URL: args.daemonUrl,
|
|
67551
|
-
CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT:
|
|
67552
|
-
CLAWD_APP_BUILDER_PUBLISH_SCRIPT:
|
|
68117
|
+
CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path75.default.join(args.deployKitScriptsDir, "new-extension.sh"),
|
|
68118
|
+
CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path75.default.join(args.deployKitScriptsDir, "publish.sh"),
|
|
67553
68119
|
...args.logPath ? { CLAWD_APP_BUILDER_LOG: args.logPath } : {}
|
|
67554
68120
|
}
|
|
67555
68121
|
}
|
|
@@ -67596,9 +68162,9 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
67596
68162
|
}
|
|
67597
68163
|
|
|
67598
68164
|
// src/extension/runtime.ts
|
|
67599
|
-
var
|
|
67600
|
-
var
|
|
67601
|
-
var
|
|
68165
|
+
var import_node_child_process24 = require("child_process");
|
|
68166
|
+
var import_node_path76 = __toESM(require("path"), 1);
|
|
68167
|
+
var import_promises20 = require("timers/promises");
|
|
67602
68168
|
|
|
67603
68169
|
// src/extension/port-allocator.ts
|
|
67604
68170
|
var import_node_net2 = __toESM(require("net"), 1);
|
|
@@ -67698,13 +68264,13 @@ var Runtime = class {
|
|
|
67698
68264
|
/\$CLAWOS_EXT_PORT/g,
|
|
67699
68265
|
String(port)
|
|
67700
68266
|
);
|
|
67701
|
-
const dir =
|
|
68267
|
+
const dir = import_node_path76.default.join(this.root, extId);
|
|
67702
68268
|
const env = {
|
|
67703
68269
|
...process.env,
|
|
67704
68270
|
CLAWOS_EXT_PORT: String(port),
|
|
67705
68271
|
CLAWOS_EXT_ID: extId
|
|
67706
68272
|
};
|
|
67707
|
-
const child = (0,
|
|
68273
|
+
const child = (0, import_node_child_process24.spawn)("sh", ["-c", cmd], {
|
|
67708
68274
|
cwd: dir,
|
|
67709
68275
|
env,
|
|
67710
68276
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -67774,7 +68340,7 @@ ${handle.stderrTail}`
|
|
|
67774
68340
|
if (res.ok) return;
|
|
67775
68341
|
} catch {
|
|
67776
68342
|
}
|
|
67777
|
-
await (0,
|
|
68343
|
+
await (0, import_promises20.setTimeout)(this.healthzIntervalMs);
|
|
67778
68344
|
}
|
|
67779
68345
|
throw new RuntimeError(
|
|
67780
68346
|
"HEALTHZ_FAILED",
|
|
@@ -67799,7 +68365,7 @@ ${handle.stderrTail}`
|
|
|
67799
68365
|
};
|
|
67800
68366
|
killGroup("SIGTERM");
|
|
67801
68367
|
const exited = new Promise((resolve9) => child.once("exit", () => resolve9()));
|
|
67802
|
-
const timed = (0,
|
|
68368
|
+
const timed = (0, import_promises20.setTimeout)(5e3).then(() => "timeout");
|
|
67803
68369
|
const winner = await Promise.race([exited.then(() => "exited"), timed]);
|
|
67804
68370
|
if (winner === "timeout" && child.exitCode === null) {
|
|
67805
68371
|
killGroup("SIGKILL");
|
|
@@ -67809,8 +68375,8 @@ ${handle.stderrTail}`
|
|
|
67809
68375
|
};
|
|
67810
68376
|
|
|
67811
68377
|
// src/extension/published-channels.ts
|
|
67812
|
-
var
|
|
67813
|
-
var
|
|
68378
|
+
var import_promises21 = __toESM(require("fs/promises"), 1);
|
|
68379
|
+
var import_node_path77 = __toESM(require("path"), 1);
|
|
67814
68380
|
init_zod();
|
|
67815
68381
|
var PublishedChannelsError = class extends Error {
|
|
67816
68382
|
constructor(code, message) {
|
|
@@ -67840,7 +68406,7 @@ var PublishedChannelStore = class {
|
|
|
67840
68406
|
this.channels.clear();
|
|
67841
68407
|
let raw;
|
|
67842
68408
|
try {
|
|
67843
|
-
raw = await
|
|
68409
|
+
raw = await import_promises21.default.readFile(this.filePath, "utf8");
|
|
67844
68410
|
} catch (e) {
|
|
67845
68411
|
if (e.code === "ENOENT") {
|
|
67846
68412
|
this.loaded = true;
|
|
@@ -67909,15 +68475,15 @@ var PublishedChannelStore = class {
|
|
|
67909
68475
|
)
|
|
67910
68476
|
};
|
|
67911
68477
|
const tmp = `${this.filePath}.tmp`;
|
|
67912
|
-
await
|
|
67913
|
-
await
|
|
67914
|
-
await
|
|
68478
|
+
await import_promises21.default.mkdir(import_node_path77.default.dirname(this.filePath), { recursive: true });
|
|
68479
|
+
await import_promises21.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
68480
|
+
await import_promises21.default.rename(tmp, this.filePath);
|
|
67915
68481
|
}
|
|
67916
68482
|
};
|
|
67917
68483
|
|
|
67918
68484
|
// src/extension/bundle-cache.ts
|
|
67919
|
-
var
|
|
67920
|
-
var
|
|
68485
|
+
var import_promises22 = __toESM(require("fs/promises"), 1);
|
|
68486
|
+
var import_node_path78 = __toESM(require("path"), 1);
|
|
67921
68487
|
var BundleCache = class {
|
|
67922
68488
|
constructor(rootDir) {
|
|
67923
68489
|
this.rootDir = rootDir;
|
|
@@ -67925,17 +68491,17 @@ var BundleCache = class {
|
|
|
67925
68491
|
rootDir;
|
|
67926
68492
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
67927
68493
|
async write(snapshotHash, buffer) {
|
|
67928
|
-
await
|
|
67929
|
-
const file =
|
|
68494
|
+
await import_promises22.default.mkdir(this.rootDir, { recursive: true });
|
|
68495
|
+
const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
67930
68496
|
const tmp = `${file}.tmp`;
|
|
67931
|
-
await
|
|
67932
|
-
await
|
|
68497
|
+
await import_promises22.default.writeFile(tmp, buffer, { mode: 384 });
|
|
68498
|
+
await import_promises22.default.rename(tmp, file);
|
|
67933
68499
|
}
|
|
67934
68500
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
67935
68501
|
async read(snapshotHash) {
|
|
67936
|
-
const file =
|
|
68502
|
+
const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
67937
68503
|
try {
|
|
67938
|
-
return await
|
|
68504
|
+
return await import_promises22.default.readFile(file);
|
|
67939
68505
|
} catch (e) {
|
|
67940
68506
|
if (e.code === "ENOENT") return null;
|
|
67941
68507
|
throw e;
|
|
@@ -67943,8 +68509,8 @@ var BundleCache = class {
|
|
|
67943
68509
|
}
|
|
67944
68510
|
/** Idempotent — missing file is not an error. */
|
|
67945
68511
|
async delete(snapshotHash) {
|
|
67946
|
-
const file =
|
|
67947
|
-
await
|
|
68512
|
+
const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
68513
|
+
await import_promises22.default.rm(file, { force: true });
|
|
67948
68514
|
}
|
|
67949
68515
|
};
|
|
67950
68516
|
|
|
@@ -67964,26 +68530,26 @@ async function startDaemon(config) {
|
|
|
67964
68530
|
},
|
|
67965
68531
|
source: "daemon",
|
|
67966
68532
|
sampling: logShippingCfg.sampling,
|
|
67967
|
-
homeDir:
|
|
68533
|
+
homeDir: import_node_os27.default.homedir()
|
|
67968
68534
|
});
|
|
67969
|
-
const logDir =
|
|
68535
|
+
const logDir = import_node_path79.default.join(config.dataDir, "log");
|
|
67970
68536
|
import_node_fs56.default.mkdirSync(logDir, { recursive: true });
|
|
67971
68537
|
const logger = createLogger({
|
|
67972
68538
|
level: config.logLevel,
|
|
67973
|
-
file:
|
|
68539
|
+
file: import_node_path79.default.join(logDir, "clawd.log"),
|
|
67974
68540
|
logClient
|
|
67975
68541
|
});
|
|
67976
68542
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
67977
68543
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
67978
|
-
file:
|
|
68544
|
+
file: import_node_path79.default.join(logDir, "screen-idle-probe.log"),
|
|
67979
68545
|
level: "debug"
|
|
67980
68546
|
});
|
|
67981
68547
|
logger.info("screen-idle probe logger enabled", {
|
|
67982
|
-
file:
|
|
68548
|
+
file: import_node_path79.default.join(logDir, "screen-idle-probe.log")
|
|
67983
68549
|
});
|
|
67984
68550
|
const CAP_TARGETS = [
|
|
67985
|
-
|
|
67986
|
-
|
|
68551
|
+
import_node_path79.default.join(logDir, "clawd.log"),
|
|
68552
|
+
import_node_path79.default.join(logDir, "screen-idle-probe.log")
|
|
67987
68553
|
];
|
|
67988
68554
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
67989
68555
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -68105,8 +68671,8 @@ async function startDaemon(config) {
|
|
|
68105
68671
|
const agents = new AgentsScanner();
|
|
68106
68672
|
const history = new ClaudeHistoryReader();
|
|
68107
68673
|
let transport = null;
|
|
68108
|
-
const personaStore = new PersonaStore(
|
|
68109
|
-
const usersRoot =
|
|
68674
|
+
const personaStore = new PersonaStore(import_node_path79.default.join(config.dataDir, "personas"));
|
|
68675
|
+
const usersRoot = import_node_path79.default.join(config.dataDir, "users");
|
|
68110
68676
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
68111
68677
|
if (defaultsRoot) {
|
|
68112
68678
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -68130,7 +68696,7 @@ async function startDaemon(config) {
|
|
|
68130
68696
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
68131
68697
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
68132
68698
|
const dispatchStore = createDispatchStore({
|
|
68133
|
-
filePath:
|
|
68699
|
+
filePath: import_node_path79.default.join(config.dataDir, "dispatch.json"),
|
|
68134
68700
|
now: () => Date.now(),
|
|
68135
68701
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
68136
68702
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -68139,7 +68705,7 @@ async function startDaemon(config) {
|
|
|
68139
68705
|
await dispatchStore.load();
|
|
68140
68706
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
68141
68707
|
const channelStore = createChannelStore({
|
|
68142
|
-
filePath:
|
|
68708
|
+
filePath: import_node_path79.default.join(config.dataDir, "channels.json"),
|
|
68143
68709
|
now: () => Date.now(),
|
|
68144
68710
|
genId: () => `ch-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
68145
68711
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
@@ -68148,7 +68714,7 @@ async function startDaemon(config) {
|
|
|
68148
68714
|
});
|
|
68149
68715
|
await channelStore.load();
|
|
68150
68716
|
const topicStore = createTopicStore({
|
|
68151
|
-
filePath:
|
|
68717
|
+
filePath: import_node_path79.default.join(config.dataDir, "topics.json"),
|
|
68152
68718
|
now: () => Date.now(),
|
|
68153
68719
|
genId: () => `tp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
68154
68720
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
@@ -68175,28 +68741,28 @@ async function startDaemon(config) {
|
|
|
68175
68741
|
});
|
|
68176
68742
|
}
|
|
68177
68743
|
});
|
|
68178
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
68744
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path79.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
|
|
68179
68745
|
const mcpConfigs = [];
|
|
68180
68746
|
const secretsBundleRoot = findSecretsBundleRoot(logger);
|
|
68181
|
-
const localSecretsDir =
|
|
68747
|
+
const localSecretsDir = import_node_path79.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
|
|
68182
68748
|
const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
|
|
68183
68749
|
const resolvePersonaMcpConfig = (personaId2) => renderPersonaMcpSecrets({
|
|
68184
68750
|
personaId: personaId2,
|
|
68185
|
-
personaDir:
|
|
68751
|
+
personaDir: import_node_path79.default.join(config.dataDir, "personas", personaId2),
|
|
68186
68752
|
secrets: readSecrets(),
|
|
68187
|
-
outDir:
|
|
68753
|
+
outDir: import_node_path79.default.join(config.dataDir, "persona-mcp"),
|
|
68188
68754
|
logger
|
|
68189
68755
|
});
|
|
68190
68756
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
68191
68757
|
const dispatchServerCandidates = [
|
|
68192
|
-
|
|
68758
|
+
import_node_path79.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
68193
68759
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
68194
|
-
|
|
68760
|
+
import_node_path79.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
68195
68761
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
68196
68762
|
];
|
|
68197
68763
|
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68198
68764
|
if (dispatchServerScriptPath) {
|
|
68199
|
-
const dispatchLogPath =
|
|
68765
|
+
const dispatchLogPath = import_node_path79.default.join(logDir, "dispatch-mcp-server.log");
|
|
68200
68766
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
68201
68767
|
dataDir: config.dataDir,
|
|
68202
68768
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -68216,12 +68782,12 @@ async function startDaemon(config) {
|
|
|
68216
68782
|
});
|
|
68217
68783
|
}
|
|
68218
68784
|
const ticketServerCandidates = [
|
|
68219
|
-
|
|
68220
|
-
|
|
68785
|
+
import_node_path79.default.join(here, "ticket", "mcp-server.cjs"),
|
|
68786
|
+
import_node_path79.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
68221
68787
|
];
|
|
68222
68788
|
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68223
68789
|
if (ticketServerScriptPath) {
|
|
68224
|
-
const ticketLogPath =
|
|
68790
|
+
const ticketLogPath = import_node_path79.default.join(logDir, "ticket-mcp-server.log");
|
|
68225
68791
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
68226
68792
|
dataDir: config.dataDir,
|
|
68227
68793
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -68243,12 +68809,12 @@ async function startDaemon(config) {
|
|
|
68243
68809
|
});
|
|
68244
68810
|
}
|
|
68245
68811
|
const shiftServerCandidates = [
|
|
68246
|
-
|
|
68247
|
-
|
|
68812
|
+
import_node_path79.default.join(here, "shift", "mcp-server.cjs"),
|
|
68813
|
+
import_node_path79.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
68248
68814
|
];
|
|
68249
68815
|
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68250
68816
|
if (shiftServerScriptPath) {
|
|
68251
|
-
const shiftLogPath =
|
|
68817
|
+
const shiftLogPath = import_node_path79.default.join(logDir, "shift-mcp-server.log");
|
|
68252
68818
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
68253
68819
|
dataDir: config.dataDir,
|
|
68254
68820
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -68269,12 +68835,12 @@ async function startDaemon(config) {
|
|
|
68269
68835
|
);
|
|
68270
68836
|
}
|
|
68271
68837
|
const inboxServerCandidates = [
|
|
68272
|
-
|
|
68273
|
-
|
|
68838
|
+
import_node_path79.default.join(here, "inbox", "mcp-server.cjs"),
|
|
68839
|
+
import_node_path79.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
68274
68840
|
];
|
|
68275
68841
|
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68276
68842
|
if (inboxServerScriptPath) {
|
|
68277
|
-
const inboxLogPath =
|
|
68843
|
+
const inboxLogPath = import_node_path79.default.join(logDir, "inbox-mcp-server.log");
|
|
68278
68844
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
68279
68845
|
dataDir: config.dataDir,
|
|
68280
68846
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -68295,8 +68861,8 @@ async function startDaemon(config) {
|
|
|
68295
68861
|
);
|
|
68296
68862
|
}
|
|
68297
68863
|
const peerOpsServerCandidates = [
|
|
68298
|
-
|
|
68299
|
-
|
|
68864
|
+
import_node_path79.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
68865
|
+
import_node_path79.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
68300
68866
|
];
|
|
68301
68867
|
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68302
68868
|
if (peerOpsServerScriptPath) {
|
|
@@ -68318,12 +68884,12 @@ async function startDaemon(config) {
|
|
|
68318
68884
|
);
|
|
68319
68885
|
}
|
|
68320
68886
|
const rpcToolServerCandidates = [
|
|
68321
|
-
|
|
68322
|
-
|
|
68887
|
+
import_node_path79.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
68888
|
+
import_node_path79.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
68323
68889
|
];
|
|
68324
68890
|
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68325
68891
|
if (rpcToolServerScriptPath) {
|
|
68326
|
-
const rpcToolLogPath =
|
|
68892
|
+
const rpcToolLogPath = import_node_path79.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
68327
68893
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
68328
68894
|
dataDir: config.dataDir,
|
|
68329
68895
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -68344,18 +68910,18 @@ async function startDaemon(config) {
|
|
|
68344
68910
|
);
|
|
68345
68911
|
}
|
|
68346
68912
|
const appBuilderServerCandidates = [
|
|
68347
|
-
|
|
68348
|
-
|
|
68913
|
+
import_node_path79.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
|
|
68914
|
+
import_node_path79.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
|
|
68349
68915
|
];
|
|
68350
68916
|
const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68351
68917
|
if (appBuilderServerScriptPath) {
|
|
68352
|
-
const appBuilderLogPath =
|
|
68918
|
+
const appBuilderLogPath = import_node_path79.default.join(logDir, "app-builder-mcp-server.log");
|
|
68353
68919
|
const appBuilderCfgPath = writeAppBuilderMcpConfig({
|
|
68354
68920
|
dataDir: config.dataDir,
|
|
68355
68921
|
serverScriptPath: appBuilderServerScriptPath,
|
|
68356
68922
|
daemonToken: resolvedAuthToken,
|
|
68357
68923
|
daemonUrl: mcpDaemonUrl,
|
|
68358
|
-
deployKitScriptsDir:
|
|
68924
|
+
deployKitScriptsDir: import_node_path79.default.join(config.dataDir, "deploy-kit", "scripts"),
|
|
68359
68925
|
logPath: appBuilderLogPath
|
|
68360
68926
|
});
|
|
68361
68927
|
mcpConfigs.push({ id: "app-builder", path: appBuilderCfgPath, personas: APP_BUILDER_PERSONAS });
|
|
@@ -68371,7 +68937,7 @@ async function startDaemon(config) {
|
|
|
68371
68937
|
);
|
|
68372
68938
|
}
|
|
68373
68939
|
const shiftStore = createShiftStore({
|
|
68374
|
-
filePath:
|
|
68940
|
+
filePath: import_node_path79.default.join(config.dataDir, "shift.json"),
|
|
68375
68941
|
ownerIdProvider: () => ownerPrincipalId,
|
|
68376
68942
|
now: () => Date.now()
|
|
68377
68943
|
});
|
|
@@ -68393,7 +68959,7 @@ async function startDaemon(config) {
|
|
|
68393
68959
|
getAdapter,
|
|
68394
68960
|
historyReader: history,
|
|
68395
68961
|
dataDir: config.dataDir,
|
|
68396
|
-
personaRoot:
|
|
68962
|
+
personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
|
|
68397
68963
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
68398
68964
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
68399
68965
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -68450,7 +69016,7 @@ async function startDaemon(config) {
|
|
|
68450
69016
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
68451
69017
|
attachmentGroup: {
|
|
68452
69018
|
onFileEdit: (input) => {
|
|
68453
|
-
const absPath =
|
|
69019
|
+
const absPath = import_node_path79.default.isAbsolute(input.relPath) ? input.relPath : import_node_path79.default.join(input.cwd, input.relPath);
|
|
68454
69020
|
let size = 0;
|
|
68455
69021
|
try {
|
|
68456
69022
|
size = import_node_fs56.default.statSync(absPath).size;
|
|
@@ -68483,9 +69049,9 @@ async function startDaemon(config) {
|
|
|
68483
69049
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
68484
69050
|
}
|
|
68485
69051
|
const projectsStore = new ProjectsStore({
|
|
68486
|
-
file:
|
|
69052
|
+
file: import_node_path79.default.join(config.dataDir, "projects.json"),
|
|
68487
69053
|
clawdDir: config.dataDir,
|
|
68488
|
-
codexStateFile:
|
|
69054
|
+
codexStateFile: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
68489
69055
|
logger
|
|
68490
69056
|
});
|
|
68491
69057
|
const observer = new SessionObserver({
|
|
@@ -68545,12 +69111,12 @@ async function startDaemon(config) {
|
|
|
68545
69111
|
screenIdleProbeLogger
|
|
68546
69112
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
68547
69113
|
registerAdapter("claude", claudeAdapter);
|
|
68548
|
-
const codexIsolatedHome =
|
|
69114
|
+
const codexIsolatedHome = import_node_path79.default.join(config.dataDir, "codex-home");
|
|
68549
69115
|
try {
|
|
68550
69116
|
import_node_fs56.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
68551
69117
|
for (const f of ["auth.json", "config.toml"]) {
|
|
68552
|
-
const link =
|
|
68553
|
-
const target =
|
|
69118
|
+
const link = import_node_path79.default.join(codexIsolatedHome, f);
|
|
69119
|
+
const target = import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", f);
|
|
68554
69120
|
if (!import_node_fs56.default.existsSync(link) && import_node_fs56.default.existsSync(target)) import_node_fs56.default.symlinkSync(target, link);
|
|
68555
69121
|
}
|
|
68556
69122
|
} catch (err) {
|
|
@@ -68564,11 +69130,11 @@ async function startDaemon(config) {
|
|
|
68564
69130
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
68565
69131
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
68566
69132
|
cwd,
|
|
68567
|
-
personaRoot:
|
|
69133
|
+
personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
|
|
68568
69134
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
68569
69135
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
68570
69136
|
projectPaths: projectsStore.listMerged().map((x) => x.path),
|
|
68571
|
-
sharedHome:
|
|
69137
|
+
sharedHome: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex"),
|
|
68572
69138
|
isolatedHome: codexIsolatedHome
|
|
68573
69139
|
})
|
|
68574
69140
|
})
|
|
@@ -68853,11 +69419,11 @@ async function startDaemon(config) {
|
|
|
68853
69419
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
68854
69420
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
68855
69421
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
68856
|
-
personaRoot:
|
|
69422
|
+
personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
|
|
68857
69423
|
usersRoot
|
|
68858
69424
|
},
|
|
68859
69425
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
68860
|
-
personaRoot:
|
|
69426
|
+
personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
|
|
68861
69427
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
68862
69428
|
usersRoot,
|
|
68863
69429
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -68958,11 +69524,11 @@ async function startDaemon(config) {
|
|
|
68958
69524
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
68959
69525
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
68960
69526
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
68961
|
-
appBuilderPersonaRoot:
|
|
69527
|
+
appBuilderPersonaRoot: import_node_path79.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
68962
69528
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
68963
|
-
deployKitRoot:
|
|
69529
|
+
deployKitRoot: import_node_path79.default.join(config.dataDir, "deploy-kit"),
|
|
68964
69530
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
68965
|
-
resolvePersonaRoot: (personaId2) =>
|
|
69531
|
+
resolvePersonaRoot: (personaId2) => import_node_path79.default.join(config.dataDir, "personas", personaId2),
|
|
68966
69532
|
// 凭据表(M1b Step 5):与 MCP 那条同一张表、同一个来源,只是交付给另一个子进程。
|
|
68967
69533
|
readSecrets,
|
|
68968
69534
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
@@ -69019,7 +69585,7 @@ async function startDaemon(config) {
|
|
|
69019
69585
|
sourceSessionId: args.sourceSessionId
|
|
69020
69586
|
});
|
|
69021
69587
|
const sourceFile = manager.findOwnedSession(args.sourceSessionId);
|
|
69022
|
-
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile,
|
|
69588
|
+
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os27.default.homedir());
|
|
69023
69589
|
logger.info("dispatch.spawnB.source-resolved", {
|
|
69024
69590
|
dispatchId: args.dispatchId,
|
|
69025
69591
|
sourceJsonlPath,
|
|
@@ -69077,12 +69643,12 @@ async function startDaemon(config) {
|
|
|
69077
69643
|
});
|
|
69078
69644
|
Object.assign(handlers, shiftHandlers);
|
|
69079
69645
|
const deployReceipts = createReceiptStore({
|
|
69080
|
-
filePath:
|
|
69646
|
+
filePath: import_node_path79.default.join(config.dataDir, "deploy.json"),
|
|
69081
69647
|
now: () => Date.now(),
|
|
69082
69648
|
onFlushError: (err) => logger.error("deploy receipts flush failed", { error: String(err) })
|
|
69083
69649
|
});
|
|
69084
69650
|
const deploySecrets = createSecretStore({
|
|
69085
|
-
filePath:
|
|
69651
|
+
filePath: import_node_path79.default.join(config.dataDir, "deploy-secrets.json"),
|
|
69086
69652
|
now: () => Date.now(),
|
|
69087
69653
|
onFlushError: (err) => logger.error("deploy secrets flush failed", { error: String(err) })
|
|
69088
69654
|
});
|
|
@@ -69090,13 +69656,72 @@ async function startDaemon(config) {
|
|
|
69090
69656
|
await deploySecrets.load();
|
|
69091
69657
|
const interrupted = reconcileInterruptedScans(deployReceipts);
|
|
69092
69658
|
if (interrupted.length > 0) logger.warn("deploy scans interrupted by restart", { deployIds: interrupted });
|
|
69659
|
+
const interruptedTrials = reconcileInterruptedTrials(deployReceipts);
|
|
69660
|
+
if (interruptedTrials.length > 0) logger.warn("deploy trials interrupted by restart", { deployIds: interruptedTrials });
|
|
69661
|
+
async function runTrialForReceipt(deployId) {
|
|
69662
|
+
const receipt = deployReceipts.get(deployId);
|
|
69663
|
+
if (!receipt) return;
|
|
69664
|
+
let cloudHost;
|
|
69665
|
+
try {
|
|
69666
|
+
cloudHost = await loadCloudHostConfig(config.dataDir);
|
|
69667
|
+
} catch (err) {
|
|
69668
|
+
deployReceipts.update(deployId, {
|
|
69669
|
+
status: "failed",
|
|
69670
|
+
trialStage: void 0,
|
|
69671
|
+
// 同 gap 的其它两个来源:自由文本落单据前一律过涂抹
|
|
69672
|
+
gaps: [{ errorText: redactSecretValues(err instanceof CloudHostConfigError ? err.message : String(err)) }]
|
|
69673
|
+
});
|
|
69674
|
+
return;
|
|
69675
|
+
}
|
|
69676
|
+
const outcome = await runTrial(
|
|
69677
|
+
{
|
|
69678
|
+
cloudHost,
|
|
69679
|
+
runNode: (script, args, opts) => runNodeScript(script, args, opts.timeoutMs),
|
|
69680
|
+
fetchImpl: fetch,
|
|
69681
|
+
now: () => Date.now(),
|
|
69682
|
+
onStage: (stage) => {
|
|
69683
|
+
deployReceipts.update(deployId, { trialStage: stage });
|
|
69684
|
+
},
|
|
69685
|
+
logger: {
|
|
69686
|
+
info: (msg, meta) => logger.info(msg, meta),
|
|
69687
|
+
warn: (msg, meta) => logger.warn(msg, meta)
|
|
69688
|
+
}
|
|
69689
|
+
},
|
|
69690
|
+
{
|
|
69691
|
+
receipt,
|
|
69692
|
+
// 试装带全量(含使用者自带那几条的临时垫付值)——它要真跑一次发布
|
|
69693
|
+
secretTable: secretTableFor(receipt, deploySecrets.resolve(deployId), "all"),
|
|
69694
|
+
round: receipt.trialRound
|
|
69695
|
+
}
|
|
69696
|
+
);
|
|
69697
|
+
if (outcome.ok) {
|
|
69698
|
+
deployReceipts.update(deployId, {
|
|
69699
|
+
// 通过之后回 ready 而不是直接 deployed:部署是人的第二次决定(见 deploy-schemas 状态机)
|
|
69700
|
+
status: "ready",
|
|
69701
|
+
trialStage: void 0,
|
|
69702
|
+
trialPassedAt: Date.now(),
|
|
69703
|
+
trialImage: outcome.image,
|
|
69704
|
+
gaps: []
|
|
69705
|
+
});
|
|
69706
|
+
logger.info("deploy trial passed", { deployId, image: outcome.image });
|
|
69707
|
+
} else {
|
|
69708
|
+
const current = deployReceipts.get(deployId)?.trialRound ?? receipt.trialRound;
|
|
69709
|
+
deployReceipts.update(deployId, {
|
|
69710
|
+
status: "failed",
|
|
69711
|
+
trialStage: void 0,
|
|
69712
|
+
gaps: outcome.gaps,
|
|
69713
|
+
...outcome.spent ? {} : { trialRound: Math.max(0, current - 1) }
|
|
69714
|
+
});
|
|
69715
|
+
logger.warn("deploy trial failed", { deployId, gaps: outcome.gaps.length, spent: outcome.spent });
|
|
69716
|
+
}
|
|
69717
|
+
}
|
|
69093
69718
|
const deployHandlers = buildDeployHandlers({
|
|
69094
69719
|
receipts: deployReceipts,
|
|
69095
69720
|
secrets: deploySecrets,
|
|
69096
69721
|
hasPersona: (personaId2) => personaStore.has(personaId2),
|
|
69097
69722
|
startScan: (deployId, personaId2) => {
|
|
69098
69723
|
const assetLines = SCANNABLE_ASSETS.map(
|
|
69099
|
-
(name) => ` - ${name}\uFF1A${
|
|
69724
|
+
(name) => ` - ${name}\uFF1A${import_node_path79.default.join(config.dataDir, name)}`
|
|
69100
69725
|
).join("\n");
|
|
69101
69726
|
const prompt = [
|
|
69102
69727
|
`\u626B\u63CF persona\u300C${personaId2}\u300D\u7684\u90E8\u7F72\u73AF\u5883\uFF0CdeployId=${deployId}\u3002`,
|
|
@@ -69124,6 +69749,30 @@ async function startDaemon(config) {
|
|
|
69124
69749
|
});
|
|
69125
69750
|
return handle.sessionId;
|
|
69126
69751
|
},
|
|
69752
|
+
startTrial: (deployId) => {
|
|
69753
|
+
void runTrialForReceipt(deployId).catch((err) => {
|
|
69754
|
+
logger.error("deploy trial crashed", { deployId, error: String(err) });
|
|
69755
|
+
deployReceipts.update(deployId, {
|
|
69756
|
+
status: "failed",
|
|
69757
|
+
trialStage: void 0,
|
|
69758
|
+
gaps: [{ errorText: redactSecretValues(`\u8BD5\u88C5\u8FD9\u6761\u6D41\u6C34\u7EBF\u81EA\u5DF1\u51FA\u9519\u4E86\uFF1A${String(err)}`) }]
|
|
69759
|
+
});
|
|
69760
|
+
});
|
|
69761
|
+
},
|
|
69762
|
+
registerOfficial: async (receipt) => {
|
|
69763
|
+
const cloudHost = await loadCloudHostConfig(config.dataDir);
|
|
69764
|
+
return await registerOfficialDeployment(
|
|
69765
|
+
{ cloudHost, fetchImpl: fetch, now: () => Date.now() },
|
|
69766
|
+
receipt,
|
|
69767
|
+
// **只带部署者自供的那些**:使用者自带的由每个人各自绑,把部署者垫的试装临时值
|
|
69768
|
+
// 带上云等于所有人共用他的额度,跟单据上写的正好相反
|
|
69769
|
+
secretTableFor(receipt, deploySecrets.resolve(receipt.deployId), "deployer")
|
|
69770
|
+
);
|
|
69771
|
+
},
|
|
69772
|
+
unregisterDeployment: async (deployId) => {
|
|
69773
|
+
const cloudHost = await loadCloudHostConfig(config.dataDir);
|
|
69774
|
+
await gatewayAdmin({ cloudHost, fetchImpl: fetch }, "/admin/deployments:remove", { deployId });
|
|
69775
|
+
},
|
|
69127
69776
|
genId: () => `dp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
69128
69777
|
now: () => Date.now()
|
|
69129
69778
|
});
|
|
@@ -69137,7 +69786,7 @@ async function startDaemon(config) {
|
|
|
69137
69786
|
});
|
|
69138
69787
|
shiftScheduler.start();
|
|
69139
69788
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
69140
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
69789
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path79.default.join(config.dataDir, "personas"));
|
|
69141
69790
|
const larkBotCloud = createLarkBotCloudClient({
|
|
69142
69791
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
69143
69792
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -69151,7 +69800,7 @@ async function startDaemon(config) {
|
|
|
69151
69800
|
store: larkBotStore,
|
|
69152
69801
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
69153
69802
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
69154
|
-
mediaRootFor: (chatId) =>
|
|
69803
|
+
mediaRootFor: (chatId) => import_node_path79.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
69155
69804
|
isShuttingDown: () => larkDraining,
|
|
69156
69805
|
logger: {
|
|
69157
69806
|
warn: (msg) => logger.warn(msg),
|
|
@@ -69456,8 +70105,8 @@ async function startDaemon(config) {
|
|
|
69456
70105
|
const lines = [
|
|
69457
70106
|
`Tunnel: ${r.url}`,
|
|
69458
70107
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
69459
|
-
`Frpc config: ${
|
|
69460
|
-
`Frpc log: ${
|
|
70108
|
+
`Frpc config: ${import_node_path79.default.join(config.dataDir, "frpc.toml")}`,
|
|
70109
|
+
`Frpc log: ${import_node_path79.default.join(logDir, "frpc.log")}`
|
|
69461
70110
|
];
|
|
69462
70111
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
69463
70112
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -69470,7 +70119,7 @@ ${bar}
|
|
|
69470
70119
|
|
|
69471
70120
|
`);
|
|
69472
70121
|
try {
|
|
69473
|
-
const connectPath =
|
|
70122
|
+
const connectPath = import_node_path79.default.join(config.dataDir, "connect.txt");
|
|
69474
70123
|
import_node_fs56.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
69475
70124
|
} catch {
|
|
69476
70125
|
}
|
|
@@ -69560,7 +70209,7 @@ ${bar}
|
|
|
69560
70209
|
};
|
|
69561
70210
|
}
|
|
69562
70211
|
function migrateDropPersonsDir(dataDir) {
|
|
69563
|
-
const dir =
|
|
70212
|
+
const dir = import_node_path79.default.join(dataDir, "persons");
|
|
69564
70213
|
try {
|
|
69565
70214
|
import_node_fs56.default.rmSync(dir, { recursive: true, force: true });
|
|
69566
70215
|
} catch {
|