@clawos-dev/clawd 0.2.460 → 0.2.462
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 +115 -1
- package/dist/cli.cjs +1242 -608
- package/dist/dispatch/mcp-server.cjs +38 -0
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/{guest-CC5Z0Nwd.js → guest-D93kvm-H.js} +114 -114
- package/dist/share-ui/assets/guest-DVSKTQaV.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-GnZTCQ46.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(),
|
|
@@ -8878,6 +8909,14 @@ var init_methods = __esm({
|
|
|
8878
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",
|
|
8879
8910
|
args: DeployFinishScanArgsSchema
|
|
8880
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
|
+
},
|
|
8881
8920
|
"deploy:remove": {
|
|
8882
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",
|
|
8883
8922
|
args: DeployIdArgsSchema
|
|
@@ -9866,8 +9905,8 @@ var require_req = __commonJS({
|
|
|
9866
9905
|
if (req.originalUrl) {
|
|
9867
9906
|
_req.url = req.originalUrl;
|
|
9868
9907
|
} else {
|
|
9869
|
-
const
|
|
9870
|
-
_req.url = typeof
|
|
9908
|
+
const path98 = req.path;
|
|
9909
|
+
_req.url = typeof path98 === "string" ? path98 : req.url ? req.url.path || req.url : void 0;
|
|
9871
9910
|
}
|
|
9872
9911
|
if (req.query) {
|
|
9873
9912
|
_req.query = req.query;
|
|
@@ -10032,14 +10071,14 @@ var require_redact = __commonJS({
|
|
|
10032
10071
|
}
|
|
10033
10072
|
return obj;
|
|
10034
10073
|
}
|
|
10035
|
-
function parsePath(
|
|
10074
|
+
function parsePath(path98) {
|
|
10036
10075
|
const parts = [];
|
|
10037
10076
|
let current = "";
|
|
10038
10077
|
let inBrackets = false;
|
|
10039
10078
|
let inQuotes = false;
|
|
10040
10079
|
let quoteChar = "";
|
|
10041
|
-
for (let i = 0; i <
|
|
10042
|
-
const char =
|
|
10080
|
+
for (let i = 0; i < path98.length; i++) {
|
|
10081
|
+
const char = path98[i];
|
|
10043
10082
|
if (!inBrackets && char === ".") {
|
|
10044
10083
|
if (current) {
|
|
10045
10084
|
parts.push(current);
|
|
@@ -10170,10 +10209,10 @@ var require_redact = __commonJS({
|
|
|
10170
10209
|
return current;
|
|
10171
10210
|
}
|
|
10172
10211
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
10173
|
-
for (const
|
|
10174
|
-
const parts = parsePath(
|
|
10212
|
+
for (const path98 of paths) {
|
|
10213
|
+
const parts = parsePath(path98);
|
|
10175
10214
|
if (parts.includes("*")) {
|
|
10176
|
-
redactWildcardPath(obj, parts, censor,
|
|
10215
|
+
redactWildcardPath(obj, parts, censor, path98, remove);
|
|
10177
10216
|
} else {
|
|
10178
10217
|
if (remove) {
|
|
10179
10218
|
removeKey(obj, parts);
|
|
@@ -10258,8 +10297,8 @@ var require_redact = __commonJS({
|
|
|
10258
10297
|
}
|
|
10259
10298
|
} else {
|
|
10260
10299
|
if (afterWildcard.includes("*")) {
|
|
10261
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10262
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
10300
|
+
const wrappedCensor = typeof censor === "function" ? (value, path98) => {
|
|
10301
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path98];
|
|
10263
10302
|
return censor(value, fullPath);
|
|
10264
10303
|
} : censor;
|
|
10265
10304
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -10294,8 +10333,8 @@ var require_redact = __commonJS({
|
|
|
10294
10333
|
return null;
|
|
10295
10334
|
}
|
|
10296
10335
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
10297
|
-
for (const
|
|
10298
|
-
const parts = parsePath(
|
|
10336
|
+
for (const path98 of pathsToClone) {
|
|
10337
|
+
const parts = parsePath(path98);
|
|
10299
10338
|
let current = pathStructure;
|
|
10300
10339
|
for (let i = 0; i < parts.length; i++) {
|
|
10301
10340
|
const part = parts[i];
|
|
@@ -10347,24 +10386,24 @@ var require_redact = __commonJS({
|
|
|
10347
10386
|
}
|
|
10348
10387
|
return cloneSelectively(obj, pathStructure);
|
|
10349
10388
|
}
|
|
10350
|
-
function validatePath(
|
|
10351
|
-
if (typeof
|
|
10389
|
+
function validatePath(path98) {
|
|
10390
|
+
if (typeof path98 !== "string") {
|
|
10352
10391
|
throw new Error("Paths must be (non-empty) strings");
|
|
10353
10392
|
}
|
|
10354
|
-
if (
|
|
10393
|
+
if (path98 === "") {
|
|
10355
10394
|
throw new Error("Invalid redaction path ()");
|
|
10356
10395
|
}
|
|
10357
|
-
if (
|
|
10358
|
-
throw new Error(`Invalid redaction path (${
|
|
10396
|
+
if (path98.includes("..")) {
|
|
10397
|
+
throw new Error(`Invalid redaction path (${path98})`);
|
|
10359
10398
|
}
|
|
10360
|
-
if (
|
|
10361
|
-
throw new Error(`Invalid redaction path (${
|
|
10399
|
+
if (path98.includes(",")) {
|
|
10400
|
+
throw new Error(`Invalid redaction path (${path98})`);
|
|
10362
10401
|
}
|
|
10363
10402
|
let bracketCount = 0;
|
|
10364
10403
|
let inQuotes = false;
|
|
10365
10404
|
let quoteChar = "";
|
|
10366
|
-
for (let i = 0; i <
|
|
10367
|
-
const char =
|
|
10405
|
+
for (let i = 0; i < path98.length; i++) {
|
|
10406
|
+
const char = path98[i];
|
|
10368
10407
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
10369
10408
|
if (!inQuotes) {
|
|
10370
10409
|
inQuotes = true;
|
|
@@ -10378,20 +10417,20 @@ var require_redact = __commonJS({
|
|
|
10378
10417
|
} else if (char === "]" && !inQuotes) {
|
|
10379
10418
|
bracketCount--;
|
|
10380
10419
|
if (bracketCount < 0) {
|
|
10381
|
-
throw new Error(`Invalid redaction path (${
|
|
10420
|
+
throw new Error(`Invalid redaction path (${path98})`);
|
|
10382
10421
|
}
|
|
10383
10422
|
}
|
|
10384
10423
|
}
|
|
10385
10424
|
if (bracketCount !== 0) {
|
|
10386
|
-
throw new Error(`Invalid redaction path (${
|
|
10425
|
+
throw new Error(`Invalid redaction path (${path98})`);
|
|
10387
10426
|
}
|
|
10388
10427
|
}
|
|
10389
10428
|
function validatePaths(paths) {
|
|
10390
10429
|
if (!Array.isArray(paths)) {
|
|
10391
10430
|
throw new TypeError("paths must be an array");
|
|
10392
10431
|
}
|
|
10393
|
-
for (const
|
|
10394
|
-
validatePath(
|
|
10432
|
+
for (const path98 of paths) {
|
|
10433
|
+
validatePath(path98);
|
|
10395
10434
|
}
|
|
10396
10435
|
}
|
|
10397
10436
|
function slowRedact(options = {}) {
|
|
@@ -10559,8 +10598,8 @@ var require_redaction = __commonJS({
|
|
|
10559
10598
|
if (shape[k2] === null) {
|
|
10560
10599
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
10561
10600
|
} else {
|
|
10562
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10563
|
-
return censor(value, [k2, ...
|
|
10601
|
+
const wrappedCensor = typeof censor === "function" ? (value, path98) => {
|
|
10602
|
+
return censor(value, [k2, ...path98]);
|
|
10564
10603
|
} : censor;
|
|
10565
10604
|
o[k2] = Redact({
|
|
10566
10605
|
paths: shape[k2],
|
|
@@ -10778,10 +10817,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
10778
10817
|
var require_sonic_boom = __commonJS({
|
|
10779
10818
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
10780
10819
|
"use strict";
|
|
10781
|
-
var
|
|
10820
|
+
var fs87 = require("fs");
|
|
10782
10821
|
var EventEmitter3 = require("events");
|
|
10783
10822
|
var inherits = require("util").inherits;
|
|
10784
|
-
var
|
|
10823
|
+
var path98 = require("path");
|
|
10785
10824
|
var sleep2 = require_atomic_sleep();
|
|
10786
10825
|
var assert = require("assert");
|
|
10787
10826
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -10835,20 +10874,20 @@ var require_sonic_boom = __commonJS({
|
|
|
10835
10874
|
const mode = sonic.mode;
|
|
10836
10875
|
if (sonic.sync) {
|
|
10837
10876
|
try {
|
|
10838
|
-
if (sonic.mkdir)
|
|
10839
|
-
const fd =
|
|
10877
|
+
if (sonic.mkdir) fs87.mkdirSync(path98.dirname(file), { recursive: true });
|
|
10878
|
+
const fd = fs87.openSync(file, flags, mode);
|
|
10840
10879
|
fileOpened(null, fd);
|
|
10841
10880
|
} catch (err) {
|
|
10842
10881
|
fileOpened(err);
|
|
10843
10882
|
throw err;
|
|
10844
10883
|
}
|
|
10845
10884
|
} else if (sonic.mkdir) {
|
|
10846
|
-
|
|
10885
|
+
fs87.mkdir(path98.dirname(file), { recursive: true }, (err) => {
|
|
10847
10886
|
if (err) return fileOpened(err);
|
|
10848
|
-
|
|
10887
|
+
fs87.open(file, flags, mode, fileOpened);
|
|
10849
10888
|
});
|
|
10850
10889
|
} else {
|
|
10851
|
-
|
|
10890
|
+
fs87.open(file, flags, mode, fileOpened);
|
|
10852
10891
|
}
|
|
10853
10892
|
}
|
|
10854
10893
|
function SonicBoom(opts) {
|
|
@@ -10889,8 +10928,8 @@ var require_sonic_boom = __commonJS({
|
|
|
10889
10928
|
this.flush = flushBuffer;
|
|
10890
10929
|
this.flushSync = flushBufferSync;
|
|
10891
10930
|
this._actualWrite = actualWriteBuffer;
|
|
10892
|
-
fsWriteSync = () =>
|
|
10893
|
-
fsWrite = () =>
|
|
10931
|
+
fsWriteSync = () => fs87.writeSync(this.fd, this._writingBuf);
|
|
10932
|
+
fsWrite = () => fs87.write(this.fd, this._writingBuf, this.release);
|
|
10894
10933
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
10895
10934
|
this._writingBuf = "";
|
|
10896
10935
|
this.write = write;
|
|
@@ -10899,15 +10938,15 @@ var require_sonic_boom = __commonJS({
|
|
|
10899
10938
|
this._actualWrite = actualWrite;
|
|
10900
10939
|
fsWriteSync = () => {
|
|
10901
10940
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10902
|
-
return
|
|
10941
|
+
return fs87.writeSync(this.fd, this._writingBuf);
|
|
10903
10942
|
}
|
|
10904
|
-
return
|
|
10943
|
+
return fs87.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10905
10944
|
};
|
|
10906
10945
|
fsWrite = () => {
|
|
10907
10946
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10908
|
-
return
|
|
10947
|
+
return fs87.write(this.fd, this._writingBuf, this.release);
|
|
10909
10948
|
}
|
|
10910
|
-
return
|
|
10949
|
+
return fs87.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
10911
10950
|
};
|
|
10912
10951
|
} else {
|
|
10913
10952
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -10964,7 +11003,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10964
11003
|
}
|
|
10965
11004
|
}
|
|
10966
11005
|
if (this._fsync) {
|
|
10967
|
-
|
|
11006
|
+
fs87.fsyncSync(this.fd);
|
|
10968
11007
|
}
|
|
10969
11008
|
const len = this._len;
|
|
10970
11009
|
if (this._reopening) {
|
|
@@ -11078,7 +11117,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11078
11117
|
const onDrain = () => {
|
|
11079
11118
|
if (!this._fsync) {
|
|
11080
11119
|
try {
|
|
11081
|
-
|
|
11120
|
+
fs87.fsync(this.fd, (err) => {
|
|
11082
11121
|
this._flushPending = false;
|
|
11083
11122
|
cb(err);
|
|
11084
11123
|
});
|
|
@@ -11180,7 +11219,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11180
11219
|
const fd = this.fd;
|
|
11181
11220
|
this.once("ready", () => {
|
|
11182
11221
|
if (fd !== this.fd) {
|
|
11183
|
-
|
|
11222
|
+
fs87.close(fd, (err) => {
|
|
11184
11223
|
if (err) {
|
|
11185
11224
|
return this.emit("error", err);
|
|
11186
11225
|
}
|
|
@@ -11229,7 +11268,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11229
11268
|
buf = this._bufs[0];
|
|
11230
11269
|
}
|
|
11231
11270
|
try {
|
|
11232
|
-
const n = Buffer.isBuffer(buf) ?
|
|
11271
|
+
const n = Buffer.isBuffer(buf) ? fs87.writeSync(this.fd, buf) : fs87.writeSync(this.fd, buf, "utf8");
|
|
11233
11272
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
11234
11273
|
buf = releasedBufObj.writingBuf;
|
|
11235
11274
|
this._len = releasedBufObj.len;
|
|
@@ -11245,7 +11284,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11245
11284
|
}
|
|
11246
11285
|
}
|
|
11247
11286
|
try {
|
|
11248
|
-
|
|
11287
|
+
fs87.fsyncSync(this.fd);
|
|
11249
11288
|
} catch {
|
|
11250
11289
|
}
|
|
11251
11290
|
}
|
|
@@ -11266,7 +11305,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11266
11305
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
11267
11306
|
}
|
|
11268
11307
|
try {
|
|
11269
|
-
const n =
|
|
11308
|
+
const n = fs87.writeSync(this.fd, buf);
|
|
11270
11309
|
buf = buf.subarray(n);
|
|
11271
11310
|
this._len = Math.max(this._len - n, 0);
|
|
11272
11311
|
if (buf.length <= 0) {
|
|
@@ -11294,13 +11333,13 @@ var require_sonic_boom = __commonJS({
|
|
|
11294
11333
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
11295
11334
|
if (this.sync) {
|
|
11296
11335
|
try {
|
|
11297
|
-
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");
|
|
11298
11337
|
release(null, written);
|
|
11299
11338
|
} catch (err) {
|
|
11300
11339
|
release(err);
|
|
11301
11340
|
}
|
|
11302
11341
|
} else {
|
|
11303
|
-
|
|
11342
|
+
fs87.write(this.fd, this._writingBuf, release);
|
|
11304
11343
|
}
|
|
11305
11344
|
}
|
|
11306
11345
|
function actualWriteBuffer() {
|
|
@@ -11309,7 +11348,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11309
11348
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
11310
11349
|
if (this.sync) {
|
|
11311
11350
|
try {
|
|
11312
|
-
const written =
|
|
11351
|
+
const written = fs87.writeSync(this.fd, this._writingBuf);
|
|
11313
11352
|
release(null, written);
|
|
11314
11353
|
} catch (err) {
|
|
11315
11354
|
release(err);
|
|
@@ -11318,7 +11357,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11318
11357
|
if (kCopyBuffer) {
|
|
11319
11358
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
11320
11359
|
}
|
|
11321
|
-
|
|
11360
|
+
fs87.write(this.fd, this._writingBuf, release);
|
|
11322
11361
|
}
|
|
11323
11362
|
}
|
|
11324
11363
|
function actualClose(sonic) {
|
|
@@ -11334,12 +11373,12 @@ var require_sonic_boom = __commonJS({
|
|
|
11334
11373
|
sonic._lens = [];
|
|
11335
11374
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
11336
11375
|
try {
|
|
11337
|
-
|
|
11376
|
+
fs87.fsync(sonic.fd, closeWrapped);
|
|
11338
11377
|
} catch {
|
|
11339
11378
|
}
|
|
11340
11379
|
function closeWrapped() {
|
|
11341
11380
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
11342
|
-
|
|
11381
|
+
fs87.close(sonic.fd, done);
|
|
11343
11382
|
} else {
|
|
11344
11383
|
done();
|
|
11345
11384
|
}
|
|
@@ -13703,7 +13742,7 @@ var require_multistream = __commonJS({
|
|
|
13703
13742
|
var require_pino = __commonJS({
|
|
13704
13743
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
13705
13744
|
"use strict";
|
|
13706
|
-
var
|
|
13745
|
+
var os32 = require("os");
|
|
13707
13746
|
var stdSerializers = require_pino_std_serializers();
|
|
13708
13747
|
var caller = require_caller();
|
|
13709
13748
|
var redaction = require_redaction();
|
|
@@ -13750,7 +13789,7 @@ var require_pino = __commonJS({
|
|
|
13750
13789
|
} = symbols;
|
|
13751
13790
|
var { epochTime, nullTime } = time;
|
|
13752
13791
|
var { pid } = process;
|
|
13753
|
-
var hostname =
|
|
13792
|
+
var hostname = os32.hostname();
|
|
13754
13793
|
var defaultErrorSerializer = stdSerializers.err;
|
|
13755
13794
|
var defaultOptions2 = {
|
|
13756
13795
|
level: "info",
|
|
@@ -14474,11 +14513,11 @@ var init_lib = __esm({
|
|
|
14474
14513
|
}
|
|
14475
14514
|
}
|
|
14476
14515
|
},
|
|
14477
|
-
addToPath: function addToPath(
|
|
14478
|
-
var last =
|
|
14516
|
+
addToPath: function addToPath(path98, added, removed, oldPosInc, options) {
|
|
14517
|
+
var last = path98.lastComponent;
|
|
14479
14518
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14480
14519
|
return {
|
|
14481
|
-
oldPos:
|
|
14520
|
+
oldPos: path98.oldPos + oldPosInc,
|
|
14482
14521
|
lastComponent: {
|
|
14483
14522
|
count: last.count + 1,
|
|
14484
14523
|
added,
|
|
@@ -14488,7 +14527,7 @@ var init_lib = __esm({
|
|
|
14488
14527
|
};
|
|
14489
14528
|
} else {
|
|
14490
14529
|
return {
|
|
14491
|
-
oldPos:
|
|
14530
|
+
oldPos: path98.oldPos + oldPosInc,
|
|
14492
14531
|
lastComponent: {
|
|
14493
14532
|
count: 1,
|
|
14494
14533
|
added,
|
|
@@ -15070,10 +15109,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
15070
15109
|
const memories = raw.map((m2) => {
|
|
15071
15110
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15072
15111
|
const rec4 = m2;
|
|
15073
|
-
const
|
|
15112
|
+
const path98 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15074
15113
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15075
|
-
if (!
|
|
15076
|
-
const entry = { path:
|
|
15114
|
+
if (!path98 || content == null) return null;
|
|
15115
|
+
const entry = { path: path98, content };
|
|
15077
15116
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
15078
15117
|
return entry;
|
|
15079
15118
|
}).filter((m2) => m2 !== null);
|
|
@@ -15939,10 +15978,10 @@ function parseAttachment(obj) {
|
|
|
15939
15978
|
const memories = raw.map((m2) => {
|
|
15940
15979
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15941
15980
|
const rec4 = m2;
|
|
15942
|
-
const
|
|
15981
|
+
const path98 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15943
15982
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15944
|
-
if (!
|
|
15945
|
-
const out = { path:
|
|
15983
|
+
if (!path98 || content == null) return null;
|
|
15984
|
+
const out = { path: path98, content };
|
|
15946
15985
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
15947
15986
|
return out;
|
|
15948
15987
|
}).filter((m2) => m2 !== null);
|
|
@@ -36916,8 +36955,8 @@ var require_utils = __commonJS({
|
|
|
36916
36955
|
var result = transform[inputType][outputType](input);
|
|
36917
36956
|
return result;
|
|
36918
36957
|
};
|
|
36919
|
-
exports2.resolve = function(
|
|
36920
|
-
var parts =
|
|
36958
|
+
exports2.resolve = function(path98) {
|
|
36959
|
+
var parts = path98.split("/");
|
|
36921
36960
|
var result = [];
|
|
36922
36961
|
for (var index = 0; index < parts.length; index++) {
|
|
36923
36962
|
var part = parts[index];
|
|
@@ -42770,18 +42809,18 @@ var require_object = __commonJS({
|
|
|
42770
42809
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
42771
42810
|
this.files[name] = object;
|
|
42772
42811
|
};
|
|
42773
|
-
var parentFolder = function(
|
|
42774
|
-
if (
|
|
42775
|
-
|
|
42812
|
+
var parentFolder = function(path98) {
|
|
42813
|
+
if (path98.slice(-1) === "/") {
|
|
42814
|
+
path98 = path98.substring(0, path98.length - 1);
|
|
42776
42815
|
}
|
|
42777
|
-
var lastSlash =
|
|
42778
|
-
return lastSlash > 0 ?
|
|
42816
|
+
var lastSlash = path98.lastIndexOf("/");
|
|
42817
|
+
return lastSlash > 0 ? path98.substring(0, lastSlash) : "";
|
|
42779
42818
|
};
|
|
42780
|
-
var forceTrailingSlash = function(
|
|
42781
|
-
if (
|
|
42782
|
-
|
|
42819
|
+
var forceTrailingSlash = function(path98) {
|
|
42820
|
+
if (path98.slice(-1) !== "/") {
|
|
42821
|
+
path98 += "/";
|
|
42783
42822
|
}
|
|
42784
|
-
return
|
|
42823
|
+
return path98;
|
|
42785
42824
|
};
|
|
42786
42825
|
var folderAdd = function(name, createFolders) {
|
|
42787
42826
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -43783,7 +43822,7 @@ var require_lib3 = __commonJS({
|
|
|
43783
43822
|
// src/run-case/recorder.ts
|
|
43784
43823
|
function startRunCaseRecorder(opts) {
|
|
43785
43824
|
const now = opts.now ?? Date.now;
|
|
43786
|
-
const dir =
|
|
43825
|
+
const dir = import_node_path80.default.dirname(opts.recordPath);
|
|
43787
43826
|
let stream = null;
|
|
43788
43827
|
let closing = false;
|
|
43789
43828
|
let closedSettled = false;
|
|
@@ -43823,12 +43862,12 @@ function startRunCaseRecorder(opts) {
|
|
|
43823
43862
|
};
|
|
43824
43863
|
return { tap, close, closed };
|
|
43825
43864
|
}
|
|
43826
|
-
var import_node_fs57,
|
|
43865
|
+
var import_node_fs57, import_node_path80;
|
|
43827
43866
|
var init_recorder = __esm({
|
|
43828
43867
|
"src/run-case/recorder.ts"() {
|
|
43829
43868
|
"use strict";
|
|
43830
43869
|
import_node_fs57 = __toESM(require("fs"), 1);
|
|
43831
|
-
|
|
43870
|
+
import_node_path80 = __toESM(require("path"), 1);
|
|
43832
43871
|
}
|
|
43833
43872
|
});
|
|
43834
43873
|
|
|
@@ -43871,7 +43910,7 @@ var init_wire = __esm({
|
|
|
43871
43910
|
// src/run-case/controller.ts
|
|
43872
43911
|
async function runController(opts) {
|
|
43873
43912
|
const now = opts.now ?? Date.now;
|
|
43874
|
-
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-"));
|
|
43875
43914
|
const ownsCwd = opts.cwd === void 0;
|
|
43876
43915
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
43877
43916
|
const spawnCtx = { cwd };
|
|
@@ -44038,13 +44077,13 @@ async function runController(opts) {
|
|
|
44038
44077
|
}
|
|
44039
44078
|
return exitCode ?? 0;
|
|
44040
44079
|
}
|
|
44041
|
-
var import_node_fs58,
|
|
44080
|
+
var import_node_fs58, import_node_os28, import_node_path81;
|
|
44042
44081
|
var init_controller = __esm({
|
|
44043
44082
|
"src/run-case/controller.ts"() {
|
|
44044
44083
|
"use strict";
|
|
44045
44084
|
import_node_fs58 = require("fs");
|
|
44046
|
-
|
|
44047
|
-
|
|
44085
|
+
import_node_os28 = __toESM(require("os"), 1);
|
|
44086
|
+
import_node_path81 = __toESM(require("path"), 1);
|
|
44048
44087
|
init_claude();
|
|
44049
44088
|
init_stdout_splitter();
|
|
44050
44089
|
init_permission_stdio();
|
|
@@ -44319,9 +44358,9 @@ Env (advanced):
|
|
|
44319
44358
|
`;
|
|
44320
44359
|
|
|
44321
44360
|
// src/index.ts
|
|
44322
|
-
var
|
|
44361
|
+
var import_node_path79 = __toESM(require("path"), 1);
|
|
44323
44362
|
var import_node_fs56 = __toESM(require("fs"), 1);
|
|
44324
|
-
var
|
|
44363
|
+
var import_node_os27 = __toESM(require("os"), 1);
|
|
44325
44364
|
var import_node_crypto22 = require("crypto");
|
|
44326
44365
|
var import_node_url5 = require("url");
|
|
44327
44366
|
|
|
@@ -51577,8 +51616,8 @@ function turnStartInput(text) {
|
|
|
51577
51616
|
const items = [];
|
|
51578
51617
|
let leftover = text;
|
|
51579
51618
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
51580
|
-
const [marker, name,
|
|
51581
|
-
items.push({ type: "skill", name, path:
|
|
51619
|
+
const [marker, name, path98] = m2;
|
|
51620
|
+
items.push({ type: "skill", name, path: path98 });
|
|
51582
51621
|
leftover = leftover.replace(marker, "");
|
|
51583
51622
|
}
|
|
51584
51623
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -54641,6 +54680,38 @@ function redactEvidence(evidence) {
|
|
|
54641
54680
|
};
|
|
54642
54681
|
}
|
|
54643
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
|
+
|
|
54644
54715
|
// src/handlers/deploy.ts
|
|
54645
54716
|
function ensureOwner(ctx) {
|
|
54646
54717
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
@@ -54670,6 +54741,11 @@ function secretStatusOf(deps, receipt) {
|
|
|
54670
54741
|
total: s.env.length
|
|
54671
54742
|
}));
|
|
54672
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
|
+
}
|
|
54673
54749
|
function buildDeployHandlers(deps) {
|
|
54674
54750
|
const view = (receipt) => ({
|
|
54675
54751
|
response: { type: "deploy:receipt", receipt, secretStatus: secretStatusOf(deps, receipt) }
|
|
@@ -54705,6 +54781,12 @@ function buildDeployHandlers(deps) {
|
|
|
54705
54781
|
if (receipt.status === "scanning") {
|
|
54706
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");
|
|
54707
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
|
+
}
|
|
54708
54790
|
deps.receipts.update(args.deployId, {
|
|
54709
54791
|
status: "scanning",
|
|
54710
54792
|
manifest: void 0,
|
|
@@ -54712,7 +54794,12 @@ function buildDeployHandlers(deps) {
|
|
|
54712
54794
|
notes: [],
|
|
54713
54795
|
smokeTask: void 0,
|
|
54714
54796
|
error: void 0,
|
|
54715
|
-
scanSessionId: void 0
|
|
54797
|
+
scanSessionId: void 0,
|
|
54798
|
+
// 重扫 = 一次新的判断,试装轮次跟着清零(不是同一条路上的第 N 次撞墙)
|
|
54799
|
+
trialRound: 0,
|
|
54800
|
+
gaps: [],
|
|
54801
|
+
trialPassedAt: void 0,
|
|
54802
|
+
trialImage: void 0
|
|
54716
54803
|
});
|
|
54717
54804
|
const scanSessionId = deps.startScan(args.deployId, receipt.personaId);
|
|
54718
54805
|
if (scanSessionId) deps.receipts.update(args.deployId, { scanSessionId });
|
|
@@ -54742,8 +54829,9 @@ function buildDeployHandlers(deps) {
|
|
|
54742
54829
|
}
|
|
54743
54830
|
}
|
|
54744
54831
|
}
|
|
54745
|
-
const
|
|
54746
|
-
|
|
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));
|
|
54747
54835
|
};
|
|
54748
54836
|
const putSecret = async (frame, _client, ctx) => {
|
|
54749
54837
|
ensureOwner(ctx);
|
|
@@ -54763,7 +54851,7 @@ function buildDeployHandlers(deps) {
|
|
|
54763
54851
|
}
|
|
54764
54852
|
}
|
|
54765
54853
|
deps.secrets.put({ deployId: args.deployId, name: args.name, values: args.values });
|
|
54766
|
-
return view(receipt);
|
|
54854
|
+
return view(applyReadiness(deps, receipt));
|
|
54767
54855
|
};
|
|
54768
54856
|
const reportFinding = async (frame, _client, ctx) => {
|
|
54769
54857
|
ensureOwner(ctx);
|
|
@@ -54806,12 +54894,77 @@ function buildDeployHandlers(deps) {
|
|
|
54806
54894
|
notes: args.notes?.map(redactSecretValues),
|
|
54807
54895
|
error: void 0
|
|
54808
54896
|
});
|
|
54809
|
-
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);
|
|
54810
54962
|
};
|
|
54811
54963
|
const remove = async (frame, _client, ctx) => {
|
|
54812
54964
|
ensureOwner(ctx);
|
|
54813
54965
|
const args = parseArgs2(DeployIdArgsSchema, frame, "deploy:remove");
|
|
54814
|
-
mustGet(deps, args.deployId);
|
|
54966
|
+
const receipt = mustGet(deps, args.deployId);
|
|
54967
|
+
if (receipt.placement) await deps.unregisterDeployment(receipt.deployId);
|
|
54815
54968
|
deps.receipts.remove(args.deployId);
|
|
54816
54969
|
deps.secrets.removeDeploy(args.deployId);
|
|
54817
54970
|
return { response: { type: "deploy:remove", deployId: args.deployId } };
|
|
@@ -54825,6 +54978,8 @@ function buildDeployHandlers(deps) {
|
|
|
54825
54978
|
"deploy:putSecret": putSecret,
|
|
54826
54979
|
"deploy:reportFinding": reportFinding,
|
|
54827
54980
|
"deploy:finishScan": finishScan,
|
|
54981
|
+
"deploy:trial": trial,
|
|
54982
|
+
"deploy:deploy": deploy,
|
|
54828
54983
|
"deploy:remove": remove
|
|
54829
54984
|
};
|
|
54830
54985
|
}
|
|
@@ -54881,6 +55036,7 @@ function createReceiptStore(deps) {
|
|
|
54881
55036
|
notes: [],
|
|
54882
55037
|
fulfillment: {},
|
|
54883
55038
|
gaps: [],
|
|
55039
|
+
trialRound: 0,
|
|
54884
55040
|
createdAt: ts,
|
|
54885
55041
|
updatedAt: ts
|
|
54886
55042
|
};
|
|
@@ -55009,6 +55165,384 @@ function createSecretStore(deps) {
|
|
|
55009
55165
|
};
|
|
55010
55166
|
}
|
|
55011
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
|
+
|
|
55012
55546
|
// src/deploy/scan-task.ts
|
|
55013
55547
|
var BUTLER_PERSONA_ID = "persona-clawd-butler";
|
|
55014
55548
|
var SCANNABLE_ASSETS = ["deploy-kit"];
|
|
@@ -55026,6 +55560,17 @@ function reconcileInterruptedScans(deps) {
|
|
|
55026
55560
|
}
|
|
55027
55561
|
return stale.map((r) => r.deployId);
|
|
55028
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
|
+
}
|
|
55029
55574
|
|
|
55030
55575
|
// src/handlers/lark-bot.ts
|
|
55031
55576
|
init_protocol();
|
|
@@ -55415,9 +55960,9 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
55415
55960
|
|
|
55416
55961
|
// src/lark-bot-connector/binding-store.ts
|
|
55417
55962
|
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
55418
|
-
var
|
|
55963
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
55419
55964
|
function createLarkBotBindingStore(personaRoot) {
|
|
55420
|
-
const filePath = (personaId2) =>
|
|
55965
|
+
const filePath = (personaId2) => import_node_path34.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
55421
55966
|
const read = (personaId2) => {
|
|
55422
55967
|
const file = filePath(personaId2);
|
|
55423
55968
|
if (!import_node_fs28.default.existsSync(file)) return null;
|
|
@@ -55431,7 +55976,7 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
55431
55976
|
};
|
|
55432
55977
|
const write = (personaId2, meta) => {
|
|
55433
55978
|
const file = filePath(personaId2);
|
|
55434
|
-
import_node_fs28.default.mkdirSync(
|
|
55979
|
+
import_node_fs28.default.mkdirSync(import_node_path34.default.dirname(file), { recursive: true });
|
|
55435
55980
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
55436
55981
|
import_node_fs28.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
55437
55982
|
import_node_fs28.default.renameSync(tmp, file);
|
|
@@ -55599,7 +56144,7 @@ function createLarkBotCloudClient(opts) {
|
|
|
55599
56144
|
|
|
55600
56145
|
// src/lark-bot-connector/chat-router.ts
|
|
55601
56146
|
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
55602
|
-
var
|
|
56147
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
55603
56148
|
init_protocol();
|
|
55604
56149
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
55605
56150
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -55666,7 +56211,7 @@ function createLarkChatRouter(deps) {
|
|
|
55666
56211
|
}
|
|
55667
56212
|
const dir = deps.mediaRootFor(env.chatId);
|
|
55668
56213
|
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
55669
|
-
const p2 =
|
|
56214
|
+
const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
|
|
55670
56215
|
import_node_fs29.default.writeFileSync(p2, r.data);
|
|
55671
56216
|
lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
55672
56217
|
} catch (err) {
|
|
@@ -55689,7 +56234,7 @@ function createLarkChatRouter(deps) {
|
|
|
55689
56234
|
}
|
|
55690
56235
|
const dir = deps.mediaRootFor(env.chatId);
|
|
55691
56236
|
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
55692
|
-
const p2 =
|
|
56237
|
+
const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
55693
56238
|
import_node_fs29.default.writeFileSync(p2, r.data);
|
|
55694
56239
|
lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
55695
56240
|
} catch (err) {
|
|
@@ -56779,7 +57324,7 @@ var CodexHistoryReader = class {
|
|
|
56779
57324
|
};
|
|
56780
57325
|
|
|
56781
57326
|
// src/tools/codex-skills.ts
|
|
56782
|
-
var
|
|
57327
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
56783
57328
|
function str3(v2) {
|
|
56784
57329
|
return typeof v2 === "string" ? v2 : void 0;
|
|
56785
57330
|
}
|
|
@@ -56794,13 +57339,13 @@ function mapSkillsListResponse(res) {
|
|
|
56794
57339
|
const r = s ?? {};
|
|
56795
57340
|
const name = str3(r.name);
|
|
56796
57341
|
if (!name) continue;
|
|
56797
|
-
const
|
|
57342
|
+
const path98 = str3(r.path);
|
|
56798
57343
|
const description = str3(r.description);
|
|
56799
57344
|
const isPlugin = name.includes(":");
|
|
56800
57345
|
out.push({
|
|
56801
57346
|
name,
|
|
56802
57347
|
source: isPlugin ? "plugin" : "project",
|
|
56803
|
-
...
|
|
57348
|
+
...path98 ? { path: path98 } : {},
|
|
56804
57349
|
...description ? { description } : {},
|
|
56805
57350
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
56806
57351
|
});
|
|
@@ -56816,14 +57361,14 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
56816
57361
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
56817
57362
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
56818
57363
|
beforeRequest: (client) => {
|
|
56819
|
-
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);
|
|
56820
57365
|
}
|
|
56821
57366
|
});
|
|
56822
57367
|
return mapSkillsListResponse(res);
|
|
56823
57368
|
}
|
|
56824
57369
|
|
|
56825
57370
|
// src/tools/codex-turn-context.ts
|
|
56826
|
-
var
|
|
57371
|
+
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
56827
57372
|
function parseTurnContextFromRollout(raw) {
|
|
56828
57373
|
const lines = raw.split("\n");
|
|
56829
57374
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -56858,7 +57403,7 @@ async function readCodexTurnContext(args, deps = {}) {
|
|
|
56858
57403
|
);
|
|
56859
57404
|
const rolloutPath = str4(rec3(res?.thread)?.path);
|
|
56860
57405
|
if (!rolloutPath) return null;
|
|
56861
|
-
return parseTurnContextFromRollout(await
|
|
57406
|
+
return parseTurnContextFromRollout(await import_promises8.default.readFile(rolloutPath, "utf8"));
|
|
56862
57407
|
}
|
|
56863
57408
|
function createCodexResolvedMetaHydrator(deps) {
|
|
56864
57409
|
const fetchedThreadIds = /* @__PURE__ */ new Set();
|
|
@@ -56902,15 +57447,15 @@ function str4(v2) {
|
|
|
56902
57447
|
|
|
56903
57448
|
// src/workspace/browser.ts
|
|
56904
57449
|
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
56905
|
-
var
|
|
56906
|
-
var
|
|
57450
|
+
var import_node_os9 = __toESM(require("os"), 1);
|
|
57451
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56907
57452
|
init_protocol();
|
|
56908
57453
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
56909
57454
|
function resolveInsideCwd(cwd, subpath) {
|
|
56910
|
-
const absCwd =
|
|
56911
|
-
const joined =
|
|
56912
|
-
const rel =
|
|
56913
|
-
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)) {
|
|
56914
57459
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
56915
57460
|
}
|
|
56916
57461
|
return joined;
|
|
@@ -56928,7 +57473,7 @@ function ensureCwd(cwd) {
|
|
|
56928
57473
|
}
|
|
56929
57474
|
var WorkspaceBrowser = class {
|
|
56930
57475
|
list(args) {
|
|
56931
|
-
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();
|
|
56932
57477
|
ensureCwd(cwd);
|
|
56933
57478
|
const full = resolveInsideCwd(cwd, args.path);
|
|
56934
57479
|
const dirents = import_node_fs30.default.readdirSync(full, { withFileTypes: true });
|
|
@@ -56941,7 +57486,7 @@ var WorkspaceBrowser = class {
|
|
|
56941
57486
|
mtime: ""
|
|
56942
57487
|
};
|
|
56943
57488
|
try {
|
|
56944
|
-
const st = import_node_fs30.default.statSync(
|
|
57489
|
+
const st = import_node_fs30.default.statSync(import_node_path37.default.join(full, d.name));
|
|
56945
57490
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
56946
57491
|
if (d.isFile()) entry.size = st.size;
|
|
56947
57492
|
} catch {
|
|
@@ -56987,8 +57532,8 @@ var WorkspaceBrowser = class {
|
|
|
56987
57532
|
|
|
56988
57533
|
// src/skills/agents-scanner.ts
|
|
56989
57534
|
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
56990
|
-
var
|
|
56991
|
-
var
|
|
57535
|
+
var import_node_os10 = __toESM(require("os"), 1);
|
|
57536
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
56992
57537
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
56993
57538
|
function isDirLikeSync2(p2) {
|
|
56994
57539
|
try {
|
|
@@ -57026,10 +57571,10 @@ function scanAgentsDir(dir, source, seen, out) {
|
|
|
57026
57571
|
}
|
|
57027
57572
|
for (const ent of entries) {
|
|
57028
57573
|
if (!ent.name.endsWith(".md")) continue;
|
|
57029
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
57574
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path38.default.join(dir, ent.name)))) {
|
|
57030
57575
|
continue;
|
|
57031
57576
|
}
|
|
57032
|
-
const filePath =
|
|
57577
|
+
const filePath = import_node_path38.default.join(dir, ent.name);
|
|
57033
57578
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
57034
57579
|
if (seen.has(baseName)) continue;
|
|
57035
57580
|
seen.add(baseName);
|
|
@@ -57052,7 +57597,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
57052
57597
|
return;
|
|
57053
57598
|
}
|
|
57054
57599
|
for (const ent of entries) {
|
|
57055
|
-
const childPath =
|
|
57600
|
+
const childPath = import_node_path38.default.join(dir, ent.name);
|
|
57056
57601
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
57057
57602
|
walk2(childPath, [...namespaces, ent.name]);
|
|
57058
57603
|
continue;
|
|
@@ -57077,9 +57622,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
57077
57622
|
walk2(root, []);
|
|
57078
57623
|
}
|
|
57079
57624
|
function readInstalledPlugins2(home) {
|
|
57080
|
-
const pluginsDir =
|
|
57081
|
-
const v2 =
|
|
57082
|
-
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");
|
|
57083
57628
|
let raw = null;
|
|
57084
57629
|
for (const candidate of [v2, v1]) {
|
|
57085
57630
|
try {
|
|
@@ -57108,19 +57653,19 @@ function readInstalledPlugins2(home) {
|
|
|
57108
57653
|
return out;
|
|
57109
57654
|
}
|
|
57110
57655
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
57111
|
-
let cur =
|
|
57112
|
-
const fsRoot =
|
|
57656
|
+
let cur = import_node_path38.default.resolve(startCwd);
|
|
57657
|
+
const fsRoot = import_node_path38.default.parse(cur).root;
|
|
57113
57658
|
while (true) {
|
|
57114
|
-
scanAgentsDir(
|
|
57659
|
+
scanAgentsDir(import_node_path38.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
57115
57660
|
let hasGit = false;
|
|
57116
57661
|
try {
|
|
57117
|
-
hasGit = import_node_fs31.default.existsSync(
|
|
57662
|
+
hasGit = import_node_fs31.default.existsSync(import_node_path38.default.join(cur, ".git"));
|
|
57118
57663
|
} catch {
|
|
57119
57664
|
}
|
|
57120
57665
|
if (hasGit) return;
|
|
57121
57666
|
if (cur === home) return;
|
|
57122
57667
|
if (cur === fsRoot) return;
|
|
57123
|
-
const parent =
|
|
57668
|
+
const parent = import_node_path38.default.dirname(cur);
|
|
57124
57669
|
if (parent === cur) return;
|
|
57125
57670
|
cur = parent;
|
|
57126
57671
|
}
|
|
@@ -57130,7 +57675,7 @@ var AgentsScanner = class {
|
|
|
57130
57675
|
extraPluginRoots;
|
|
57131
57676
|
policyDir;
|
|
57132
57677
|
constructor(opts = {}) {
|
|
57133
|
-
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ??
|
|
57678
|
+
this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os10.default.homedir();
|
|
57134
57679
|
this.extraPluginRoots = opts.extraPluginRoots ?? [];
|
|
57135
57680
|
if (opts.policyDir !== void 0) {
|
|
57136
57681
|
this.policyDir = opts.policyDir;
|
|
@@ -57155,7 +57700,7 @@ var AgentsScanner = class {
|
|
|
57155
57700
|
}
|
|
57156
57701
|
const fsBlock = [];
|
|
57157
57702
|
scanAgentsDir(
|
|
57158
|
-
|
|
57703
|
+
import_node_path38.default.join(this.home, ".claude", "agents"),
|
|
57159
57704
|
"global",
|
|
57160
57705
|
seen,
|
|
57161
57706
|
fsBlock
|
|
@@ -57169,7 +57714,7 @@ var AgentsScanner = class {
|
|
|
57169
57714
|
...this.extraPluginRoots
|
|
57170
57715
|
];
|
|
57171
57716
|
for (const { name, root } of plugins) {
|
|
57172
|
-
const agentsRoot =
|
|
57717
|
+
const agentsRoot = import_node_path38.default.join(root, "agents");
|
|
57173
57718
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
57174
57719
|
}
|
|
57175
57720
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -57178,27 +57723,27 @@ var AgentsScanner = class {
|
|
|
57178
57723
|
|
|
57179
57724
|
// src/observer/session-observer.ts
|
|
57180
57725
|
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
57181
|
-
var
|
|
57182
|
-
var
|
|
57726
|
+
var import_node_os12 = __toESM(require("os"), 1);
|
|
57727
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
57183
57728
|
init_claude_history();
|
|
57184
57729
|
|
|
57185
57730
|
// src/observer/subagent-meta-observer.ts
|
|
57186
57731
|
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
57187
|
-
var
|
|
57188
|
-
var
|
|
57732
|
+
var import_node_os11 = __toESM(require("os"), 1);
|
|
57733
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
57189
57734
|
init_claude_history();
|
|
57190
57735
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
57191
57736
|
var SubagentMetaObserver = class {
|
|
57192
57737
|
constructor(opts) {
|
|
57193
57738
|
this.opts = opts;
|
|
57194
|
-
this.home = opts.home ??
|
|
57739
|
+
this.home = opts.home ?? import_node_os11.default.homedir();
|
|
57195
57740
|
}
|
|
57196
57741
|
opts;
|
|
57197
57742
|
home;
|
|
57198
57743
|
watches = /* @__PURE__ */ new Map();
|
|
57199
57744
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
57200
57745
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
57201
|
-
return
|
|
57746
|
+
return import_node_path39.default.join(
|
|
57202
57747
|
this.home,
|
|
57203
57748
|
".claude",
|
|
57204
57749
|
"projects",
|
|
@@ -57254,7 +57799,7 @@ var SubagentMetaObserver = class {
|
|
|
57254
57799
|
if (!m2) return;
|
|
57255
57800
|
const agentId = m2[1];
|
|
57256
57801
|
if (w2.emitted.has(agentId)) return;
|
|
57257
|
-
const file =
|
|
57802
|
+
const file = import_node_path39.default.join(w2.dirPath, name);
|
|
57258
57803
|
let raw;
|
|
57259
57804
|
try {
|
|
57260
57805
|
raw = import_node_fs32.default.readFileSync(file, "utf8");
|
|
@@ -57302,7 +57847,7 @@ var SubagentMetaObserver = class {
|
|
|
57302
57847
|
var SessionObserver = class {
|
|
57303
57848
|
constructor(opts) {
|
|
57304
57849
|
this.opts = opts;
|
|
57305
|
-
this.home = opts.home ??
|
|
57850
|
+
this.home = opts.home ?? import_node_os12.default.homedir();
|
|
57306
57851
|
this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
|
|
57307
57852
|
}
|
|
57308
57853
|
opts;
|
|
@@ -57314,7 +57859,7 @@ var SessionObserver = class {
|
|
|
57314
57859
|
metaObserver;
|
|
57315
57860
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
57316
57861
|
if (override) return override;
|
|
57317
|
-
return
|
|
57862
|
+
return import_node_path40.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
57318
57863
|
}
|
|
57319
57864
|
start(args) {
|
|
57320
57865
|
this.stop(args.sessionId);
|
|
@@ -57340,10 +57885,10 @@ var SessionObserver = class {
|
|
|
57340
57885
|
lastDeriveMs: 0
|
|
57341
57886
|
};
|
|
57342
57887
|
try {
|
|
57343
|
-
import_node_fs33.default.mkdirSync(
|
|
57888
|
+
import_node_fs33.default.mkdirSync(import_node_path40.default.dirname(filePath), { recursive: true });
|
|
57344
57889
|
} catch {
|
|
57345
57890
|
}
|
|
57346
|
-
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) => {
|
|
57347
57892
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
57348
57893
|
this.poll(w2);
|
|
57349
57894
|
});
|
|
@@ -57440,7 +57985,7 @@ var SessionObserver = class {
|
|
|
57440
57985
|
const now = Date.now();
|
|
57441
57986
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
57442
57987
|
w2.lastRelocateScanMs = now;
|
|
57443
|
-
const projectsRoot =
|
|
57988
|
+
const projectsRoot = import_node_path40.default.join(this.home, ".claude", "projects");
|
|
57444
57989
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
57445
57990
|
if (!found || found === w2.filePath) return;
|
|
57446
57991
|
try {
|
|
@@ -57449,7 +57994,7 @@ var SessionObserver = class {
|
|
|
57449
57994
|
}
|
|
57450
57995
|
w2.filePath = found;
|
|
57451
57996
|
try {
|
|
57452
|
-
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) => {
|
|
57453
57998
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
57454
57999
|
this.poll(w2);
|
|
57455
58000
|
});
|
|
@@ -57569,10 +58114,10 @@ function listRegistered() {
|
|
|
57569
58114
|
}
|
|
57570
58115
|
|
|
57571
58116
|
// src/tools/title-generator.ts
|
|
57572
|
-
var
|
|
58117
|
+
var import_node_child_process9 = require("child_process");
|
|
57573
58118
|
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
57574
|
-
var
|
|
57575
|
-
var
|
|
58119
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
58120
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
57576
58121
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
57577
58122
|
var TITLE_MODEL_BY_TOOL = {
|
|
57578
58123
|
claude: "haiku",
|
|
@@ -57643,7 +58188,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
57643
58188
|
if (!text) return null;
|
|
57644
58189
|
let workDir;
|
|
57645
58190
|
try {
|
|
57646
|
-
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));
|
|
57647
58192
|
} catch {
|
|
57648
58193
|
return null;
|
|
57649
58194
|
}
|
|
@@ -57653,8 +58198,8 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
57653
58198
|
} catch {
|
|
57654
58199
|
}
|
|
57655
58200
|
};
|
|
57656
|
-
const outFile =
|
|
57657
|
-
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");
|
|
57658
58203
|
if (tool === "codex") {
|
|
57659
58204
|
try {
|
|
57660
58205
|
import_node_fs34.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
@@ -57665,7 +58210,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
57665
58210
|
}
|
|
57666
58211
|
const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
|
|
57667
58212
|
const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text)) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile);
|
|
57668
|
-
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"] }));
|
|
57669
58214
|
const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
|
|
57670
58215
|
return await new Promise((resolve9) => {
|
|
57671
58216
|
let proc;
|
|
@@ -58408,8 +58953,8 @@ async function authenticate(token, deps) {
|
|
|
58408
58953
|
}
|
|
58409
58954
|
|
|
58410
58955
|
// src/legacy-cleanup.ts
|
|
58411
|
-
var
|
|
58412
|
-
var
|
|
58956
|
+
var fs47 = __toESM(require("fs/promises"), 1);
|
|
58957
|
+
var path49 = __toESM(require("path"), 1);
|
|
58413
58958
|
var LEGACY_FILES = [
|
|
58414
58959
|
"personal-capability.json",
|
|
58415
58960
|
"received-capabilities.json",
|
|
@@ -58418,9 +58963,9 @@ var LEGACY_FILES = [
|
|
|
58418
58963
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
58419
58964
|
const removed = [];
|
|
58420
58965
|
for (const name of LEGACY_FILES) {
|
|
58421
|
-
const p2 =
|
|
58966
|
+
const p2 = path49.join(dataDir, name);
|
|
58422
58967
|
try {
|
|
58423
|
-
await
|
|
58968
|
+
await fs47.unlink(p2);
|
|
58424
58969
|
removed.push(name);
|
|
58425
58970
|
logger.debug("legacy capability file removed", { file: name });
|
|
58426
58971
|
} catch (err) {
|
|
@@ -58432,13 +58977,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
58432
58977
|
}
|
|
58433
58978
|
|
|
58434
58979
|
// src/inbox/inbox-store.ts
|
|
58435
|
-
var
|
|
58436
|
-
var
|
|
58980
|
+
var fs48 = __toESM(require("fs"), 1);
|
|
58981
|
+
var path50 = __toESM(require("path"), 1);
|
|
58437
58982
|
var INBOX_SUBDIR = "inbox";
|
|
58438
58983
|
var InboxStore = class {
|
|
58439
58984
|
constructor(dataDir) {
|
|
58440
58985
|
this.dataDir = dataDir;
|
|
58441
|
-
|
|
58986
|
+
fs48.mkdirSync(this.dirPath(), { recursive: true });
|
|
58442
58987
|
}
|
|
58443
58988
|
dataDir;
|
|
58444
58989
|
/**
|
|
@@ -58450,7 +58995,7 @@ var InboxStore = class {
|
|
|
58450
58995
|
const file = this.filePath(peerDeviceId);
|
|
58451
58996
|
let raw;
|
|
58452
58997
|
try {
|
|
58453
|
-
raw =
|
|
58998
|
+
raw = fs48.readFileSync(file, "utf8");
|
|
58454
58999
|
} catch (err) {
|
|
58455
59000
|
if (err?.code === "ENOENT") return [];
|
|
58456
59001
|
return [];
|
|
@@ -58466,7 +59011,7 @@ var InboxStore = class {
|
|
|
58466
59011
|
const dir = this.dirPath();
|
|
58467
59012
|
let entries;
|
|
58468
59013
|
try {
|
|
58469
|
-
entries =
|
|
59014
|
+
entries = fs48.readdirSync(dir);
|
|
58470
59015
|
} catch (err) {
|
|
58471
59016
|
if (err?.code === "ENOENT") return [];
|
|
58472
59017
|
return [];
|
|
@@ -58482,9 +59027,9 @@ var InboxStore = class {
|
|
|
58482
59027
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
58483
59028
|
const file = this.filePath(message.peerDeviceId);
|
|
58484
59029
|
const line = JSON.stringify(message) + "\n";
|
|
58485
|
-
|
|
59030
|
+
fs48.appendFileSync(file, line, { mode: 384 });
|
|
58486
59031
|
try {
|
|
58487
|
-
|
|
59032
|
+
fs48.chmodSync(file, 384);
|
|
58488
59033
|
} catch {
|
|
58489
59034
|
}
|
|
58490
59035
|
}
|
|
@@ -58514,7 +59059,7 @@ var InboxStore = class {
|
|
|
58514
59059
|
removeByPeerDeviceId(peerDeviceId) {
|
|
58515
59060
|
const file = this.filePath(peerDeviceId);
|
|
58516
59061
|
try {
|
|
58517
|
-
|
|
59062
|
+
fs48.unlinkSync(file);
|
|
58518
59063
|
} catch (err) {
|
|
58519
59064
|
if (err?.code === "ENOENT") return;
|
|
58520
59065
|
}
|
|
@@ -58523,18 +59068,18 @@ var InboxStore = class {
|
|
|
58523
59068
|
const file = this.filePath(peerDeviceId);
|
|
58524
59069
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
58525
59070
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
58526
|
-
|
|
58527
|
-
|
|
59071
|
+
fs48.writeFileSync(tmp, content, { mode: 384 });
|
|
59072
|
+
fs48.renameSync(tmp, file);
|
|
58528
59073
|
try {
|
|
58529
|
-
|
|
59074
|
+
fs48.chmodSync(file, 384);
|
|
58530
59075
|
} catch {
|
|
58531
59076
|
}
|
|
58532
59077
|
}
|
|
58533
59078
|
dirPath() {
|
|
58534
|
-
return
|
|
59079
|
+
return path50.join(this.dataDir, INBOX_SUBDIR);
|
|
58535
59080
|
}
|
|
58536
59081
|
filePath(peerDeviceId) {
|
|
58537
|
-
return
|
|
59082
|
+
return path50.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
58538
59083
|
}
|
|
58539
59084
|
};
|
|
58540
59085
|
function parseAllLines(raw) {
|
|
@@ -58622,8 +59167,8 @@ var InboxManager = class {
|
|
|
58622
59167
|
};
|
|
58623
59168
|
|
|
58624
59169
|
// src/state/contact-store.ts
|
|
58625
|
-
var
|
|
58626
|
-
var
|
|
59170
|
+
var fs49 = __toESM(require("fs"), 1);
|
|
59171
|
+
var path51 = __toESM(require("path"), 1);
|
|
58627
59172
|
var FILE_NAME = "contacts.json";
|
|
58628
59173
|
var ContactStore = class {
|
|
58629
59174
|
constructor(dataDir) {
|
|
@@ -58633,10 +59178,10 @@ var ContactStore = class {
|
|
|
58633
59178
|
contacts = /* @__PURE__ */ new Map();
|
|
58634
59179
|
load() {
|
|
58635
59180
|
this.contacts.clear();
|
|
58636
|
-
const file =
|
|
59181
|
+
const file = path51.join(this.dataDir, FILE_NAME);
|
|
58637
59182
|
let raw;
|
|
58638
59183
|
try {
|
|
58639
|
-
raw =
|
|
59184
|
+
raw = fs49.readFileSync(file, "utf8");
|
|
58640
59185
|
} catch (err) {
|
|
58641
59186
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
58642
59187
|
return;
|
|
@@ -58717,20 +59262,20 @@ var ContactStore = class {
|
|
|
58717
59262
|
return true;
|
|
58718
59263
|
}
|
|
58719
59264
|
flush() {
|
|
58720
|
-
const file =
|
|
59265
|
+
const file = path51.join(this.dataDir, FILE_NAME);
|
|
58721
59266
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
58722
59267
|
const content = JSON.stringify(
|
|
58723
59268
|
{ contacts: Array.from(this.contacts.values()) },
|
|
58724
59269
|
null,
|
|
58725
59270
|
2
|
|
58726
59271
|
);
|
|
58727
|
-
|
|
58728
|
-
|
|
58729
|
-
|
|
59272
|
+
fs49.mkdirSync(this.dataDir, { recursive: true });
|
|
59273
|
+
fs49.writeFileSync(tmp, content, { mode: 384 });
|
|
59274
|
+
fs49.renameSync(tmp, file);
|
|
58730
59275
|
}
|
|
58731
59276
|
renameBak(file) {
|
|
58732
59277
|
try {
|
|
58733
|
-
|
|
59278
|
+
fs49.renameSync(file, `${file}.bak`);
|
|
58734
59279
|
} catch {
|
|
58735
59280
|
}
|
|
58736
59281
|
}
|
|
@@ -58838,61 +59383,61 @@ async function connectRemote(args) {
|
|
|
58838
59383
|
}
|
|
58839
59384
|
|
|
58840
59385
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
58841
|
-
var
|
|
58842
|
-
var
|
|
59386
|
+
var fs50 = __toESM(require("fs"), 1);
|
|
59387
|
+
var path52 = __toESM(require("path"), 1);
|
|
58843
59388
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
58844
59389
|
function migrateFlattenSessions(opts) {
|
|
58845
59390
|
const dataDir = opts.dataDir;
|
|
58846
59391
|
const now = opts.now ?? Date.now;
|
|
58847
|
-
const sessionsDir =
|
|
58848
|
-
const flagPath =
|
|
59392
|
+
const sessionsDir = path52.join(dataDir, "sessions");
|
|
59393
|
+
const flagPath = path52.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
58849
59394
|
if (existsSync3(flagPath)) {
|
|
58850
59395
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
58851
59396
|
}
|
|
58852
59397
|
let movedBare = 0;
|
|
58853
59398
|
let movedVmOwner = 0;
|
|
58854
59399
|
let archivedListener = 0;
|
|
58855
|
-
const defaultDir =
|
|
59400
|
+
const defaultDir = path52.join(sessionsDir, "default");
|
|
58856
59401
|
if (existsSync3(defaultDir)) {
|
|
58857
59402
|
for (const entry of readdirSafe(defaultDir)) {
|
|
58858
59403
|
if (!entry.endsWith(".json")) continue;
|
|
58859
|
-
const src =
|
|
58860
|
-
const dst =
|
|
58861
|
-
|
|
59404
|
+
const src = path52.join(defaultDir, entry);
|
|
59405
|
+
const dst = path52.join(sessionsDir, entry);
|
|
59406
|
+
fs50.renameSync(src, dst);
|
|
58862
59407
|
movedBare += 1;
|
|
58863
59408
|
}
|
|
58864
59409
|
rmdirIfEmpty(defaultDir);
|
|
58865
59410
|
}
|
|
58866
59411
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
58867
|
-
const personaDir =
|
|
59412
|
+
const personaDir = path52.join(sessionsDir, pid);
|
|
58868
59413
|
if (!isDir(personaDir)) continue;
|
|
58869
59414
|
if (pid === "default") continue;
|
|
58870
|
-
const ownerSrc =
|
|
59415
|
+
const ownerSrc = path52.join(personaDir, "owner");
|
|
58871
59416
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
58872
|
-
const ownerDst =
|
|
58873
|
-
|
|
59417
|
+
const ownerDst = path52.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
59418
|
+
fs50.mkdirSync(ownerDst, { recursive: true });
|
|
58874
59419
|
for (const file of readdirSafe(ownerSrc)) {
|
|
58875
59420
|
if (!file.endsWith(".json")) continue;
|
|
58876
|
-
|
|
59421
|
+
fs50.renameSync(path52.join(ownerSrc, file), path52.join(ownerDst, file));
|
|
58877
59422
|
movedVmOwner += 1;
|
|
58878
59423
|
}
|
|
58879
59424
|
rmdirIfEmpty(ownerSrc);
|
|
58880
59425
|
}
|
|
58881
|
-
const listenerSrc =
|
|
59426
|
+
const listenerSrc = path52.join(personaDir, "listener");
|
|
58882
59427
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
58883
|
-
const archiveDst =
|
|
58884
|
-
|
|
59428
|
+
const archiveDst = path52.join(dataDir, ".legacy", `listener-${pid}`);
|
|
59429
|
+
fs50.mkdirSync(archiveDst, { recursive: true });
|
|
58885
59430
|
for (const file of readdirSafe(listenerSrc)) {
|
|
58886
59431
|
if (!file.endsWith(".json")) continue;
|
|
58887
|
-
|
|
59432
|
+
fs50.renameSync(path52.join(listenerSrc, file), path52.join(archiveDst, file));
|
|
58888
59433
|
archivedListener += 1;
|
|
58889
59434
|
}
|
|
58890
59435
|
rmdirIfEmpty(listenerSrc);
|
|
58891
59436
|
}
|
|
58892
59437
|
rmdirIfEmpty(personaDir);
|
|
58893
59438
|
}
|
|
58894
|
-
|
|
58895
|
-
|
|
59439
|
+
fs50.mkdirSync(sessionsDir, { recursive: true });
|
|
59440
|
+
fs50.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
58896
59441
|
return {
|
|
58897
59442
|
skipped: false,
|
|
58898
59443
|
flagWritten: true,
|
|
@@ -58903,7 +59448,7 @@ function migrateFlattenSessions(opts) {
|
|
|
58903
59448
|
}
|
|
58904
59449
|
function existsSync3(p2) {
|
|
58905
59450
|
try {
|
|
58906
|
-
|
|
59451
|
+
fs50.statSync(p2);
|
|
58907
59452
|
return true;
|
|
58908
59453
|
} catch {
|
|
58909
59454
|
return false;
|
|
@@ -58911,61 +59456,61 @@ function existsSync3(p2) {
|
|
|
58911
59456
|
}
|
|
58912
59457
|
function isDir(p2) {
|
|
58913
59458
|
try {
|
|
58914
|
-
return
|
|
59459
|
+
return fs50.statSync(p2).isDirectory();
|
|
58915
59460
|
} catch {
|
|
58916
59461
|
return false;
|
|
58917
59462
|
}
|
|
58918
59463
|
}
|
|
58919
59464
|
function readdirSafe(p2) {
|
|
58920
59465
|
try {
|
|
58921
|
-
return
|
|
59466
|
+
return fs50.readdirSync(p2);
|
|
58922
59467
|
} catch {
|
|
58923
59468
|
return [];
|
|
58924
59469
|
}
|
|
58925
59470
|
}
|
|
58926
59471
|
function rmdirIfEmpty(p2) {
|
|
58927
59472
|
try {
|
|
58928
|
-
|
|
59473
|
+
fs50.rmdirSync(p2);
|
|
58929
59474
|
} catch {
|
|
58930
59475
|
}
|
|
58931
59476
|
}
|
|
58932
59477
|
|
|
58933
59478
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
58934
|
-
var
|
|
58935
|
-
var
|
|
59479
|
+
var fs51 = __toESM(require("fs"), 1);
|
|
59480
|
+
var path53 = __toESM(require("path"), 1);
|
|
58936
59481
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
58937
59482
|
function dropSeededProjects(opts) {
|
|
58938
|
-
|
|
58939
|
-
const flag =
|
|
58940
|
-
if (
|
|
58941
|
-
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");
|
|
58942
59487
|
let raw = null;
|
|
58943
59488
|
let dropped = 0;
|
|
58944
59489
|
try {
|
|
58945
|
-
raw =
|
|
59490
|
+
raw = fs51.readFileSync(file, "utf8");
|
|
58946
59491
|
dropped = JSON.parse(raw).projects?.length ?? 0;
|
|
58947
59492
|
} catch {
|
|
58948
59493
|
}
|
|
58949
59494
|
let backup = null;
|
|
58950
59495
|
if (raw != null && dropped > 0) {
|
|
58951
|
-
const dir =
|
|
58952
|
-
|
|
58953
|
-
backup =
|
|
58954
|
-
|
|
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);
|
|
58955
59500
|
}
|
|
58956
59501
|
if (raw != null || dropped > 0) {
|
|
58957
|
-
|
|
59502
|
+
fs51.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
|
|
58958
59503
|
}
|
|
58959
|
-
|
|
59504
|
+
fs51.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
|
|
58960
59505
|
return { skipped: false, dropped, backup };
|
|
58961
59506
|
}
|
|
58962
59507
|
|
|
58963
59508
|
// src/transport/http-router.ts
|
|
58964
59509
|
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
58965
|
-
var
|
|
59510
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
58966
59511
|
|
|
58967
59512
|
// src/attachment/mime.ts
|
|
58968
|
-
var
|
|
59513
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
58969
59514
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
58970
59515
|
var EXT_TO_NATIVE_MIME = {
|
|
58971
59516
|
// 图片
|
|
@@ -59072,7 +59617,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
59072
59617
|
".mk"
|
|
59073
59618
|
]);
|
|
59074
59619
|
function lookupMime(filePathOrName) {
|
|
59075
|
-
const ext =
|
|
59620
|
+
const ext = import_node_path42.default.extname(filePathOrName).toLowerCase();
|
|
59076
59621
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
59077
59622
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
59078
59623
|
return "application/octet-stream";
|
|
@@ -59143,9 +59688,9 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
59143
59688
|
|
|
59144
59689
|
// src/attachment/upload.ts
|
|
59145
59690
|
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
59146
|
-
var
|
|
59691
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
59147
59692
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
59148
|
-
var
|
|
59693
|
+
var import_promises9 = require("stream/promises");
|
|
59149
59694
|
var UploadError = class extends Error {
|
|
59150
59695
|
constructor(code, message) {
|
|
59151
59696
|
super(message);
|
|
@@ -59155,14 +59700,14 @@ var UploadError = class extends Error {
|
|
|
59155
59700
|
code;
|
|
59156
59701
|
};
|
|
59157
59702
|
function assertValidFileName(fileName) {
|
|
59158
|
-
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)) {
|
|
59159
59704
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
59160
59705
|
}
|
|
59161
59706
|
}
|
|
59162
59707
|
var HASH_PREFIX_LEN = 16;
|
|
59163
59708
|
async function writeUploadedAttachment(args) {
|
|
59164
59709
|
assertValidFileName(args.fileName);
|
|
59165
|
-
const attachmentsRoot =
|
|
59710
|
+
const attachmentsRoot = import_node_path43.default.join(args.baseDir, ".attachments");
|
|
59166
59711
|
try {
|
|
59167
59712
|
import_node_fs35.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
59168
59713
|
} catch (err) {
|
|
@@ -59170,12 +59715,12 @@ async function writeUploadedAttachment(args) {
|
|
|
59170
59715
|
}
|
|
59171
59716
|
const hasher = import_node_crypto10.default.createHash("sha256");
|
|
59172
59717
|
let actualSize = 0;
|
|
59173
|
-
const tmpPath =
|
|
59718
|
+
const tmpPath = import_node_path43.default.join(
|
|
59174
59719
|
attachmentsRoot,
|
|
59175
59720
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto10.default.randomBytes(4).toString("hex")}`
|
|
59176
59721
|
);
|
|
59177
59722
|
try {
|
|
59178
|
-
await (0,
|
|
59723
|
+
await (0, import_promises9.pipeline)(
|
|
59179
59724
|
args.body,
|
|
59180
59725
|
async function* (source) {
|
|
59181
59726
|
for await (const chunk of source) {
|
|
@@ -59205,7 +59750,7 @@ async function writeUploadedAttachment(args) {
|
|
|
59205
59750
|
);
|
|
59206
59751
|
}
|
|
59207
59752
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
59208
|
-
const hashDir =
|
|
59753
|
+
const hashDir = import_node_path43.default.join(attachmentsRoot, attachmentId);
|
|
59209
59754
|
let finalFileName;
|
|
59210
59755
|
let hashDirExists = false;
|
|
59211
59756
|
try {
|
|
@@ -59223,7 +59768,7 @@ async function writeUploadedAttachment(args) {
|
|
|
59223
59768
|
try {
|
|
59224
59769
|
import_node_fs35.default.mkdirSync(hashDir, { recursive: true });
|
|
59225
59770
|
finalFileName = args.fileName;
|
|
59226
|
-
import_node_fs35.default.renameSync(tmpPath,
|
|
59771
|
+
import_node_fs35.default.renameSync(tmpPath, import_node_path43.default.join(hashDir, finalFileName));
|
|
59227
59772
|
} catch (err) {
|
|
59228
59773
|
try {
|
|
59229
59774
|
import_node_fs35.default.unlinkSync(tmpPath);
|
|
@@ -59232,7 +59777,7 @@ async function writeUploadedAttachment(args) {
|
|
|
59232
59777
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
59233
59778
|
}
|
|
59234
59779
|
}
|
|
59235
|
-
const absPath =
|
|
59780
|
+
const absPath = import_node_path43.default.join(hashDir, finalFileName);
|
|
59236
59781
|
const relPath = absPath;
|
|
59237
59782
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
59238
59783
|
relPath: absPath,
|
|
@@ -59246,9 +59791,9 @@ async function writeUploadedAttachment(args) {
|
|
|
59246
59791
|
}
|
|
59247
59792
|
|
|
59248
59793
|
// src/extension/import.ts
|
|
59249
|
-
var
|
|
59250
|
-
var
|
|
59251
|
-
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);
|
|
59252
59797
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
59253
59798
|
var ImportError = class extends Error {
|
|
59254
59799
|
constructor(code, message) {
|
|
@@ -59265,7 +59810,7 @@ async function importZip(buf, root) {
|
|
|
59265
59810
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
59266
59811
|
}
|
|
59267
59812
|
for (const name of Object.keys(zip.files)) {
|
|
59268
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
59813
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path44.default.isAbsolute(name)) {
|
|
59269
59814
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
59270
59815
|
}
|
|
59271
59816
|
}
|
|
@@ -59298,33 +59843,33 @@ async function importZip(buf, root) {
|
|
|
59298
59843
|
);
|
|
59299
59844
|
}
|
|
59300
59845
|
}
|
|
59301
|
-
const destDir =
|
|
59846
|
+
const destDir = import_node_path44.default.join(root, manifest.id);
|
|
59302
59847
|
let destExists = false;
|
|
59303
59848
|
try {
|
|
59304
|
-
await
|
|
59849
|
+
await import_promises10.default.access(destDir);
|
|
59305
59850
|
destExists = true;
|
|
59306
59851
|
} catch {
|
|
59307
59852
|
}
|
|
59308
59853
|
if (destExists) {
|
|
59309
59854
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
59310
59855
|
}
|
|
59311
|
-
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}-`));
|
|
59312
59857
|
try {
|
|
59313
59858
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
59314
|
-
const dest =
|
|
59859
|
+
const dest = import_node_path44.default.join(stage, name);
|
|
59315
59860
|
if (entry.dir) {
|
|
59316
|
-
await
|
|
59861
|
+
await import_promises10.default.mkdir(dest, { recursive: true });
|
|
59317
59862
|
continue;
|
|
59318
59863
|
}
|
|
59319
|
-
await
|
|
59864
|
+
await import_promises10.default.mkdir(import_node_path44.default.dirname(dest), { recursive: true });
|
|
59320
59865
|
const content = await entry.async("nodebuffer");
|
|
59321
|
-
await
|
|
59866
|
+
await import_promises10.default.writeFile(dest, content);
|
|
59322
59867
|
}
|
|
59323
|
-
await
|
|
59324
|
-
await
|
|
59868
|
+
await import_promises10.default.mkdir(root, { recursive: true });
|
|
59869
|
+
await import_promises10.default.rename(stage, destDir);
|
|
59325
59870
|
return { extId: manifest.id };
|
|
59326
59871
|
} catch (e) {
|
|
59327
|
-
await
|
|
59872
|
+
await import_promises10.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
59328
59873
|
});
|
|
59329
59874
|
throw e;
|
|
59330
59875
|
}
|
|
@@ -59346,7 +59891,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
59346
59891
|
".wasm": "application/wasm"
|
|
59347
59892
|
};
|
|
59348
59893
|
function shareUiAssetMime(filePath) {
|
|
59349
|
-
const ext =
|
|
59894
|
+
const ext = import_node_path45.default.extname(filePath).toLowerCase();
|
|
59350
59895
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
59351
59896
|
}
|
|
59352
59897
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -59445,7 +59990,7 @@ function isValidUploadFileName(fileName) {
|
|
|
59445
59990
|
if (fileName === "." || fileName === "..") return false;
|
|
59446
59991
|
if (fileName.startsWith(".")) return false;
|
|
59447
59992
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
59448
|
-
return fileName ===
|
|
59993
|
+
return fileName === import_node_path45.default.basename(fileName);
|
|
59449
59994
|
}
|
|
59450
59995
|
function createHttpRouter(deps) {
|
|
59451
59996
|
return async (req, res) => {
|
|
@@ -59681,7 +60226,7 @@ function createHttpRouter(deps) {
|
|
|
59681
60226
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
59682
60227
|
return true;
|
|
59683
60228
|
}
|
|
59684
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
60229
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path45.default.basename(r.absPath)));
|
|
59685
60230
|
return true;
|
|
59686
60231
|
}
|
|
59687
60232
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -59802,7 +60347,7 @@ function createHttpRouter(deps) {
|
|
|
59802
60347
|
return true;
|
|
59803
60348
|
}
|
|
59804
60349
|
let absPath;
|
|
59805
|
-
if (
|
|
60350
|
+
if (import_node_path45.default.isAbsolute(pathParam)) {
|
|
59806
60351
|
absPath = pathParam;
|
|
59807
60352
|
} else if (deps.sessionStore) {
|
|
59808
60353
|
const file = deps.sessionStore.read(sid);
|
|
@@ -59810,7 +60355,7 @@ function createHttpRouter(deps) {
|
|
|
59810
60355
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
59811
60356
|
return true;
|
|
59812
60357
|
}
|
|
59813
|
-
absPath =
|
|
60358
|
+
absPath = import_node_path45.default.join(file.cwd, pathParam);
|
|
59814
60359
|
} else {
|
|
59815
60360
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
59816
60361
|
return true;
|
|
@@ -59912,7 +60457,7 @@ function streamFile(res, absPath, logger) {
|
|
|
59912
60457
|
return;
|
|
59913
60458
|
}
|
|
59914
60459
|
const mime = lookupMime(absPath);
|
|
59915
|
-
const basename2 =
|
|
60460
|
+
const basename2 = import_node_path45.default.basename(absPath);
|
|
59916
60461
|
res.writeHead(200, {
|
|
59917
60462
|
"Content-Type": mime,
|
|
59918
60463
|
"Content-Length": String(stat.size),
|
|
@@ -59930,7 +60475,7 @@ function streamFile(res, absPath, logger) {
|
|
|
59930
60475
|
|
|
59931
60476
|
// src/attachment/gc.ts
|
|
59932
60477
|
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
59933
|
-
var
|
|
60478
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
59934
60479
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
59935
60480
|
function runAttachmentGc(args) {
|
|
59936
60481
|
const now = (args.now ?? Date.now)();
|
|
@@ -59939,12 +60484,12 @@ function runAttachmentGc(args) {
|
|
|
59939
60484
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
59940
60485
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
59941
60486
|
if (entry.stale) continue;
|
|
59942
|
-
if (
|
|
60487
|
+
if (import_node_path46.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
59943
60488
|
}
|
|
59944
60489
|
}
|
|
59945
60490
|
const visited = /* @__PURE__ */ new Set();
|
|
59946
60491
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
59947
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
60492
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path46.default.join(
|
|
59948
60493
|
args.dataDir,
|
|
59949
60494
|
"sessions",
|
|
59950
60495
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -59957,7 +60502,7 @@ function runAttachmentGc(args) {
|
|
|
59957
60502
|
return true;
|
|
59958
60503
|
});
|
|
59959
60504
|
for (const rootDir of roots) {
|
|
59960
|
-
const attRoot =
|
|
60505
|
+
const attRoot = import_node_path46.default.join(rootDir, ".attachments");
|
|
59961
60506
|
let hashDirs;
|
|
59962
60507
|
try {
|
|
59963
60508
|
hashDirs = import_node_fs37.default.readdirSync(attRoot);
|
|
@@ -59967,7 +60512,7 @@ function runAttachmentGc(args) {
|
|
|
59967
60512
|
continue;
|
|
59968
60513
|
}
|
|
59969
60514
|
for (const hashDir of hashDirs) {
|
|
59970
|
-
const hashDirAbs =
|
|
60515
|
+
const hashDirAbs = import_node_path46.default.join(attRoot, hashDir);
|
|
59971
60516
|
let files;
|
|
59972
60517
|
try {
|
|
59973
60518
|
files = import_node_fs37.default.readdirSync(hashDirAbs);
|
|
@@ -59975,7 +60520,7 @@ function runAttachmentGc(args) {
|
|
|
59975
60520
|
continue;
|
|
59976
60521
|
}
|
|
59977
60522
|
for (const name of files) {
|
|
59978
|
-
const file =
|
|
60523
|
+
const file = import_node_path46.default.join(hashDirAbs, name);
|
|
59979
60524
|
let stat;
|
|
59980
60525
|
try {
|
|
59981
60526
|
stat = import_node_fs37.default.statSync(file);
|
|
@@ -60007,7 +60552,7 @@ function runAttachmentGc(args) {
|
|
|
60007
60552
|
|
|
60008
60553
|
// src/attachment/group.ts
|
|
60009
60554
|
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
60010
|
-
var
|
|
60555
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
60011
60556
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
60012
60557
|
init_protocol();
|
|
60013
60558
|
var GroupFileStore = class {
|
|
@@ -60019,11 +60564,11 @@ var GroupFileStore = class {
|
|
|
60019
60564
|
this.logger = opts.logger;
|
|
60020
60565
|
}
|
|
60021
60566
|
rootForScope(scope) {
|
|
60022
|
-
return
|
|
60567
|
+
return import_node_path47.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
60023
60568
|
}
|
|
60024
60569
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
60025
60570
|
filePath(scope, sessionId) {
|
|
60026
|
-
return
|
|
60571
|
+
return import_node_path47.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
60027
60572
|
}
|
|
60028
60573
|
cacheKey(scope, sessionId) {
|
|
60029
60574
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -60058,7 +60603,7 @@ var GroupFileStore = class {
|
|
|
60058
60603
|
}
|
|
60059
60604
|
writeFile(scope, sessionId, entries) {
|
|
60060
60605
|
const file = this.filePath(scope, sessionId);
|
|
60061
|
-
import_node_fs38.default.mkdirSync(
|
|
60606
|
+
import_node_fs38.default.mkdirSync(import_node_path47.default.dirname(file), { recursive: true });
|
|
60062
60607
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
60063
60608
|
import_node_fs38.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
60064
60609
|
import_node_fs38.default.renameSync(tmp, file);
|
|
@@ -60148,9 +60693,9 @@ var GroupFileStore = class {
|
|
|
60148
60693
|
|
|
60149
60694
|
// src/discovery/state-file.ts
|
|
60150
60695
|
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
60151
|
-
var
|
|
60696
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
60152
60697
|
function defaultStateFilePath(dataDir) {
|
|
60153
|
-
return
|
|
60698
|
+
return import_node_path48.default.join(dataDir, "state.json");
|
|
60154
60699
|
}
|
|
60155
60700
|
function isPidAlive(pid) {
|
|
60156
60701
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -60186,7 +60731,7 @@ var StateFileManager = class {
|
|
|
60186
60731
|
return { status: "stale", existing };
|
|
60187
60732
|
}
|
|
60188
60733
|
write(state) {
|
|
60189
|
-
import_node_fs39.default.mkdirSync(
|
|
60734
|
+
import_node_fs39.default.mkdirSync(import_node_path48.default.dirname(this.file), { recursive: true });
|
|
60190
60735
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
60191
60736
|
import_node_fs39.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
60192
60737
|
import_node_fs39.default.renameSync(tmp, this.file);
|
|
@@ -60214,13 +60759,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
60214
60759
|
|
|
60215
60760
|
// src/tunnel/tunnel-manager.ts
|
|
60216
60761
|
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
60217
|
-
var
|
|
60762
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
60218
60763
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
60219
|
-
var
|
|
60764
|
+
var import_node_child_process12 = require("child_process");
|
|
60220
60765
|
|
|
60221
60766
|
// src/tunnel/tunnel-store.ts
|
|
60222
60767
|
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
60223
|
-
var
|
|
60768
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
60224
60769
|
var TunnelStore = class {
|
|
60225
60770
|
constructor(filePath) {
|
|
60226
60771
|
this.filePath = filePath;
|
|
@@ -60239,7 +60784,7 @@ var TunnelStore = class {
|
|
|
60239
60784
|
}
|
|
60240
60785
|
}
|
|
60241
60786
|
async set(v2) {
|
|
60242
|
-
const dir =
|
|
60787
|
+
const dir = import_node_path49.default.dirname(this.filePath);
|
|
60243
60788
|
await import_node_fs40.default.promises.mkdir(dir, { recursive: true });
|
|
60244
60789
|
const data = JSON.stringify(v2, null, 2);
|
|
60245
60790
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
@@ -60350,11 +60895,11 @@ function escape(v2) {
|
|
|
60350
60895
|
|
|
60351
60896
|
// src/tunnel/frpc-binary.ts
|
|
60352
60897
|
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
60353
|
-
var
|
|
60354
|
-
var
|
|
60355
|
-
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");
|
|
60356
60901
|
var import_node_stream3 = require("stream");
|
|
60357
|
-
var
|
|
60902
|
+
var import_promises11 = require("stream/promises");
|
|
60358
60903
|
var FRPC_VERSION = "0.68.0";
|
|
60359
60904
|
var UnsupportedPlatformError = class extends Error {
|
|
60360
60905
|
constructor(platform, arch) {
|
|
@@ -60390,13 +60935,13 @@ async function ensureFrpcBinary(opts) {
|
|
|
60390
60935
|
}
|
|
60391
60936
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
60392
60937
|
const platform = opts.platform ?? detectPlatform();
|
|
60393
|
-
const binDir =
|
|
60938
|
+
const binDir = import_node_path50.default.join(opts.dataDir, "bin");
|
|
60394
60939
|
import_node_fs41.default.mkdirSync(binDir, { recursive: true });
|
|
60395
60940
|
cleanupStaleArtifacts(binDir);
|
|
60396
|
-
const stableBin =
|
|
60941
|
+
const stableBin = import_node_path50.default.join(binDir, "frpc");
|
|
60397
60942
|
if (import_node_fs41.default.existsSync(stableBin)) return stableBin;
|
|
60398
60943
|
const partialBin = `${stableBin}.partial`;
|
|
60399
|
-
const tarballPath =
|
|
60944
|
+
const tarballPath = import_node_path50.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
60400
60945
|
try {
|
|
60401
60946
|
const url = frpcDownloadUrl(version2, platform);
|
|
60402
60947
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -60422,7 +60967,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
60422
60967
|
}
|
|
60423
60968
|
for (const name of entries) {
|
|
60424
60969
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
60425
|
-
const full =
|
|
60970
|
+
const full = import_node_path50.default.join(binDir, name);
|
|
60426
60971
|
try {
|
|
60427
60972
|
import_node_fs41.default.rmSync(full, { recursive: true, force: true });
|
|
60428
60973
|
} catch {
|
|
@@ -60445,19 +60990,19 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
60445
60990
|
}
|
|
60446
60991
|
const out = import_node_fs41.default.createWriteStream(dest);
|
|
60447
60992
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
60448
|
-
await (0,
|
|
60993
|
+
await (0, import_promises11.pipeline)(nodeStream, out);
|
|
60449
60994
|
}
|
|
60450
60995
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
60451
|
-
const work =
|
|
60996
|
+
const work = import_node_path50.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
60452
60997
|
import_node_fs41.default.mkdirSync(work, { recursive: true });
|
|
60453
60998
|
try {
|
|
60454
60999
|
await new Promise((resolve9, reject) => {
|
|
60455
|
-
const proc = (0,
|
|
61000
|
+
const proc = (0, import_node_child_process10.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
60456
61001
|
proc.on("error", reject);
|
|
60457
61002
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
60458
61003
|
});
|
|
60459
61004
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
60460
|
-
const src =
|
|
61005
|
+
const src = import_node_path50.default.join(work, dirName, "frpc");
|
|
60461
61006
|
if (!import_node_fs41.default.existsSync(src)) {
|
|
60462
61007
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
60463
61008
|
}
|
|
@@ -60469,10 +61014,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
60469
61014
|
|
|
60470
61015
|
// src/tunnel/frpc-process.ts
|
|
60471
61016
|
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
60472
|
-
var
|
|
60473
|
-
var
|
|
61017
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
61018
|
+
var import_node_child_process11 = require("child_process");
|
|
60474
61019
|
function frpcPidFilePath(dataDir) {
|
|
60475
|
-
return
|
|
61020
|
+
return import_node_path51.default.join(dataDir, "frpc.pid");
|
|
60476
61021
|
}
|
|
60477
61022
|
function writeFrpcPid(dataDir, pid) {
|
|
60478
61023
|
try {
|
|
@@ -60514,7 +61059,7 @@ function defaultSleep2(ms) {
|
|
|
60514
61059
|
}
|
|
60515
61060
|
async function killStaleFrpc(deps) {
|
|
60516
61061
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
60517
|
-
const tomlPath =
|
|
61062
|
+
const tomlPath = import_node_path51.default.join(deps.dataDir, "frpc.toml");
|
|
60518
61063
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
60519
61064
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
60520
61065
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -60556,7 +61101,7 @@ async function killStaleFrpc(deps) {
|
|
|
60556
61101
|
async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
|
|
60557
61102
|
if (process.platform === "win32") return [];
|
|
60558
61103
|
return new Promise((resolve9) => {
|
|
60559
|
-
const ps = (0,
|
|
61104
|
+
const ps = (0, import_node_child_process11.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
|
|
60560
61105
|
let buf = "";
|
|
60561
61106
|
ps.stdout.on("data", (c) => {
|
|
60562
61107
|
buf += c.toString();
|
|
@@ -60586,7 +61131,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
60586
61131
|
var TunnelManager = class {
|
|
60587
61132
|
constructor(deps) {
|
|
60588
61133
|
this.deps = deps;
|
|
60589
|
-
this.store = deps.store ?? new TunnelStore(
|
|
61134
|
+
this.store = deps.store ?? new TunnelStore(import_node_path52.default.join(deps.dataDir, "tunnel.json"));
|
|
60590
61135
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
60591
61136
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
60592
61137
|
}
|
|
@@ -60713,7 +61258,7 @@ var TunnelManager = class {
|
|
|
60713
61258
|
dataDir: this.deps.dataDir,
|
|
60714
61259
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
60715
61260
|
});
|
|
60716
|
-
const tomlPath =
|
|
61261
|
+
const tomlPath = import_node_path52.default.join(this.deps.dataDir, "frpc.toml");
|
|
60717
61262
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto12.default.randomBytes(3).toString("hex")}`;
|
|
60718
61263
|
const toml = buildFrpcToml({
|
|
60719
61264
|
serverAddr: t.frpsHost,
|
|
@@ -60725,12 +61270,12 @@ var TunnelManager = class {
|
|
|
60725
61270
|
logLevel: "info"
|
|
60726
61271
|
});
|
|
60727
61272
|
await import_node_fs43.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
60728
|
-
const proc = (this.deps.spawnImpl ??
|
|
61273
|
+
const proc = (this.deps.spawnImpl ?? import_node_child_process12.spawn)(frpcBin, ["-c", tomlPath], {
|
|
60729
61274
|
stdio: ["ignore", "pipe", "pipe"]
|
|
60730
61275
|
});
|
|
60731
|
-
const logDir =
|
|
61276
|
+
const logDir = import_node_path52.default.join(this.deps.dataDir, "log");
|
|
60732
61277
|
import_node_fs43.default.mkdirSync(logDir, { recursive: true });
|
|
60733
|
-
const logFilePath =
|
|
61278
|
+
const logFilePath = import_node_path52.default.join(logDir, "frpc.log");
|
|
60734
61279
|
const logStream = import_node_fs43.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
60735
61280
|
logStream.on("error", () => {
|
|
60736
61281
|
});
|
|
@@ -60813,16 +61358,16 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
60813
61358
|
}
|
|
60814
61359
|
|
|
60815
61360
|
// src/tunnel/device-key.ts
|
|
60816
|
-
var
|
|
60817
|
-
var
|
|
61361
|
+
var import_node_os16 = __toESM(require("os"), 1);
|
|
61362
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
60818
61363
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
60819
61364
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
60820
61365
|
function deriveStableDeviceKey(opts = {}) {
|
|
60821
|
-
const hostname = opts.hostname ??
|
|
60822
|
-
const uid = opts.uid ?? (typeof
|
|
60823
|
-
const home = opts.home ??
|
|
60824
|
-
const defaultDataDir =
|
|
60825
|
-
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;
|
|
60826
61371
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
60827
61372
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
60828
61373
|
return import_node_crypto13.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
@@ -60830,11 +61375,11 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
60830
61375
|
|
|
60831
61376
|
// src/auth-store.ts
|
|
60832
61377
|
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
60833
|
-
var
|
|
61378
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
60834
61379
|
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
60835
61380
|
var AUTH_FILE_NAME = "auth.json";
|
|
60836
61381
|
function authFilePath(dataDir) {
|
|
60837
|
-
return
|
|
61382
|
+
return import_node_path54.default.join(dataDir, AUTH_FILE_NAME);
|
|
60838
61383
|
}
|
|
60839
61384
|
function loadOrCreateAuthFile(opts) {
|
|
60840
61385
|
const file = authFilePath(opts.dataDir);
|
|
@@ -60886,7 +61431,7 @@ function readAuthFile(file) {
|
|
|
60886
61431
|
}
|
|
60887
61432
|
}
|
|
60888
61433
|
function writeAuthFile(file, content) {
|
|
60889
|
-
import_node_fs44.default.mkdirSync(
|
|
61434
|
+
import_node_fs44.default.mkdirSync(import_node_path54.default.dirname(file), { recursive: true });
|
|
60890
61435
|
import_node_fs44.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
60891
61436
|
try {
|
|
60892
61437
|
import_node_fs44.default.chmodSync(file, 384);
|
|
@@ -60896,11 +61441,11 @@ function writeAuthFile(file, content) {
|
|
|
60896
61441
|
|
|
60897
61442
|
// src/owner-profile.ts
|
|
60898
61443
|
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
60899
|
-
var
|
|
60900
|
-
var
|
|
61444
|
+
var import_node_os17 = __toESM(require("os"), 1);
|
|
61445
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
60901
61446
|
var PROFILE_FILENAME = "profile.json";
|
|
60902
61447
|
function profilePath(dataDir) {
|
|
60903
|
-
return
|
|
61448
|
+
return import_node_path55.default.join(dataDir, PROFILE_FILENAME);
|
|
60904
61449
|
}
|
|
60905
61450
|
function loadOwnerProfile(dataDir) {
|
|
60906
61451
|
let raw;
|
|
@@ -60925,7 +61470,7 @@ function patchOwnerProfile(dataDir, patch) {
|
|
|
60925
61470
|
return merged;
|
|
60926
61471
|
}
|
|
60927
61472
|
function loadOwnerDisplayName(dataDir) {
|
|
60928
|
-
const fallback =
|
|
61473
|
+
const fallback = import_node_os17.default.userInfo().username;
|
|
60929
61474
|
const displayName = loadOwnerProfile(dataDir).displayName;
|
|
60930
61475
|
if (typeof displayName !== "string" || displayName.length === 0) {
|
|
60931
61476
|
if (displayName !== void 0) {
|
|
@@ -60938,12 +61483,12 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
60938
61483
|
|
|
60939
61484
|
// src/feishu-auth/owner-identity-store.ts
|
|
60940
61485
|
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
60941
|
-
var
|
|
61486
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
60942
61487
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
60943
61488
|
var OwnerIdentityStore = class {
|
|
60944
61489
|
file;
|
|
60945
61490
|
constructor(dataDir) {
|
|
60946
|
-
this.file =
|
|
61491
|
+
this.file = import_node_path56.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
60947
61492
|
}
|
|
60948
61493
|
read() {
|
|
60949
61494
|
let raw;
|
|
@@ -60976,7 +61521,7 @@ var OwnerIdentityStore = class {
|
|
|
60976
61521
|
};
|
|
60977
61522
|
}
|
|
60978
61523
|
write(record3) {
|
|
60979
|
-
import_node_fs46.default.mkdirSync(
|
|
61524
|
+
import_node_fs46.default.mkdirSync(import_node_path56.default.dirname(this.file), { recursive: true });
|
|
60980
61525
|
import_node_fs46.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
|
|
60981
61526
|
try {
|
|
60982
61527
|
import_node_fs46.default.chmodSync(this.file, 384);
|
|
@@ -61122,9 +61667,9 @@ var CentralClientError = class extends Error {
|
|
|
61122
61667
|
code;
|
|
61123
61668
|
cause;
|
|
61124
61669
|
};
|
|
61125
|
-
async function centralRequest(opts,
|
|
61670
|
+
async function centralRequest(opts, path98, init) {
|
|
61126
61671
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
61127
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
61672
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path98}`;
|
|
61128
61673
|
const ctrl = new AbortController();
|
|
61129
61674
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
61130
61675
|
let res;
|
|
@@ -61561,8 +62106,8 @@ function verifyConnectToken(args) {
|
|
|
61561
62106
|
}
|
|
61562
62107
|
|
|
61563
62108
|
// src/feishu-auth/server-key.ts
|
|
61564
|
-
var
|
|
61565
|
-
var
|
|
62109
|
+
var fs65 = __toESM(require("fs"), 1);
|
|
62110
|
+
var path69 = __toESM(require("path"), 1);
|
|
61566
62111
|
var FILE_NAME2 = "server-signing-key.json";
|
|
61567
62112
|
var ServerKeyStore = class {
|
|
61568
62113
|
constructor(dataDir) {
|
|
@@ -61570,12 +62115,12 @@ var ServerKeyStore = class {
|
|
|
61570
62115
|
}
|
|
61571
62116
|
dataDir;
|
|
61572
62117
|
filePath() {
|
|
61573
|
-
return
|
|
62118
|
+
return path69.join(this.dataDir, FILE_NAME2);
|
|
61574
62119
|
}
|
|
61575
62120
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
61576
62121
|
read() {
|
|
61577
62122
|
try {
|
|
61578
|
-
const raw =
|
|
62123
|
+
const raw = fs65.readFileSync(this.filePath(), "utf8");
|
|
61579
62124
|
const parsed = JSON.parse(raw);
|
|
61580
62125
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
61581
62126
|
return parsed.publicKeyPem;
|
|
@@ -61590,12 +62135,12 @@ var ServerKeyStore = class {
|
|
|
61590
62135
|
publicKeyPem,
|
|
61591
62136
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
61592
62137
|
};
|
|
61593
|
-
|
|
61594
|
-
|
|
62138
|
+
fs65.mkdirSync(this.dataDir, { recursive: true });
|
|
62139
|
+
fs65.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
61595
62140
|
}
|
|
61596
62141
|
clear() {
|
|
61597
62142
|
try {
|
|
61598
|
-
|
|
62143
|
+
fs65.unlinkSync(this.filePath());
|
|
61599
62144
|
} catch {
|
|
61600
62145
|
}
|
|
61601
62146
|
}
|
|
@@ -61605,15 +62150,15 @@ var ServerKeyStore = class {
|
|
|
61605
62150
|
init_protocol();
|
|
61606
62151
|
|
|
61607
62152
|
// src/handlers/index.ts
|
|
61608
|
-
var
|
|
62153
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
61609
62154
|
|
|
61610
62155
|
// src/handlers/session.ts
|
|
61611
62156
|
init_protocol();
|
|
61612
62157
|
|
|
61613
62158
|
// src/session/fork.ts
|
|
61614
62159
|
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
61615
|
-
var
|
|
61616
|
-
var
|
|
62160
|
+
var import_node_os18 = __toESM(require("os"), 1);
|
|
62161
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
61617
62162
|
var import_node_crypto16 = require("crypto");
|
|
61618
62163
|
init_claude_history();
|
|
61619
62164
|
function readJsonlEntries(file) {
|
|
@@ -61630,19 +62175,19 @@ function readJsonlEntries(file) {
|
|
|
61630
62175
|
return out;
|
|
61631
62176
|
}
|
|
61632
62177
|
function forkSession(input) {
|
|
61633
|
-
const baseDir = input.baseDir ??
|
|
61634
|
-
let projectDir =
|
|
61635
|
-
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`);
|
|
61636
62181
|
if (!import_node_fs47.default.existsSync(sourceFile)) {
|
|
61637
62182
|
const found = findTranscriptByToolSessionId(
|
|
61638
|
-
|
|
62183
|
+
import_node_path57.default.join(baseDir, "projects"),
|
|
61639
62184
|
input.toolSessionId
|
|
61640
62185
|
);
|
|
61641
62186
|
if (!found) {
|
|
61642
62187
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
61643
62188
|
}
|
|
61644
62189
|
sourceFile = found;
|
|
61645
|
-
projectDir =
|
|
62190
|
+
projectDir = import_node_path57.default.dirname(found);
|
|
61646
62191
|
}
|
|
61647
62192
|
const entries = readJsonlEntries(sourceFile);
|
|
61648
62193
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -61671,8 +62216,8 @@ function forkSession(input) {
|
|
|
61671
62216
|
}
|
|
61672
62217
|
forkedLines.push(JSON.stringify(forked));
|
|
61673
62218
|
}
|
|
61674
|
-
const outDir = input.targetCwd ?
|
|
61675
|
-
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`);
|
|
61676
62221
|
import_node_fs47.default.mkdirSync(outDir, { recursive: true });
|
|
61677
62222
|
import_node_fs47.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
61678
62223
|
return { forkedToolSessionId, forkedFilePath };
|
|
@@ -61680,18 +62225,18 @@ function forkSession(input) {
|
|
|
61680
62225
|
|
|
61681
62226
|
// src/session/external-scan.ts
|
|
61682
62227
|
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
61683
|
-
var
|
|
61684
|
-
var
|
|
61685
|
-
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);
|
|
61686
62231
|
var import_node_module = require("module");
|
|
61687
|
-
var
|
|
62232
|
+
var import_node_child_process13 = require("child_process");
|
|
61688
62233
|
var import_meta5 = {};
|
|
61689
62234
|
function defaultRoots() {
|
|
61690
|
-
const home =
|
|
62235
|
+
const home = import_node_os19.default.homedir();
|
|
61691
62236
|
return {
|
|
61692
|
-
claudeProjectsDir:
|
|
61693
|
-
codexDir:
|
|
61694
|
-
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")
|
|
61695
62240
|
};
|
|
61696
62241
|
}
|
|
61697
62242
|
function width(s) {
|
|
@@ -61719,7 +62264,7 @@ function toMs(v2) {
|
|
|
61719
62264
|
async function* jsonLines(file) {
|
|
61720
62265
|
let raw;
|
|
61721
62266
|
try {
|
|
61722
|
-
raw = await
|
|
62267
|
+
raw = await import_promises12.default.readFile(file, "utf8");
|
|
61723
62268
|
} catch {
|
|
61724
62269
|
return;
|
|
61725
62270
|
}
|
|
@@ -61759,13 +62304,13 @@ async function scanClaude(roots) {
|
|
|
61759
62304
|
if (!d.isDirectory()) continue;
|
|
61760
62305
|
let files;
|
|
61761
62306
|
try {
|
|
61762
|
-
files = import_node_fs48.default.readdirSync(
|
|
62307
|
+
files = import_node_fs48.default.readdirSync(import_node_path58.default.join(roots.claudeProjectsDir, d.name));
|
|
61763
62308
|
} catch {
|
|
61764
62309
|
continue;
|
|
61765
62310
|
}
|
|
61766
62311
|
for (const name of files) {
|
|
61767
62312
|
if (!name.endsWith(".jsonl")) continue;
|
|
61768
|
-
const file =
|
|
62313
|
+
const file = import_node_path58.default.join(roots.claudeProjectsDir, d.name, name);
|
|
61769
62314
|
let st;
|
|
61770
62315
|
try {
|
|
61771
62316
|
st = import_node_fs48.default.statSync(file);
|
|
@@ -61852,14 +62397,14 @@ function readCodexThreads(db) {
|
|
|
61852
62397
|
} catch {
|
|
61853
62398
|
}
|
|
61854
62399
|
try {
|
|
61855
|
-
const info = (0,
|
|
62400
|
+
const info = (0, import_node_child_process13.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
|
|
61856
62401
|
if (info.status !== 0) return null;
|
|
61857
62402
|
const have = new Set(
|
|
61858
62403
|
info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
|
|
61859
62404
|
);
|
|
61860
62405
|
if (!["id", "cwd", "updated_at", "thread_source"].every((c) => have.has(c))) return null;
|
|
61861
62406
|
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
61862
|
-
const res = (0,
|
|
62407
|
+
const res = (0, import_node_child_process13.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
|
|
61863
62408
|
encoding: "utf8",
|
|
61864
62409
|
maxBuffer: 64 * 1024 * 1024
|
|
61865
62410
|
});
|
|
@@ -61895,7 +62440,7 @@ async function codexFromRows(rows) {
|
|
|
61895
62440
|
async function scanCodex(roots) {
|
|
61896
62441
|
let dbs = [];
|
|
61897
62442
|
try {
|
|
61898
|
-
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));
|
|
61899
62444
|
} catch {
|
|
61900
62445
|
}
|
|
61901
62446
|
if (!dbs.length) return [];
|
|
@@ -61904,14 +62449,14 @@ async function scanCodex(roots) {
|
|
|
61904
62449
|
}
|
|
61905
62450
|
async function scanExternalSessions(rootsIn) {
|
|
61906
62451
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
61907
|
-
const personaRoot =
|
|
62452
|
+
const personaRoot = import_node_path58.default.join(roots.clawdDir, "personas");
|
|
61908
62453
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
61909
62454
|
const out = [];
|
|
61910
62455
|
for (const c of all) {
|
|
61911
62456
|
if (c.skip) continue;
|
|
61912
62457
|
if (c.turns < 1) continue;
|
|
61913
62458
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
61914
|
-
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)) {
|
|
61915
62460
|
continue;
|
|
61916
62461
|
}
|
|
61917
62462
|
out.push({
|
|
@@ -61929,12 +62474,12 @@ async function scanExternalSessions(rootsIn) {
|
|
|
61929
62474
|
|
|
61930
62475
|
// src/session/import-ledger.ts
|
|
61931
62476
|
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
61932
|
-
var
|
|
62477
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
61933
62478
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
61934
62479
|
function readImportLedger(dataDir) {
|
|
61935
62480
|
try {
|
|
61936
62481
|
const parsed = JSON.parse(
|
|
61937
|
-
import_node_fs49.default.readFileSync(
|
|
62482
|
+
import_node_fs49.default.readFileSync(import_node_path59.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
61938
62483
|
);
|
|
61939
62484
|
return Array.isArray(parsed) ? parsed : [];
|
|
61940
62485
|
} catch {
|
|
@@ -61942,7 +62487,7 @@ function readImportLedger(dataDir) {
|
|
|
61942
62487
|
}
|
|
61943
62488
|
}
|
|
61944
62489
|
function appendImportLedger(dataDir, entry) {
|
|
61945
|
-
const file =
|
|
62490
|
+
const file = import_node_path59.default.join(dataDir, LEDGER_FILENAME);
|
|
61946
62491
|
const entries = readImportLedger(dataDir);
|
|
61947
62492
|
entries.push(entry);
|
|
61948
62493
|
import_node_fs49.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
@@ -61950,7 +62495,7 @@ function appendImportLedger(dataDir, entry) {
|
|
|
61950
62495
|
|
|
61951
62496
|
// src/tools/transcript-search.ts
|
|
61952
62497
|
var import_node_fs50 = __toESM(require("fs"), 1);
|
|
61953
|
-
var
|
|
62498
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
61954
62499
|
var SNIPPET_PAD = 60;
|
|
61955
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/;
|
|
61956
62501
|
var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
|
|
@@ -62043,7 +62588,7 @@ function createCodexRolloutLocator(roots) {
|
|
|
62043
62588
|
return;
|
|
62044
62589
|
}
|
|
62045
62590
|
for (const entry of entries) {
|
|
62046
|
-
const full =
|
|
62591
|
+
const full = import_node_path60.default.join(dir, entry.name);
|
|
62047
62592
|
if (entry.isDirectory()) {
|
|
62048
62593
|
walk2(full, into);
|
|
62049
62594
|
continue;
|
|
@@ -62063,16 +62608,16 @@ function createCodexRolloutLocator(roots) {
|
|
|
62063
62608
|
|
|
62064
62609
|
// src/handlers/session.ts
|
|
62065
62610
|
init_protocol();
|
|
62066
|
-
var
|
|
62067
|
-
var
|
|
62611
|
+
var import_node_os20 = __toESM(require("os"), 1);
|
|
62612
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
62068
62613
|
function canReadSearchHit(ctx, file) {
|
|
62069
62614
|
if (!ctx || ctx.principal.kind === "owner") return true;
|
|
62070
62615
|
return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
|
|
62071
62616
|
}
|
|
62072
62617
|
var DEFAULT_SEARCH_LIMIT = 9;
|
|
62073
62618
|
function codexRolloutRoots(dataDir) {
|
|
62074
|
-
const roots = [
|
|
62075
|
-
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"));
|
|
62076
62621
|
return roots;
|
|
62077
62622
|
}
|
|
62078
62623
|
function buildSessionHandlers(deps) {
|
|
@@ -62614,7 +63159,7 @@ function buildPermissionHandlers(deps) {
|
|
|
62614
63159
|
}
|
|
62615
63160
|
|
|
62616
63161
|
// src/handlers/history.ts
|
|
62617
|
-
var
|
|
63162
|
+
var path76 = __toESM(require("path"), 1);
|
|
62618
63163
|
init_protocol();
|
|
62619
63164
|
|
|
62620
63165
|
// src/session/recent-dirs.ts
|
|
@@ -62632,7 +63177,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
62632
63177
|
}
|
|
62633
63178
|
|
|
62634
63179
|
// src/permission/persona-paths.ts
|
|
62635
|
-
var
|
|
63180
|
+
var path75 = __toESM(require("path"), 1);
|
|
62636
63181
|
function getAllowedPersonaIds(grants, action) {
|
|
62637
63182
|
const ids = /* @__PURE__ */ new Set();
|
|
62638
63183
|
for (const g2 of grants) {
|
|
@@ -62645,42 +63190,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
62645
63190
|
return ids;
|
|
62646
63191
|
}
|
|
62647
63192
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
62648
|
-
const target =
|
|
63193
|
+
const target = path75.resolve(absPath);
|
|
62649
63194
|
if (userWorkDir) {
|
|
62650
|
-
const u =
|
|
62651
|
-
const usep = u.endsWith(
|
|
63195
|
+
const u = path75.resolve(userWorkDir);
|
|
63196
|
+
const usep = u.endsWith(path75.sep) ? "" : path75.sep;
|
|
62652
63197
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
62653
63198
|
}
|
|
62654
|
-
const root =
|
|
62655
|
-
const sep4 = root.endsWith(
|
|
63199
|
+
const root = path75.resolve(personaRoot);
|
|
63200
|
+
const sep4 = root.endsWith(path75.sep) ? "" : path75.sep;
|
|
62656
63201
|
if (!target.startsWith(root + sep4)) return false;
|
|
62657
|
-
const rel =
|
|
63202
|
+
const rel = path75.relative(root, target);
|
|
62658
63203
|
if (!rel || rel.startsWith("..")) return false;
|
|
62659
|
-
const personaId2 = rel.split(
|
|
63204
|
+
const personaId2 = rel.split(path75.sep)[0];
|
|
62660
63205
|
if (!personaId2) return false;
|
|
62661
63206
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
62662
63207
|
if (allowed === "*") return true;
|
|
62663
63208
|
return allowed.has(personaId2);
|
|
62664
63209
|
}
|
|
62665
63210
|
function personaIdFromPath(absPath, personaRoot) {
|
|
62666
|
-
const root =
|
|
62667
|
-
const target =
|
|
62668
|
-
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;
|
|
62669
63214
|
if (!target.startsWith(root + sep4)) return null;
|
|
62670
|
-
const rel =
|
|
63215
|
+
const rel = path75.relative(root, target);
|
|
62671
63216
|
if (!rel || rel.startsWith("..")) return null;
|
|
62672
|
-
const id = rel.split(
|
|
63217
|
+
const id = rel.split(path75.sep)[0];
|
|
62673
63218
|
return id || null;
|
|
62674
63219
|
}
|
|
62675
63220
|
function isPathWithin(dir, absPath) {
|
|
62676
|
-
const d =
|
|
62677
|
-
const t =
|
|
62678
|
-
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;
|
|
62679
63224
|
return t === d || t.startsWith(d + sep4);
|
|
62680
63225
|
}
|
|
62681
63226
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
62682
63227
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
62683
|
-
return personaIdFromPath(
|
|
63228
|
+
return personaIdFromPath(path75.resolve(absPath), personaRoot) === personaId2;
|
|
62684
63229
|
}
|
|
62685
63230
|
|
|
62686
63231
|
// src/handlers/history.ts
|
|
@@ -62733,7 +63278,7 @@ function buildHistoryHandlers(deps) {
|
|
|
62733
63278
|
if (!pid) return false;
|
|
62734
63279
|
return isGuestPathAllowed(
|
|
62735
63280
|
ctx.grants,
|
|
62736
|
-
|
|
63281
|
+
path76.join(personaRoot, pid),
|
|
62737
63282
|
personaRoot,
|
|
62738
63283
|
"read",
|
|
62739
63284
|
userWorkDir
|
|
@@ -62745,7 +63290,7 @@ function buildHistoryHandlers(deps) {
|
|
|
62745
63290
|
};
|
|
62746
63291
|
const list = async (frame, _client, ctx) => {
|
|
62747
63292
|
const args = HistoryListArgs.parse(frame);
|
|
62748
|
-
assertGuestPath(ctx,
|
|
63293
|
+
assertGuestPath(ctx, path76.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
62749
63294
|
const sessions = await history.listSessions(args);
|
|
62750
63295
|
return { response: { type: "history:list", sessions } };
|
|
62751
63296
|
};
|
|
@@ -62793,14 +63338,14 @@ function buildHistoryHandlers(deps) {
|
|
|
62793
63338
|
};
|
|
62794
63339
|
const subagents = async (frame, _client, ctx) => {
|
|
62795
63340
|
const args = HistorySubagentsArgs.parse(frame);
|
|
62796
|
-
assertGuestPath(ctx,
|
|
63341
|
+
assertGuestPath(ctx, path76.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
62797
63342
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
62798
63343
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
62799
63344
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
62800
63345
|
};
|
|
62801
63346
|
const subagentRead = async (frame, _client, ctx) => {
|
|
62802
63347
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
62803
|
-
assertGuestPath(ctx,
|
|
63348
|
+
assertGuestPath(ctx, path76.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
62804
63349
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
62805
63350
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
62806
63351
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -62810,7 +63355,7 @@ function buildHistoryHandlers(deps) {
|
|
|
62810
63355
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
62811
63356
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
62812
63357
|
const filtered = dirs.filter(
|
|
62813
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
63358
|
+
(d) => isGuestPathAllowed(ctx.grants, path76.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
62814
63359
|
);
|
|
62815
63360
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
62816
63361
|
}
|
|
@@ -62827,17 +63372,17 @@ function buildHistoryHandlers(deps) {
|
|
|
62827
63372
|
}
|
|
62828
63373
|
|
|
62829
63374
|
// src/handlers/projects.ts
|
|
62830
|
-
var
|
|
62831
|
-
var
|
|
62832
|
-
var
|
|
62833
|
-
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");
|
|
62834
63379
|
init_protocol();
|
|
62835
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
63380
|
+
var DEFAULT_PROJECTS_ROOT = path77.join(os22.homedir(), "Documents", "ChatGPT");
|
|
62836
63381
|
function allocateDir(root, name) {
|
|
62837
|
-
let candidate =
|
|
63382
|
+
let candidate = path77.join(root, name);
|
|
62838
63383
|
let n = 2;
|
|
62839
|
-
while (
|
|
62840
|
-
candidate =
|
|
63384
|
+
while (fs70.existsSync(candidate)) {
|
|
63385
|
+
candidate = path77.join(root, `${name} ${n}`);
|
|
62841
63386
|
n += 1;
|
|
62842
63387
|
}
|
|
62843
63388
|
return candidate;
|
|
@@ -62865,11 +63410,11 @@ function buildProjectHandlers(deps) {
|
|
|
62865
63410
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
62866
63411
|
}
|
|
62867
63412
|
try {
|
|
62868
|
-
if (!
|
|
63413
|
+
if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
62869
63414
|
} catch {
|
|
62870
63415
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
62871
63416
|
}
|
|
62872
|
-
const r = (0,
|
|
63417
|
+
const r = (0, import_node_child_process14.spawnSync)("open", ["-R", args.path], { stdio: "ignore" });
|
|
62873
63418
|
if (r.status !== 0) {
|
|
62874
63419
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `open -R \u5931\u8D25: exit ${r.status}`);
|
|
62875
63420
|
}
|
|
@@ -62881,7 +63426,7 @@ function buildProjectHandlers(deps) {
|
|
|
62881
63426
|
let target;
|
|
62882
63427
|
if (args.path) {
|
|
62883
63428
|
try {
|
|
62884
|
-
if (!
|
|
63429
|
+
if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
62885
63430
|
} catch {
|
|
62886
63431
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
62887
63432
|
}
|
|
@@ -62889,15 +63434,15 @@ function buildProjectHandlers(deps) {
|
|
|
62889
63434
|
} else {
|
|
62890
63435
|
const name = args.name;
|
|
62891
63436
|
try {
|
|
62892
|
-
|
|
63437
|
+
fs70.mkdirSync(root, { recursive: true });
|
|
62893
63438
|
target = allocateDir(root, name);
|
|
62894
|
-
|
|
63439
|
+
fs70.mkdirSync(target);
|
|
62895
63440
|
} catch (err) {
|
|
62896
63441
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
62897
63442
|
}
|
|
62898
|
-
const git = (0,
|
|
63443
|
+
const git = (0, import_node_child_process14.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
62899
63444
|
if (git.status !== 0) {
|
|
62900
|
-
|
|
63445
|
+
fs70.rmSync(target, { recursive: true, force: true });
|
|
62901
63446
|
throw new ClawdError(
|
|
62902
63447
|
ERROR_CODES.INVALID_CWD,
|
|
62903
63448
|
`git init \u5931\u8D25\uFF08${git.error ? String(git.error) : `exit ${git.status}`}\uFF09: ${target}`
|
|
@@ -62922,8 +63467,8 @@ function buildProjectHandlers(deps) {
|
|
|
62922
63467
|
}
|
|
62923
63468
|
|
|
62924
63469
|
// src/handlers/workspace.ts
|
|
62925
|
-
var
|
|
62926
|
-
var
|
|
63470
|
+
var path78 = __toESM(require("path"), 1);
|
|
63471
|
+
var os23 = __toESM(require("os"), 1);
|
|
62927
63472
|
init_protocol();
|
|
62928
63473
|
init_protocol();
|
|
62929
63474
|
function buildEnabledPluginNames(personaManager, personaId2) {
|
|
@@ -62963,23 +63508,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
62963
63508
|
const list = async (frame, _client, ctx) => {
|
|
62964
63509
|
const args = WorkspaceListArgs.parse(frame);
|
|
62965
63510
|
const isGuest = ctx?.principal.kind === "guest";
|
|
62966
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
62967
|
-
const resolvedCwd =
|
|
62968
|
-
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;
|
|
62969
63514
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
62970
63515
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
62971
63516
|
return { response: { type: "workspace:list", ...res } };
|
|
62972
63517
|
};
|
|
62973
63518
|
const read = async (frame, _client, ctx) => {
|
|
62974
63519
|
const args = WorkspaceReadArgs.parse(frame);
|
|
62975
|
-
const target =
|
|
63520
|
+
const target = path78.isAbsolute(args.path) ? path78.resolve(args.path) : path78.resolve(args.cwd, args.path);
|
|
62976
63521
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
62977
63522
|
const res = workspace.read(args);
|
|
62978
63523
|
return { response: { type: "workspace:read", ...res } };
|
|
62979
63524
|
};
|
|
62980
63525
|
const skillsList = async (frame, _client, ctx) => {
|
|
62981
63526
|
const args = SkillsListArgs.parse(frame);
|
|
62982
|
-
const cwdAbs =
|
|
63527
|
+
const cwdAbs = path78.resolve(args.cwd);
|
|
62983
63528
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
62984
63529
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
62985
63530
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -62991,7 +63536,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
62991
63536
|
};
|
|
62992
63537
|
const agentsList = async (frame, _client, ctx) => {
|
|
62993
63538
|
const args = AgentsListArgs.parse(frame);
|
|
62994
|
-
const cwdAbs =
|
|
63539
|
+
const cwdAbs = path78.resolve(args.cwd);
|
|
62995
63540
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
62996
63541
|
if (args.tool === "codex") {
|
|
62997
63542
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -63013,18 +63558,18 @@ function buildWorkspaceHandlers(deps) {
|
|
|
63013
63558
|
}
|
|
63014
63559
|
|
|
63015
63560
|
// src/handlers/git.ts
|
|
63016
|
-
var
|
|
63561
|
+
var path80 = __toESM(require("path"), 1);
|
|
63017
63562
|
init_protocol();
|
|
63018
63563
|
init_protocol();
|
|
63019
63564
|
|
|
63020
63565
|
// src/workspace/git.ts
|
|
63021
|
-
var
|
|
63566
|
+
var import_node_child_process15 = require("child_process");
|
|
63022
63567
|
var import_node_fs51 = __toESM(require("fs"), 1);
|
|
63023
|
-
var
|
|
63568
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
63024
63569
|
var import_node_util = require("util");
|
|
63025
|
-
var pexec = (0, import_node_util.promisify)(
|
|
63570
|
+
var pexec = (0, import_node_util.promisify)(import_node_child_process15.execFile);
|
|
63026
63571
|
function normalizePath(p2) {
|
|
63027
|
-
const resolved =
|
|
63572
|
+
const resolved = import_node_path62.default.resolve(p2);
|
|
63028
63573
|
try {
|
|
63029
63574
|
return import_node_fs51.default.realpathSync(resolved);
|
|
63030
63575
|
} catch {
|
|
@@ -63100,7 +63645,7 @@ async function listGitBranches(cwd) {
|
|
|
63100
63645
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
63101
63646
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
63102
63647
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
63103
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
63648
|
+
if (!isGuestPathAllowed(ctx.grants, path80.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
63104
63649
|
throw new ClawdError(
|
|
63105
63650
|
ERROR_CODES.UNAUTHORIZED,
|
|
63106
63651
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -63645,7 +64190,7 @@ function buildFeishuAuthHandlers(deps) {
|
|
|
63645
64190
|
}
|
|
63646
64191
|
|
|
63647
64192
|
// src/handlers/meta.ts
|
|
63648
|
-
var
|
|
64193
|
+
var import_node_os21 = __toESM(require("os"), 1);
|
|
63649
64194
|
init_protocol();
|
|
63650
64195
|
|
|
63651
64196
|
// src/handlers/method-grants.ts
|
|
@@ -63700,6 +64245,8 @@ var METHOD_GRANT_MAP = {
|
|
|
63700
64245
|
"deploy:putSecret": ADMIN_ANY,
|
|
63701
64246
|
"deploy:reportFinding": ADMIN_ANY,
|
|
63702
64247
|
"deploy:finishScan": ADMIN_ANY,
|
|
64248
|
+
"deploy:trial": ADMIN_ANY,
|
|
64249
|
+
"deploy:deploy": ADMIN_ANY,
|
|
63703
64250
|
"deploy:remove": ADMIN_ANY,
|
|
63704
64251
|
// ---- session:* / chat:* 业务方法(v2 Phase 8 两层模型)----
|
|
63705
64252
|
// dispatcher 不验资源,handler 内按 ctx + frame.args 反查 ownerPersonaId 调 assertGrant。
|
|
@@ -63946,21 +64493,21 @@ function computeMethodAccess(args) {
|
|
|
63946
64493
|
}
|
|
63947
64494
|
|
|
63948
64495
|
// src/version.ts
|
|
63949
|
-
var version = "0.2.
|
|
64496
|
+
var version = "0.2.462".length > 0 ? "0.2.462" : "dev";
|
|
63950
64497
|
|
|
63951
64498
|
// src/cli-probe/probe.ts
|
|
63952
|
-
var
|
|
63953
|
-
var
|
|
64499
|
+
var fs72 = __toESM(require("fs"), 1);
|
|
64500
|
+
var path81 = __toESM(require("path"), 1);
|
|
63954
64501
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
63955
64502
|
var BIN_NAME = "clawd";
|
|
63956
64503
|
var MAX_PARENT_HOPS = 5;
|
|
63957
64504
|
function probeGlobalCli(pathEnv) {
|
|
63958
64505
|
if (!pathEnv) return null;
|
|
63959
|
-
for (const dir of pathEnv.split(
|
|
64506
|
+
for (const dir of pathEnv.split(path81.delimiter)) {
|
|
63960
64507
|
if (!dir) continue;
|
|
63961
64508
|
let real;
|
|
63962
64509
|
try {
|
|
63963
|
-
real =
|
|
64510
|
+
real = fs72.realpathSync(path81.join(dir, BIN_NAME));
|
|
63964
64511
|
} catch {
|
|
63965
64512
|
continue;
|
|
63966
64513
|
}
|
|
@@ -63970,15 +64517,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
63970
64517
|
return null;
|
|
63971
64518
|
}
|
|
63972
64519
|
function readOwnPackageVersion(entryPath) {
|
|
63973
|
-
let dir =
|
|
64520
|
+
let dir = path81.dirname(entryPath);
|
|
63974
64521
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
63975
64522
|
try {
|
|
63976
|
-
const raw =
|
|
64523
|
+
const raw = fs72.readFileSync(path81.join(dir, "package.json"), "utf8");
|
|
63977
64524
|
const pkg = JSON.parse(raw);
|
|
63978
64525
|
if (pkg.name !== PKG_NAME) return null;
|
|
63979
64526
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
63980
64527
|
} catch {
|
|
63981
|
-
const parent =
|
|
64528
|
+
const parent = path81.dirname(dir);
|
|
63982
64529
|
if (parent === dir) return null;
|
|
63983
64530
|
dir = parent;
|
|
63984
64531
|
}
|
|
@@ -64014,7 +64561,7 @@ function buildReadyFrame(deps, client) {
|
|
|
64014
64561
|
return {
|
|
64015
64562
|
version,
|
|
64016
64563
|
protocolVersion: PROTOCOL_VERSION,
|
|
64017
|
-
hostname:
|
|
64564
|
+
hostname: import_node_os21.default.hostname(),
|
|
64018
64565
|
os: process.platform,
|
|
64019
64566
|
tools,
|
|
64020
64567
|
runningSessions: info.runningSessions,
|
|
@@ -64150,7 +64697,7 @@ function buildPersonaHandlers(deps) {
|
|
|
64150
64697
|
}
|
|
64151
64698
|
|
|
64152
64699
|
// src/handlers/attachment.ts
|
|
64153
|
-
var
|
|
64700
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
64154
64701
|
init_protocol();
|
|
64155
64702
|
init_protocol();
|
|
64156
64703
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -64230,12 +64777,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
64230
64777
|
`session ${args.sessionId} scope unresolved`
|
|
64231
64778
|
);
|
|
64232
64779
|
}
|
|
64233
|
-
const cwdAbs =
|
|
64234
|
-
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);
|
|
64235
64782
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
64236
64783
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
64237
64784
|
const entry = entries.find((e) => {
|
|
64238
|
-
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);
|
|
64239
64786
|
return storedAbs === candidateAbs && !e.stale;
|
|
64240
64787
|
});
|
|
64241
64788
|
if (!entry) {
|
|
@@ -64260,7 +64807,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
64260
64807
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
64261
64808
|
const f = deps.sessionStore.read(sessionId);
|
|
64262
64809
|
if (!f) return;
|
|
64263
|
-
assertGuestAttachmentPath(ctx,
|
|
64810
|
+
assertGuestAttachmentPath(ctx, import_node_path63.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
64264
64811
|
}
|
|
64265
64812
|
const groupAdd = async (frame, _client, ctx) => {
|
|
64266
64813
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -64275,8 +64822,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
64275
64822
|
if (!scope) {
|
|
64276
64823
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
64277
64824
|
}
|
|
64278
|
-
const cwdAbs =
|
|
64279
|
-
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);
|
|
64280
64827
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
64281
64828
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
64282
64829
|
const size = 0;
|
|
@@ -64334,21 +64881,21 @@ function buildAttachmentHandlers(deps) {
|
|
|
64334
64881
|
}
|
|
64335
64882
|
|
|
64336
64883
|
// src/handlers/extension.ts
|
|
64337
|
-
var
|
|
64338
|
-
var
|
|
64884
|
+
var import_promises16 = __toESM(require("fs/promises"), 1);
|
|
64885
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
64339
64886
|
init_protocol();
|
|
64340
64887
|
|
|
64341
64888
|
// src/extension/bundle-zip.ts
|
|
64342
|
-
var
|
|
64343
|
-
var
|
|
64889
|
+
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
64890
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
64344
64891
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
64345
64892
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
64346
64893
|
async function bundleExtensionDir(dir) {
|
|
64347
64894
|
const entries = await listFilesSorted(dir);
|
|
64348
64895
|
const zip = new import_jszip2.default();
|
|
64349
64896
|
for (const rel of entries) {
|
|
64350
|
-
const abs =
|
|
64351
|
-
const content = await
|
|
64897
|
+
const abs = import_node_path64.default.join(dir, rel);
|
|
64898
|
+
const content = await import_promises13.default.readFile(abs);
|
|
64352
64899
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
64353
64900
|
}
|
|
64354
64901
|
const buffer = await zip.generateAsync({
|
|
@@ -64368,8 +64915,8 @@ async function listFilesSorted(rootDir) {
|
|
|
64368
64915
|
return out;
|
|
64369
64916
|
}
|
|
64370
64917
|
async function walk(absRoot, relPrefix, out) {
|
|
64371
|
-
const dirAbs =
|
|
64372
|
-
const entries = await
|
|
64918
|
+
const dirAbs = import_node_path64.default.join(absRoot, relPrefix);
|
|
64919
|
+
const entries = await import_promises13.default.readdir(dirAbs, { withFileTypes: true });
|
|
64373
64920
|
for (const e of entries) {
|
|
64374
64921
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
64375
64922
|
const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
|
|
@@ -64421,26 +64968,26 @@ function computePublishCheck(args) {
|
|
|
64421
64968
|
}
|
|
64422
64969
|
|
|
64423
64970
|
// src/extension/install-flow.ts
|
|
64424
|
-
var
|
|
64425
|
-
var
|
|
64426
|
-
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);
|
|
64427
64974
|
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
64428
64975
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
64429
64976
|
|
|
64430
64977
|
// src/extension/paths.ts
|
|
64431
|
-
var
|
|
64432
|
-
var
|
|
64978
|
+
var import_node_os22 = __toESM(require("os"), 1);
|
|
64979
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
64433
64980
|
function clawdHomeRoot(override) {
|
|
64434
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
64981
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path65.default.join(import_node_os22.default.homedir(), ".clawd");
|
|
64435
64982
|
}
|
|
64436
64983
|
function extensionsRoot(override) {
|
|
64437
|
-
return
|
|
64984
|
+
return import_node_path65.default.join(clawdHomeRoot(override), "extensions");
|
|
64438
64985
|
}
|
|
64439
64986
|
function publishedChannelsFile(override) {
|
|
64440
|
-
return
|
|
64987
|
+
return import_node_path65.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
64441
64988
|
}
|
|
64442
64989
|
function bundleCacheRoot(override) {
|
|
64443
|
-
return
|
|
64990
|
+
return import_node_path65.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
64444
64991
|
}
|
|
64445
64992
|
|
|
64446
64993
|
// src/extension/install-flow.ts
|
|
@@ -64467,7 +65014,7 @@ async function installFromChannel(args, deps) {
|
|
|
64467
65014
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
64468
65015
|
}
|
|
64469
65016
|
for (const name of Object.keys(zip.files)) {
|
|
64470
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
65017
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path66.default.isAbsolute(name)) {
|
|
64471
65018
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
64472
65019
|
}
|
|
64473
65020
|
}
|
|
@@ -64499,10 +65046,10 @@ async function installFromChannel(args, deps) {
|
|
|
64499
65046
|
);
|
|
64500
65047
|
}
|
|
64501
65048
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
64502
|
-
const destDir =
|
|
65049
|
+
const destDir = import_node_path66.default.join(deps.extensionsRoot, localExtId);
|
|
64503
65050
|
let destExists = false;
|
|
64504
65051
|
try {
|
|
64505
|
-
await
|
|
65052
|
+
await import_promises14.default.access(destDir);
|
|
64506
65053
|
destExists = true;
|
|
64507
65054
|
} catch {
|
|
64508
65055
|
}
|
|
@@ -64512,28 +65059,28 @@ async function installFromChannel(args, deps) {
|
|
|
64512
65059
|
`extension ${localExtId} already installed locally (from owner ${channelRef.ownerPrincipalId})`
|
|
64513
65060
|
);
|
|
64514
65061
|
}
|
|
64515
|
-
const stage = await
|
|
64516
|
-
|
|
65062
|
+
const stage = await import_promises14.default.mkdtemp(
|
|
65063
|
+
import_node_path66.default.join(import_node_os23.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
64517
65064
|
);
|
|
64518
65065
|
try {
|
|
64519
65066
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
64520
|
-
const dest =
|
|
65067
|
+
const dest = import_node_path66.default.join(stage, name);
|
|
64521
65068
|
if (entry.dir) {
|
|
64522
|
-
await
|
|
65069
|
+
await import_promises14.default.mkdir(dest, { recursive: true });
|
|
64523
65070
|
continue;
|
|
64524
65071
|
}
|
|
64525
|
-
await
|
|
65072
|
+
await import_promises14.default.mkdir(import_node_path66.default.dirname(dest), { recursive: true });
|
|
64526
65073
|
if (name === "manifest.json") {
|
|
64527
65074
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
64528
|
-
await
|
|
65075
|
+
await import_promises14.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
64529
65076
|
} else {
|
|
64530
|
-
await
|
|
65077
|
+
await import_promises14.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
64531
65078
|
}
|
|
64532
65079
|
}
|
|
64533
|
-
await
|
|
64534
|
-
await
|
|
65080
|
+
await import_promises14.default.mkdir(deps.extensionsRoot, { recursive: true });
|
|
65081
|
+
await import_promises14.default.rename(stage, destDir);
|
|
64535
65082
|
} catch (e) {
|
|
64536
|
-
await
|
|
65083
|
+
await import_promises14.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
64537
65084
|
});
|
|
64538
65085
|
throw e;
|
|
64539
65086
|
}
|
|
@@ -64542,9 +65089,9 @@ async function installFromChannel(args, deps) {
|
|
|
64542
65089
|
}
|
|
64543
65090
|
|
|
64544
65091
|
// src/extension/update-flow.ts
|
|
64545
|
-
var
|
|
64546
|
-
var
|
|
64547
|
-
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);
|
|
64548
65095
|
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
64549
65096
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
64550
65097
|
var UpdateError = class extends Error {
|
|
@@ -64560,11 +65107,11 @@ async function updateFromChannel(args, deps) {
|
|
|
64560
65107
|
channelRef.extId,
|
|
64561
65108
|
channelRef.ownerPrincipalId
|
|
64562
65109
|
);
|
|
64563
|
-
const liveDir =
|
|
65110
|
+
const liveDir = import_node_path67.default.join(deps.extensionsRoot, localExtId);
|
|
64564
65111
|
const prevDir = `${liveDir}.prev`;
|
|
64565
65112
|
let existingVersion;
|
|
64566
65113
|
try {
|
|
64567
|
-
const raw = await
|
|
65114
|
+
const raw = await import_promises15.default.readFile(import_node_path67.default.join(liveDir, "manifest.json"), "utf8");
|
|
64568
65115
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
64569
65116
|
if (!parsed2.success) {
|
|
64570
65117
|
throw new UpdateError(
|
|
@@ -64597,7 +65144,7 @@ async function updateFromChannel(args, deps) {
|
|
|
64597
65144
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
64598
65145
|
}
|
|
64599
65146
|
for (const name of Object.keys(zip.files)) {
|
|
64600
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
65147
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path67.default.isAbsolute(name)) {
|
|
64601
65148
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
64602
65149
|
}
|
|
64603
65150
|
}
|
|
@@ -64629,31 +65176,31 @@ async function updateFromChannel(args, deps) {
|
|
|
64629
65176
|
);
|
|
64630
65177
|
}
|
|
64631
65178
|
await deps.runtime.close(localExtId);
|
|
64632
|
-
await
|
|
64633
|
-
await
|
|
64634
|
-
const stage = await
|
|
64635
|
-
|
|
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}-`)
|
|
64636
65183
|
);
|
|
64637
65184
|
try {
|
|
64638
65185
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
64639
|
-
const dest =
|
|
65186
|
+
const dest = import_node_path67.default.join(stage, name);
|
|
64640
65187
|
if (entry.dir) {
|
|
64641
|
-
await
|
|
65188
|
+
await import_promises15.default.mkdir(dest, { recursive: true });
|
|
64642
65189
|
continue;
|
|
64643
65190
|
}
|
|
64644
|
-
await
|
|
65191
|
+
await import_promises15.default.mkdir(import_node_path67.default.dirname(dest), { recursive: true });
|
|
64645
65192
|
if (name === "manifest.json") {
|
|
64646
65193
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
64647
|
-
await
|
|
65194
|
+
await import_promises15.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
64648
65195
|
} else {
|
|
64649
|
-
await
|
|
65196
|
+
await import_promises15.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
64650
65197
|
}
|
|
64651
65198
|
}
|
|
64652
|
-
await
|
|
65199
|
+
await import_promises15.default.rename(stage, liveDir);
|
|
64653
65200
|
} catch (e) {
|
|
64654
|
-
await
|
|
65201
|
+
await import_promises15.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
64655
65202
|
});
|
|
64656
|
-
await
|
|
65203
|
+
await import_promises15.default.rename(prevDir, liveDir).catch(() => {
|
|
64657
65204
|
});
|
|
64658
65205
|
await deps.runtime.open(localExtId).catch(() => {
|
|
64659
65206
|
});
|
|
@@ -64675,7 +65222,7 @@ async function updateFromChannel(args, deps) {
|
|
|
64675
65222
|
reason: e.message
|
|
64676
65223
|
};
|
|
64677
65224
|
}
|
|
64678
|
-
await
|
|
65225
|
+
await import_promises15.default.rm(prevDir, { recursive: true, force: true });
|
|
64679
65226
|
return {
|
|
64680
65227
|
kind: "updated",
|
|
64681
65228
|
extId: localExtId,
|
|
@@ -64683,9 +65230,9 @@ async function updateFromChannel(args, deps) {
|
|
|
64683
65230
|
};
|
|
64684
65231
|
}
|
|
64685
65232
|
async function rollback(deps, localExtId, liveDir, prevDir) {
|
|
64686
|
-
await
|
|
65233
|
+
await import_promises15.default.rm(liveDir, { recursive: true, force: true }).catch(() => {
|
|
64687
65234
|
});
|
|
64688
|
-
await
|
|
65235
|
+
await import_promises15.default.rename(prevDir, liveDir).catch(() => {
|
|
64689
65236
|
});
|
|
64690
65237
|
await deps.runtime.open(localExtId).catch(() => {
|
|
64691
65238
|
});
|
|
@@ -64708,18 +65255,18 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
64708
65255
|
);
|
|
64709
65256
|
}
|
|
64710
65257
|
}
|
|
64711
|
-
const manifestPath =
|
|
65258
|
+
const manifestPath = import_node_path68.default.join(root, extId, "manifest.json");
|
|
64712
65259
|
const manifest = await readManifest(root, extId);
|
|
64713
65260
|
const next = { ...manifest, version: newVersion };
|
|
64714
65261
|
const tmp = `${manifestPath}.tmp`;
|
|
64715
|
-
await
|
|
64716
|
-
await
|
|
65262
|
+
await import_promises16.default.writeFile(tmp, JSON.stringify(next, null, 2));
|
|
65263
|
+
await import_promises16.default.rename(tmp, manifestPath);
|
|
64717
65264
|
}
|
|
64718
65265
|
async function readManifest(root, extId) {
|
|
64719
|
-
const file =
|
|
65266
|
+
const file = import_node_path68.default.join(root, extId, "manifest.json");
|
|
64720
65267
|
let raw;
|
|
64721
65268
|
try {
|
|
64722
|
-
raw = await
|
|
65269
|
+
raw = await import_promises16.default.readFile(file, "utf8");
|
|
64723
65270
|
} catch (e) {
|
|
64724
65271
|
if (e.code === "ENOENT") {
|
|
64725
65272
|
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `extension ${extId} not installed`);
|
|
@@ -64800,7 +65347,7 @@ function buildExtensionHandlers(deps) {
|
|
|
64800
65347
|
};
|
|
64801
65348
|
async function buildSnapshotMeta(extId) {
|
|
64802
65349
|
const manifest = await readManifest(deps.root, extId);
|
|
64803
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
65350
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path68.default.join(deps.root, extId));
|
|
64804
65351
|
return { manifest, contentHash: sha256, buffer };
|
|
64805
65352
|
}
|
|
64806
65353
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -64975,7 +65522,7 @@ function buildExtensionHandlers(deps) {
|
|
|
64975
65522
|
}
|
|
64976
65523
|
|
|
64977
65524
|
// src/app-builder/kill-port.ts
|
|
64978
|
-
var
|
|
65525
|
+
var import_node_child_process16 = require("child_process");
|
|
64979
65526
|
async function killPortOccupants(port, ownedPids, logger) {
|
|
64980
65527
|
let pids;
|
|
64981
65528
|
try {
|
|
@@ -65017,7 +65564,7 @@ async function killPortOccupants(port, ownedPids, logger) {
|
|
|
65017
65564
|
}
|
|
65018
65565
|
function listPidsOnPort(port) {
|
|
65019
65566
|
return new Promise((resolve9, reject) => {
|
|
65020
|
-
(0,
|
|
65567
|
+
(0, import_node_child_process16.execFile)(
|
|
65021
65568
|
"lsof",
|
|
65022
65569
|
["-ti", `:${port}`],
|
|
65023
65570
|
{ timeout: 3e3 },
|
|
@@ -65043,7 +65590,7 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
|
65043
65590
|
|
|
65044
65591
|
// src/handlers/app-builder.ts
|
|
65045
65592
|
init_protocol();
|
|
65046
|
-
var
|
|
65593
|
+
var import_node_path69 = require("path");
|
|
65047
65594
|
var import_node_fs52 = require("fs");
|
|
65048
65595
|
var DEFAULT_TEMPLATE = "nestjs-react";
|
|
65049
65596
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
@@ -65190,13 +65737,13 @@ function buildAppBuilderHandlers(deps) {
|
|
|
65190
65737
|
const created = await deps.createProjectOnDisk({
|
|
65191
65738
|
store: userStore,
|
|
65192
65739
|
name: f.name,
|
|
65193
|
-
templateSrcDir: (0,
|
|
65194
|
-
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"),
|
|
65195
65742
|
reservedPorts,
|
|
65196
65743
|
// 凭据只进 scaffold 子进程的 env,且**只给这个 persona 的 kit 模板声明要的那几个变量**
|
|
65197
65744
|
// (M1b Step 5)。整表塞进去粒度只到「进程」——那会把 service-role key 交给一个用不到
|
|
65198
65745
|
// 它的脚本。new-extension.sh 用它把模板的 `${VAR}` 渲成项目可跑的 server/.env。
|
|
65199
|
-
extraEnv: secretsForKit(deps.readSecrets?.(), (0,
|
|
65746
|
+
extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path69.join)(personaRoot, "extension-kit")),
|
|
65200
65747
|
...deps.logger ? { logger: deps.logger } : {}
|
|
65201
65748
|
});
|
|
65202
65749
|
project = created.project;
|
|
@@ -65395,7 +65942,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
65395
65942
|
await userStore.clearPublishJob(args.name);
|
|
65396
65943
|
}
|
|
65397
65944
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
65398
|
-
const scriptPath = (0,
|
|
65945
|
+
const scriptPath = (0, import_node_path69.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
65399
65946
|
deps.logger?.info("app-builder.publish.start", {
|
|
65400
65947
|
name: args.name,
|
|
65401
65948
|
sessionId: boundSession.sessionId,
|
|
@@ -65411,7 +65958,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
65411
65958
|
// 凭据只进 publish.sh 这个子进程的 env,且只给它的 kit 模板声明要的那几个变量
|
|
65412
65959
|
// (M1b Step 5)。那个进程里跑着 `eval "$BUILD_CMD"`——项目自带的构建命令会继承这份
|
|
65413
65960
|
// env,多给一个变量就是多交一个凭据给它。personaRoot 上面已按绑定 session 的 persona 解析。
|
|
65414
|
-
extraEnv: secretsForKit(deps.readSecrets?.(), (0,
|
|
65961
|
+
extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path69.join)(personaRoot, "extension-kit")),
|
|
65415
65962
|
hooks: {
|
|
65416
65963
|
// 元数据每次写盘(publishJob 起落 / prodUrl 回填)后重推一帧:UI 渲染 PublishProgress
|
|
65417
65964
|
// 三段 checklist 依赖 project.publishJob.status==='in-flight',而 publishJob 字段只有
|
|
@@ -65819,7 +66366,7 @@ function buildTopicHandlers(deps) {
|
|
|
65819
66366
|
init_protocol();
|
|
65820
66367
|
|
|
65821
66368
|
// src/channel/authority.ts
|
|
65822
|
-
var
|
|
66369
|
+
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
65823
66370
|
init_protocol();
|
|
65824
66371
|
var DEFAULT_AUTHORITY_RULES = [
|
|
65825
66372
|
{ id: "outbound-message", desc: "\u4EE5\u8001\u677F\u540D\u4E49\u7ED9\u5176\u4ED6\u4EBA\u53D1\u6D88\u606F\uFF08IM/\u90AE\u4EF6\uFF09", action: "ask" },
|
|
@@ -65837,7 +66384,7 @@ async function resolveAuthority(args) {
|
|
|
65837
66384
|
let source;
|
|
65838
66385
|
let raw = null;
|
|
65839
66386
|
try {
|
|
65840
|
-
raw = await
|
|
66387
|
+
raw = await import_promises17.default.readFile(args.tablePath, "utf8");
|
|
65841
66388
|
} catch (e) {
|
|
65842
66389
|
if (e.code !== "ENOENT") {
|
|
65843
66390
|
return askBecause(`\u6388\u6743\u8BBE\u5B9A\u8BFB\u4E0D\u51FA\u6765\uFF08${args.tablePath}\uFF09\uFF1A${e.message}`);
|
|
@@ -66146,12 +66693,12 @@ function buildVisitorHandlers(deps) {
|
|
|
66146
66693
|
}
|
|
66147
66694
|
|
|
66148
66695
|
// src/extension/registry.ts
|
|
66149
|
-
var
|
|
66150
|
-
var
|
|
66696
|
+
var import_promises18 = __toESM(require("fs/promises"), 1);
|
|
66697
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
66151
66698
|
async function loadAll(root) {
|
|
66152
66699
|
let entries;
|
|
66153
66700
|
try {
|
|
66154
|
-
entries = await
|
|
66701
|
+
entries = await import_promises18.default.readdir(root, { withFileTypes: true });
|
|
66155
66702
|
} catch (e) {
|
|
66156
66703
|
if (e.code === "ENOENT") return [];
|
|
66157
66704
|
throw e;
|
|
@@ -66160,16 +66707,16 @@ async function loadAll(root) {
|
|
|
66160
66707
|
for (const ent of entries) {
|
|
66161
66708
|
if (!ent.isDirectory()) continue;
|
|
66162
66709
|
if (ent.name.startsWith(".")) continue;
|
|
66163
|
-
records.push(await loadOne(
|
|
66710
|
+
records.push(await loadOne(import_node_path70.default.join(root, ent.name), ent.name));
|
|
66164
66711
|
}
|
|
66165
66712
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
66166
66713
|
return records;
|
|
66167
66714
|
}
|
|
66168
66715
|
async function loadOne(dir, dirName) {
|
|
66169
|
-
const manifestPath =
|
|
66716
|
+
const manifestPath = import_node_path70.default.join(dir, "manifest.json");
|
|
66170
66717
|
let raw;
|
|
66171
66718
|
try {
|
|
66172
|
-
raw = await
|
|
66719
|
+
raw = await import_promises18.default.readFile(manifestPath, "utf8");
|
|
66173
66720
|
} catch {
|
|
66174
66721
|
return {
|
|
66175
66722
|
extId: dirName,
|
|
@@ -66210,8 +66757,8 @@ async function loadOne(dir, dirName) {
|
|
|
66210
66757
|
}
|
|
66211
66758
|
|
|
66212
66759
|
// src/extension/uninstall.ts
|
|
66213
|
-
var
|
|
66214
|
-
var
|
|
66760
|
+
var import_promises19 = __toESM(require("fs/promises"), 1);
|
|
66761
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
66215
66762
|
var UninstallError = class extends Error {
|
|
66216
66763
|
constructor(code, message) {
|
|
66217
66764
|
super(message);
|
|
@@ -66220,14 +66767,14 @@ var UninstallError = class extends Error {
|
|
|
66220
66767
|
code;
|
|
66221
66768
|
};
|
|
66222
66769
|
async function uninstall(deps) {
|
|
66223
|
-
const dir =
|
|
66770
|
+
const dir = import_node_path71.default.join(deps.root, deps.extId);
|
|
66224
66771
|
try {
|
|
66225
|
-
await
|
|
66772
|
+
await import_promises19.default.access(dir);
|
|
66226
66773
|
} catch {
|
|
66227
66774
|
throw new UninstallError("NOT_FOUND", `extension ${deps.extId} not installed`);
|
|
66228
66775
|
}
|
|
66229
66776
|
await deps.runtime.close(deps.extId);
|
|
66230
|
-
await
|
|
66777
|
+
await import_promises19.default.rm(dir, { recursive: true, force: true });
|
|
66231
66778
|
}
|
|
66232
66779
|
|
|
66233
66780
|
// src/handlers/index.ts
|
|
@@ -66237,15 +66784,15 @@ var import_node_crypto20 = require("crypto");
|
|
|
66237
66784
|
init_protocol();
|
|
66238
66785
|
|
|
66239
66786
|
// src/peer-ops/run-command.ts
|
|
66240
|
-
var
|
|
66241
|
-
var
|
|
66787
|
+
var import_node_child_process17 = require("child_process");
|
|
66788
|
+
var import_node_os25 = __toESM(require("os"), 1);
|
|
66242
66789
|
var DEFAULT_TIMEOUT_MS5 = 3e4;
|
|
66243
66790
|
var MAX_TIMEOUT_MS = 3e5;
|
|
66244
66791
|
var MAX_OUTPUT_BYTES = 1048576;
|
|
66245
66792
|
function runCommand(command, opts = {}) {
|
|
66246
66793
|
const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5, MAX_TIMEOUT_MS);
|
|
66247
66794
|
return new Promise((resolve9) => {
|
|
66248
|
-
const child = (0,
|
|
66795
|
+
const child = (0, import_node_child_process17.spawn)("bash", ["-c", command], { cwd: import_node_os25.default.homedir() });
|
|
66249
66796
|
const out = [];
|
|
66250
66797
|
const err = [];
|
|
66251
66798
|
let outBytes = 0;
|
|
@@ -66456,7 +67003,7 @@ function buildMethodHandlers(deps) {
|
|
|
66456
67003
|
broadcast: deps.broadcastToOwners
|
|
66457
67004
|
}),
|
|
66458
67005
|
...buildMasterHandlers({
|
|
66459
|
-
authorityTablePath:
|
|
67006
|
+
authorityTablePath: import_node_path72.default.join(deps.masterDataDir, "master-authority.json")
|
|
66460
67007
|
}),
|
|
66461
67008
|
...buildTopicHandlers({
|
|
66462
67009
|
topicStore: deps.topicStore,
|
|
@@ -66487,23 +67034,23 @@ function buildMethodHandlers(deps) {
|
|
|
66487
67034
|
init_protocol();
|
|
66488
67035
|
|
|
66489
67036
|
// src/tools/version-probe.ts
|
|
66490
|
-
var
|
|
67037
|
+
var import_node_child_process19 = require("child_process");
|
|
66491
67038
|
init_claude();
|
|
66492
67039
|
|
|
66493
67040
|
// src/tools/shell-path.ts
|
|
66494
|
-
var
|
|
66495
|
-
var
|
|
67041
|
+
var import_node_child_process18 = require("child_process");
|
|
67042
|
+
var import_node_os26 = __toESM(require("os"), 1);
|
|
66496
67043
|
function refreshPathFromLoginShell() {
|
|
66497
67044
|
if (process.platform === "win32") return;
|
|
66498
|
-
const shell = process.env.SHELL ??
|
|
67045
|
+
const shell = process.env.SHELL ?? import_node_os26.default.userInfo().shell ?? "/bin/zsh";
|
|
66499
67046
|
try {
|
|
66500
|
-
const out = (0,
|
|
67047
|
+
const out = (0, import_node_child_process18.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
|
|
66501
67048
|
encoding: "utf8",
|
|
66502
67049
|
timeout: 3e3,
|
|
66503
67050
|
stdio: ["ignore", "pipe", "ignore"]
|
|
66504
67051
|
});
|
|
66505
|
-
const
|
|
66506
|
-
if (
|
|
67052
|
+
const path98 = out.trim();
|
|
67053
|
+
if (path98) process.env.PATH = path98;
|
|
66507
67054
|
} catch {
|
|
66508
67055
|
}
|
|
66509
67056
|
}
|
|
@@ -66514,7 +67061,7 @@ function parseVersionOutput(out) {
|
|
|
66514
67061
|
}
|
|
66515
67062
|
function execVersion(bin) {
|
|
66516
67063
|
return new Promise((resolve9, reject) => {
|
|
66517
|
-
(0,
|
|
67064
|
+
(0, import_node_child_process19.execFile)(bin, ["--version"], { timeout: 5e3 }, (err, stdout) => {
|
|
66518
67065
|
if (err) reject(err);
|
|
66519
67066
|
else resolve9(String(stdout));
|
|
66520
67067
|
});
|
|
@@ -66628,8 +67175,8 @@ function buildOnboardingHandlers(deps) {
|
|
|
66628
67175
|
|
|
66629
67176
|
// src/app-builder-plugin/project-store.ts
|
|
66630
67177
|
var import_node_fs53 = require("fs");
|
|
66631
|
-
var
|
|
66632
|
-
var
|
|
67178
|
+
var import_node_child_process20 = require("child_process");
|
|
67179
|
+
var import_node_path73 = require("path");
|
|
66633
67180
|
init_protocol();
|
|
66634
67181
|
var PROJECTS_DIR = "projects";
|
|
66635
67182
|
var META_FILE = ".clawd-project.json";
|
|
@@ -66659,14 +67206,14 @@ var ProjectStore = class {
|
|
|
66659
67206
|
}
|
|
66660
67207
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
66661
67208
|
metaPath(name) {
|
|
66662
|
-
return (0,
|
|
67209
|
+
return (0, import_node_path73.join)(this.projectsRoot(), name, META_FILE);
|
|
66663
67210
|
}
|
|
66664
67211
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
66665
67212
|
projectDir(name) {
|
|
66666
|
-
return (0,
|
|
67213
|
+
return (0, import_node_path73.join)(this.projectsRoot(), name);
|
|
66667
67214
|
}
|
|
66668
67215
|
projectsRoot() {
|
|
66669
|
-
return (0,
|
|
67216
|
+
return (0, import_node_path73.join)(this.root, PROJECTS_DIR);
|
|
66670
67217
|
}
|
|
66671
67218
|
async list() {
|
|
66672
67219
|
let entries;
|
|
@@ -66749,7 +67296,7 @@ var ProjectStore = class {
|
|
|
66749
67296
|
async scaffold(name, templateSrcDir, scaffoldScriptPath, extraEnv) {
|
|
66750
67297
|
const destDir = this.projectDir(name);
|
|
66751
67298
|
return await new Promise((resolve9, reject) => {
|
|
66752
|
-
const child = (0,
|
|
67299
|
+
const child = (0, import_node_child_process20.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
|
|
66753
67300
|
// extraEnv 排在 PATH **之前**:凭据表里若混进一条名叫 PATH 的条目,顶掉 PATH 会让
|
|
66754
67301
|
// 脚本以「命令找不到」的形态崩在离现场很远的地方。
|
|
66755
67302
|
env: { ...process.env, ...extraEnv ?? {}, PATH: process.env.PATH ?? "" },
|
|
@@ -66863,7 +67410,7 @@ var ProjectStore = class {
|
|
|
66863
67410
|
};
|
|
66864
67411
|
|
|
66865
67412
|
// src/app-builder/dev-server-supervisor.ts
|
|
66866
|
-
var
|
|
67413
|
+
var import_node_child_process21 = require("child_process");
|
|
66867
67414
|
var import_node_events2 = require("events");
|
|
66868
67415
|
var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
|
|
66869
67416
|
var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
@@ -66900,7 +67447,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
66900
67447
|
tunnelHost: args.tunnelHost,
|
|
66901
67448
|
devCommand: cmd
|
|
66902
67449
|
});
|
|
66903
|
-
const child = (0,
|
|
67450
|
+
const child = (0, import_node_child_process21.spawn)("sh", ["-c", cmd], {
|
|
66904
67451
|
cwd: args.cwd,
|
|
66905
67452
|
env,
|
|
66906
67453
|
stdio: "pipe",
|
|
@@ -67116,6 +67663,9 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
67116
67663
|
}
|
|
67117
67664
|
};
|
|
67118
67665
|
|
|
67666
|
+
// src/app-builder-plugin/core.ts
|
|
67667
|
+
var import_node_child_process23 = require("child_process");
|
|
67668
|
+
|
|
67119
67669
|
// src/app-builder-plugin/publish-registry.ts
|
|
67120
67670
|
var import_node_crypto21 = require("crypto");
|
|
67121
67671
|
var PublishJobRegistry = class {
|
|
@@ -67167,9 +67717,9 @@ var PublishJobRegistry = class {
|
|
|
67167
67717
|
};
|
|
67168
67718
|
|
|
67169
67719
|
// src/app-builder-plugin/publish-job-runner.ts
|
|
67170
|
-
var
|
|
67720
|
+
var import_node_child_process22 = require("child_process");
|
|
67171
67721
|
var import_node_fs54 = require("fs");
|
|
67172
|
-
var
|
|
67722
|
+
var import_node_path74 = require("path");
|
|
67173
67723
|
|
|
67174
67724
|
// src/app-builder-plugin/publish-stage-parser.ts
|
|
67175
67725
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -67196,19 +67746,19 @@ function tailStderrLines(buf, n) {
|
|
|
67196
67746
|
// src/app-builder-plugin/publish-job-runner.ts
|
|
67197
67747
|
async function startPublishJob(deps, args) {
|
|
67198
67748
|
const { registry: registry2, projectDir } = deps;
|
|
67199
|
-
const
|
|
67749
|
+
const spawn14 = deps.spawnImpl ?? import_node_child_process22.spawn;
|
|
67200
67750
|
if (registry2.has(args.name)) {
|
|
67201
67751
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
67202
67752
|
}
|
|
67203
67753
|
const projDir = projectDir(args.name);
|
|
67204
|
-
const logPath = (0,
|
|
67754
|
+
const logPath = (0, import_node_path74.join)(projDir, ".publish.log");
|
|
67205
67755
|
let logStream = null;
|
|
67206
67756
|
try {
|
|
67207
67757
|
logStream = (0, import_node_fs54.createWriteStream)(logPath, { flags: "w" });
|
|
67208
67758
|
} catch {
|
|
67209
67759
|
logStream = null;
|
|
67210
67760
|
}
|
|
67211
|
-
const child =
|
|
67761
|
+
const child = spawn14("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
|
|
67212
67762
|
cwd: projDir,
|
|
67213
67763
|
// 宿主给的 env 覆盖在 process.env 之上:daemon 进程本身没有这些变量(它们只在这一个
|
|
67214
67764
|
// 子进程里活着)。云上宿主不传 extraEnv,凭据本来就在容器 env 里。
|
|
@@ -67538,6 +68088,7 @@ async function createProjectOnDisk(args) {
|
|
|
67538
68088
|
}
|
|
67539
68089
|
return { project, projectDir: store.projectDir(name) };
|
|
67540
68090
|
}
|
|
68091
|
+
var REMOVE_TIMEOUT_MS = 10 * 6e4;
|
|
67541
68092
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
67542
68093
|
await recoverInterruptedJobs({
|
|
67543
68094
|
listAllProjects: async () => store.list(),
|
|
@@ -67547,9 +68098,9 @@ async function recoverInterruptedPublishJobs(store, logger) {
|
|
|
67547
68098
|
|
|
67548
68099
|
// src/app-builder-plugin/mcp-config.ts
|
|
67549
68100
|
var import_node_fs55 = __toESM(require("fs"), 1);
|
|
67550
|
-
var
|
|
68101
|
+
var import_node_path75 = __toESM(require("path"), 1);
|
|
67551
68102
|
function appBuilderMcpConfigPath(dataDir) {
|
|
67552
|
-
return
|
|
68103
|
+
return import_node_path75.default.join(dataDir, "app-builder.mcp.json");
|
|
67553
68104
|
}
|
|
67554
68105
|
function writeAppBuilderMcpConfig(args) {
|
|
67555
68106
|
const cfgPath = appBuilderMcpConfigPath(args.dataDir);
|
|
@@ -67563,8 +68114,8 @@ function writeAppBuilderMcpConfig(args) {
|
|
|
67563
68114
|
env: {
|
|
67564
68115
|
CLAWD_DAEMON_TOKEN: args.daemonToken,
|
|
67565
68116
|
CLAWD_DAEMON_URL: args.daemonUrl,
|
|
67566
|
-
CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT:
|
|
67567
|
-
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"),
|
|
67568
68119
|
...args.logPath ? { CLAWD_APP_BUILDER_LOG: args.logPath } : {}
|
|
67569
68120
|
}
|
|
67570
68121
|
}
|
|
@@ -67611,9 +68162,9 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
67611
68162
|
}
|
|
67612
68163
|
|
|
67613
68164
|
// src/extension/runtime.ts
|
|
67614
|
-
var
|
|
67615
|
-
var
|
|
67616
|
-
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");
|
|
67617
68168
|
|
|
67618
68169
|
// src/extension/port-allocator.ts
|
|
67619
68170
|
var import_node_net2 = __toESM(require("net"), 1);
|
|
@@ -67713,13 +68264,13 @@ var Runtime = class {
|
|
|
67713
68264
|
/\$CLAWOS_EXT_PORT/g,
|
|
67714
68265
|
String(port)
|
|
67715
68266
|
);
|
|
67716
|
-
const dir =
|
|
68267
|
+
const dir = import_node_path76.default.join(this.root, extId);
|
|
67717
68268
|
const env = {
|
|
67718
68269
|
...process.env,
|
|
67719
68270
|
CLAWOS_EXT_PORT: String(port),
|
|
67720
68271
|
CLAWOS_EXT_ID: extId
|
|
67721
68272
|
};
|
|
67722
|
-
const child = (0,
|
|
68273
|
+
const child = (0, import_node_child_process24.spawn)("sh", ["-c", cmd], {
|
|
67723
68274
|
cwd: dir,
|
|
67724
68275
|
env,
|
|
67725
68276
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -67789,7 +68340,7 @@ ${handle.stderrTail}`
|
|
|
67789
68340
|
if (res.ok) return;
|
|
67790
68341
|
} catch {
|
|
67791
68342
|
}
|
|
67792
|
-
await (0,
|
|
68343
|
+
await (0, import_promises20.setTimeout)(this.healthzIntervalMs);
|
|
67793
68344
|
}
|
|
67794
68345
|
throw new RuntimeError(
|
|
67795
68346
|
"HEALTHZ_FAILED",
|
|
@@ -67814,7 +68365,7 @@ ${handle.stderrTail}`
|
|
|
67814
68365
|
};
|
|
67815
68366
|
killGroup("SIGTERM");
|
|
67816
68367
|
const exited = new Promise((resolve9) => child.once("exit", () => resolve9()));
|
|
67817
|
-
const timed = (0,
|
|
68368
|
+
const timed = (0, import_promises20.setTimeout)(5e3).then(() => "timeout");
|
|
67818
68369
|
const winner = await Promise.race([exited.then(() => "exited"), timed]);
|
|
67819
68370
|
if (winner === "timeout" && child.exitCode === null) {
|
|
67820
68371
|
killGroup("SIGKILL");
|
|
@@ -67824,8 +68375,8 @@ ${handle.stderrTail}`
|
|
|
67824
68375
|
};
|
|
67825
68376
|
|
|
67826
68377
|
// src/extension/published-channels.ts
|
|
67827
|
-
var
|
|
67828
|
-
var
|
|
68378
|
+
var import_promises21 = __toESM(require("fs/promises"), 1);
|
|
68379
|
+
var import_node_path77 = __toESM(require("path"), 1);
|
|
67829
68380
|
init_zod();
|
|
67830
68381
|
var PublishedChannelsError = class extends Error {
|
|
67831
68382
|
constructor(code, message) {
|
|
@@ -67855,7 +68406,7 @@ var PublishedChannelStore = class {
|
|
|
67855
68406
|
this.channels.clear();
|
|
67856
68407
|
let raw;
|
|
67857
68408
|
try {
|
|
67858
|
-
raw = await
|
|
68409
|
+
raw = await import_promises21.default.readFile(this.filePath, "utf8");
|
|
67859
68410
|
} catch (e) {
|
|
67860
68411
|
if (e.code === "ENOENT") {
|
|
67861
68412
|
this.loaded = true;
|
|
@@ -67924,15 +68475,15 @@ var PublishedChannelStore = class {
|
|
|
67924
68475
|
)
|
|
67925
68476
|
};
|
|
67926
68477
|
const tmp = `${this.filePath}.tmp`;
|
|
67927
|
-
await
|
|
67928
|
-
await
|
|
67929
|
-
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);
|
|
67930
68481
|
}
|
|
67931
68482
|
};
|
|
67932
68483
|
|
|
67933
68484
|
// src/extension/bundle-cache.ts
|
|
67934
|
-
var
|
|
67935
|
-
var
|
|
68485
|
+
var import_promises22 = __toESM(require("fs/promises"), 1);
|
|
68486
|
+
var import_node_path78 = __toESM(require("path"), 1);
|
|
67936
68487
|
var BundleCache = class {
|
|
67937
68488
|
constructor(rootDir) {
|
|
67938
68489
|
this.rootDir = rootDir;
|
|
@@ -67940,17 +68491,17 @@ var BundleCache = class {
|
|
|
67940
68491
|
rootDir;
|
|
67941
68492
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
67942
68493
|
async write(snapshotHash, buffer) {
|
|
67943
|
-
await
|
|
67944
|
-
const file =
|
|
68494
|
+
await import_promises22.default.mkdir(this.rootDir, { recursive: true });
|
|
68495
|
+
const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
67945
68496
|
const tmp = `${file}.tmp`;
|
|
67946
|
-
await
|
|
67947
|
-
await
|
|
68497
|
+
await import_promises22.default.writeFile(tmp, buffer, { mode: 384 });
|
|
68498
|
+
await import_promises22.default.rename(tmp, file);
|
|
67948
68499
|
}
|
|
67949
68500
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
67950
68501
|
async read(snapshotHash) {
|
|
67951
|
-
const file =
|
|
68502
|
+
const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
67952
68503
|
try {
|
|
67953
|
-
return await
|
|
68504
|
+
return await import_promises22.default.readFile(file);
|
|
67954
68505
|
} catch (e) {
|
|
67955
68506
|
if (e.code === "ENOENT") return null;
|
|
67956
68507
|
throw e;
|
|
@@ -67958,8 +68509,8 @@ var BundleCache = class {
|
|
|
67958
68509
|
}
|
|
67959
68510
|
/** Idempotent — missing file is not an error. */
|
|
67960
68511
|
async delete(snapshotHash) {
|
|
67961
|
-
const file =
|
|
67962
|
-
await
|
|
68512
|
+
const file = import_node_path78.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
68513
|
+
await import_promises22.default.rm(file, { force: true });
|
|
67963
68514
|
}
|
|
67964
68515
|
};
|
|
67965
68516
|
|
|
@@ -67979,26 +68530,26 @@ async function startDaemon(config) {
|
|
|
67979
68530
|
},
|
|
67980
68531
|
source: "daemon",
|
|
67981
68532
|
sampling: logShippingCfg.sampling,
|
|
67982
|
-
homeDir:
|
|
68533
|
+
homeDir: import_node_os27.default.homedir()
|
|
67983
68534
|
});
|
|
67984
|
-
const logDir =
|
|
68535
|
+
const logDir = import_node_path79.default.join(config.dataDir, "log");
|
|
67985
68536
|
import_node_fs56.default.mkdirSync(logDir, { recursive: true });
|
|
67986
68537
|
const logger = createLogger({
|
|
67987
68538
|
level: config.logLevel,
|
|
67988
|
-
file:
|
|
68539
|
+
file: import_node_path79.default.join(logDir, "clawd.log"),
|
|
67989
68540
|
logClient
|
|
67990
68541
|
});
|
|
67991
68542
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
67992
68543
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
67993
|
-
file:
|
|
68544
|
+
file: import_node_path79.default.join(logDir, "screen-idle-probe.log"),
|
|
67994
68545
|
level: "debug"
|
|
67995
68546
|
});
|
|
67996
68547
|
logger.info("screen-idle probe logger enabled", {
|
|
67997
|
-
file:
|
|
68548
|
+
file: import_node_path79.default.join(logDir, "screen-idle-probe.log")
|
|
67998
68549
|
});
|
|
67999
68550
|
const CAP_TARGETS = [
|
|
68000
|
-
|
|
68001
|
-
|
|
68551
|
+
import_node_path79.default.join(logDir, "clawd.log"),
|
|
68552
|
+
import_node_path79.default.join(logDir, "screen-idle-probe.log")
|
|
68002
68553
|
];
|
|
68003
68554
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
68004
68555
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -68120,8 +68671,8 @@ async function startDaemon(config) {
|
|
|
68120
68671
|
const agents = new AgentsScanner();
|
|
68121
68672
|
const history = new ClaudeHistoryReader();
|
|
68122
68673
|
let transport = null;
|
|
68123
|
-
const personaStore = new PersonaStore(
|
|
68124
|
-
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");
|
|
68125
68676
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
68126
68677
|
if (defaultsRoot) {
|
|
68127
68678
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -68145,7 +68696,7 @@ async function startDaemon(config) {
|
|
|
68145
68696
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
68146
68697
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
68147
68698
|
const dispatchStore = createDispatchStore({
|
|
68148
|
-
filePath:
|
|
68699
|
+
filePath: import_node_path79.default.join(config.dataDir, "dispatch.json"),
|
|
68149
68700
|
now: () => Date.now(),
|
|
68150
68701
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
68151
68702
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -68154,7 +68705,7 @@ async function startDaemon(config) {
|
|
|
68154
68705
|
await dispatchStore.load();
|
|
68155
68706
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
68156
68707
|
const channelStore = createChannelStore({
|
|
68157
|
-
filePath:
|
|
68708
|
+
filePath: import_node_path79.default.join(config.dataDir, "channels.json"),
|
|
68158
68709
|
now: () => Date.now(),
|
|
68159
68710
|
genId: () => `ch-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
68160
68711
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
@@ -68163,7 +68714,7 @@ async function startDaemon(config) {
|
|
|
68163
68714
|
});
|
|
68164
68715
|
await channelStore.load();
|
|
68165
68716
|
const topicStore = createTopicStore({
|
|
68166
|
-
filePath:
|
|
68717
|
+
filePath: import_node_path79.default.join(config.dataDir, "topics.json"),
|
|
68167
68718
|
now: () => Date.now(),
|
|
68168
68719
|
genId: () => `tp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
68169
68720
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
@@ -68190,28 +68741,28 @@ async function startDaemon(config) {
|
|
|
68190
68741
|
});
|
|
68191
68742
|
}
|
|
68192
68743
|
});
|
|
68193
|
-
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));
|
|
68194
68745
|
const mcpConfigs = [];
|
|
68195
68746
|
const secretsBundleRoot = findSecretsBundleRoot(logger);
|
|
68196
|
-
const localSecretsDir =
|
|
68747
|
+
const localSecretsDir = import_node_path79.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
|
|
68197
68748
|
const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
|
|
68198
68749
|
const resolvePersonaMcpConfig = (personaId2) => renderPersonaMcpSecrets({
|
|
68199
68750
|
personaId: personaId2,
|
|
68200
|
-
personaDir:
|
|
68751
|
+
personaDir: import_node_path79.default.join(config.dataDir, "personas", personaId2),
|
|
68201
68752
|
secrets: readSecrets(),
|
|
68202
|
-
outDir:
|
|
68753
|
+
outDir: import_node_path79.default.join(config.dataDir, "persona-mcp"),
|
|
68203
68754
|
logger
|
|
68204
68755
|
});
|
|
68205
68756
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
68206
68757
|
const dispatchServerCandidates = [
|
|
68207
|
-
|
|
68758
|
+
import_node_path79.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
68208
68759
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
68209
|
-
|
|
68760
|
+
import_node_path79.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
68210
68761
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
68211
68762
|
];
|
|
68212
68763
|
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68213
68764
|
if (dispatchServerScriptPath) {
|
|
68214
|
-
const dispatchLogPath =
|
|
68765
|
+
const dispatchLogPath = import_node_path79.default.join(logDir, "dispatch-mcp-server.log");
|
|
68215
68766
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
68216
68767
|
dataDir: config.dataDir,
|
|
68217
68768
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -68231,12 +68782,12 @@ async function startDaemon(config) {
|
|
|
68231
68782
|
});
|
|
68232
68783
|
}
|
|
68233
68784
|
const ticketServerCandidates = [
|
|
68234
|
-
|
|
68235
|
-
|
|
68785
|
+
import_node_path79.default.join(here, "ticket", "mcp-server.cjs"),
|
|
68786
|
+
import_node_path79.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
68236
68787
|
];
|
|
68237
68788
|
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68238
68789
|
if (ticketServerScriptPath) {
|
|
68239
|
-
const ticketLogPath =
|
|
68790
|
+
const ticketLogPath = import_node_path79.default.join(logDir, "ticket-mcp-server.log");
|
|
68240
68791
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
68241
68792
|
dataDir: config.dataDir,
|
|
68242
68793
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -68258,12 +68809,12 @@ async function startDaemon(config) {
|
|
|
68258
68809
|
});
|
|
68259
68810
|
}
|
|
68260
68811
|
const shiftServerCandidates = [
|
|
68261
|
-
|
|
68262
|
-
|
|
68812
|
+
import_node_path79.default.join(here, "shift", "mcp-server.cjs"),
|
|
68813
|
+
import_node_path79.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
68263
68814
|
];
|
|
68264
68815
|
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68265
68816
|
if (shiftServerScriptPath) {
|
|
68266
|
-
const shiftLogPath =
|
|
68817
|
+
const shiftLogPath = import_node_path79.default.join(logDir, "shift-mcp-server.log");
|
|
68267
68818
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
68268
68819
|
dataDir: config.dataDir,
|
|
68269
68820
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -68284,12 +68835,12 @@ async function startDaemon(config) {
|
|
|
68284
68835
|
);
|
|
68285
68836
|
}
|
|
68286
68837
|
const inboxServerCandidates = [
|
|
68287
|
-
|
|
68288
|
-
|
|
68838
|
+
import_node_path79.default.join(here, "inbox", "mcp-server.cjs"),
|
|
68839
|
+
import_node_path79.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
68289
68840
|
];
|
|
68290
68841
|
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68291
68842
|
if (inboxServerScriptPath) {
|
|
68292
|
-
const inboxLogPath =
|
|
68843
|
+
const inboxLogPath = import_node_path79.default.join(logDir, "inbox-mcp-server.log");
|
|
68293
68844
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
68294
68845
|
dataDir: config.dataDir,
|
|
68295
68846
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -68310,8 +68861,8 @@ async function startDaemon(config) {
|
|
|
68310
68861
|
);
|
|
68311
68862
|
}
|
|
68312
68863
|
const peerOpsServerCandidates = [
|
|
68313
|
-
|
|
68314
|
-
|
|
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")
|
|
68315
68866
|
];
|
|
68316
68867
|
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68317
68868
|
if (peerOpsServerScriptPath) {
|
|
@@ -68333,12 +68884,12 @@ async function startDaemon(config) {
|
|
|
68333
68884
|
);
|
|
68334
68885
|
}
|
|
68335
68886
|
const rpcToolServerCandidates = [
|
|
68336
|
-
|
|
68337
|
-
|
|
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")
|
|
68338
68889
|
];
|
|
68339
68890
|
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68340
68891
|
if (rpcToolServerScriptPath) {
|
|
68341
|
-
const rpcToolLogPath =
|
|
68892
|
+
const rpcToolLogPath = import_node_path79.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
68342
68893
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
68343
68894
|
dataDir: config.dataDir,
|
|
68344
68895
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -68359,18 +68910,18 @@ async function startDaemon(config) {
|
|
|
68359
68910
|
);
|
|
68360
68911
|
}
|
|
68361
68912
|
const appBuilderServerCandidates = [
|
|
68362
|
-
|
|
68363
|
-
|
|
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")
|
|
68364
68915
|
];
|
|
68365
68916
|
const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs56.default.existsSync(p2));
|
|
68366
68917
|
if (appBuilderServerScriptPath) {
|
|
68367
|
-
const appBuilderLogPath =
|
|
68918
|
+
const appBuilderLogPath = import_node_path79.default.join(logDir, "app-builder-mcp-server.log");
|
|
68368
68919
|
const appBuilderCfgPath = writeAppBuilderMcpConfig({
|
|
68369
68920
|
dataDir: config.dataDir,
|
|
68370
68921
|
serverScriptPath: appBuilderServerScriptPath,
|
|
68371
68922
|
daemonToken: resolvedAuthToken,
|
|
68372
68923
|
daemonUrl: mcpDaemonUrl,
|
|
68373
|
-
deployKitScriptsDir:
|
|
68924
|
+
deployKitScriptsDir: import_node_path79.default.join(config.dataDir, "deploy-kit", "scripts"),
|
|
68374
68925
|
logPath: appBuilderLogPath
|
|
68375
68926
|
});
|
|
68376
68927
|
mcpConfigs.push({ id: "app-builder", path: appBuilderCfgPath, personas: APP_BUILDER_PERSONAS });
|
|
@@ -68386,7 +68937,7 @@ async function startDaemon(config) {
|
|
|
68386
68937
|
);
|
|
68387
68938
|
}
|
|
68388
68939
|
const shiftStore = createShiftStore({
|
|
68389
|
-
filePath:
|
|
68940
|
+
filePath: import_node_path79.default.join(config.dataDir, "shift.json"),
|
|
68390
68941
|
ownerIdProvider: () => ownerPrincipalId,
|
|
68391
68942
|
now: () => Date.now()
|
|
68392
68943
|
});
|
|
@@ -68408,7 +68959,7 @@ async function startDaemon(config) {
|
|
|
68408
68959
|
getAdapter,
|
|
68409
68960
|
historyReader: history,
|
|
68410
68961
|
dataDir: config.dataDir,
|
|
68411
|
-
personaRoot:
|
|
68962
|
+
personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
|
|
68412
68963
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
68413
68964
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
68414
68965
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -68465,7 +69016,7 @@ async function startDaemon(config) {
|
|
|
68465
69016
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
68466
69017
|
attachmentGroup: {
|
|
68467
69018
|
onFileEdit: (input) => {
|
|
68468
|
-
const absPath =
|
|
69019
|
+
const absPath = import_node_path79.default.isAbsolute(input.relPath) ? input.relPath : import_node_path79.default.join(input.cwd, input.relPath);
|
|
68469
69020
|
let size = 0;
|
|
68470
69021
|
try {
|
|
68471
69022
|
size = import_node_fs56.default.statSync(absPath).size;
|
|
@@ -68498,9 +69049,9 @@ async function startDaemon(config) {
|
|
|
68498
69049
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
68499
69050
|
}
|
|
68500
69051
|
const projectsStore = new ProjectsStore({
|
|
68501
|
-
file:
|
|
69052
|
+
file: import_node_path79.default.join(config.dataDir, "projects.json"),
|
|
68502
69053
|
clawdDir: config.dataDir,
|
|
68503
|
-
codexStateFile:
|
|
69054
|
+
codexStateFile: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
68504
69055
|
logger
|
|
68505
69056
|
});
|
|
68506
69057
|
const observer = new SessionObserver({
|
|
@@ -68560,12 +69111,12 @@ async function startDaemon(config) {
|
|
|
68560
69111
|
screenIdleProbeLogger
|
|
68561
69112
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
68562
69113
|
registerAdapter("claude", claudeAdapter);
|
|
68563
|
-
const codexIsolatedHome =
|
|
69114
|
+
const codexIsolatedHome = import_node_path79.default.join(config.dataDir, "codex-home");
|
|
68564
69115
|
try {
|
|
68565
69116
|
import_node_fs56.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
68566
69117
|
for (const f of ["auth.json", "config.toml"]) {
|
|
68567
|
-
const link =
|
|
68568
|
-
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);
|
|
68569
69120
|
if (!import_node_fs56.default.existsSync(link) && import_node_fs56.default.existsSync(target)) import_node_fs56.default.symlinkSync(target, link);
|
|
68570
69121
|
}
|
|
68571
69122
|
} catch (err) {
|
|
@@ -68579,11 +69130,11 @@ async function startDaemon(config) {
|
|
|
68579
69130
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
68580
69131
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
68581
69132
|
cwd,
|
|
68582
|
-
personaRoot:
|
|
69133
|
+
personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
|
|
68583
69134
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
68584
69135
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
68585
69136
|
projectPaths: projectsStore.listMerged().map((x) => x.path),
|
|
68586
|
-
sharedHome:
|
|
69137
|
+
sharedHome: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex"),
|
|
68587
69138
|
isolatedHome: codexIsolatedHome
|
|
68588
69139
|
})
|
|
68589
69140
|
})
|
|
@@ -68868,11 +69419,11 @@ async function startDaemon(config) {
|
|
|
68868
69419
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
68869
69420
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
68870
69421
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
68871
|
-
personaRoot:
|
|
69422
|
+
personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
|
|
68872
69423
|
usersRoot
|
|
68873
69424
|
},
|
|
68874
69425
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
68875
|
-
personaRoot:
|
|
69426
|
+
personaRoot: import_node_path79.default.join(config.dataDir, "personas"),
|
|
68876
69427
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
68877
69428
|
usersRoot,
|
|
68878
69429
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -68973,11 +69524,11 @@ async function startDaemon(config) {
|
|
|
68973
69524
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
68974
69525
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
68975
69526
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
68976
|
-
appBuilderPersonaRoot:
|
|
69527
|
+
appBuilderPersonaRoot: import_node_path79.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
68977
69528
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
68978
|
-
deployKitRoot:
|
|
69529
|
+
deployKitRoot: import_node_path79.default.join(config.dataDir, "deploy-kit"),
|
|
68979
69530
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
68980
|
-
resolvePersonaRoot: (personaId2) =>
|
|
69531
|
+
resolvePersonaRoot: (personaId2) => import_node_path79.default.join(config.dataDir, "personas", personaId2),
|
|
68981
69532
|
// 凭据表(M1b Step 5):与 MCP 那条同一张表、同一个来源,只是交付给另一个子进程。
|
|
68982
69533
|
readSecrets,
|
|
68983
69534
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
@@ -69034,7 +69585,7 @@ async function startDaemon(config) {
|
|
|
69034
69585
|
sourceSessionId: args.sourceSessionId
|
|
69035
69586
|
});
|
|
69036
69587
|
const sourceFile = manager.findOwnedSession(args.sourceSessionId);
|
|
69037
|
-
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile,
|
|
69588
|
+
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os27.default.homedir());
|
|
69038
69589
|
logger.info("dispatch.spawnB.source-resolved", {
|
|
69039
69590
|
dispatchId: args.dispatchId,
|
|
69040
69591
|
sourceJsonlPath,
|
|
@@ -69092,12 +69643,12 @@ async function startDaemon(config) {
|
|
|
69092
69643
|
});
|
|
69093
69644
|
Object.assign(handlers, shiftHandlers);
|
|
69094
69645
|
const deployReceipts = createReceiptStore({
|
|
69095
|
-
filePath:
|
|
69646
|
+
filePath: import_node_path79.default.join(config.dataDir, "deploy.json"),
|
|
69096
69647
|
now: () => Date.now(),
|
|
69097
69648
|
onFlushError: (err) => logger.error("deploy receipts flush failed", { error: String(err) })
|
|
69098
69649
|
});
|
|
69099
69650
|
const deploySecrets = createSecretStore({
|
|
69100
|
-
filePath:
|
|
69651
|
+
filePath: import_node_path79.default.join(config.dataDir, "deploy-secrets.json"),
|
|
69101
69652
|
now: () => Date.now(),
|
|
69102
69653
|
onFlushError: (err) => logger.error("deploy secrets flush failed", { error: String(err) })
|
|
69103
69654
|
});
|
|
@@ -69105,13 +69656,72 @@ async function startDaemon(config) {
|
|
|
69105
69656
|
await deploySecrets.load();
|
|
69106
69657
|
const interrupted = reconcileInterruptedScans(deployReceipts);
|
|
69107
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
|
+
}
|
|
69108
69718
|
const deployHandlers = buildDeployHandlers({
|
|
69109
69719
|
receipts: deployReceipts,
|
|
69110
69720
|
secrets: deploySecrets,
|
|
69111
69721
|
hasPersona: (personaId2) => personaStore.has(personaId2),
|
|
69112
69722
|
startScan: (deployId, personaId2) => {
|
|
69113
69723
|
const assetLines = SCANNABLE_ASSETS.map(
|
|
69114
|
-
(name) => ` - ${name}\uFF1A${
|
|
69724
|
+
(name) => ` - ${name}\uFF1A${import_node_path79.default.join(config.dataDir, name)}`
|
|
69115
69725
|
).join("\n");
|
|
69116
69726
|
const prompt = [
|
|
69117
69727
|
`\u626B\u63CF persona\u300C${personaId2}\u300D\u7684\u90E8\u7F72\u73AF\u5883\uFF0CdeployId=${deployId}\u3002`,
|
|
@@ -69139,6 +69749,30 @@ async function startDaemon(config) {
|
|
|
69139
69749
|
});
|
|
69140
69750
|
return handle.sessionId;
|
|
69141
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
|
+
},
|
|
69142
69776
|
genId: () => `dp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
69143
69777
|
now: () => Date.now()
|
|
69144
69778
|
});
|
|
@@ -69152,7 +69786,7 @@ async function startDaemon(config) {
|
|
|
69152
69786
|
});
|
|
69153
69787
|
shiftScheduler.start();
|
|
69154
69788
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
69155
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
69789
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path79.default.join(config.dataDir, "personas"));
|
|
69156
69790
|
const larkBotCloud = createLarkBotCloudClient({
|
|
69157
69791
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
69158
69792
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -69166,7 +69800,7 @@ async function startDaemon(config) {
|
|
|
69166
69800
|
store: larkBotStore,
|
|
69167
69801
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
69168
69802
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
69169
|
-
mediaRootFor: (chatId) =>
|
|
69803
|
+
mediaRootFor: (chatId) => import_node_path79.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
69170
69804
|
isShuttingDown: () => larkDraining,
|
|
69171
69805
|
logger: {
|
|
69172
69806
|
warn: (msg) => logger.warn(msg),
|
|
@@ -69471,8 +70105,8 @@ async function startDaemon(config) {
|
|
|
69471
70105
|
const lines = [
|
|
69472
70106
|
`Tunnel: ${r.url}`,
|
|
69473
70107
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
69474
|
-
`Frpc config: ${
|
|
69475
|
-
`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")}`
|
|
69476
70110
|
];
|
|
69477
70111
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
69478
70112
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -69485,7 +70119,7 @@ ${bar}
|
|
|
69485
70119
|
|
|
69486
70120
|
`);
|
|
69487
70121
|
try {
|
|
69488
|
-
const connectPath =
|
|
70122
|
+
const connectPath = import_node_path79.default.join(config.dataDir, "connect.txt");
|
|
69489
70123
|
import_node_fs56.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
69490
70124
|
} catch {
|
|
69491
70125
|
}
|
|
@@ -69575,7 +70209,7 @@ ${bar}
|
|
|
69575
70209
|
};
|
|
69576
70210
|
}
|
|
69577
70211
|
function migrateDropPersonsDir(dataDir) {
|
|
69578
|
-
const dir =
|
|
70212
|
+
const dir = import_node_path79.default.join(dataDir, "persons");
|
|
69579
70213
|
try {
|
|
69580
70214
|
import_node_fs56.default.rmSync(dir, { recursive: true, force: true });
|
|
69581
70215
|
} catch {
|