@clawos-dev/clawd 0.2.502 → 0.2.504
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 +62 -8
- package/dist/cli.cjs +1119 -747
- package/dist/dispatch/mcp-server.cjs +62 -8
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-persona-for-deploy/SKILL.md +81 -15
- package/dist/pi-mcp-bridge/extension.cjs +16 -1
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/{guest-B8V08f7r.js → guest-BNp2t0XF.js} +135 -135
- package/dist/share-ui/assets/guest-DcjEUWDn.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-Ci_CRwfz.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: path101, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path101, ...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, path101, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path101;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -5951,7 +5951,24 @@ var init_contact_handshake = __esm({
|
|
|
5951
5951
|
});
|
|
5952
5952
|
|
|
5953
5953
|
// ../protocol/src/environment-schemas.ts
|
|
5954
|
-
|
|
5954
|
+
function connectorBlockers(c) {
|
|
5955
|
+
if (!c.credentialSource) return [`\u8FDE\u63A5\u5668 ${c.name} \u8FD8\u6CA1\u5B9A\u51ED\u636E\u6765\u6E90\uFF08\u65E0 / \u5171\u4EAB / \u4E2A\u4EBA\uFF09`];
|
|
5956
|
+
const out = [];
|
|
5957
|
+
if (c.credentialSource === "personal") {
|
|
5958
|
+
if (!c.auth) out.push(`\u8FDE\u63A5\u5668 ${c.name} \u8FD8\u6CA1\u9009\u5173\u8054\u8FD8\u662F\u586B\u5199`);
|
|
5959
|
+
else if (c.auth === "oauth" && c.kind === "env") out.push(`\u8FDE\u63A5\u5668 ${c.name} \u662F\u8FDB\u7A0B\u578B\uFF08stdio MCP / CLI\uFF09\uFF0C\u53EA\u80FD\u586B\u5199\u4E0D\u80FD\u5173\u8054`);
|
|
5960
|
+
else if (c.auth === "fields" && c.fields.length === 0) out.push(`\u8FDE\u63A5\u5668 ${c.name} \u8981\u586B\u7684\u683C\u8FD8\u6CA1\u5217`);
|
|
5961
|
+
}
|
|
5962
|
+
if (c.credentialSource === "shared" && c.fields.length === 0) out.push(`\u8FDE\u63A5\u5668 ${c.name} \u9009\u4E86\u5171\u4EAB\uFF0C\u4F46\u8981\u586B\u7684\u683C\u8FD8\u6CA1\u5217`);
|
|
5963
|
+
return out;
|
|
5964
|
+
}
|
|
5965
|
+
function sharedConnectorSecrets(m2) {
|
|
5966
|
+
return m2.connectors.filter((c) => c.credentialSource === "shared" && c.fields.length > 0).map((c) => ({ name: c.name, env: [...c.fields] }));
|
|
5967
|
+
}
|
|
5968
|
+
function requiredSecretEnvNames(m2) {
|
|
5969
|
+
return [.../* @__PURE__ */ new Set([...m2.secrets.flatMap((s) => s.env), ...sharedConnectorSecrets(m2).flatMap((s) => s.env)])];
|
|
5970
|
+
}
|
|
5971
|
+
var EnvCliSchema, EnvSecretSchema, EnvAssetSchema, ConnectorNameSchema, CONNECTOR_KINDS, CONNECTOR_RUNNERS, CONNECTOR_PROTOCOLS, CREDENTIAL_SOURCES, CONNECTOR_AUTHS, ConnectorFieldSchema, EnvConnectorSchema, MANIFEST_BODY, EnvManifestBodySchema, EnvironmentManifestSchema, EnvEvidenceSchema;
|
|
5955
5972
|
var init_environment_schemas = __esm({
|
|
5956
5973
|
"../protocol/src/environment-schemas.ts"() {
|
|
5957
5974
|
"use strict";
|
|
@@ -5994,21 +6011,36 @@ var init_environment_schemas = __esm({
|
|
|
5994
6011
|
name: external_exports.string().min(1)
|
|
5995
6012
|
});
|
|
5996
6013
|
ConnectorNameSchema = external_exports.string().regex(/^[a-z0-9-]+$/, "\u8FDE\u63A5\u5668\u540D\u53EA\u80FD\u662F\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u77ED\u6A2A\u7EBF");
|
|
5997
|
-
|
|
6014
|
+
CONNECTOR_KINDS = ["proxy", "env"];
|
|
6015
|
+
CONNECTOR_RUNNERS = ["mcp", "cli"];
|
|
6016
|
+
CONNECTOR_PROTOCOLS = ["bearer", "lark-sidecar"];
|
|
6017
|
+
CREDENTIAL_SOURCES = ["none", "shared", "personal"];
|
|
6018
|
+
CONNECTOR_AUTHS = ["oauth", "fields"];
|
|
6019
|
+
ConnectorFieldSchema = external_exports.string().regex(/^[A-Z][A-Z0-9_]*$/, "\u8981\u586B\u7684\u683C\u7684\u540D\u5B57\u53EA\u80FD\u662F\u5927\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u4E0B\u5212\u7EBF\uFF0C\u4E14\u4EE5\u5B57\u6BCD\u5F00\u5934");
|
|
6020
|
+
EnvConnectorSchema = external_exports.object({
|
|
6021
|
+
name: ConnectorNameSchema,
|
|
6022
|
+
kind: external_exports.enum(CONNECTOR_KINDS),
|
|
6023
|
+
runner: external_exports.enum(CONNECTOR_RUNNERS),
|
|
6024
|
+
protocol: external_exports.enum(CONNECTOR_PROTOCOLS).optional(),
|
|
6025
|
+
id: external_exports.string().min(1),
|
|
6026
|
+
credentialSource: external_exports.enum(CREDENTIAL_SOURCES).optional(),
|
|
6027
|
+
auth: external_exports.enum(CONNECTOR_AUTHS).optional(),
|
|
6028
|
+
fields: external_exports.array(ConnectorFieldSchema).default([]),
|
|
6029
|
+
http: external_exports.object({ url: external_exports.string().min(1), headers: external_exports.record(external_exports.string(), external_exports.string()) }).optional()
|
|
6030
|
+
});
|
|
5998
6031
|
MANIFEST_BODY = {
|
|
5999
6032
|
clis: external_exports.array(EnvCliSchema),
|
|
6000
6033
|
secrets: external_exports.array(EnvSecretSchema),
|
|
6001
6034
|
assets: external_exports.array(EnvAssetSchema),
|
|
6002
6035
|
/**
|
|
6003
|
-
* 装了哪些连接器(design 2026-09-
|
|
6004
|
-
* 是四段里唯一不是 `{name}` 对象数组的一段:连接器没有任何附加属性,包一层对象只是多一层壳。
|
|
6036
|
+
* 装了哪些连接器(design 2026-09-11-mcp-connector §3.1)。一条一个对象,形状见 `EnvConnectorSchema`。
|
|
6005
6037
|
*
|
|
6006
|
-
* 不复用 secrets
|
|
6007
|
-
*
|
|
6038
|
+
* 不复用 secrets:那段说的是「需要一份值,由部署者填」;连接器的凭据谁出是单据上点出来的,
|
|
6039
|
+
* 三种来源里只有「共享」才落到 Secrets,而且靠 `sharedConnectorSecrets` 在消费处并入,不写进那段。
|
|
6008
6040
|
*
|
|
6009
|
-
*
|
|
6041
|
+
* **缺省空而不是必填**:本机上已有的单据不用为此重扫一遍;没声明就是没装。
|
|
6010
6042
|
*/
|
|
6011
|
-
connectors: external_exports.array(
|
|
6043
|
+
connectors: external_exports.array(EnvConnectorSchema).default([])
|
|
6012
6044
|
};
|
|
6013
6045
|
EnvManifestBodySchema = external_exports.object(MANIFEST_BODY);
|
|
6014
6046
|
EnvironmentManifestSchema = external_exports.object({
|
|
@@ -6198,7 +6230,8 @@ var init_deploy_schemas = __esm({
|
|
|
6198
6230
|
personaId: external_exports.string().min(1),
|
|
6199
6231
|
kind: external_exports.enum(["cli", "secret", "asset", "connector"]),
|
|
6200
6232
|
// 该条目在 manifest 对应数组里的内容(形状随 kind 变,handler 按 kind 收窄校验)
|
|
6201
|
-
// connector 的 item
|
|
6233
|
+
// connector 的 item 是 butler 报的 CLI 连接器({ name, fields? }),daemon 补齐 kind / runner / id 后落进清单;
|
|
6234
|
+
// MCP 连接器不经这里——由 daemon 从 .mcp.json 机械列出(design 2026-09-11-mcp-connector §3.2)
|
|
6202
6235
|
item: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
6203
6236
|
// 这条发现的来历(一句人话 + 原文出处),形状同 EnvEvidence,target 由 handler 从 kind+name 派生
|
|
6204
6237
|
evidence: external_exports.object({
|
|
@@ -6238,6 +6271,43 @@ var init_contact_remote_access = __esm({
|
|
|
6238
6271
|
}
|
|
6239
6272
|
});
|
|
6240
6273
|
|
|
6274
|
+
// ../protocol/src/cloud-connector-schemas.ts
|
|
6275
|
+
var CloudConnectorsListArgsSchema, CLOUD_CONNECTOR_STATUSES, CLOUD_CONNECTOR_ACTIONS, CloudConnectorStatusSchema, CloudConnectorsListResultSchema, CloudConnectorFillArgsSchema;
|
|
6276
|
+
var init_cloud_connector_schemas = __esm({
|
|
6277
|
+
"../protocol/src/cloud-connector-schemas.ts"() {
|
|
6278
|
+
"use strict";
|
|
6279
|
+
init_zod();
|
|
6280
|
+
init_environment_schemas();
|
|
6281
|
+
CloudConnectorsListArgsSchema = external_exports.object({
|
|
6282
|
+
/** 本机 registry 里的键(`<gateway 名>-cloud`);daemon 从它的 `cloud.personaId` 找 gateway 登记行 */
|
|
6283
|
+
personaId: external_exports.string().min(1)
|
|
6284
|
+
}).strict();
|
|
6285
|
+
CLOUD_CONNECTOR_STATUSES = ["connected", "missing", "reauth"];
|
|
6286
|
+
CLOUD_CONNECTOR_ACTIONS = ["link", "fill"];
|
|
6287
|
+
CloudConnectorStatusSchema = external_exports.object({
|
|
6288
|
+
name: ConnectorNameSchema,
|
|
6289
|
+
id: external_exports.string().min(1),
|
|
6290
|
+
kind: external_exports.enum(CONNECTOR_KINDS),
|
|
6291
|
+
runner: external_exports.enum(CONNECTOR_RUNNERS),
|
|
6292
|
+
auth: external_exports.enum(CONNECTOR_AUTHS),
|
|
6293
|
+
status: external_exports.enum(CLOUD_CONNECTOR_STATUSES),
|
|
6294
|
+
action: external_exports.enum(CLOUD_CONNECTOR_ACTIONS),
|
|
6295
|
+
/** 只有 `action: link` 且没连上(或要重新关联)时有;它不是凭证,几分钟过期 */
|
|
6296
|
+
authUrl: external_exports.string().optional(),
|
|
6297
|
+
fields: external_exports.array(ConnectorFieldSchema)
|
|
6298
|
+
}).strict();
|
|
6299
|
+
CloudConnectorsListResultSchema = external_exports.object({
|
|
6300
|
+
connectors: external_exports.array(CloudConnectorStatusSchema)
|
|
6301
|
+
}).strict();
|
|
6302
|
+
CloudConnectorFillArgsSchema = external_exports.object({
|
|
6303
|
+
personaId: external_exports.string().min(1),
|
|
6304
|
+
name: ConnectorNameSchema,
|
|
6305
|
+
/** 格名 → 值。格名必须是该连接器声明过的 `fields` 之一,中心校验 */
|
|
6306
|
+
values: external_exports.record(ConnectorFieldSchema, external_exports.string().min(1))
|
|
6307
|
+
}).strict();
|
|
6308
|
+
}
|
|
6309
|
+
});
|
|
6310
|
+
|
|
6241
6311
|
// ../protocol/src/contact.ts
|
|
6242
6312
|
var ContactSchema, ContactWireSchema, ContactRemoveArgsSchema, ContactRemoveOkSchema, ContactListOkSchema, ContactAddedFrameSchema, ContactRemovedFrameSchema, ContactPinArgsSchema, ContactSetNoteArgsSchema, ContactSetNoteOkSchema, ContactPinOkSchema, ContactPinnedFrameSchema;
|
|
6243
6313
|
var init_contact = __esm({
|
|
@@ -8781,6 +8851,7 @@ var init_methods = __esm({
|
|
|
8781
8851
|
init_contact_handshake();
|
|
8782
8852
|
init_deploy_schemas();
|
|
8783
8853
|
init_contact_remote_access();
|
|
8854
|
+
init_cloud_connector_schemas();
|
|
8784
8855
|
init_contact();
|
|
8785
8856
|
init_feishu_auth();
|
|
8786
8857
|
init_dispatch();
|
|
@@ -9016,6 +9087,15 @@ var init_methods = __esm({
|
|
|
9016
9087
|
summary: "\u539F\u6837\u91CD\u8DD1\u6700\u65B0\u90A3\u6761\u6D41\u6C34\u7EBF\u91CC\u5931\u8D25\u7684\u67D0\u4E00\u6BB5\uFF08gh run rerun --job\uFF09\u3002**\u540C\u4E00\u4E2A commit\u3001\u540C\u4E00\u4EFD\u8F93\u5165**\uFF0C\u4E0D\u4EA7\u751F\u65B0\u63D0\u4EA4\u2014\u2014\u6539\u4E86 persona \u5185\u5BB9\u6216\u51ED\u636E\u8981\u8D70 deploy:release\u3002jobId \u5FC5\u987B\u5C5E\u4E8E\u6700\u65B0\u90A3\u6761 run\uFF1Bowner-only",
|
|
9017
9088
|
args: DeployRerunJobArgsSchema
|
|
9018
9089
|
},
|
|
9090
|
+
// ---- cloud:connectors:*(云 persona 卡片上的连接器;design 2026-09-11-mcp-connector §3.8)----
|
|
9091
|
+
"cloud:connectors:list": {
|
|
9092
|
+
summary: "\u4E91\u4E0A persona \u5361\u7247\u4E0A\u7684\u8FDE\u63A5\u5668\u533A\uFF1A\u8FD9\u4E2A persona \u58F0\u660E\u7684\u3001**\u8981\u4F7F\u7528\u8005\u672C\u4EBA\u6388\u6743\u7684**\u8FDE\u63A5\u5668\u5404\u81EA\u8FDE\u6CA1\u8FDE\u4E0A\uFF08connected / missing / reauth\uFF09\u3001\u6309\u94AE\u662F\u5173\u8054\uFF08\u5E26\u73B0\u7B97\u7684 authUrl\uFF09\u8FD8\u662F\u586B\u5199\uFF08\u5E26\u8981\u586B\u7684\u683C\uFF09\u3002daemon \u62FF gateway \u767B\u8BB0\u884C + \u672C\u673A\u767B\u5F55\u51ED\u8BC1\u5411\u4E2D\u5FC3\u4EE3\u67E5\uFF0C\u51ED\u8BC1\u4E0D\u51FA ws\uFF1Bowner-only",
|
|
9093
|
+
args: CloudConnectorsListArgsSchema
|
|
9094
|
+
},
|
|
9095
|
+
"cloud:connectors:fill": {
|
|
9096
|
+
summary: "\u586B\u5199\u578B\u8FDE\u63A5\u5668\uFF1A\u628A\u4F7F\u7528\u8005\u672C\u4EBA\u7684\u51ED\u636E\u503C\u4EA4\u7ED9\u4E2D\u5FC3\u52A0\u5BC6\u5165\u5E93\uFF08\u4E00\u6B21\u586B\u5199\u5168\u5C40\u5171\u7528\uFF09\u3002**\u8FD9\u662F\u503C\u552F\u4E00\u7684\u5165\u53E3**\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u3001\u672C\u673A\u4E0D\u843D\u76D8\uFF1B\u683C\u540D\u5FC5\u987B\u662F\u8BE5\u8FDE\u63A5\u5668\u58F0\u660E\u8FC7\u7684\uFF1Bowner-only",
|
|
9097
|
+
args: CloudConnectorFillArgsSchema
|
|
9098
|
+
},
|
|
9019
9099
|
"shift:list": {
|
|
9020
9100
|
summary: "\u5217\u51FA owner \u7684\u5168\u90E8 shift\uFF08\u6392\u73ED\uFF09\uFF0C\u7ED9 UI \u65E5\u5386\u6E32\u67D3\u7528\uFF1Bowner-only",
|
|
9021
9101
|
args: NO_ARGS
|
|
@@ -9728,6 +9808,7 @@ var init_runtime = __esm({
|
|
|
9728
9808
|
init_schemas();
|
|
9729
9809
|
init_frames();
|
|
9730
9810
|
init_environment_schemas();
|
|
9811
|
+
init_cloud_connector_schemas();
|
|
9731
9812
|
init_deploy_schemas();
|
|
9732
9813
|
init_persona_schemas();
|
|
9733
9814
|
init_persona_mode();
|
|
@@ -10028,8 +10109,8 @@ var require_req = __commonJS({
|
|
|
10028
10109
|
if (req.originalUrl) {
|
|
10029
10110
|
_req.url = req.originalUrl;
|
|
10030
10111
|
} else {
|
|
10031
|
-
const
|
|
10032
|
-
_req.url = typeof
|
|
10112
|
+
const path101 = req.path;
|
|
10113
|
+
_req.url = typeof path101 === "string" ? path101 : req.url ? req.url.path || req.url : void 0;
|
|
10033
10114
|
}
|
|
10034
10115
|
if (req.query) {
|
|
10035
10116
|
_req.query = req.query;
|
|
@@ -10194,14 +10275,14 @@ var require_redact = __commonJS({
|
|
|
10194
10275
|
}
|
|
10195
10276
|
return obj;
|
|
10196
10277
|
}
|
|
10197
|
-
function parsePath(
|
|
10278
|
+
function parsePath(path101) {
|
|
10198
10279
|
const parts = [];
|
|
10199
10280
|
let current = "";
|
|
10200
10281
|
let inBrackets = false;
|
|
10201
10282
|
let inQuotes = false;
|
|
10202
10283
|
let quoteChar = "";
|
|
10203
|
-
for (let i = 0; i <
|
|
10204
|
-
const char =
|
|
10284
|
+
for (let i = 0; i < path101.length; i++) {
|
|
10285
|
+
const char = path101[i];
|
|
10205
10286
|
if (!inBrackets && char === ".") {
|
|
10206
10287
|
if (current) {
|
|
10207
10288
|
parts.push(current);
|
|
@@ -10332,10 +10413,10 @@ var require_redact = __commonJS({
|
|
|
10332
10413
|
return current;
|
|
10333
10414
|
}
|
|
10334
10415
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
10335
|
-
for (const
|
|
10336
|
-
const parts = parsePath(
|
|
10416
|
+
for (const path101 of paths) {
|
|
10417
|
+
const parts = parsePath(path101);
|
|
10337
10418
|
if (parts.includes("*")) {
|
|
10338
|
-
redactWildcardPath(obj, parts, censor,
|
|
10419
|
+
redactWildcardPath(obj, parts, censor, path101, remove);
|
|
10339
10420
|
} else {
|
|
10340
10421
|
if (remove) {
|
|
10341
10422
|
removeKey(obj, parts);
|
|
@@ -10420,8 +10501,8 @@ var require_redact = __commonJS({
|
|
|
10420
10501
|
}
|
|
10421
10502
|
} else {
|
|
10422
10503
|
if (afterWildcard.includes("*")) {
|
|
10423
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10424
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
10504
|
+
const wrappedCensor = typeof censor === "function" ? (value, path101) => {
|
|
10505
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path101];
|
|
10425
10506
|
return censor(value, fullPath);
|
|
10426
10507
|
} : censor;
|
|
10427
10508
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -10456,8 +10537,8 @@ var require_redact = __commonJS({
|
|
|
10456
10537
|
return null;
|
|
10457
10538
|
}
|
|
10458
10539
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
10459
|
-
for (const
|
|
10460
|
-
const parts = parsePath(
|
|
10540
|
+
for (const path101 of pathsToClone) {
|
|
10541
|
+
const parts = parsePath(path101);
|
|
10461
10542
|
let current = pathStructure;
|
|
10462
10543
|
for (let i = 0; i < parts.length; i++) {
|
|
10463
10544
|
const part = parts[i];
|
|
@@ -10509,24 +10590,24 @@ var require_redact = __commonJS({
|
|
|
10509
10590
|
}
|
|
10510
10591
|
return cloneSelectively(obj, pathStructure);
|
|
10511
10592
|
}
|
|
10512
|
-
function validatePath(
|
|
10513
|
-
if (typeof
|
|
10593
|
+
function validatePath(path101) {
|
|
10594
|
+
if (typeof path101 !== "string") {
|
|
10514
10595
|
throw new Error("Paths must be (non-empty) strings");
|
|
10515
10596
|
}
|
|
10516
|
-
if (
|
|
10597
|
+
if (path101 === "") {
|
|
10517
10598
|
throw new Error("Invalid redaction path ()");
|
|
10518
10599
|
}
|
|
10519
|
-
if (
|
|
10520
|
-
throw new Error(`Invalid redaction path (${
|
|
10600
|
+
if (path101.includes("..")) {
|
|
10601
|
+
throw new Error(`Invalid redaction path (${path101})`);
|
|
10521
10602
|
}
|
|
10522
|
-
if (
|
|
10523
|
-
throw new Error(`Invalid redaction path (${
|
|
10603
|
+
if (path101.includes(",")) {
|
|
10604
|
+
throw new Error(`Invalid redaction path (${path101})`);
|
|
10524
10605
|
}
|
|
10525
10606
|
let bracketCount = 0;
|
|
10526
10607
|
let inQuotes = false;
|
|
10527
10608
|
let quoteChar = "";
|
|
10528
|
-
for (let i = 0; i <
|
|
10529
|
-
const char =
|
|
10609
|
+
for (let i = 0; i < path101.length; i++) {
|
|
10610
|
+
const char = path101[i];
|
|
10530
10611
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
10531
10612
|
if (!inQuotes) {
|
|
10532
10613
|
inQuotes = true;
|
|
@@ -10540,20 +10621,20 @@ var require_redact = __commonJS({
|
|
|
10540
10621
|
} else if (char === "]" && !inQuotes) {
|
|
10541
10622
|
bracketCount--;
|
|
10542
10623
|
if (bracketCount < 0) {
|
|
10543
|
-
throw new Error(`Invalid redaction path (${
|
|
10624
|
+
throw new Error(`Invalid redaction path (${path101})`);
|
|
10544
10625
|
}
|
|
10545
10626
|
}
|
|
10546
10627
|
}
|
|
10547
10628
|
if (bracketCount !== 0) {
|
|
10548
|
-
throw new Error(`Invalid redaction path (${
|
|
10629
|
+
throw new Error(`Invalid redaction path (${path101})`);
|
|
10549
10630
|
}
|
|
10550
10631
|
}
|
|
10551
10632
|
function validatePaths(paths) {
|
|
10552
10633
|
if (!Array.isArray(paths)) {
|
|
10553
10634
|
throw new TypeError("paths must be an array");
|
|
10554
10635
|
}
|
|
10555
|
-
for (const
|
|
10556
|
-
validatePath(
|
|
10636
|
+
for (const path101 of paths) {
|
|
10637
|
+
validatePath(path101);
|
|
10557
10638
|
}
|
|
10558
10639
|
}
|
|
10559
10640
|
function slowRedact(options = {}) {
|
|
@@ -10721,8 +10802,8 @@ var require_redaction = __commonJS({
|
|
|
10721
10802
|
if (shape[k2] === null) {
|
|
10722
10803
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
10723
10804
|
} else {
|
|
10724
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10725
|
-
return censor(value, [k2, ...
|
|
10805
|
+
const wrappedCensor = typeof censor === "function" ? (value, path101) => {
|
|
10806
|
+
return censor(value, [k2, ...path101]);
|
|
10726
10807
|
} : censor;
|
|
10727
10808
|
o[k2] = Redact({
|
|
10728
10809
|
paths: shape[k2],
|
|
@@ -10940,10 +11021,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
10940
11021
|
var require_sonic_boom = __commonJS({
|
|
10941
11022
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
10942
11023
|
"use strict";
|
|
10943
|
-
var
|
|
11024
|
+
var fs92 = require("fs");
|
|
10944
11025
|
var EventEmitter3 = require("events");
|
|
10945
11026
|
var inherits = require("util").inherits;
|
|
10946
|
-
var
|
|
11027
|
+
var path101 = require("path");
|
|
10947
11028
|
var sleep2 = require_atomic_sleep();
|
|
10948
11029
|
var assert = require("assert");
|
|
10949
11030
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -10997,20 +11078,20 @@ var require_sonic_boom = __commonJS({
|
|
|
10997
11078
|
const mode = sonic.mode;
|
|
10998
11079
|
if (sonic.sync) {
|
|
10999
11080
|
try {
|
|
11000
|
-
if (sonic.mkdir)
|
|
11001
|
-
const fd =
|
|
11081
|
+
if (sonic.mkdir) fs92.mkdirSync(path101.dirname(file), { recursive: true });
|
|
11082
|
+
const fd = fs92.openSync(file, flags, mode);
|
|
11002
11083
|
fileOpened(null, fd);
|
|
11003
11084
|
} catch (err) {
|
|
11004
11085
|
fileOpened(err);
|
|
11005
11086
|
throw err;
|
|
11006
11087
|
}
|
|
11007
11088
|
} else if (sonic.mkdir) {
|
|
11008
|
-
|
|
11089
|
+
fs92.mkdir(path101.dirname(file), { recursive: true }, (err) => {
|
|
11009
11090
|
if (err) return fileOpened(err);
|
|
11010
|
-
|
|
11091
|
+
fs92.open(file, flags, mode, fileOpened);
|
|
11011
11092
|
});
|
|
11012
11093
|
} else {
|
|
11013
|
-
|
|
11094
|
+
fs92.open(file, flags, mode, fileOpened);
|
|
11014
11095
|
}
|
|
11015
11096
|
}
|
|
11016
11097
|
function SonicBoom(opts) {
|
|
@@ -11051,8 +11132,8 @@ var require_sonic_boom = __commonJS({
|
|
|
11051
11132
|
this.flush = flushBuffer;
|
|
11052
11133
|
this.flushSync = flushBufferSync;
|
|
11053
11134
|
this._actualWrite = actualWriteBuffer;
|
|
11054
|
-
fsWriteSync = () =>
|
|
11055
|
-
fsWrite = () =>
|
|
11135
|
+
fsWriteSync = () => fs92.writeSync(this.fd, this._writingBuf);
|
|
11136
|
+
fsWrite = () => fs92.write(this.fd, this._writingBuf, this.release);
|
|
11056
11137
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
11057
11138
|
this._writingBuf = "";
|
|
11058
11139
|
this.write = write;
|
|
@@ -11061,15 +11142,15 @@ var require_sonic_boom = __commonJS({
|
|
|
11061
11142
|
this._actualWrite = actualWrite;
|
|
11062
11143
|
fsWriteSync = () => {
|
|
11063
11144
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
11064
|
-
return
|
|
11145
|
+
return fs92.writeSync(this.fd, this._writingBuf);
|
|
11065
11146
|
}
|
|
11066
|
-
return
|
|
11147
|
+
return fs92.writeSync(this.fd, this._writingBuf, "utf8");
|
|
11067
11148
|
};
|
|
11068
11149
|
fsWrite = () => {
|
|
11069
11150
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
11070
|
-
return
|
|
11151
|
+
return fs92.write(this.fd, this._writingBuf, this.release);
|
|
11071
11152
|
}
|
|
11072
|
-
return
|
|
11153
|
+
return fs92.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
11073
11154
|
};
|
|
11074
11155
|
} else {
|
|
11075
11156
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -11126,7 +11207,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11126
11207
|
}
|
|
11127
11208
|
}
|
|
11128
11209
|
if (this._fsync) {
|
|
11129
|
-
|
|
11210
|
+
fs92.fsyncSync(this.fd);
|
|
11130
11211
|
}
|
|
11131
11212
|
const len = this._len;
|
|
11132
11213
|
if (this._reopening) {
|
|
@@ -11240,7 +11321,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11240
11321
|
const onDrain = () => {
|
|
11241
11322
|
if (!this._fsync) {
|
|
11242
11323
|
try {
|
|
11243
|
-
|
|
11324
|
+
fs92.fsync(this.fd, (err) => {
|
|
11244
11325
|
this._flushPending = false;
|
|
11245
11326
|
cb(err);
|
|
11246
11327
|
});
|
|
@@ -11342,7 +11423,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11342
11423
|
const fd = this.fd;
|
|
11343
11424
|
this.once("ready", () => {
|
|
11344
11425
|
if (fd !== this.fd) {
|
|
11345
|
-
|
|
11426
|
+
fs92.close(fd, (err) => {
|
|
11346
11427
|
if (err) {
|
|
11347
11428
|
return this.emit("error", err);
|
|
11348
11429
|
}
|
|
@@ -11391,7 +11472,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11391
11472
|
buf = this._bufs[0];
|
|
11392
11473
|
}
|
|
11393
11474
|
try {
|
|
11394
|
-
const n = Buffer.isBuffer(buf) ?
|
|
11475
|
+
const n = Buffer.isBuffer(buf) ? fs92.writeSync(this.fd, buf) : fs92.writeSync(this.fd, buf, "utf8");
|
|
11395
11476
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
11396
11477
|
buf = releasedBufObj.writingBuf;
|
|
11397
11478
|
this._len = releasedBufObj.len;
|
|
@@ -11407,7 +11488,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11407
11488
|
}
|
|
11408
11489
|
}
|
|
11409
11490
|
try {
|
|
11410
|
-
|
|
11491
|
+
fs92.fsyncSync(this.fd);
|
|
11411
11492
|
} catch {
|
|
11412
11493
|
}
|
|
11413
11494
|
}
|
|
@@ -11428,7 +11509,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11428
11509
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
11429
11510
|
}
|
|
11430
11511
|
try {
|
|
11431
|
-
const n =
|
|
11512
|
+
const n = fs92.writeSync(this.fd, buf);
|
|
11432
11513
|
buf = buf.subarray(n);
|
|
11433
11514
|
this._len = Math.max(this._len - n, 0);
|
|
11434
11515
|
if (buf.length <= 0) {
|
|
@@ -11456,13 +11537,13 @@ var require_sonic_boom = __commonJS({
|
|
|
11456
11537
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
11457
11538
|
if (this.sync) {
|
|
11458
11539
|
try {
|
|
11459
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
11540
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs92.writeSync(this.fd, this._writingBuf) : fs92.writeSync(this.fd, this._writingBuf, "utf8");
|
|
11460
11541
|
release2(null, written);
|
|
11461
11542
|
} catch (err) {
|
|
11462
11543
|
release2(err);
|
|
11463
11544
|
}
|
|
11464
11545
|
} else {
|
|
11465
|
-
|
|
11546
|
+
fs92.write(this.fd, this._writingBuf, release2);
|
|
11466
11547
|
}
|
|
11467
11548
|
}
|
|
11468
11549
|
function actualWriteBuffer() {
|
|
@@ -11471,7 +11552,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11471
11552
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
11472
11553
|
if (this.sync) {
|
|
11473
11554
|
try {
|
|
11474
|
-
const written =
|
|
11555
|
+
const written = fs92.writeSync(this.fd, this._writingBuf);
|
|
11475
11556
|
release2(null, written);
|
|
11476
11557
|
} catch (err) {
|
|
11477
11558
|
release2(err);
|
|
@@ -11480,7 +11561,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11480
11561
|
if (kCopyBuffer) {
|
|
11481
11562
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
11482
11563
|
}
|
|
11483
|
-
|
|
11564
|
+
fs92.write(this.fd, this._writingBuf, release2);
|
|
11484
11565
|
}
|
|
11485
11566
|
}
|
|
11486
11567
|
function actualClose(sonic) {
|
|
@@ -11496,12 +11577,12 @@ var require_sonic_boom = __commonJS({
|
|
|
11496
11577
|
sonic._lens = [];
|
|
11497
11578
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
11498
11579
|
try {
|
|
11499
|
-
|
|
11580
|
+
fs92.fsync(sonic.fd, closeWrapped);
|
|
11500
11581
|
} catch {
|
|
11501
11582
|
}
|
|
11502
11583
|
function closeWrapped() {
|
|
11503
11584
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
11504
|
-
|
|
11585
|
+
fs92.close(sonic.fd, done);
|
|
11505
11586
|
} else {
|
|
11506
11587
|
done();
|
|
11507
11588
|
}
|
|
@@ -14636,11 +14717,11 @@ var init_lib = __esm({
|
|
|
14636
14717
|
}
|
|
14637
14718
|
}
|
|
14638
14719
|
},
|
|
14639
|
-
addToPath: function addToPath(
|
|
14640
|
-
var last =
|
|
14720
|
+
addToPath: function addToPath(path101, added, removed, oldPosInc, options) {
|
|
14721
|
+
var last = path101.lastComponent;
|
|
14641
14722
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14642
14723
|
return {
|
|
14643
|
-
oldPos:
|
|
14724
|
+
oldPos: path101.oldPos + oldPosInc,
|
|
14644
14725
|
lastComponent: {
|
|
14645
14726
|
count: last.count + 1,
|
|
14646
14727
|
added,
|
|
@@ -14650,7 +14731,7 @@ var init_lib = __esm({
|
|
|
14650
14731
|
};
|
|
14651
14732
|
} else {
|
|
14652
14733
|
return {
|
|
14653
|
-
oldPos:
|
|
14734
|
+
oldPos: path101.oldPos + oldPosInc,
|
|
14654
14735
|
lastComponent: {
|
|
14655
14736
|
count: 1,
|
|
14656
14737
|
added,
|
|
@@ -15232,10 +15313,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
15232
15313
|
const memories = raw.map((m2) => {
|
|
15233
15314
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15234
15315
|
const rec5 = m2;
|
|
15235
|
-
const
|
|
15316
|
+
const path101 = typeof rec5.path === "string" ? rec5.path : null;
|
|
15236
15317
|
const content = typeof rec5.content === "string" ? rec5.content : null;
|
|
15237
|
-
if (!
|
|
15238
|
-
const entry = { path:
|
|
15318
|
+
if (!path101 || content == null) return null;
|
|
15319
|
+
const entry = { path: path101, content };
|
|
15239
15320
|
if (typeof rec5.mtimeMs === "number") entry.mtimeMs = rec5.mtimeMs;
|
|
15240
15321
|
return entry;
|
|
15241
15322
|
}).filter((m2) => m2 !== null);
|
|
@@ -16101,10 +16182,10 @@ function parseAttachment(obj) {
|
|
|
16101
16182
|
const memories = raw.map((m2) => {
|
|
16102
16183
|
if (!m2 || typeof m2 !== "object") return null;
|
|
16103
16184
|
const rec5 = m2;
|
|
16104
|
-
const
|
|
16185
|
+
const path101 = typeof rec5.path === "string" ? rec5.path : null;
|
|
16105
16186
|
const content = typeof rec5.content === "string" ? rec5.content : null;
|
|
16106
|
-
if (!
|
|
16107
|
-
const out = { path:
|
|
16187
|
+
if (!path101 || content == null) return null;
|
|
16188
|
+
const out = { path: path101, content };
|
|
16108
16189
|
if (typeof rec5.mtimeMs === "number") out.mtimeMs = rec5.mtimeMs;
|
|
16109
16190
|
return out;
|
|
16110
16191
|
}).filter((m2) => m2 !== null);
|
|
@@ -24576,12 +24657,12 @@ var require_luxon = __commonJS({
|
|
|
24576
24657
|
if (!reason) {
|
|
24577
24658
|
throw new InvalidArgumentError("need to specify a reason the Duration is invalid");
|
|
24578
24659
|
}
|
|
24579
|
-
const
|
|
24660
|
+
const invalid3 = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
|
|
24580
24661
|
if (Settings.throwOnInvalid) {
|
|
24581
|
-
throw new InvalidDurationError(
|
|
24662
|
+
throw new InvalidDurationError(invalid3);
|
|
24582
24663
|
} else {
|
|
24583
24664
|
return new _Duration({
|
|
24584
|
-
invalid:
|
|
24665
|
+
invalid: invalid3
|
|
24585
24666
|
});
|
|
24586
24667
|
}
|
|
24587
24668
|
}
|
|
@@ -25173,12 +25254,12 @@ var require_luxon = __commonJS({
|
|
|
25173
25254
|
if (!reason) {
|
|
25174
25255
|
throw new InvalidArgumentError("need to specify a reason the Interval is invalid");
|
|
25175
25256
|
}
|
|
25176
|
-
const
|
|
25257
|
+
const invalid3 = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
|
|
25177
25258
|
if (Settings.throwOnInvalid) {
|
|
25178
|
-
throw new InvalidIntervalError(
|
|
25259
|
+
throw new InvalidIntervalError(invalid3);
|
|
25179
25260
|
} else {
|
|
25180
25261
|
return new _Interval({
|
|
25181
|
-
invalid:
|
|
25262
|
+
invalid: invalid3
|
|
25182
25263
|
});
|
|
25183
25264
|
}
|
|
25184
25265
|
}
|
|
@@ -26680,9 +26761,9 @@ var require_luxon = __commonJS({
|
|
|
26680
26761
|
obj[u] = defaultUnitValues[u];
|
|
26681
26762
|
}
|
|
26682
26763
|
}
|
|
26683
|
-
const
|
|
26684
|
-
if (
|
|
26685
|
-
return DateTime.invalid(
|
|
26764
|
+
const invalid3 = hasInvalidGregorianData(obj) || hasInvalidTimeData(obj);
|
|
26765
|
+
if (invalid3) {
|
|
26766
|
+
return DateTime.invalid(invalid3);
|
|
26686
26767
|
}
|
|
26687
26768
|
const offsetProvis = guessOffsetForZone(zone);
|
|
26688
26769
|
[ts, o] = objToTS(obj, offsetProvis, zone);
|
|
@@ -26739,24 +26820,24 @@ var require_luxon = __commonJS({
|
|
|
26739
26820
|
*/
|
|
26740
26821
|
constructor(config) {
|
|
26741
26822
|
const zone = config.zone || Settings.defaultZone;
|
|
26742
|
-
let
|
|
26823
|
+
let invalid3 = config.invalid || (Number.isNaN(config.ts) ? new Invalid("invalid input") : null) || (!zone.isValid ? unsupportedZone(zone) : null);
|
|
26743
26824
|
this.ts = isUndefined(config.ts) ? Settings.now() : config.ts;
|
|
26744
26825
|
let c = null, o = null;
|
|
26745
|
-
if (!
|
|
26826
|
+
if (!invalid3) {
|
|
26746
26827
|
const unchanged = config.old && config.old.ts === this.ts && config.old.zone.equals(zone);
|
|
26747
26828
|
if (unchanged) {
|
|
26748
26829
|
[c, o] = [config.old.c, config.old.o];
|
|
26749
26830
|
} else {
|
|
26750
26831
|
const ot = isNumber(config.o) && !config.old ? config.o : zone.offset(this.ts);
|
|
26751
26832
|
c = tsToObj(this.ts, ot);
|
|
26752
|
-
|
|
26753
|
-
c =
|
|
26754
|
-
o =
|
|
26833
|
+
invalid3 = Number.isNaN(c.year) ? new Invalid("invalid input") : null;
|
|
26834
|
+
c = invalid3 ? null : c;
|
|
26835
|
+
o = invalid3 ? null : ot;
|
|
26755
26836
|
}
|
|
26756
26837
|
}
|
|
26757
26838
|
this._zone = zone;
|
|
26758
26839
|
this.loc = config.loc || Locale.create();
|
|
26759
|
-
this.invalid =
|
|
26840
|
+
this.invalid = invalid3;
|
|
26760
26841
|
this.weekData = null;
|
|
26761
26842
|
this.localWeekData = null;
|
|
26762
26843
|
this.c = c;
|
|
@@ -26990,9 +27071,9 @@ var require_luxon = __commonJS({
|
|
|
26990
27071
|
normalized[u] = objNow[u];
|
|
26991
27072
|
}
|
|
26992
27073
|
}
|
|
26993
|
-
const higherOrderInvalid = useWeekData ? hasInvalidWeekData(normalized, minDaysInFirstWeek, startOfWeek) : containsOrdinal ? hasInvalidOrdinalData(normalized) : hasInvalidGregorianData(normalized),
|
|
26994
|
-
if (
|
|
26995
|
-
return _DateTime.invalid(
|
|
27074
|
+
const higherOrderInvalid = useWeekData ? hasInvalidWeekData(normalized, minDaysInFirstWeek, startOfWeek) : containsOrdinal ? hasInvalidOrdinalData(normalized) : hasInvalidGregorianData(normalized), invalid3 = higherOrderInvalid || hasInvalidTimeData(normalized);
|
|
27075
|
+
if (invalid3) {
|
|
27076
|
+
return _DateTime.invalid(invalid3);
|
|
26996
27077
|
}
|
|
26997
27078
|
const gregorian = useWeekData ? weekToGregorian(normalized, minDaysInFirstWeek, startOfWeek) : containsOrdinal ? ordinalToGregorian(normalized) : normalized, [tsFinal, offsetFinal] = objToTS(gregorian, offsetProvis, zoneToUse), inst = new _DateTime({
|
|
26998
27079
|
ts: tsFinal,
|
|
@@ -27093,9 +27174,9 @@ var require_luxon = __commonJS({
|
|
|
27093
27174
|
locale,
|
|
27094
27175
|
numberingSystem,
|
|
27095
27176
|
defaultToEN: true
|
|
27096
|
-
}), [vals, parsedZone, specificOffset,
|
|
27097
|
-
if (
|
|
27098
|
-
return _DateTime.invalid(
|
|
27177
|
+
}), [vals, parsedZone, specificOffset, invalid3] = parseFromTokens(localeToUse, text, fmt);
|
|
27178
|
+
if (invalid3) {
|
|
27179
|
+
return _DateTime.invalid(invalid3);
|
|
27099
27180
|
} else {
|
|
27100
27181
|
return parseDataToDateTime(vals, parsedZone, opts, `format ${fmt}`, text, specificOffset);
|
|
27101
27182
|
}
|
|
@@ -27141,12 +27222,12 @@ var require_luxon = __commonJS({
|
|
|
27141
27222
|
if (!reason) {
|
|
27142
27223
|
throw new InvalidArgumentError("need to specify a reason the DateTime is invalid");
|
|
27143
27224
|
}
|
|
27144
|
-
const
|
|
27225
|
+
const invalid3 = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
|
|
27145
27226
|
if (Settings.throwOnInvalid) {
|
|
27146
|
-
throw new InvalidDateTimeError(
|
|
27227
|
+
throw new InvalidDateTimeError(invalid3);
|
|
27147
27228
|
} else {
|
|
27148
27229
|
return new _DateTime({
|
|
27149
|
-
invalid:
|
|
27230
|
+
invalid: invalid3
|
|
27150
27231
|
});
|
|
27151
27232
|
}
|
|
27152
27233
|
}
|
|
@@ -37078,8 +37159,8 @@ var require_utils = __commonJS({
|
|
|
37078
37159
|
var result = transform[inputType][outputType](input);
|
|
37079
37160
|
return result;
|
|
37080
37161
|
};
|
|
37081
|
-
exports2.resolve = function(
|
|
37082
|
-
var parts =
|
|
37162
|
+
exports2.resolve = function(path101) {
|
|
37163
|
+
var parts = path101.split("/");
|
|
37083
37164
|
var result = [];
|
|
37084
37165
|
for (var index = 0; index < parts.length; index++) {
|
|
37085
37166
|
var part = parts[index];
|
|
@@ -42932,18 +43013,18 @@ var require_object = __commonJS({
|
|
|
42932
43013
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
42933
43014
|
this.files[name] = object;
|
|
42934
43015
|
};
|
|
42935
|
-
var parentFolder = function(
|
|
42936
|
-
if (
|
|
42937
|
-
|
|
43016
|
+
var parentFolder = function(path101) {
|
|
43017
|
+
if (path101.slice(-1) === "/") {
|
|
43018
|
+
path101 = path101.substring(0, path101.length - 1);
|
|
42938
43019
|
}
|
|
42939
|
-
var lastSlash =
|
|
42940
|
-
return lastSlash > 0 ?
|
|
43020
|
+
var lastSlash = path101.lastIndexOf("/");
|
|
43021
|
+
return lastSlash > 0 ? path101.substring(0, lastSlash) : "";
|
|
42941
43022
|
};
|
|
42942
|
-
var forceTrailingSlash = function(
|
|
42943
|
-
if (
|
|
42944
|
-
|
|
43023
|
+
var forceTrailingSlash = function(path101) {
|
|
43024
|
+
if (path101.slice(-1) !== "/") {
|
|
43025
|
+
path101 += "/";
|
|
42945
43026
|
}
|
|
42946
|
-
return
|
|
43027
|
+
return path101;
|
|
42947
43028
|
};
|
|
42948
43029
|
var folderAdd = function(name, createFolders) {
|
|
42949
43030
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -43945,7 +44026,7 @@ var require_lib3 = __commonJS({
|
|
|
43945
44026
|
// src/run-case/recorder.ts
|
|
43946
44027
|
function startRunCaseRecorder(opts) {
|
|
43947
44028
|
const now = opts.now ?? Date.now;
|
|
43948
|
-
const dir =
|
|
44029
|
+
const dir = import_node_path83.default.dirname(opts.recordPath);
|
|
43949
44030
|
let stream = null;
|
|
43950
44031
|
let closing = false;
|
|
43951
44032
|
let closedSettled = false;
|
|
@@ -43959,8 +44040,8 @@ function startRunCaseRecorder(opts) {
|
|
|
43959
44040
|
});
|
|
43960
44041
|
const ensureStream = () => {
|
|
43961
44042
|
if (stream) return stream;
|
|
43962
|
-
|
|
43963
|
-
stream =
|
|
44043
|
+
import_node_fs64.default.mkdirSync(dir, { recursive: true });
|
|
44044
|
+
stream = import_node_fs64.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
43964
44045
|
stream.on("close", () => closedResolve());
|
|
43965
44046
|
return stream;
|
|
43966
44047
|
};
|
|
@@ -43985,12 +44066,12 @@ function startRunCaseRecorder(opts) {
|
|
|
43985
44066
|
};
|
|
43986
44067
|
return { tap, close, closed };
|
|
43987
44068
|
}
|
|
43988
|
-
var
|
|
44069
|
+
var import_node_fs64, import_node_path83;
|
|
43989
44070
|
var init_recorder = __esm({
|
|
43990
44071
|
"src/run-case/recorder.ts"() {
|
|
43991
44072
|
"use strict";
|
|
43992
|
-
|
|
43993
|
-
|
|
44073
|
+
import_node_fs64 = __toESM(require("fs"), 1);
|
|
44074
|
+
import_node_path83 = __toESM(require("path"), 1);
|
|
43994
44075
|
}
|
|
43995
44076
|
});
|
|
43996
44077
|
|
|
@@ -44033,7 +44114,7 @@ var init_wire = __esm({
|
|
|
44033
44114
|
// src/run-case/controller.ts
|
|
44034
44115
|
async function runController(opts) {
|
|
44035
44116
|
const now = opts.now ?? Date.now;
|
|
44036
|
-
const cwd = opts.cwd ?? (0,
|
|
44117
|
+
const cwd = opts.cwd ?? (0, import_node_fs65.mkdtempSync)(import_node_path84.default.join(import_node_os29.default.tmpdir(), "clawd-runcase-"));
|
|
44037
44118
|
const ownsCwd = opts.cwd === void 0;
|
|
44038
44119
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
44039
44120
|
const spawnCtx = { cwd };
|
|
@@ -44194,19 +44275,19 @@ async function runController(opts) {
|
|
|
44194
44275
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
44195
44276
|
if (ownsCwd) {
|
|
44196
44277
|
try {
|
|
44197
|
-
(0,
|
|
44278
|
+
(0, import_node_fs65.rmSync)(cwd, { recursive: true, force: true });
|
|
44198
44279
|
} catch {
|
|
44199
44280
|
}
|
|
44200
44281
|
}
|
|
44201
44282
|
return exitCode ?? 0;
|
|
44202
44283
|
}
|
|
44203
|
-
var
|
|
44284
|
+
var import_node_fs65, import_node_os29, import_node_path84;
|
|
44204
44285
|
var init_controller = __esm({
|
|
44205
44286
|
"src/run-case/controller.ts"() {
|
|
44206
44287
|
"use strict";
|
|
44207
|
-
|
|
44288
|
+
import_node_fs65 = require("fs");
|
|
44208
44289
|
import_node_os29 = __toESM(require("os"), 1);
|
|
44209
|
-
|
|
44290
|
+
import_node_path84 = __toESM(require("path"), 1);
|
|
44210
44291
|
init_claude();
|
|
44211
44292
|
init_stdout_splitter();
|
|
44212
44293
|
init_permission_stdio();
|
|
@@ -44481,8 +44562,8 @@ Env (advanced):
|
|
|
44481
44562
|
`;
|
|
44482
44563
|
|
|
44483
44564
|
// src/index.ts
|
|
44484
|
-
var
|
|
44485
|
-
var
|
|
44565
|
+
var import_node_path82 = __toESM(require("path"), 1);
|
|
44566
|
+
var import_node_fs63 = __toESM(require("fs"), 1);
|
|
44486
44567
|
var import_node_os28 = __toESM(require("os"), 1);
|
|
44487
44568
|
var import_node_crypto23 = require("crypto");
|
|
44488
44569
|
var import_node_url5 = require("url");
|
|
@@ -46656,17 +46737,23 @@ function renderPersonaMcpSecrets(args) {
|
|
|
46656
46737
|
if (Array.isArray(def.args) && def.args.some(hasPlaceholder)) {
|
|
46657
46738
|
args.logger?.warn("persona.mcp-secret.placeholder-in-args", { persona: args.personaId, server: name });
|
|
46658
46739
|
}
|
|
46659
|
-
|
|
46660
|
-
const
|
|
46661
|
-
|
|
46662
|
-
|
|
46663
|
-
|
|
46664
|
-
|
|
46665
|
-
|
|
46666
|
-
|
|
46667
|
-
|
|
46668
|
-
|
|
46669
|
-
|
|
46740
|
+
const headers = def.headers && typeof def.headers === "object" ? def.headers : void 0;
|
|
46741
|
+
const envHas = !!env && Object.values(env).some(hasPlaceholder);
|
|
46742
|
+
const headersHas = !!headers && Object.values(headers).some(hasPlaceholder);
|
|
46743
|
+
if (!envHas && !headersHas) continue;
|
|
46744
|
+
const renderTable = (table) => {
|
|
46745
|
+
const out = {};
|
|
46746
|
+
for (const [k2, v2] of Object.entries(table)) {
|
|
46747
|
+
if (typeof v2 !== "string") continue;
|
|
46748
|
+
out[k2] = v2.replace(PLACEHOLDER, (_m, varName) => {
|
|
46749
|
+
const hit = args.secrets[varName];
|
|
46750
|
+
if (hit === void 0) missing.add(varName);
|
|
46751
|
+
return hit ?? "";
|
|
46752
|
+
});
|
|
46753
|
+
}
|
|
46754
|
+
return out;
|
|
46755
|
+
};
|
|
46756
|
+
rendered[name] = { ...def, ...envHas ? { env: renderTable(env) } : {}, ...headersHas ? { headers: renderTable(headers) } : {} };
|
|
46670
46757
|
}
|
|
46671
46758
|
if (Object.keys(rendered).length === 0) return void 0;
|
|
46672
46759
|
if (missing.size > 0) {
|
|
@@ -51770,7 +51857,7 @@ function codexGuestCliArgs(cs, opts = {}) {
|
|
|
51770
51857
|
function codexMcpCliArgs(defs) {
|
|
51771
51858
|
const out = [];
|
|
51772
51859
|
for (const d of defs) {
|
|
51773
|
-
const cfg = {
|
|
51860
|
+
const cfg = "url" in d ? { url: d.url, ...d.httpHeaders && Object.keys(d.httpHeaders).length > 0 ? { http_headers: d.httpHeaders } : {} } : {
|
|
51774
51861
|
command: d.command,
|
|
51775
51862
|
...d.args && d.args.length > 0 ? { args: d.args } : {},
|
|
51776
51863
|
...d.env && Object.keys(d.env).length > 0 ? { env: d.env } : {}
|
|
@@ -51816,8 +51903,8 @@ function turnStartInput(text, resolveImage) {
|
|
|
51816
51903
|
const items = [];
|
|
51817
51904
|
let leftover = text;
|
|
51818
51905
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
51819
|
-
const [marker, name,
|
|
51820
|
-
items.push({ type: "skill", name, path:
|
|
51906
|
+
const [marker, name, path101] = m2;
|
|
51907
|
+
items.push({ type: "skill", name, path: path101 });
|
|
51821
51908
|
leftover = leftover.replace(marker, "");
|
|
51822
51909
|
}
|
|
51823
51910
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -51963,6 +52050,7 @@ function stringValue2(value) {
|
|
|
51963
52050
|
// src/tools/codex-mcp-config.ts
|
|
51964
52051
|
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
51965
52052
|
var import_node_path15 = __toESM(require("path"), 1);
|
|
52053
|
+
var HTTP_TYPES = /* @__PURE__ */ new Set(["http", "sse", "streamable_http", "streamable-http"]);
|
|
51966
52054
|
function loadCodexMcpServerDefs(args) {
|
|
51967
52055
|
const out = [];
|
|
51968
52056
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -51982,7 +52070,21 @@ function loadCodexMcpServerDefs(args) {
|
|
|
51982
52070
|
if (!servers || typeof servers !== "object") continue;
|
|
51983
52071
|
for (const [name, raw] of Object.entries(servers)) {
|
|
51984
52072
|
const def = raw ?? {};
|
|
51985
|
-
const type = typeof def.type === "string" ? def.type : "stdio";
|
|
52073
|
+
const type = typeof def.type === "string" ? def.type.toLowerCase() : typeof def.url === "string" ? "http" : "stdio";
|
|
52074
|
+
if (HTTP_TYPES.has(type)) {
|
|
52075
|
+
if (typeof def.url !== "string" || !def.url) {
|
|
52076
|
+
args.logger?.warn("codex mcp server http without url, skipped", { file, name });
|
|
52077
|
+
continue;
|
|
52078
|
+
}
|
|
52079
|
+
if (seen.has(name)) {
|
|
52080
|
+
args.logger?.warn("codex mcp server name collision, first-wins", { file, name });
|
|
52081
|
+
continue;
|
|
52082
|
+
}
|
|
52083
|
+
seen.add(name);
|
|
52084
|
+
const headers = def.headers && typeof def.headers === "object" ? Object.fromEntries(Object.entries(def.headers).filter((kv) => typeof kv[1] === "string")) : {};
|
|
52085
|
+
out.push({ name, url: def.url, ...Object.keys(headers).length > 0 ? { httpHeaders: headers } : {} });
|
|
52086
|
+
continue;
|
|
52087
|
+
}
|
|
51986
52088
|
if (type !== "stdio") {
|
|
51987
52089
|
args.logger?.warn("codex mcp server type unsupported, skipped", { file, name, type });
|
|
51988
52090
|
continue;
|
|
@@ -55259,10 +55361,160 @@ function redactEvidence(evidence) {
|
|
|
55259
55361
|
|
|
55260
55362
|
// src/deploy/deploy-file.ts
|
|
55261
55363
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
55364
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
55365
|
+
init_protocol();
|
|
55366
|
+
|
|
55367
|
+
// src/deploy/connectors.ts
|
|
55368
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
55262
55369
|
var import_node_path32 = __toESM(require("path"), 1);
|
|
55370
|
+
init_zod();
|
|
55263
55371
|
init_protocol();
|
|
55264
|
-
var
|
|
55265
|
-
var
|
|
55372
|
+
var PLACEHOLDER2 = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
55373
|
+
var MCP_SCAN_NOTE_PREFIX = "\u3010.mcp.json\u3011";
|
|
55374
|
+
var LARK_SIDECAR_CONNECTOR = "feishu";
|
|
55375
|
+
var CliConnectorFindingSchema = external_exports.object({
|
|
55376
|
+
name: ConnectorNameSchema,
|
|
55377
|
+
fields: external_exports.array(ConnectorFieldSchema).default([])
|
|
55378
|
+
});
|
|
55379
|
+
function canonicalConnectorUrl(raw) {
|
|
55380
|
+
const u = new URL(raw);
|
|
55381
|
+
return `${u.origin}${u.pathname.replace(/\/+$/, "")}${u.search}`;
|
|
55382
|
+
}
|
|
55383
|
+
function placeholdersIn(value) {
|
|
55384
|
+
if (typeof value !== "string") return [];
|
|
55385
|
+
return [...value.matchAll(new RegExp(PLACEHOLDER2))].map((m2) => m2[1]);
|
|
55386
|
+
}
|
|
55387
|
+
var uniq = (xs) => [...new Set(xs)];
|
|
55388
|
+
function fieldsOf(name, where, placeholders, warnings) {
|
|
55389
|
+
const ok = [];
|
|
55390
|
+
for (const p2 of uniq(placeholders)) {
|
|
55391
|
+
if (ConnectorFieldSchema.safeParse(p2).success) ok.push(p2);
|
|
55392
|
+
else warnings.push(`MCP server\u300C${name}\u300D\u7684 ${where} \u91CC\u6709\u5360\u4F4D \${${p2}}\uFF0C\u53D8\u91CF\u540D\u4E0D\u5408\u5F62\u72B6\uFF08\u53EA\u80FD\u5927\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\uFF0C\u5B57\u6BCD\u5F00\u5934\uFF09\uFF0C\u6CA1\u7B97\u8FDB\u8981\u586B\u7684\u683C\uFF1B\u6539\u540D\u540E\u91CD\u65B0\u626B\u63CF`);
|
|
55393
|
+
}
|
|
55394
|
+
return ok;
|
|
55395
|
+
}
|
|
55396
|
+
function sanitizeForQuote(def) {
|
|
55397
|
+
const strip2 = (obj) => {
|
|
55398
|
+
if (!obj || typeof obj !== "object") return obj;
|
|
55399
|
+
return Object.fromEntries(
|
|
55400
|
+
Object.entries(obj).map(([k2, v2]) => [
|
|
55401
|
+
k2,
|
|
55402
|
+
// 用一份新正则做 test:全局正则的 lastIndex 会串进后面的 matchAll(mcp-secret-render.ts 同款写法)
|
|
55403
|
+
typeof v2 === "string" && v2.length > 0 && !new RegExp(PLACEHOLDER2).test(v2) ? REDACTED : v2
|
|
55404
|
+
])
|
|
55405
|
+
);
|
|
55406
|
+
};
|
|
55407
|
+
const out = {};
|
|
55408
|
+
for (const [k2, v2] of Object.entries(def)) {
|
|
55409
|
+
out[k2] = k2 === "env" || k2 === "headers" ? strip2(v2) : v2;
|
|
55410
|
+
}
|
|
55411
|
+
return out;
|
|
55412
|
+
}
|
|
55413
|
+
var stringRecord = (v2) => v2 && typeof v2 === "object" ? Object.fromEntries(Object.entries(v2).filter((kv) => typeof kv[1] === "string")) : {};
|
|
55414
|
+
var HTTP_TYPES2 = /* @__PURE__ */ new Set(["http", "sse", "streamable_http", "streamable-http"]);
|
|
55415
|
+
var PACKAGE_RUNNERS = /* @__PURE__ */ new Set(["npx", "uvx", "pnpx", "bunx"]);
|
|
55416
|
+
function scanMcpConnectors(personaDir) {
|
|
55417
|
+
const file = import_node_path32.default.join(personaDir, ".mcp.json");
|
|
55418
|
+
const out = { readable: true, connectors: [], evidence: [], warnings: [] };
|
|
55419
|
+
let parsed;
|
|
55420
|
+
try {
|
|
55421
|
+
parsed = JSON.parse(import_node_fs29.default.readFileSync(file, "utf8"));
|
|
55422
|
+
} catch (e) {
|
|
55423
|
+
if (e.code === "ENOENT") return out;
|
|
55424
|
+
out.readable = false;
|
|
55425
|
+
out.warnings.push(`.mcp.json \u8BFB\u4E0D\u51FA\u6765\uFF08${e.message.split("\n")[0]}\uFF09\uFF0C\u91CC\u9762\u7684 MCP server \u8FD9\u6B21\u6CA1\u91CD\u65B0\u5217\uFF1B\u6E05\u5355\u91CC\u539F\u6709\u7684\u7167\u65E7`);
|
|
55426
|
+
return out;
|
|
55427
|
+
}
|
|
55428
|
+
const servers = parsed?.mcpServers;
|
|
55429
|
+
if (!servers || typeof servers !== "object") return out;
|
|
55430
|
+
for (const [name, raw] of Object.entries(servers)) {
|
|
55431
|
+
const def = raw && typeof raw === "object" ? raw : {};
|
|
55432
|
+
if (!ConnectorNameSchema.safeParse(name).success) {
|
|
55433
|
+
out.warnings.push(`MCP server\u300C${name}\u300D\u7684\u540D\u5B57\u4E0D\u5408\u5F62\u72B6\uFF08\u53EA\u80FD\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u77ED\u6A2A\u7EBF\uFF09\uFF0C\u6CA1\u5217\u8FDB\u6E05\u5355\uFF1B\u6539\u540D\u540E\u91CD\u65B0\u626B\u63CF`);
|
|
55434
|
+
continue;
|
|
55435
|
+
}
|
|
55436
|
+
const type = typeof def.type === "string" ? def.type.toLowerCase() : typeof def.url === "string" ? "http" : "stdio";
|
|
55437
|
+
const quote = JSON.stringify({ [name]: sanitizeForQuote(def) }, null, 2);
|
|
55438
|
+
if (HTTP_TYPES2.has(type)) {
|
|
55439
|
+
const url = typeof def.url === "string" ? def.url : "";
|
|
55440
|
+
let id2;
|
|
55441
|
+
try {
|
|
55442
|
+
id2 = canonicalConnectorUrl(url);
|
|
55443
|
+
} catch {
|
|
55444
|
+
out.warnings.push(`MCP server\u300C${name}\u300D\u662F http \u578B\u4F46 url \u4E0D\u5408\u6CD5\uFF08${url || "\u7A7A"}\uFF09\uFF0C\u6CA1\u5217\u8FDB\u6E05\u5355`);
|
|
55445
|
+
continue;
|
|
55446
|
+
}
|
|
55447
|
+
const headers = stringRecord(def.headers);
|
|
55448
|
+
if (placeholdersIn(url).length > 0) {
|
|
55449
|
+
out.warnings.push(`MCP server\u300C${name}\u300D\u7684 url \u91CC\u6709 \${VAR} \u5360\u4F4D\u2014\u2014url \u4E0D\u4F1A\u88AB\u6E32\uFF0C\u51ED\u636E\u8BF7\u6539\u5230 headers \u91CC`);
|
|
55450
|
+
}
|
|
55451
|
+
const fields2 = fieldsOf(name, "headers", Object.values(headers).flatMap(placeholdersIn), out.warnings);
|
|
55452
|
+
out.connectors.push({ name, kind: "proxy", runner: "mcp", id: id2, fields: fields2, http: { url, headers } });
|
|
55453
|
+
out.evidence.push({
|
|
55454
|
+
target: `connector:${name}`,
|
|
55455
|
+
reason: `.mcp.json \u91CC\u6302\u4E86 http \u578B MCP server\u300C${name}\u300D\uFF08${id2}\uFF09\u3002` + (fields2.length > 0 ? `\u8BF7\u6C42\u5934\u91CC\u8981\u586B ${fields2.join(" / ")}\u3002` : "\u6CA1\u6709\u5360\u4F4D\uFF1A\u51ED\u636E\u7531\u4F7F\u7528\u8005\u5173\u8054\uFF0C\u6216\u90E8\u7F72\u8005\u5B9A\u4E00\u79CD\u3002") + "\u8C01\u51FA\u51ED\u636E\u5728\u5355\u636E\u4E0A\u70B9\u3002",
|
|
55456
|
+
file: ".mcp.json",
|
|
55457
|
+
quote
|
|
55458
|
+
});
|
|
55459
|
+
continue;
|
|
55460
|
+
}
|
|
55461
|
+
const command = typeof def.command === "string" ? def.command : "";
|
|
55462
|
+
if (!command) {
|
|
55463
|
+
out.warnings.push(`MCP server\u300C${name}\u300D\u65E2\u6CA1\u6709 url \u4E5F\u6CA1\u6709 command\uFF0C\u6CA1\u5217\u8FDB\u6E05\u5355`);
|
|
55464
|
+
continue;
|
|
55465
|
+
}
|
|
55466
|
+
const args = Array.isArray(def.args) ? def.args.map(String) : [];
|
|
55467
|
+
const pkg = PACKAGE_RUNNERS.has(command) ? args.find((a) => !a.startsWith("-")) : void 0;
|
|
55468
|
+
const id = pkg ?? command;
|
|
55469
|
+
const fields = fieldsOf(name, "env", Object.values(stringRecord(def.env)).flatMap(placeholdersIn), out.warnings);
|
|
55470
|
+
if (args.some((a) => placeholdersIn(a).length > 0)) {
|
|
55471
|
+
out.warnings.push(`MCP server\u300C${name}\u300D\u7684 args \u91CC\u6709 \${VAR} \u5360\u4F4D\u2014\u2014args \u4F1A\u8FDB ps\uFF0C\u4E91\u4E0A\u548C\u672C\u673A\u90FD\u53EA\u6E32 env\uFF0C\u8FD9\u4E9B\u5360\u4F4D\u4E0D\u4F1A\u88AB\u586B\uFF1B\u628A\u51ED\u636E\u6539\u5230 env \u91CC`);
|
|
55472
|
+
}
|
|
55473
|
+
out.connectors.push({ name, kind: "env", runner: "mcp", id, fields });
|
|
55474
|
+
out.evidence.push({
|
|
55475
|
+
target: `connector:${name}`,
|
|
55476
|
+
reason: `.mcp.json \u91CC\u6302\u4E86 stdio \u578B MCP server\u300C${name}\u300D\uFF08${id}\uFF09\u3002` + (fields.length > 0 ? `\u5B83\u4ECE\u73AF\u5883\u53D8\u91CF\u8BFB ${fields.join(" / ")}\u3002` : "\u6CA1\u6709\u8981\u586B\u7684\u73AF\u5883\u53D8\u91CF\u3002") + "\u8C01\u51FA\u51ED\u636E\u5728\u5355\u636E\u4E0A\u70B9\uFF1A\u5171\u4EAB = \u90E8\u7F72\u8005\u586B\u8FDB\u4ED3\u5E93 Secrets\uFF0C\u4E2A\u4EBA = \u6BCF\u4E2A\u4F7F\u7528\u8005\u5728\u5361\u7247\u4E0A\u586B\u3002",
|
|
55477
|
+
file: ".mcp.json",
|
|
55478
|
+
quote
|
|
55479
|
+
});
|
|
55480
|
+
}
|
|
55481
|
+
return out;
|
|
55482
|
+
}
|
|
55483
|
+
function cliConnectorFromFinding(item) {
|
|
55484
|
+
if (item.name === LARK_SIDECAR_CONNECTOR) {
|
|
55485
|
+
return {
|
|
55486
|
+
name: item.name,
|
|
55487
|
+
kind: "proxy",
|
|
55488
|
+
runner: "cli",
|
|
55489
|
+
protocol: "lark-sidecar",
|
|
55490
|
+
id: item.name,
|
|
55491
|
+
credentialSource: "personal",
|
|
55492
|
+
auth: "oauth",
|
|
55493
|
+
fields: []
|
|
55494
|
+
};
|
|
55495
|
+
}
|
|
55496
|
+
return { name: item.name, kind: "env", runner: "cli", id: item.name, fields: item.fields };
|
|
55497
|
+
}
|
|
55498
|
+
function mergeConnector(existing, incoming) {
|
|
55499
|
+
if (!existing) return incoming;
|
|
55500
|
+
const reviewed = existing.credentialSource !== void 0;
|
|
55501
|
+
return {
|
|
55502
|
+
...incoming,
|
|
55503
|
+
...existing.credentialSource ? { credentialSource: existing.credentialSource } : {},
|
|
55504
|
+
...existing.auth ? { auth: existing.auth } : {},
|
|
55505
|
+
fields: reviewed ? existing.fields : incoming.fields
|
|
55506
|
+
};
|
|
55507
|
+
}
|
|
55508
|
+
function mergeScannedConnectors(existing, scanned) {
|
|
55509
|
+
const byName = new Map(existing.map((c) => [c.name, c]));
|
|
55510
|
+
const mcp = scanned.map((c) => mergeConnector(byName.get(c.name), c));
|
|
55511
|
+
const cli = existing.filter((c) => c.runner === "cli" && !scanned.some((s) => s.name === c.name));
|
|
55512
|
+
return [...mcp, ...cli];
|
|
55513
|
+
}
|
|
55514
|
+
|
|
55515
|
+
// src/deploy/deploy-file.ts
|
|
55516
|
+
var DEPLOY_FILE = import_node_path33.default.join(".clawd", "deploy.json");
|
|
55517
|
+
var SCAN_FILE = import_node_path33.default.join(".clawd", "deploy-scan.json");
|
|
55266
55518
|
async function readJson(file) {
|
|
55267
55519
|
let raw;
|
|
55268
55520
|
try {
|
|
@@ -55278,14 +55530,14 @@ async function readJson(file) {
|
|
|
55278
55530
|
}
|
|
55279
55531
|
}
|
|
55280
55532
|
async function writeJson(file, value) {
|
|
55281
|
-
await import_promises4.default.mkdir(
|
|
55533
|
+
await import_promises4.default.mkdir(import_node_path33.default.dirname(file), { recursive: true });
|
|
55282
55534
|
const tmp = `${file}.tmp-${process.pid}`;
|
|
55283
55535
|
await import_promises4.default.writeFile(tmp, `${JSON.stringify(value, null, 2)}
|
|
55284
55536
|
`);
|
|
55285
55537
|
await import_promises4.default.rename(tmp, file);
|
|
55286
55538
|
}
|
|
55287
55539
|
async function readDeployFile(dir) {
|
|
55288
|
-
const raw = await readJson(
|
|
55540
|
+
const raw = await readJson(import_node_path33.default.join(dir, DEPLOY_FILE));
|
|
55289
55541
|
if (raw === void 0) return void 0;
|
|
55290
55542
|
const parsed = DeployFileSchema.safeParse(raw);
|
|
55291
55543
|
if (!parsed.success) {
|
|
@@ -55295,10 +55547,10 @@ async function readDeployFile(dir) {
|
|
|
55295
55547
|
return parsed.data;
|
|
55296
55548
|
}
|
|
55297
55549
|
async function writeDeployFile(dir, file) {
|
|
55298
|
-
await writeJson(
|
|
55550
|
+
await writeJson(import_node_path33.default.join(dir, DEPLOY_FILE), DeployFileSchema.parse(file));
|
|
55299
55551
|
}
|
|
55300
55552
|
async function readScan(dir) {
|
|
55301
|
-
const raw = await readJson(
|
|
55553
|
+
const raw = await readJson(import_node_path33.default.join(dir, SCAN_FILE));
|
|
55302
55554
|
if (raw === void 0) return void 0;
|
|
55303
55555
|
const parsed = DeployScanSchema.safeParse(raw);
|
|
55304
55556
|
if (!parsed.success) {
|
|
@@ -55308,7 +55560,7 @@ async function readScan(dir) {
|
|
|
55308
55560
|
return parsed.data;
|
|
55309
55561
|
}
|
|
55310
55562
|
async function writeScan(dir, scan) {
|
|
55311
|
-
await writeJson(
|
|
55563
|
+
await writeJson(import_node_path33.default.join(dir, SCAN_FILE), DeployScanSchema.parse(scan));
|
|
55312
55564
|
}
|
|
55313
55565
|
function emptyDeployFile() {
|
|
55314
55566
|
return { version: 1, manifest: { version: 1, clis: [], secrets: [], assets: [], connectors: [] } };
|
|
@@ -55317,7 +55569,9 @@ var FINDING_SCHEMAS = {
|
|
|
55317
55569
|
cli: EnvCliSchema,
|
|
55318
55570
|
secret: EnvSecretSchema,
|
|
55319
55571
|
asset: EnvAssetSchema,
|
|
55320
|
-
|
|
55572
|
+
// butler 报的是 CLI 连接器的「名字 + 它读的环境变量名」,kind / runner / id 由 daemon 补
|
|
55573
|
+
//(handlers/deploy.ts 的 cliConnectorFromFinding)。MCP 连接器不经上报口,由 scanMcpConnectors 机械列出。
|
|
55574
|
+
connector: CliConnectorFindingSchema
|
|
55321
55575
|
};
|
|
55322
55576
|
function parseFinding(kind, item) {
|
|
55323
55577
|
const parsed = FINDING_SCHEMAS[kind].safeParse(item);
|
|
@@ -55329,8 +55583,12 @@ function parseFinding(kind, item) {
|
|
|
55329
55583
|
}
|
|
55330
55584
|
function upsertFinding(file, kind, item) {
|
|
55331
55585
|
if (kind === "connector") {
|
|
55586
|
+
const incoming = item;
|
|
55332
55587
|
const have = file.manifest.connectors;
|
|
55333
|
-
const
|
|
55588
|
+
const idx2 = have.findIndex((c) => c.name === incoming.name);
|
|
55589
|
+
if (idx2 !== -1 && have[idx2].runner === "mcp" && incoming.runner === "cli") return file;
|
|
55590
|
+
const merged = mergeConnector(idx2 === -1 ? void 0 : have[idx2], incoming);
|
|
55591
|
+
const connectors = idx2 === -1 ? [...have, merged] : have.map((c, i) => i === idx2 ? merged : c);
|
|
55334
55592
|
return { ...file, manifest: { ...file.manifest, connectors } };
|
|
55335
55593
|
}
|
|
55336
55594
|
const key = kind === "cli" ? "clis" : kind === "secret" ? "secrets" : "assets";
|
|
@@ -55342,13 +55600,13 @@ function upsertFinding(file, kind, item) {
|
|
|
55342
55600
|
}
|
|
55343
55601
|
function requiredEnvNames(file) {
|
|
55344
55602
|
if (!file) return [];
|
|
55345
|
-
return
|
|
55603
|
+
return requiredSecretEnvNames(file.manifest);
|
|
55346
55604
|
}
|
|
55347
55605
|
|
|
55348
55606
|
// src/deploy/repo.ts
|
|
55349
55607
|
var import_node_child_process8 = require("child_process");
|
|
55350
55608
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
55351
|
-
var
|
|
55609
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
55352
55610
|
init_protocol();
|
|
55353
55611
|
|
|
55354
55612
|
// src/deploy/templates.ts
|
|
@@ -55582,7 +55840,7 @@ var L = [
|
|
|
55582
55840
|
var WORKFLOW_TEMPLATE = L.join("\n");
|
|
55583
55841
|
|
|
55584
55842
|
// src/deploy/repo.ts
|
|
55585
|
-
var DEPLOY_FILE_REL = DEPLOY_FILE.split(
|
|
55843
|
+
var DEPLOY_FILE_REL = DEPLOY_FILE.split(import_node_path34.default.sep).join("/");
|
|
55586
55844
|
var DEFAULT_TIMEOUT_MS3 = 6e4;
|
|
55587
55845
|
var runCommand = (cmd, args, opts = {}) => new Promise((resolve9) => {
|
|
55588
55846
|
const child = (0, import_node_child_process8.spawn)(cmd, args, {
|
|
@@ -55649,7 +55907,7 @@ async function samePath(a, b2) {
|
|
|
55649
55907
|
try {
|
|
55650
55908
|
return await import_promises5.default.realpath(x);
|
|
55651
55909
|
} catch {
|
|
55652
|
-
return
|
|
55910
|
+
return import_node_path34.default.resolve(x);
|
|
55653
55911
|
}
|
|
55654
55912
|
};
|
|
55655
55913
|
return await real(a) === await real(b2);
|
|
@@ -55675,7 +55933,7 @@ async function identityArgs(exec, dir) {
|
|
|
55675
55933
|
return ["-c", "user.name=clawd", "-c", "user.email=clawd@clawos.local"];
|
|
55676
55934
|
}
|
|
55677
55935
|
async function writeTemplates(dir) {
|
|
55678
|
-
const gi =
|
|
55936
|
+
const gi = import_node_path34.default.join(dir, ".gitignore");
|
|
55679
55937
|
let existing;
|
|
55680
55938
|
try {
|
|
55681
55939
|
existing = await import_promises5.default.readFile(gi, "utf8");
|
|
@@ -55683,8 +55941,8 @@ async function writeTemplates(dir) {
|
|
|
55683
55941
|
existing = void 0;
|
|
55684
55942
|
}
|
|
55685
55943
|
await import_promises5.default.writeFile(gi, mergeGitignore(existing));
|
|
55686
|
-
const wf =
|
|
55687
|
-
await import_promises5.default.mkdir(
|
|
55944
|
+
const wf = import_node_path34.default.join(dir, WORKFLOW_PATH);
|
|
55945
|
+
await import_promises5.default.mkdir(import_node_path34.default.dirname(wf), { recursive: true });
|
|
55688
55946
|
await import_promises5.default.writeFile(wf, WORKFLOW_TEMPLATE);
|
|
55689
55947
|
}
|
|
55690
55948
|
async function ensureRepo(exec, args) {
|
|
@@ -55813,8 +56071,8 @@ function runStatusOf(status) {
|
|
|
55813
56071
|
if (status === "queued" || status === "waiting" || status === "requested" || status === "pending") return "queued";
|
|
55814
56072
|
return "running";
|
|
55815
56073
|
}
|
|
55816
|
-
async function ghJson(exec,
|
|
55817
|
-
const r = await exec("gh", ["api",
|
|
56074
|
+
async function ghJson(exec, path101) {
|
|
56075
|
+
const r = await exec("gh", ["api", path101], { timeoutMs: TIMEOUT_MS });
|
|
55818
56076
|
if (r.spawnError || r.code !== 0) return void 0;
|
|
55819
56077
|
try {
|
|
55820
56078
|
return JSON.parse(r.stdout);
|
|
@@ -55874,12 +56132,12 @@ async function rerunJob(exec, slug, runId, jobId) {
|
|
|
55874
56132
|
}
|
|
55875
56133
|
|
|
55876
56134
|
// src/deploy/scan-task.ts
|
|
55877
|
-
var
|
|
56135
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
55878
56136
|
var BUTLER_PERSONA_ID = "persona-clawd-butler";
|
|
55879
56137
|
var SCANNABLE_ASSETS = [
|
|
55880
56138
|
{
|
|
55881
56139
|
name: "deploy-kit",
|
|
55882
|
-
path: (dataDir) =>
|
|
56140
|
+
path: (dataDir) => import_node_path35.default.join(dataDir, "deploy-kit"),
|
|
55883
56141
|
what: "FC \u90E8\u7F72\u80FD\u529B\uFF08publish.sh / new-extension.sh / \u5DE5\u5177\u94FE / \u51ED\u8BC1\u76EE\u5F55\uFF09\u3002persona \u7528\u7EDD\u5BF9\u8DEF\u5F84\u53BB\u8C03\u8FD9\u91CC\u7684\u811A\u672C\u65F6\uFF0C\u5C31\u8BE5\u62A5\u4E00\u6761 asset\u3002"
|
|
55884
56142
|
},
|
|
55885
56143
|
{
|
|
@@ -56042,7 +56300,7 @@ function buildDeployHandlers(deps) {
|
|
|
56042
56300
|
const startedAt = deps.now();
|
|
56043
56301
|
const base = {
|
|
56044
56302
|
evidence: scanBase.kind === "hard" ? [] : current?.evidence ?? [],
|
|
56045
|
-
// notes
|
|
56303
|
+
// notes 反过来不沿用:它是「这次扫描要老板处理的事」,沿用会把上次的事项一直复读
|
|
56046
56304
|
notes: [],
|
|
56047
56305
|
scannedAssets: [],
|
|
56048
56306
|
startedAt,
|
|
@@ -56059,13 +56317,27 @@ function buildDeployHandlers(deps) {
|
|
|
56059
56317
|
};
|
|
56060
56318
|
await writeScan(dir, { status: "scanning", ...base });
|
|
56061
56319
|
if (scanBase.kind === "hard") await writeDeployFile(dir, emptyDeployFile());
|
|
56320
|
+
const mcp = scanMcpConnectors(dir);
|
|
56321
|
+
const current0 = await readDeployFile(dir) ?? emptyDeployFile();
|
|
56322
|
+
const carried = scanBase.kind === "hard" ? (prevManifest?.manifest.connectors ?? []).filter((c) => c.runner === "mcp") : current0.manifest.connectors;
|
|
56323
|
+
await writeDeployFile(dir, {
|
|
56324
|
+
...current0,
|
|
56325
|
+
// 文件读不出来(坏 JSON)时保持原样:当成「零个 MCP」会把清单里的连接器清光,而发布闸对零连接器是放行的
|
|
56326
|
+
manifest: { ...current0.manifest, connectors: mcp.readable ? mergeScannedConnectors(carried, mcp.connectors) : carried }
|
|
56327
|
+
});
|
|
56328
|
+
const mcpTargets = new Set(mcp.evidence.map((e) => e.target));
|
|
56329
|
+
const withMcp = {
|
|
56330
|
+
...base,
|
|
56331
|
+
evidence: [...base.evidence.filter((e) => !mcpTargets.has(e.target)), ...mcp.evidence.map(redactEvidence)],
|
|
56332
|
+
notes: mcp.warnings.map((w2) => `${MCP_SCAN_NOTE_PREFIX}${w2}`)
|
|
56333
|
+
};
|
|
56062
56334
|
const started = deps.startScan(personaId2, scanBase);
|
|
56063
56335
|
if ("sessionId" in started) {
|
|
56064
|
-
await writeScan(dir, { status: "scanning", scanSessionId: started.sessionId, ...
|
|
56336
|
+
await writeScan(dir, { status: "scanning", scanSessionId: started.sessionId, ...withMcp });
|
|
56065
56337
|
} else {
|
|
56066
56338
|
await writeScan(dir, {
|
|
56067
56339
|
status: "failed",
|
|
56068
|
-
...
|
|
56340
|
+
...withMcp,
|
|
56069
56341
|
finishedAt: deps.now(),
|
|
56070
56342
|
error: `\u8D77\u626B\u63CF\u4F1A\u8BDD\u5931\u8D25\uFF1A${started.error}`
|
|
56071
56343
|
});
|
|
@@ -56095,7 +56367,7 @@ function buildDeployHandlers(deps) {
|
|
|
56095
56367
|
const args = parseArgs2(DeployPutSecretArgsSchema, frame, "deploy:putSecret");
|
|
56096
56368
|
const dir = mustPersona(args.personaId);
|
|
56097
56369
|
const file = await readDeployFile(dir);
|
|
56098
|
-
const declared = file
|
|
56370
|
+
const declared = file ? [...file.manifest.secrets, ...sharedConnectorSecrets(file.manifest)].find((s) => s.name === args.name) : void 0;
|
|
56099
56371
|
if (!declared) throw invalid(`\u6E05\u5355\u91CC\u6CA1\u6709\u53EB\u300C${args.name}\u300D\u7684\u51ED\u636E`);
|
|
56100
56372
|
const allowed = new Set(declared.env);
|
|
56101
56373
|
for (const key of Object.keys(args.values)) {
|
|
@@ -56122,6 +56394,7 @@ function buildDeployHandlers(deps) {
|
|
|
56122
56394
|
} catch (err) {
|
|
56123
56395
|
throw invalid(err instanceof Error ? err.message : String(err));
|
|
56124
56396
|
}
|
|
56397
|
+
if (args.kind === "connector") item = cliConnectorFromFinding(item);
|
|
56125
56398
|
const file = await readDeployFile(dir) ?? emptyDeployFile();
|
|
56126
56399
|
await writeDeployFile(dir, upsertFinding(file, args.kind, item));
|
|
56127
56400
|
const target = `${args.kind}:${item.name}`;
|
|
@@ -56140,8 +56413,9 @@ function buildDeployHandlers(deps) {
|
|
|
56140
56413
|
...scan,
|
|
56141
56414
|
status: "done",
|
|
56142
56415
|
finishedAt: deps.now(),
|
|
56143
|
-
// 存疑项也是 agent
|
|
56144
|
-
|
|
56416
|
+
// 存疑项也是 agent 的自由文本,跟证据同一道涂抹。daemon 自己扫 .mcp.json 时发现的问题
|
|
56417
|
+
//(带 MCP_SCAN_NOTE_PREFIX)留着——butler 不知道那些,它的那份不该把它们冲掉
|
|
56418
|
+
notes: [...scan.notes.filter((n) => n.startsWith(MCP_SCAN_NOTE_PREFIX)), ...args.notes.map(redactSecretValues)],
|
|
56145
56419
|
// 记下这次扫描**被告知有哪些共享资产**。以后资产表长出新条目时,只有扫的时候还不知道
|
|
56146
56420
|
// 它的那些记录会被提示一次(见 staleScannerAssets)
|
|
56147
56421
|
scannedAssets: SCANNABLE_ASSETS.map((a) => a.name),
|
|
@@ -56175,6 +56449,7 @@ function buildDeployHandlers(deps) {
|
|
|
56175
56449
|
}
|
|
56176
56450
|
const missing = requiredEnvNames(file).filter((e) => !present.has(e));
|
|
56177
56451
|
if (missing.length > 0) blockers.push(`${missing.join(" / ")} \u8FD8\u6CA1\u586B`);
|
|
56452
|
+
for (const c of file.manifest.connectors) blockers.push(...connectorBlockers(c));
|
|
56178
56453
|
const engine = deps.personaEngine(personaId2);
|
|
56179
56454
|
const wrongTool = wrongEngine(engine?.tool);
|
|
56180
56455
|
if (wrongTool) {
|
|
@@ -56612,15 +56887,15 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
56612
56887
|
}
|
|
56613
56888
|
|
|
56614
56889
|
// src/lark-bot-connector/binding-store.ts
|
|
56615
|
-
var
|
|
56616
|
-
var
|
|
56890
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
56891
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
56617
56892
|
function createLarkBotBindingStore(personaRoot) {
|
|
56618
|
-
const filePath = (personaId2) =>
|
|
56893
|
+
const filePath = (personaId2) => import_node_path36.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
56619
56894
|
const read = (personaId2) => {
|
|
56620
56895
|
const file = filePath(personaId2);
|
|
56621
|
-
if (!
|
|
56896
|
+
if (!import_node_fs30.default.existsSync(file)) return null;
|
|
56622
56897
|
try {
|
|
56623
|
-
const raw = JSON.parse(
|
|
56898
|
+
const raw = JSON.parse(import_node_fs30.default.readFileSync(file, "utf8"));
|
|
56624
56899
|
if (typeof raw?.appId !== "string" || raw.appId.length === 0) return null;
|
|
56625
56900
|
return raw;
|
|
56626
56901
|
} catch {
|
|
@@ -56629,16 +56904,16 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
56629
56904
|
};
|
|
56630
56905
|
const write = (personaId2, meta) => {
|
|
56631
56906
|
const file = filePath(personaId2);
|
|
56632
|
-
|
|
56907
|
+
import_node_fs30.default.mkdirSync(import_node_path36.default.dirname(file), { recursive: true });
|
|
56633
56908
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
56634
|
-
|
|
56635
|
-
|
|
56909
|
+
import_node_fs30.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
56910
|
+
import_node_fs30.default.renameSync(tmp, file);
|
|
56636
56911
|
};
|
|
56637
56912
|
return {
|
|
56638
56913
|
read,
|
|
56639
56914
|
write,
|
|
56640
56915
|
remove(personaId2) {
|
|
56641
|
-
|
|
56916
|
+
import_node_fs30.default.rmSync(filePath(personaId2), { force: true });
|
|
56642
56917
|
},
|
|
56643
56918
|
addRemovedChat(personaId2, chatId) {
|
|
56644
56919
|
const meta = read(personaId2);
|
|
@@ -56796,8 +57071,8 @@ function createLarkBotCloudClient(opts) {
|
|
|
56796
57071
|
}
|
|
56797
57072
|
|
|
56798
57073
|
// src/lark-bot-connector/chat-router.ts
|
|
56799
|
-
var
|
|
56800
|
-
var
|
|
57074
|
+
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
57075
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56801
57076
|
init_protocol();
|
|
56802
57077
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
56803
57078
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -56875,9 +57150,9 @@ function createLarkChatRouter(deps) {
|
|
|
56875
57150
|
continue;
|
|
56876
57151
|
}
|
|
56877
57152
|
const dir = deps.mediaRootFor(env.chatId);
|
|
56878
|
-
|
|
56879
|
-
const p2 =
|
|
56880
|
-
|
|
57153
|
+
import_node_fs31.default.mkdirSync(dir, { recursive: true });
|
|
57154
|
+
const p2 = import_node_path37.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
|
|
57155
|
+
import_node_fs31.default.writeFileSync(p2, r.data);
|
|
56881
57156
|
lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
56882
57157
|
} catch (err) {
|
|
56883
57158
|
deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
|
|
@@ -56898,9 +57173,9 @@ function createLarkChatRouter(deps) {
|
|
|
56898
57173
|
continue;
|
|
56899
57174
|
}
|
|
56900
57175
|
const dir = deps.mediaRootFor(env.chatId);
|
|
56901
|
-
|
|
56902
|
-
const p2 =
|
|
56903
|
-
|
|
57176
|
+
import_node_fs31.default.mkdirSync(dir, { recursive: true });
|
|
57177
|
+
const p2 = import_node_path37.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
57178
|
+
import_node_fs31.default.writeFileSync(p2, r.data);
|
|
56904
57179
|
lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
56905
57180
|
} catch (err) {
|
|
56906
57181
|
deps.logger?.warn(`larkBot file fetch failed ${f.key}: ${err.message}`);
|
|
@@ -57724,12 +57999,12 @@ async function forwardPeerExecToPeer(args) {
|
|
|
57724
57999
|
}
|
|
57725
58000
|
|
|
57726
58001
|
// src/tools/codex-history.ts
|
|
57727
|
-
var
|
|
57728
|
-
var
|
|
58002
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
58003
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
57729
58004
|
|
|
57730
58005
|
// src/tools/transcript-search.ts
|
|
57731
|
-
var
|
|
57732
|
-
var
|
|
58006
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
58007
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
57733
58008
|
var SNIPPET_PAD = 60;
|
|
57734
58009
|
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/;
|
|
57735
58010
|
var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
|
|
@@ -57784,7 +58059,7 @@ function makeSnippet(text, at2, needleLength) {
|
|
|
57784
58059
|
function searchTranscriptFile(file, query) {
|
|
57785
58060
|
let buf;
|
|
57786
58061
|
try {
|
|
57787
|
-
buf =
|
|
58062
|
+
buf = import_node_fs32.default.readFileSync(file);
|
|
57788
58063
|
} catch {
|
|
57789
58064
|
return null;
|
|
57790
58065
|
}
|
|
@@ -57817,12 +58092,12 @@ function createCodexRolloutLocator(roots) {
|
|
|
57817
58092
|
const walk2 = (dir, into) => {
|
|
57818
58093
|
let entries;
|
|
57819
58094
|
try {
|
|
57820
|
-
entries =
|
|
58095
|
+
entries = import_node_fs32.default.readdirSync(dir, { withFileTypes: true });
|
|
57821
58096
|
} catch {
|
|
57822
58097
|
return;
|
|
57823
58098
|
}
|
|
57824
58099
|
for (const entry of entries) {
|
|
57825
|
-
const full =
|
|
58100
|
+
const full = import_node_path38.default.join(dir, entry.name);
|
|
57826
58101
|
if (entry.isDirectory()) {
|
|
57827
58102
|
walk2(full, into);
|
|
57828
58103
|
continue;
|
|
@@ -58044,18 +58319,18 @@ var TITLE_BYTES = 256 * 1024;
|
|
|
58044
58319
|
function readHead(file, bytes) {
|
|
58045
58320
|
let fd;
|
|
58046
58321
|
try {
|
|
58047
|
-
fd =
|
|
58322
|
+
fd = import_node_fs33.default.openSync(file, "r");
|
|
58048
58323
|
} catch {
|
|
58049
58324
|
return null;
|
|
58050
58325
|
}
|
|
58051
58326
|
try {
|
|
58052
58327
|
const buf = Buffer.alloc(bytes);
|
|
58053
|
-
const n =
|
|
58328
|
+
const n = import_node_fs33.default.readSync(fd, buf, 0, bytes, 0);
|
|
58054
58329
|
return buf.subarray(0, n).toString("utf8");
|
|
58055
58330
|
} catch {
|
|
58056
58331
|
return null;
|
|
58057
58332
|
} finally {
|
|
58058
|
-
|
|
58333
|
+
import_node_fs33.default.closeSync(fd);
|
|
58059
58334
|
}
|
|
58060
58335
|
}
|
|
58061
58336
|
function peekSessionCwd(head) {
|
|
@@ -58071,7 +58346,7 @@ function peekSessionCwd(head) {
|
|
|
58071
58346
|
function readFirstLine(file, max = 512 * 1024) {
|
|
58072
58347
|
let fd;
|
|
58073
58348
|
try {
|
|
58074
|
-
fd =
|
|
58349
|
+
fd = import_node_fs33.default.openSync(file, "r");
|
|
58075
58350
|
} catch {
|
|
58076
58351
|
return null;
|
|
58077
58352
|
}
|
|
@@ -58080,7 +58355,7 @@ function readFirstLine(file, max = 512 * 1024) {
|
|
|
58080
58355
|
const parts = [];
|
|
58081
58356
|
let total = 0;
|
|
58082
58357
|
while (total < max) {
|
|
58083
|
-
const n =
|
|
58358
|
+
const n = import_node_fs33.default.readSync(fd, chunk, 0, chunk.length, total);
|
|
58084
58359
|
if (n <= 0) break;
|
|
58085
58360
|
const nl = chunk.subarray(0, n).indexOf(10);
|
|
58086
58361
|
if (nl >= 0) {
|
|
@@ -58094,7 +58369,7 @@ function readFirstLine(file, max = 512 * 1024) {
|
|
|
58094
58369
|
} catch {
|
|
58095
58370
|
return null;
|
|
58096
58371
|
} finally {
|
|
58097
|
-
|
|
58372
|
+
import_node_fs33.default.closeSync(fd);
|
|
58098
58373
|
}
|
|
58099
58374
|
}
|
|
58100
58375
|
function readThreadNames(sharedHome) {
|
|
@@ -58102,7 +58377,7 @@ function readThreadNames(sharedHome) {
|
|
|
58102
58377
|
if (!sharedHome) return names;
|
|
58103
58378
|
let raw;
|
|
58104
58379
|
try {
|
|
58105
|
-
raw =
|
|
58380
|
+
raw = import_node_fs33.default.readFileSync(import_node_path39.default.join(sharedHome, "session_index.jsonl"), "utf8");
|
|
58106
58381
|
} catch {
|
|
58107
58382
|
return names;
|
|
58108
58383
|
}
|
|
@@ -58121,13 +58396,13 @@ function readThreadNames(sharedHome) {
|
|
|
58121
58396
|
function walkRollouts(dir, visit) {
|
|
58122
58397
|
let entries;
|
|
58123
58398
|
try {
|
|
58124
|
-
entries =
|
|
58399
|
+
entries = import_node_fs33.default.readdirSync(dir, { withFileTypes: true });
|
|
58125
58400
|
} catch {
|
|
58126
58401
|
return true;
|
|
58127
58402
|
}
|
|
58128
58403
|
entries.sort((a, b2) => a.name < b2.name ? 1 : a.name > b2.name ? -1 : 0);
|
|
58129
58404
|
for (const entry of entries) {
|
|
58130
|
-
const full =
|
|
58405
|
+
const full = import_node_path39.default.join(dir, entry.name);
|
|
58131
58406
|
if (entry.isDirectory()) {
|
|
58132
58407
|
if (!walkRollouts(full, visit)) return false;
|
|
58133
58408
|
} else if (ROLLOUT_NAME_RE.test(entry.name)) {
|
|
@@ -58195,7 +58470,7 @@ var CodexHistoryReader = class {
|
|
|
58195
58470
|
return [];
|
|
58196
58471
|
}
|
|
58197
58472
|
async listSessions(args) {
|
|
58198
|
-
const want =
|
|
58473
|
+
const want = import_node_path39.default.resolve(args.projectPath);
|
|
58199
58474
|
const names = readThreadNames(this.deps.sharedHome);
|
|
58200
58475
|
const found = [];
|
|
58201
58476
|
let scanned = 0;
|
|
@@ -58204,13 +58479,13 @@ var CodexHistoryReader = class {
|
|
|
58204
58479
|
if (++scanned > CODEX_LIST_SESSIONS_SCAN_CAP) return false;
|
|
58205
58480
|
const head = readHead(file, PEEK_BYTES);
|
|
58206
58481
|
const cwd = head === null ? null : peekSessionCwd(head);
|
|
58207
|
-
if (!cwd ||
|
|
58482
|
+
if (!cwd || import_node_path39.default.resolve(cwd) !== want) return;
|
|
58208
58483
|
const first = readFirstLine(file);
|
|
58209
58484
|
const meta = first === null ? null : parseCodexRolloutMeta(first);
|
|
58210
58485
|
if (!meta) return;
|
|
58211
58486
|
let mtimeMs;
|
|
58212
58487
|
try {
|
|
58213
|
-
mtimeMs =
|
|
58488
|
+
mtimeMs = import_node_fs33.default.statSync(file).mtimeMs;
|
|
58214
58489
|
} catch {
|
|
58215
58490
|
return;
|
|
58216
58491
|
}
|
|
@@ -58242,7 +58517,7 @@ var CodexHistoryReader = class {
|
|
|
58242
58517
|
args.toolSessionId,
|
|
58243
58518
|
async (agentId) => {
|
|
58244
58519
|
const file = locate(agentId);
|
|
58245
|
-
return file ?
|
|
58520
|
+
return file ? import_node_fs33.default.readFileSync(file, "utf8") : null;
|
|
58246
58521
|
},
|
|
58247
58522
|
this.deps.logger
|
|
58248
58523
|
);
|
|
@@ -58269,7 +58544,7 @@ var CodexHistoryReader = class {
|
|
|
58269
58544
|
parseThread(locate, threadId) {
|
|
58270
58545
|
const file = locate(threadId);
|
|
58271
58546
|
if (!file) throw new Error(`Codex rollout not found for thread ${threadId}`);
|
|
58272
|
-
return parseCodexRollout(
|
|
58547
|
+
return parseCodexRollout(import_node_fs33.default.readFileSync(file, "utf8"));
|
|
58273
58548
|
}
|
|
58274
58549
|
};
|
|
58275
58550
|
|
|
@@ -58288,9 +58563,9 @@ var CentralClientError = class extends Error {
|
|
|
58288
58563
|
code;
|
|
58289
58564
|
cause;
|
|
58290
58565
|
};
|
|
58291
|
-
async function centralRequest(opts,
|
|
58566
|
+
async function centralRequest(opts, path101, init) {
|
|
58292
58567
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
58293
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
58568
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path101}`;
|
|
58294
58569
|
const ctrl = new AbortController();
|
|
58295
58570
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
58296
58571
|
let res;
|
|
@@ -58313,7 +58588,13 @@ async function centralRequest(opts, path100, init) {
|
|
|
58313
58588
|
throw new CentralClientError("UNAUTHORIZED", "TTC JWT invalid or expired");
|
|
58314
58589
|
}
|
|
58315
58590
|
if (!res.ok) {
|
|
58316
|
-
|
|
58591
|
+
let detail = "";
|
|
58592
|
+
try {
|
|
58593
|
+
const body = await res.json();
|
|
58594
|
+
if (typeof body?.message === "string" && body.message) detail = `: ${body.message}`;
|
|
58595
|
+
} catch {
|
|
58596
|
+
}
|
|
58597
|
+
throw new CentralClientError("API_ERROR", `central server HTTP ${res.status}${detail}`);
|
|
58317
58598
|
}
|
|
58318
58599
|
try {
|
|
58319
58600
|
return await res.json();
|
|
@@ -58425,6 +58706,23 @@ async function centralListDevices(opts) {
|
|
|
58425
58706
|
}
|
|
58426
58707
|
return out;
|
|
58427
58708
|
}
|
|
58709
|
+
async function centralConnectorsMine(opts) {
|
|
58710
|
+
const body = await centralRequest(opts, "/api/persona-cloud/connectors/mine", {
|
|
58711
|
+
method: "POST",
|
|
58712
|
+
bearer: opts.ttcJwt,
|
|
58713
|
+
body: { provider: opts.provider, personaId: opts.personaId, connectors: opts.connectors }
|
|
58714
|
+
});
|
|
58715
|
+
if (!Array.isArray(body.connectors)) throw new CentralClientError("BAD_RESPONSE", "connectors/mine: missing connectors array");
|
|
58716
|
+
return { connectors: body.connectors };
|
|
58717
|
+
}
|
|
58718
|
+
async function centralConnectorFill(opts) {
|
|
58719
|
+
const body = await centralRequest(opts, "/api/persona-cloud/connectors/fields", {
|
|
58720
|
+
method: "PUT",
|
|
58721
|
+
bearer: opts.ttcJwt,
|
|
58722
|
+
body: { provider: opts.provider, connector: opts.connector, values: opts.values }
|
|
58723
|
+
});
|
|
58724
|
+
if (body.ok !== true) throw new CentralClientError("BAD_RESPONSE", "connectors/fields: server did not ack ok");
|
|
58725
|
+
}
|
|
58428
58726
|
|
|
58429
58727
|
// src/cloud/gateway-client.ts
|
|
58430
58728
|
var GATEWAY_ROUTES = {
|
|
@@ -58483,11 +58781,18 @@ var CloudGatewayClient = class {
|
|
|
58483
58781
|
...typeof d.image === "string" ? { image: d.image } : {},
|
|
58484
58782
|
...typeof d.model === "string" && d.model ? { model: d.model } : {},
|
|
58485
58783
|
...typeof d.effort === "string" && d.effort ? { effort: d.effort } : {},
|
|
58486
|
-
...typeof d.registeredAt === "number" ? { registeredAt: d.registeredAt } : {}
|
|
58784
|
+
...typeof d.registeredAt === "number" ? { registeredAt: d.registeredAt } : {},
|
|
58785
|
+
// 形状不对的条目丢掉不抛:老 gateway 的登记行是名字数组,那种就是「没有连接器」
|
|
58786
|
+
...Array.isArray(d.connectors) ? { connectors: d.connectors.map((c) => EnvConnectorSchema.safeParse(c)).flatMap((p2) => p2.success ? [p2.data] : []) } : {}
|
|
58487
58787
|
});
|
|
58488
58788
|
}
|
|
58489
58789
|
return out;
|
|
58490
58790
|
}
|
|
58791
|
+
/** gateway 登记行上这个 persona(gateway 名)装了哪些连接器;没这行 = 空 */
|
|
58792
|
+
async personaConnectors(gatewayPersonaId) {
|
|
58793
|
+
const list = await this.listPersonas();
|
|
58794
|
+
return list.find((p2) => p2.personaId === gatewayPersonaId)?.connectors ?? [];
|
|
58795
|
+
}
|
|
58491
58796
|
/**
|
|
58492
58797
|
* 会话通道。返回的行流在 Pod 就绪前就能 write:写入先攒着,收到 `ready` 控制行后按序 POST 出去——
|
|
58493
58798
|
* 编排那头一构造就发 initialize,不用知道 Pod 还在起。
|
|
@@ -58682,7 +58987,7 @@ function openHttpLineStream(opts) {
|
|
|
58682
58987
|
init_protocol();
|
|
58683
58988
|
|
|
58684
58989
|
// src/tools/codex-cloud-session.ts
|
|
58685
|
-
var
|
|
58990
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
58686
58991
|
|
|
58687
58992
|
// src/tools/codex-cloud-history.ts
|
|
58688
58993
|
function personaIdFromCloudCwd(cwd) {
|
|
@@ -58806,7 +59111,7 @@ function cloudImageInput(deps) {
|
|
|
58806
59111
|
const mime = lookupMime(p2);
|
|
58807
59112
|
if (!mime.startsWith("image/")) return null;
|
|
58808
59113
|
try {
|
|
58809
|
-
const bytes = (deps.readFile ??
|
|
59114
|
+
const bytes = (deps.readFile ?? import_node_fs34.default.readFileSync)(p2);
|
|
58810
59115
|
return { type: "image", url: `data:${mime};base64,${bytes.toString("base64")}` };
|
|
58811
59116
|
} catch (e) {
|
|
58812
59117
|
deps.logger?.warn("cloud image attachment unreadable", { path: p2, message: e.message });
|
|
@@ -58919,7 +59224,7 @@ var CloudCodexAdapter = class {
|
|
|
58919
59224
|
|
|
58920
59225
|
// src/tools/pi.ts
|
|
58921
59226
|
var import_node_child_process10 = require("child_process");
|
|
58922
|
-
var
|
|
59227
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
58923
59228
|
init_protocol();
|
|
58924
59229
|
|
|
58925
59230
|
// src/tools/pi-rpc-client.ts
|
|
@@ -58998,8 +59303,8 @@ var PiRpcClient = class {
|
|
|
58998
59303
|
// src/tools/pi-session.ts
|
|
58999
59304
|
var import_node_child_process9 = require("child_process");
|
|
59000
59305
|
var import_node_crypto9 = require("crypto");
|
|
59001
|
-
var
|
|
59002
|
-
var
|
|
59306
|
+
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
59307
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
59003
59308
|
|
|
59004
59309
|
// src/tools/pi-events.ts
|
|
59005
59310
|
init_protocol();
|
|
@@ -59176,8 +59481,8 @@ ${dirs.map((d) => `- ${d}`).join("\n")}`;
|
|
|
59176
59481
|
function createPiSession(ctx, sink, deps = {}) {
|
|
59177
59482
|
const cmd = process.env.PI_BIN ?? "pi";
|
|
59178
59483
|
const sessionId = ctx.toolSessionId ?? (0, import_node_crypto9.randomUUID)();
|
|
59179
|
-
const skillsDir =
|
|
59180
|
-
const exists = deps.skillsDirExists ?? ((d) =>
|
|
59484
|
+
const skillsDir = import_node_path40.default.join(ctx.cwd, ".claude", "skills");
|
|
59485
|
+
const exists = deps.skillsDirExists ?? ((d) => import_node_fs35.default.existsSync(d));
|
|
59181
59486
|
const args = buildPiArgs(ctx, {
|
|
59182
59487
|
sessionId,
|
|
59183
59488
|
skillsDir: exists(skillsDir) ? skillsDir : void 0,
|
|
@@ -59293,45 +59598,45 @@ function createPiSession(ctx, sink, deps = {}) {
|
|
|
59293
59598
|
}
|
|
59294
59599
|
|
|
59295
59600
|
// src/tools/pi-history.ts
|
|
59296
|
-
var
|
|
59601
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
59297
59602
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
59298
|
-
var
|
|
59603
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
59299
59604
|
var PI_LIST_SESSIONS_LIMIT = 100;
|
|
59300
59605
|
var PI_LIST_SESSIONS_SCAN_CAP = 4e3;
|
|
59301
59606
|
function piAgentDir(env = process.env) {
|
|
59302
|
-
return env.PI_CODING_AGENT_DIR ||
|
|
59607
|
+
return env.PI_CODING_AGENT_DIR || import_node_path41.default.join(import_node_os10.default.homedir(), ".pi", "agent");
|
|
59303
59608
|
}
|
|
59304
59609
|
function piSessionsRoot(env = process.env) {
|
|
59305
|
-
return
|
|
59610
|
+
return import_node_path41.default.join(piAgentDir(env), "sessions");
|
|
59306
59611
|
}
|
|
59307
59612
|
function encodePiCwd(cwd) {
|
|
59308
59613
|
return `--${cwd.replace(/^[\\/]+/, "").replace(/[\\/:]/g, "-")}--`;
|
|
59309
59614
|
}
|
|
59310
59615
|
function piProjectSessionDir(sessionsRoot, cwd) {
|
|
59311
|
-
return
|
|
59616
|
+
return import_node_path41.default.join(sessionsRoot, encodePiCwd(cwd));
|
|
59312
59617
|
}
|
|
59313
59618
|
function findInDir(dir, toolSessionId) {
|
|
59314
59619
|
let names;
|
|
59315
59620
|
try {
|
|
59316
|
-
names =
|
|
59621
|
+
names = import_node_fs36.default.readdirSync(dir);
|
|
59317
59622
|
} catch {
|
|
59318
59623
|
return null;
|
|
59319
59624
|
}
|
|
59320
59625
|
const suffix = `_${toolSessionId}.jsonl`;
|
|
59321
59626
|
const hit = names.filter((n) => n.endsWith(suffix)).sort().at(-1);
|
|
59322
|
-
return hit ?
|
|
59627
|
+
return hit ? import_node_path41.default.join(dir, hit) : null;
|
|
59323
59628
|
}
|
|
59324
59629
|
function locatePiSessionFile(sessionsRoot, cwd, toolSessionId) {
|
|
59325
59630
|
const direct = findInDir(piProjectSessionDir(sessionsRoot, cwd), toolSessionId);
|
|
59326
59631
|
if (direct) return direct;
|
|
59327
59632
|
let dirs;
|
|
59328
59633
|
try {
|
|
59329
|
-
dirs =
|
|
59634
|
+
dirs = import_node_fs36.default.readdirSync(sessionsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
59330
59635
|
} catch {
|
|
59331
59636
|
return null;
|
|
59332
59637
|
}
|
|
59333
59638
|
for (const d of dirs) {
|
|
59334
|
-
const hit = findInDir(
|
|
59639
|
+
const hit = findInDir(import_node_path41.default.join(sessionsRoot, d), toolSessionId);
|
|
59335
59640
|
if (hit) return hit;
|
|
59336
59641
|
}
|
|
59337
59642
|
return null;
|
|
@@ -59430,11 +59735,11 @@ var PiHistoryReader = class {
|
|
|
59430
59735
|
return [];
|
|
59431
59736
|
}
|
|
59432
59737
|
async listSessions(args) {
|
|
59433
|
-
const want =
|
|
59738
|
+
const want = import_node_path41.default.resolve(args.projectPath);
|
|
59434
59739
|
const dir = piProjectSessionDir(this.deps.sessionsRoot, want);
|
|
59435
59740
|
let names;
|
|
59436
59741
|
try {
|
|
59437
|
-
names =
|
|
59742
|
+
names = import_node_fs36.default.readdirSync(dir).filter((n) => n.endsWith(".jsonl"));
|
|
59438
59743
|
} catch {
|
|
59439
59744
|
return [];
|
|
59440
59745
|
}
|
|
@@ -59442,15 +59747,15 @@ var PiHistoryReader = class {
|
|
|
59442
59747
|
let scanned = 0;
|
|
59443
59748
|
for (const n of names) {
|
|
59444
59749
|
if (++scanned > PI_LIST_SESSIONS_SCAN_CAP) break;
|
|
59445
|
-
const file =
|
|
59750
|
+
const file = import_node_path41.default.join(dir, n);
|
|
59446
59751
|
const head = parseLine2(readFirstLine(file) ?? "");
|
|
59447
59752
|
if (!head || head.type !== "session") continue;
|
|
59448
59753
|
const cwd = str3(head.cwd);
|
|
59449
59754
|
const id = str3(head.id);
|
|
59450
|
-
if (!cwd || !id ||
|
|
59755
|
+
if (!cwd || !id || import_node_path41.default.resolve(cwd) !== want) continue;
|
|
59451
59756
|
let mtimeMs;
|
|
59452
59757
|
try {
|
|
59453
|
-
mtimeMs =
|
|
59758
|
+
mtimeMs = import_node_fs36.default.statSync(file).mtimeMs;
|
|
59454
59759
|
} catch {
|
|
59455
59760
|
continue;
|
|
59456
59761
|
}
|
|
@@ -59458,7 +59763,7 @@ var PiHistoryReader = class {
|
|
|
59458
59763
|
}
|
|
59459
59764
|
found.sort((a, b2) => b2.mtimeMs - a.mtimeMs);
|
|
59460
59765
|
return found.slice(0, PI_LIST_SESSIONS_LIMIT).map((f) => {
|
|
59461
|
-
const parsed = parsePiSession(
|
|
59766
|
+
const parsed = parsePiSession(import_node_fs36.default.readFileSync(f.file, "utf8"));
|
|
59462
59767
|
const firstUser = parsed.messages.find((m2) => m2.kind === "user-text");
|
|
59463
59768
|
return {
|
|
59464
59769
|
toolSessionId: f.id,
|
|
@@ -59471,7 +59776,7 @@ var PiHistoryReader = class {
|
|
|
59471
59776
|
async read(args) {
|
|
59472
59777
|
const file = locatePiSessionFile(this.deps.sessionsRoot, args.cwd, args.toolSessionId);
|
|
59473
59778
|
if (!file) throw new Error(`pi session not found for ${args.toolSessionId}`);
|
|
59474
|
-
return pageMessages(parsePiSession(
|
|
59779
|
+
return pageMessages(parsePiSession(import_node_fs36.default.readFileSync(file, "utf8")).messages, args);
|
|
59475
59780
|
}
|
|
59476
59781
|
async listSubagents(_args) {
|
|
59477
59782
|
return [];
|
|
@@ -59506,10 +59811,10 @@ var PI_DEFAULT_MODEL_ENTRY = {
|
|
|
59506
59811
|
};
|
|
59507
59812
|
var PI_FULL_ACCESS = { id: "never", label: "Full Access", description: "pi \u65E0\u5BA1\u6279\uFF1A\u4ECE\u4E0D\u8BE2\u95EE\uFF0C\u81EA\u4E3B\u6267\u884C" };
|
|
59508
59813
|
async function probePi(env = process.env) {
|
|
59509
|
-
if (env.PI_BIN &&
|
|
59814
|
+
if (env.PI_BIN && import_node_fs37.default.existsSync(env.PI_BIN)) return { available: true, path: env.PI_BIN };
|
|
59510
59815
|
try {
|
|
59511
59816
|
const out = (0, import_node_child_process10.execFileSync)("which", ["pi"], { encoding: "utf8" }).trim();
|
|
59512
|
-
if (out &&
|
|
59817
|
+
if (out && import_node_fs37.default.existsSync(out)) return { available: true, path: out };
|
|
59513
59818
|
} catch {
|
|
59514
59819
|
}
|
|
59515
59820
|
return { available: false };
|
|
@@ -59676,7 +59981,7 @@ var PiAdapter = class {
|
|
|
59676
59981
|
init_protocol();
|
|
59677
59982
|
|
|
59678
59983
|
// src/tools/codex-skills.ts
|
|
59679
|
-
var
|
|
59984
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
59680
59985
|
function str4(v2) {
|
|
59681
59986
|
return typeof v2 === "string" ? v2 : void 0;
|
|
59682
59987
|
}
|
|
@@ -59691,13 +59996,13 @@ function mapSkillsListResponse(res) {
|
|
|
59691
59996
|
const r = s ?? {};
|
|
59692
59997
|
const name = str4(r.name);
|
|
59693
59998
|
if (!name) continue;
|
|
59694
|
-
const
|
|
59999
|
+
const path101 = str4(r.path);
|
|
59695
60000
|
const description = str4(r.description);
|
|
59696
60001
|
const isPlugin = name.includes(":");
|
|
59697
60002
|
out.push({
|
|
59698
60003
|
name,
|
|
59699
60004
|
source: isPlugin ? "plugin" : "project",
|
|
59700
|
-
...
|
|
60005
|
+
...path101 ? { path: path101 } : {},
|
|
59701
60006
|
...description ? { description } : {},
|
|
59702
60007
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
59703
60008
|
});
|
|
@@ -59713,7 +60018,7 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
59713
60018
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
59714
60019
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
59715
60020
|
beforeRequest: (client) => {
|
|
59716
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
60021
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path42.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
59717
60022
|
}
|
|
59718
60023
|
});
|
|
59719
60024
|
return mapSkillsListResponse(res);
|
|
@@ -59787,23 +60092,23 @@ function rec4(v2) {
|
|
|
59787
60092
|
}
|
|
59788
60093
|
|
|
59789
60094
|
// src/workspace/browser.ts
|
|
59790
|
-
var
|
|
60095
|
+
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
59791
60096
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
59792
|
-
var
|
|
60097
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
59793
60098
|
init_protocol();
|
|
59794
60099
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
59795
60100
|
function resolveInsideCwd(cwd, subpath) {
|
|
59796
|
-
const absCwd =
|
|
59797
|
-
const joined =
|
|
59798
|
-
const rel =
|
|
59799
|
-
if (rel.startsWith("..") ||
|
|
60101
|
+
const absCwd = import_node_path43.default.resolve(cwd);
|
|
60102
|
+
const joined = import_node_path43.default.resolve(absCwd, subpath ?? ".");
|
|
60103
|
+
const rel = import_node_path43.default.relative(absCwd, joined);
|
|
60104
|
+
if (rel.startsWith("..") || import_node_path43.default.isAbsolute(rel)) {
|
|
59800
60105
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
59801
60106
|
}
|
|
59802
60107
|
return joined;
|
|
59803
60108
|
}
|
|
59804
60109
|
function ensureCwd(cwd) {
|
|
59805
60110
|
try {
|
|
59806
|
-
const stat =
|
|
60111
|
+
const stat = import_node_fs38.default.statSync(cwd);
|
|
59807
60112
|
if (!stat.isDirectory()) {
|
|
59808
60113
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
59809
60114
|
}
|
|
@@ -59817,7 +60122,7 @@ var WorkspaceBrowser = class {
|
|
|
59817
60122
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os11.default.homedir();
|
|
59818
60123
|
ensureCwd(cwd);
|
|
59819
60124
|
const full = resolveInsideCwd(cwd, args.path);
|
|
59820
|
-
const dirents =
|
|
60125
|
+
const dirents = import_node_fs38.default.readdirSync(full, { withFileTypes: true });
|
|
59821
60126
|
const entries = [];
|
|
59822
60127
|
for (const d of dirents) {
|
|
59823
60128
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -59827,7 +60132,7 @@ var WorkspaceBrowser = class {
|
|
|
59827
60132
|
mtime: ""
|
|
59828
60133
|
};
|
|
59829
60134
|
try {
|
|
59830
|
-
const st =
|
|
60135
|
+
const st = import_node_fs38.default.statSync(import_node_path43.default.join(full, d.name));
|
|
59831
60136
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
59832
60137
|
if (d.isFile()) entry.size = st.size;
|
|
59833
60138
|
} catch {
|
|
@@ -59843,14 +60148,14 @@ var WorkspaceBrowser = class {
|
|
|
59843
60148
|
read(args) {
|
|
59844
60149
|
ensureCwd(args.cwd);
|
|
59845
60150
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
59846
|
-
const st =
|
|
60151
|
+
const st = import_node_fs38.default.statSync(full);
|
|
59847
60152
|
if (!st.isFile()) {
|
|
59848
60153
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
59849
60154
|
}
|
|
59850
60155
|
if (st.size > MAX_FILE_BYTES2) {
|
|
59851
60156
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
|
|
59852
60157
|
}
|
|
59853
|
-
const buf =
|
|
60158
|
+
const buf = import_node_fs38.default.readFileSync(full);
|
|
59854
60159
|
const isBinary = buf.includes(0);
|
|
59855
60160
|
if (isBinary) {
|
|
59856
60161
|
return {
|
|
@@ -59872,20 +60177,20 @@ var WorkspaceBrowser = class {
|
|
|
59872
60177
|
};
|
|
59873
60178
|
|
|
59874
60179
|
// src/skills/agents-scanner.ts
|
|
59875
|
-
var
|
|
60180
|
+
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
59876
60181
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
59877
|
-
var
|
|
60182
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
59878
60183
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
59879
60184
|
function isDirLikeSync2(p2) {
|
|
59880
60185
|
try {
|
|
59881
|
-
return
|
|
60186
|
+
return import_node_fs39.default.statSync(p2).isDirectory();
|
|
59882
60187
|
} catch {
|
|
59883
60188
|
return false;
|
|
59884
60189
|
}
|
|
59885
60190
|
}
|
|
59886
60191
|
function fileExistsSync(p2) {
|
|
59887
60192
|
try {
|
|
59888
|
-
return
|
|
60193
|
+
return import_node_fs39.default.statSync(p2).isFile();
|
|
59889
60194
|
} catch {
|
|
59890
60195
|
return false;
|
|
59891
60196
|
}
|
|
@@ -59893,7 +60198,7 @@ function fileExistsSync(p2) {
|
|
|
59893
60198
|
function parseAgentFile(filePath) {
|
|
59894
60199
|
let content;
|
|
59895
60200
|
try {
|
|
59896
|
-
content =
|
|
60201
|
+
content = import_node_fs39.default.readFileSync(filePath, "utf8");
|
|
59897
60202
|
} catch {
|
|
59898
60203
|
return {};
|
|
59899
60204
|
}
|
|
@@ -59906,16 +60211,16 @@ function parseAgentFile(filePath) {
|
|
|
59906
60211
|
function scanAgentsDir(dir, source, seen, out) {
|
|
59907
60212
|
let entries;
|
|
59908
60213
|
try {
|
|
59909
|
-
entries =
|
|
60214
|
+
entries = import_node_fs39.default.readdirSync(dir, { withFileTypes: true });
|
|
59910
60215
|
} catch {
|
|
59911
60216
|
return;
|
|
59912
60217
|
}
|
|
59913
60218
|
for (const ent of entries) {
|
|
59914
60219
|
if (!ent.name.endsWith(".md")) continue;
|
|
59915
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
60220
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path44.default.join(dir, ent.name)))) {
|
|
59916
60221
|
continue;
|
|
59917
60222
|
}
|
|
59918
|
-
const filePath =
|
|
60223
|
+
const filePath = import_node_path44.default.join(dir, ent.name);
|
|
59919
60224
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
59920
60225
|
if (seen.has(baseName)) continue;
|
|
59921
60226
|
seen.add(baseName);
|
|
@@ -59933,12 +60238,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
59933
60238
|
function walk2(dir, namespaces) {
|
|
59934
60239
|
let entries;
|
|
59935
60240
|
try {
|
|
59936
|
-
entries =
|
|
60241
|
+
entries = import_node_fs39.default.readdirSync(dir, { withFileTypes: true });
|
|
59937
60242
|
} catch {
|
|
59938
60243
|
return;
|
|
59939
60244
|
}
|
|
59940
60245
|
for (const ent of entries) {
|
|
59941
|
-
const childPath =
|
|
60246
|
+
const childPath = import_node_path44.default.join(dir, ent.name);
|
|
59942
60247
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
59943
60248
|
walk2(childPath, [...namespaces, ent.name]);
|
|
59944
60249
|
continue;
|
|
@@ -59963,13 +60268,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
59963
60268
|
walk2(root, []);
|
|
59964
60269
|
}
|
|
59965
60270
|
function readInstalledPlugins2(home) {
|
|
59966
|
-
const pluginsDir =
|
|
59967
|
-
const v2 =
|
|
59968
|
-
const v1 =
|
|
60271
|
+
const pluginsDir = import_node_path44.default.join(home, ".claude", "plugins");
|
|
60272
|
+
const v2 = import_node_path44.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
60273
|
+
const v1 = import_node_path44.default.join(pluginsDir, "installed_plugins.json");
|
|
59969
60274
|
let raw = null;
|
|
59970
60275
|
for (const candidate of [v2, v1]) {
|
|
59971
60276
|
try {
|
|
59972
|
-
raw =
|
|
60277
|
+
raw = import_node_fs39.default.readFileSync(candidate, "utf8");
|
|
59973
60278
|
break;
|
|
59974
60279
|
} catch {
|
|
59975
60280
|
}
|
|
@@ -59994,19 +60299,19 @@ function readInstalledPlugins2(home) {
|
|
|
59994
60299
|
return out;
|
|
59995
60300
|
}
|
|
59996
60301
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
59997
|
-
let cur =
|
|
59998
|
-
const fsRoot =
|
|
60302
|
+
let cur = import_node_path44.default.resolve(startCwd);
|
|
60303
|
+
const fsRoot = import_node_path44.default.parse(cur).root;
|
|
59999
60304
|
while (true) {
|
|
60000
|
-
scanAgentsDir(
|
|
60305
|
+
scanAgentsDir(import_node_path44.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
60001
60306
|
let hasGit = false;
|
|
60002
60307
|
try {
|
|
60003
|
-
hasGit =
|
|
60308
|
+
hasGit = import_node_fs39.default.existsSync(import_node_path44.default.join(cur, ".git"));
|
|
60004
60309
|
} catch {
|
|
60005
60310
|
}
|
|
60006
60311
|
if (hasGit) return;
|
|
60007
60312
|
if (cur === home) return;
|
|
60008
60313
|
if (cur === fsRoot) return;
|
|
60009
|
-
const parent =
|
|
60314
|
+
const parent = import_node_path44.default.dirname(cur);
|
|
60010
60315
|
if (parent === cur) return;
|
|
60011
60316
|
cur = parent;
|
|
60012
60317
|
}
|
|
@@ -60041,7 +60346,7 @@ var AgentsScanner = class {
|
|
|
60041
60346
|
}
|
|
60042
60347
|
const fsBlock = [];
|
|
60043
60348
|
scanAgentsDir(
|
|
60044
|
-
|
|
60349
|
+
import_node_path44.default.join(this.home, ".claude", "agents"),
|
|
60045
60350
|
"global",
|
|
60046
60351
|
seen,
|
|
60047
60352
|
fsBlock
|
|
@@ -60055,7 +60360,7 @@ var AgentsScanner = class {
|
|
|
60055
60360
|
...this.extraPluginRoots
|
|
60056
60361
|
];
|
|
60057
60362
|
for (const { name, root } of plugins) {
|
|
60058
|
-
const agentsRoot =
|
|
60363
|
+
const agentsRoot = import_node_path44.default.join(root, "agents");
|
|
60059
60364
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
60060
60365
|
}
|
|
60061
60366
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -60063,15 +60368,15 @@ var AgentsScanner = class {
|
|
|
60063
60368
|
};
|
|
60064
60369
|
|
|
60065
60370
|
// src/observer/session-observer.ts
|
|
60066
|
-
var
|
|
60371
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
60067
60372
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
60068
|
-
var
|
|
60373
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
60069
60374
|
init_claude_history();
|
|
60070
60375
|
|
|
60071
60376
|
// src/observer/subagent-meta-observer.ts
|
|
60072
|
-
var
|
|
60377
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
60073
60378
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
60074
|
-
var
|
|
60379
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
60075
60380
|
init_claude_history();
|
|
60076
60381
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
60077
60382
|
var SubagentMetaObserver = class {
|
|
@@ -60084,7 +60389,7 @@ var SubagentMetaObserver = class {
|
|
|
60084
60389
|
watches = /* @__PURE__ */ new Map();
|
|
60085
60390
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
60086
60391
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
60087
|
-
return
|
|
60392
|
+
return import_node_path45.default.join(
|
|
60088
60393
|
this.home,
|
|
60089
60394
|
".claude",
|
|
60090
60395
|
"projects",
|
|
@@ -60114,7 +60419,7 @@ var SubagentMetaObserver = class {
|
|
|
60114
60419
|
attachWatcher(w2) {
|
|
60115
60420
|
if (w2.watcher) return;
|
|
60116
60421
|
try {
|
|
60117
|
-
w2.watcher =
|
|
60422
|
+
w2.watcher = import_node_fs40.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
60118
60423
|
if (!name) return;
|
|
60119
60424
|
const m2 = META_RE.exec(String(name));
|
|
60120
60425
|
if (!m2) return;
|
|
@@ -60126,7 +60431,7 @@ var SubagentMetaObserver = class {
|
|
|
60126
60431
|
scan(w2) {
|
|
60127
60432
|
let entries;
|
|
60128
60433
|
try {
|
|
60129
|
-
entries =
|
|
60434
|
+
entries = import_node_fs40.default.readdirSync(w2.dirPath);
|
|
60130
60435
|
} catch {
|
|
60131
60436
|
return;
|
|
60132
60437
|
}
|
|
@@ -60140,10 +60445,10 @@ var SubagentMetaObserver = class {
|
|
|
60140
60445
|
if (!m2) return;
|
|
60141
60446
|
const agentId = m2[1];
|
|
60142
60447
|
if (w2.emitted.has(agentId)) return;
|
|
60143
|
-
const file =
|
|
60448
|
+
const file = import_node_path45.default.join(w2.dirPath, name);
|
|
60144
60449
|
let raw;
|
|
60145
60450
|
try {
|
|
60146
|
-
raw =
|
|
60451
|
+
raw = import_node_fs40.default.readFileSync(file, "utf8");
|
|
60147
60452
|
} catch {
|
|
60148
60453
|
return;
|
|
60149
60454
|
}
|
|
@@ -60200,14 +60505,14 @@ var SessionObserver = class {
|
|
|
60200
60505
|
metaObserver;
|
|
60201
60506
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
60202
60507
|
if (override) return override;
|
|
60203
|
-
return
|
|
60508
|
+
return import_node_path46.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
60204
60509
|
}
|
|
60205
60510
|
start(args) {
|
|
60206
60511
|
this.stop(args.sessionId);
|
|
60207
60512
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
60208
60513
|
let size = 0;
|
|
60209
60514
|
try {
|
|
60210
|
-
size =
|
|
60515
|
+
size = import_node_fs41.default.statSync(filePath).size;
|
|
60211
60516
|
} catch {
|
|
60212
60517
|
}
|
|
60213
60518
|
const w2 = {
|
|
@@ -60220,16 +60525,16 @@ var SessionObserver = class {
|
|
|
60220
60525
|
adapter: args.adapter,
|
|
60221
60526
|
prevIsRejectSentinel: false,
|
|
60222
60527
|
toolSessionId: args.toolSessionId,
|
|
60223
|
-
sawFile:
|
|
60528
|
+
sawFile: import_node_fs41.default.existsSync(filePath),
|
|
60224
60529
|
lastRelocateScanMs: 0,
|
|
60225
60530
|
pendingCwdDerive: false,
|
|
60226
60531
|
lastDeriveMs: 0
|
|
60227
60532
|
};
|
|
60228
60533
|
try {
|
|
60229
|
-
|
|
60534
|
+
import_node_fs41.default.mkdirSync(import_node_path46.default.dirname(filePath), { recursive: true });
|
|
60230
60535
|
} catch {
|
|
60231
60536
|
}
|
|
60232
|
-
w2.watcher =
|
|
60537
|
+
w2.watcher = import_node_fs41.default.watch(import_node_path46.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
60233
60538
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
60234
60539
|
this.poll(w2);
|
|
60235
60540
|
});
|
|
@@ -60252,7 +60557,7 @@ var SessionObserver = class {
|
|
|
60252
60557
|
// 异常静默吞,不阻塞 watcher 启动
|
|
60253
60558
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
60254
60559
|
try {
|
|
60255
|
-
const raw =
|
|
60560
|
+
const raw = import_node_fs41.default.readFileSync(w2.filePath, "utf8");
|
|
60256
60561
|
if (!raw) return;
|
|
60257
60562
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
60258
60563
|
if (allLines.length === 0) return;
|
|
@@ -60276,7 +60581,7 @@ var SessionObserver = class {
|
|
|
60276
60581
|
poll(w2) {
|
|
60277
60582
|
let size = 0;
|
|
60278
60583
|
try {
|
|
60279
|
-
size =
|
|
60584
|
+
size = import_node_fs41.default.statSync(w2.filePath).size;
|
|
60280
60585
|
} catch {
|
|
60281
60586
|
if (w2.sawFile) this.maybeRelocate(w2);
|
|
60282
60587
|
return;
|
|
@@ -60287,11 +60592,11 @@ var SessionObserver = class {
|
|
|
60287
60592
|
w2.buf = "";
|
|
60288
60593
|
}
|
|
60289
60594
|
if (size === w2.lastSize) return;
|
|
60290
|
-
const fd =
|
|
60595
|
+
const fd = import_node_fs41.default.openSync(w2.filePath, "r");
|
|
60291
60596
|
try {
|
|
60292
60597
|
const len = size - w2.lastSize;
|
|
60293
60598
|
const buf = Buffer.alloc(len);
|
|
60294
|
-
|
|
60599
|
+
import_node_fs41.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
60295
60600
|
w2.lastSize = size;
|
|
60296
60601
|
w2.buf += buf.toString("utf8");
|
|
60297
60602
|
let newlineIndex;
|
|
@@ -60314,7 +60619,7 @@ var SessionObserver = class {
|
|
|
60314
60619
|
}
|
|
60315
60620
|
}
|
|
60316
60621
|
} finally {
|
|
60317
|
-
|
|
60622
|
+
import_node_fs41.default.closeSync(fd);
|
|
60318
60623
|
}
|
|
60319
60624
|
if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
|
|
60320
60625
|
}
|
|
@@ -60326,7 +60631,7 @@ var SessionObserver = class {
|
|
|
60326
60631
|
const now = Date.now();
|
|
60327
60632
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
60328
60633
|
w2.lastRelocateScanMs = now;
|
|
60329
|
-
const projectsRoot =
|
|
60634
|
+
const projectsRoot = import_node_path46.default.join(this.home, ".claude", "projects");
|
|
60330
60635
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
60331
60636
|
if (!found || found === w2.filePath) return;
|
|
60332
60637
|
try {
|
|
@@ -60335,7 +60640,7 @@ var SessionObserver = class {
|
|
|
60335
60640
|
}
|
|
60336
60641
|
w2.filePath = found;
|
|
60337
60642
|
try {
|
|
60338
|
-
w2.watcher =
|
|
60643
|
+
w2.watcher = import_node_fs41.default.watch(import_node_path46.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
60339
60644
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
60340
60645
|
this.poll(w2);
|
|
60341
60646
|
});
|
|
@@ -60457,9 +60762,9 @@ function listRegistered() {
|
|
|
60457
60762
|
// src/tools/title-generator.ts
|
|
60458
60763
|
var import_node_child_process11 = require("child_process");
|
|
60459
60764
|
init_protocol();
|
|
60460
|
-
var
|
|
60765
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
60461
60766
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
60462
|
-
var
|
|
60767
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
60463
60768
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
60464
60769
|
var TITLE_MODEL_BY_TOOL = {
|
|
60465
60770
|
claude: "haiku",
|
|
@@ -60530,21 +60835,21 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
60530
60835
|
if (!text) return null;
|
|
60531
60836
|
let workDir;
|
|
60532
60837
|
try {
|
|
60533
|
-
workDir =
|
|
60838
|
+
workDir = import_node_fs42.default.mkdtempSync(import_node_path47.default.join(import_node_os15.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
60534
60839
|
} catch {
|
|
60535
60840
|
return null;
|
|
60536
60841
|
}
|
|
60537
60842
|
const cleanupWorkDir = () => {
|
|
60538
60843
|
try {
|
|
60539
|
-
|
|
60844
|
+
import_node_fs42.default.rmSync(workDir, { recursive: true, force: true });
|
|
60540
60845
|
} catch {
|
|
60541
60846
|
}
|
|
60542
60847
|
};
|
|
60543
|
-
const outFile =
|
|
60544
|
-
const schemaFile =
|
|
60848
|
+
const outFile = import_node_path47.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
60849
|
+
const schemaFile = import_node_path47.default.join(workDir, "title-schema.json");
|
|
60545
60850
|
if (isCodexFamily(tool)) {
|
|
60546
60851
|
try {
|
|
60547
|
-
|
|
60852
|
+
import_node_fs42.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
60548
60853
|
} catch {
|
|
60549
60854
|
cleanupWorkDir();
|
|
60550
60855
|
return null;
|
|
@@ -60594,7 +60899,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
60594
60899
|
if (tool === "claude") return finish(parseTitleJson(stdout));
|
|
60595
60900
|
let fileText = "";
|
|
60596
60901
|
try {
|
|
60597
|
-
fileText =
|
|
60902
|
+
fileText = import_node_fs42.default.readFileSync(outFile, "utf8");
|
|
60598
60903
|
} catch {
|
|
60599
60904
|
return finish(null);
|
|
60600
60905
|
}
|
|
@@ -61306,8 +61611,8 @@ async function authenticate(token, deps) {
|
|
|
61306
61611
|
}
|
|
61307
61612
|
|
|
61308
61613
|
// src/legacy-cleanup.ts
|
|
61309
|
-
var
|
|
61310
|
-
var
|
|
61614
|
+
var fs53 = __toESM(require("fs/promises"), 1);
|
|
61615
|
+
var path55 = __toESM(require("path"), 1);
|
|
61311
61616
|
var LEGACY_FILES = [
|
|
61312
61617
|
"personal-capability.json",
|
|
61313
61618
|
"received-capabilities.json",
|
|
@@ -61316,9 +61621,9 @@ var LEGACY_FILES = [
|
|
|
61316
61621
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
61317
61622
|
const removed = [];
|
|
61318
61623
|
for (const name of LEGACY_FILES) {
|
|
61319
|
-
const p2 =
|
|
61624
|
+
const p2 = path55.join(dataDir, name);
|
|
61320
61625
|
try {
|
|
61321
|
-
await
|
|
61626
|
+
await fs53.unlink(p2);
|
|
61322
61627
|
removed.push(name);
|
|
61323
61628
|
logger.debug("legacy capability file removed", { file: name });
|
|
61324
61629
|
} catch (err) {
|
|
@@ -61330,13 +61635,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
61330
61635
|
}
|
|
61331
61636
|
|
|
61332
61637
|
// src/inbox/inbox-store.ts
|
|
61333
|
-
var
|
|
61334
|
-
var
|
|
61638
|
+
var fs54 = __toESM(require("fs"), 1);
|
|
61639
|
+
var path56 = __toESM(require("path"), 1);
|
|
61335
61640
|
var INBOX_SUBDIR = "inbox";
|
|
61336
61641
|
var InboxStore = class {
|
|
61337
61642
|
constructor(dataDir) {
|
|
61338
61643
|
this.dataDir = dataDir;
|
|
61339
|
-
|
|
61644
|
+
fs54.mkdirSync(this.dirPath(), { recursive: true });
|
|
61340
61645
|
}
|
|
61341
61646
|
dataDir;
|
|
61342
61647
|
/**
|
|
@@ -61348,7 +61653,7 @@ var InboxStore = class {
|
|
|
61348
61653
|
const file = this.filePath(peerDeviceId);
|
|
61349
61654
|
let raw;
|
|
61350
61655
|
try {
|
|
61351
|
-
raw =
|
|
61656
|
+
raw = fs54.readFileSync(file, "utf8");
|
|
61352
61657
|
} catch (err) {
|
|
61353
61658
|
if (err?.code === "ENOENT") return [];
|
|
61354
61659
|
return [];
|
|
@@ -61364,7 +61669,7 @@ var InboxStore = class {
|
|
|
61364
61669
|
const dir = this.dirPath();
|
|
61365
61670
|
let entries;
|
|
61366
61671
|
try {
|
|
61367
|
-
entries =
|
|
61672
|
+
entries = fs54.readdirSync(dir);
|
|
61368
61673
|
} catch (err) {
|
|
61369
61674
|
if (err?.code === "ENOENT") return [];
|
|
61370
61675
|
return [];
|
|
@@ -61380,9 +61685,9 @@ var InboxStore = class {
|
|
|
61380
61685
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
61381
61686
|
const file = this.filePath(message.peerDeviceId);
|
|
61382
61687
|
const line = JSON.stringify(message) + "\n";
|
|
61383
|
-
|
|
61688
|
+
fs54.appendFileSync(file, line, { mode: 384 });
|
|
61384
61689
|
try {
|
|
61385
|
-
|
|
61690
|
+
fs54.chmodSync(file, 384);
|
|
61386
61691
|
} catch {
|
|
61387
61692
|
}
|
|
61388
61693
|
}
|
|
@@ -61412,7 +61717,7 @@ var InboxStore = class {
|
|
|
61412
61717
|
removeByPeerDeviceId(peerDeviceId) {
|
|
61413
61718
|
const file = this.filePath(peerDeviceId);
|
|
61414
61719
|
try {
|
|
61415
|
-
|
|
61720
|
+
fs54.unlinkSync(file);
|
|
61416
61721
|
} catch (err) {
|
|
61417
61722
|
if (err?.code === "ENOENT") return;
|
|
61418
61723
|
}
|
|
@@ -61421,18 +61726,18 @@ var InboxStore = class {
|
|
|
61421
61726
|
const file = this.filePath(peerDeviceId);
|
|
61422
61727
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
61423
61728
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
61424
|
-
|
|
61425
|
-
|
|
61729
|
+
fs54.writeFileSync(tmp, content, { mode: 384 });
|
|
61730
|
+
fs54.renameSync(tmp, file);
|
|
61426
61731
|
try {
|
|
61427
|
-
|
|
61732
|
+
fs54.chmodSync(file, 384);
|
|
61428
61733
|
} catch {
|
|
61429
61734
|
}
|
|
61430
61735
|
}
|
|
61431
61736
|
dirPath() {
|
|
61432
|
-
return
|
|
61737
|
+
return path56.join(this.dataDir, INBOX_SUBDIR);
|
|
61433
61738
|
}
|
|
61434
61739
|
filePath(peerDeviceId) {
|
|
61435
|
-
return
|
|
61740
|
+
return path56.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
61436
61741
|
}
|
|
61437
61742
|
};
|
|
61438
61743
|
function parseAllLines(raw) {
|
|
@@ -61520,8 +61825,8 @@ var InboxManager = class {
|
|
|
61520
61825
|
};
|
|
61521
61826
|
|
|
61522
61827
|
// src/state/contact-store.ts
|
|
61523
|
-
var
|
|
61524
|
-
var
|
|
61828
|
+
var fs55 = __toESM(require("fs"), 1);
|
|
61829
|
+
var path57 = __toESM(require("path"), 1);
|
|
61525
61830
|
var FILE_NAME = "contacts.json";
|
|
61526
61831
|
var ContactStore = class {
|
|
61527
61832
|
constructor(dataDir) {
|
|
@@ -61531,10 +61836,10 @@ var ContactStore = class {
|
|
|
61531
61836
|
contacts = /* @__PURE__ */ new Map();
|
|
61532
61837
|
load() {
|
|
61533
61838
|
this.contacts.clear();
|
|
61534
|
-
const file =
|
|
61839
|
+
const file = path57.join(this.dataDir, FILE_NAME);
|
|
61535
61840
|
let raw;
|
|
61536
61841
|
try {
|
|
61537
|
-
raw =
|
|
61842
|
+
raw = fs55.readFileSync(file, "utf8");
|
|
61538
61843
|
} catch (err) {
|
|
61539
61844
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
61540
61845
|
return;
|
|
@@ -61615,20 +61920,20 @@ var ContactStore = class {
|
|
|
61615
61920
|
return true;
|
|
61616
61921
|
}
|
|
61617
61922
|
flush() {
|
|
61618
|
-
const file =
|
|
61923
|
+
const file = path57.join(this.dataDir, FILE_NAME);
|
|
61619
61924
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
61620
61925
|
const content = JSON.stringify(
|
|
61621
61926
|
{ contacts: Array.from(this.contacts.values()) },
|
|
61622
61927
|
null,
|
|
61623
61928
|
2
|
|
61624
61929
|
);
|
|
61625
|
-
|
|
61626
|
-
|
|
61627
|
-
|
|
61930
|
+
fs55.mkdirSync(this.dataDir, { recursive: true });
|
|
61931
|
+
fs55.writeFileSync(tmp, content, { mode: 384 });
|
|
61932
|
+
fs55.renameSync(tmp, file);
|
|
61628
61933
|
}
|
|
61629
61934
|
renameBak(file) {
|
|
61630
61935
|
try {
|
|
61631
|
-
|
|
61936
|
+
fs55.renameSync(file, `${file}.bak`);
|
|
61632
61937
|
} catch {
|
|
61633
61938
|
}
|
|
61634
61939
|
}
|
|
@@ -61736,61 +62041,61 @@ async function connectRemote(args) {
|
|
|
61736
62041
|
}
|
|
61737
62042
|
|
|
61738
62043
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
61739
|
-
var
|
|
61740
|
-
var
|
|
62044
|
+
var fs56 = __toESM(require("fs"), 1);
|
|
62045
|
+
var path58 = __toESM(require("path"), 1);
|
|
61741
62046
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
61742
62047
|
function migrateFlattenSessions(opts) {
|
|
61743
62048
|
const dataDir = opts.dataDir;
|
|
61744
62049
|
const now = opts.now ?? Date.now;
|
|
61745
|
-
const sessionsDir =
|
|
61746
|
-
const flagPath =
|
|
62050
|
+
const sessionsDir = path58.join(dataDir, "sessions");
|
|
62051
|
+
const flagPath = path58.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
61747
62052
|
if (existsSync3(flagPath)) {
|
|
61748
62053
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
61749
62054
|
}
|
|
61750
62055
|
let movedBare = 0;
|
|
61751
62056
|
let movedVmOwner = 0;
|
|
61752
62057
|
let archivedListener = 0;
|
|
61753
|
-
const defaultDir =
|
|
62058
|
+
const defaultDir = path58.join(sessionsDir, "default");
|
|
61754
62059
|
if (existsSync3(defaultDir)) {
|
|
61755
62060
|
for (const entry of readdirSafe(defaultDir)) {
|
|
61756
62061
|
if (!entry.endsWith(".json")) continue;
|
|
61757
|
-
const src =
|
|
61758
|
-
const dst =
|
|
61759
|
-
|
|
62062
|
+
const src = path58.join(defaultDir, entry);
|
|
62063
|
+
const dst = path58.join(sessionsDir, entry);
|
|
62064
|
+
fs56.renameSync(src, dst);
|
|
61760
62065
|
movedBare += 1;
|
|
61761
62066
|
}
|
|
61762
62067
|
rmdirIfEmpty(defaultDir);
|
|
61763
62068
|
}
|
|
61764
62069
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
61765
|
-
const personaDir =
|
|
62070
|
+
const personaDir = path58.join(sessionsDir, pid);
|
|
61766
62071
|
if (!isDir(personaDir)) continue;
|
|
61767
62072
|
if (pid === "default") continue;
|
|
61768
|
-
const ownerSrc =
|
|
62073
|
+
const ownerSrc = path58.join(personaDir, "owner");
|
|
61769
62074
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
61770
|
-
const ownerDst =
|
|
61771
|
-
|
|
62075
|
+
const ownerDst = path58.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
62076
|
+
fs56.mkdirSync(ownerDst, { recursive: true });
|
|
61772
62077
|
for (const file of readdirSafe(ownerSrc)) {
|
|
61773
62078
|
if (!file.endsWith(".json")) continue;
|
|
61774
|
-
|
|
62079
|
+
fs56.renameSync(path58.join(ownerSrc, file), path58.join(ownerDst, file));
|
|
61775
62080
|
movedVmOwner += 1;
|
|
61776
62081
|
}
|
|
61777
62082
|
rmdirIfEmpty(ownerSrc);
|
|
61778
62083
|
}
|
|
61779
|
-
const listenerSrc =
|
|
62084
|
+
const listenerSrc = path58.join(personaDir, "listener");
|
|
61780
62085
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
61781
|
-
const archiveDst =
|
|
61782
|
-
|
|
62086
|
+
const archiveDst = path58.join(dataDir, ".legacy", `listener-${pid}`);
|
|
62087
|
+
fs56.mkdirSync(archiveDst, { recursive: true });
|
|
61783
62088
|
for (const file of readdirSafe(listenerSrc)) {
|
|
61784
62089
|
if (!file.endsWith(".json")) continue;
|
|
61785
|
-
|
|
62090
|
+
fs56.renameSync(path58.join(listenerSrc, file), path58.join(archiveDst, file));
|
|
61786
62091
|
archivedListener += 1;
|
|
61787
62092
|
}
|
|
61788
62093
|
rmdirIfEmpty(listenerSrc);
|
|
61789
62094
|
}
|
|
61790
62095
|
rmdirIfEmpty(personaDir);
|
|
61791
62096
|
}
|
|
61792
|
-
|
|
61793
|
-
|
|
62097
|
+
fs56.mkdirSync(sessionsDir, { recursive: true });
|
|
62098
|
+
fs56.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
61794
62099
|
return {
|
|
61795
62100
|
skipped: false,
|
|
61796
62101
|
flagWritten: true,
|
|
@@ -61801,7 +62106,7 @@ function migrateFlattenSessions(opts) {
|
|
|
61801
62106
|
}
|
|
61802
62107
|
function existsSync3(p2) {
|
|
61803
62108
|
try {
|
|
61804
|
-
|
|
62109
|
+
fs56.statSync(p2);
|
|
61805
62110
|
return true;
|
|
61806
62111
|
} catch {
|
|
61807
62112
|
return false;
|
|
@@ -61809,62 +62114,62 @@ function existsSync3(p2) {
|
|
|
61809
62114
|
}
|
|
61810
62115
|
function isDir(p2) {
|
|
61811
62116
|
try {
|
|
61812
|
-
return
|
|
62117
|
+
return fs56.statSync(p2).isDirectory();
|
|
61813
62118
|
} catch {
|
|
61814
62119
|
return false;
|
|
61815
62120
|
}
|
|
61816
62121
|
}
|
|
61817
62122
|
function readdirSafe(p2) {
|
|
61818
62123
|
try {
|
|
61819
|
-
return
|
|
62124
|
+
return fs56.readdirSync(p2);
|
|
61820
62125
|
} catch {
|
|
61821
62126
|
return [];
|
|
61822
62127
|
}
|
|
61823
62128
|
}
|
|
61824
62129
|
function rmdirIfEmpty(p2) {
|
|
61825
62130
|
try {
|
|
61826
|
-
|
|
62131
|
+
fs56.rmdirSync(p2);
|
|
61827
62132
|
} catch {
|
|
61828
62133
|
}
|
|
61829
62134
|
}
|
|
61830
62135
|
|
|
61831
62136
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
61832
|
-
var
|
|
61833
|
-
var
|
|
62137
|
+
var fs57 = __toESM(require("fs"), 1);
|
|
62138
|
+
var path59 = __toESM(require("path"), 1);
|
|
61834
62139
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
61835
62140
|
function dropSeededProjects(opts) {
|
|
61836
|
-
|
|
61837
|
-
const flag =
|
|
61838
|
-
if (
|
|
61839
|
-
const file =
|
|
62141
|
+
fs57.mkdirSync(opts.dataDir, { recursive: true });
|
|
62142
|
+
const flag = path59.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
|
|
62143
|
+
if (fs57.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
|
|
62144
|
+
const file = path59.join(opts.dataDir, "projects.json");
|
|
61840
62145
|
let raw = null;
|
|
61841
62146
|
let dropped = 0;
|
|
61842
62147
|
try {
|
|
61843
|
-
raw =
|
|
62148
|
+
raw = fs57.readFileSync(file, "utf8");
|
|
61844
62149
|
dropped = JSON.parse(raw).projects?.length ?? 0;
|
|
61845
62150
|
} catch {
|
|
61846
62151
|
}
|
|
61847
62152
|
let backup = null;
|
|
61848
62153
|
if (raw != null && dropped > 0) {
|
|
61849
|
-
const dir =
|
|
61850
|
-
|
|
61851
|
-
backup =
|
|
61852
|
-
|
|
62154
|
+
const dir = path59.join(opts.dataDir, "backups");
|
|
62155
|
+
fs57.mkdirSync(dir, { recursive: true });
|
|
62156
|
+
backup = path59.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
|
|
62157
|
+
fs57.writeFileSync(backup, raw);
|
|
61853
62158
|
}
|
|
61854
62159
|
if (raw != null || dropped > 0) {
|
|
61855
|
-
|
|
62160
|
+
fs57.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
|
|
61856
62161
|
}
|
|
61857
|
-
|
|
62162
|
+
fs57.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
|
|
61858
62163
|
return { skipped: false, dropped, backup };
|
|
61859
62164
|
}
|
|
61860
62165
|
|
|
61861
62166
|
// src/transport/http-router.ts
|
|
61862
|
-
var
|
|
61863
|
-
var
|
|
62167
|
+
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
62168
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
61864
62169
|
|
|
61865
62170
|
// src/attachment/upload.ts
|
|
61866
|
-
var
|
|
61867
|
-
var
|
|
62171
|
+
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
62172
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
61868
62173
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
61869
62174
|
var import_promises7 = require("stream/promises");
|
|
61870
62175
|
var UploadError = class extends Error {
|
|
@@ -61876,22 +62181,22 @@ var UploadError = class extends Error {
|
|
|
61876
62181
|
code;
|
|
61877
62182
|
};
|
|
61878
62183
|
function assertValidFileName(fileName) {
|
|
61879
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
62184
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path48.default.basename(fileName)) {
|
|
61880
62185
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
61881
62186
|
}
|
|
61882
62187
|
}
|
|
61883
62188
|
var HASH_PREFIX_LEN = 16;
|
|
61884
62189
|
async function writeUploadedAttachment(args) {
|
|
61885
62190
|
assertValidFileName(args.fileName);
|
|
61886
|
-
const attachmentsRoot =
|
|
62191
|
+
const attachmentsRoot = import_node_path48.default.join(args.baseDir, ".attachments");
|
|
61887
62192
|
try {
|
|
61888
|
-
|
|
62193
|
+
import_node_fs43.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
61889
62194
|
} catch (err) {
|
|
61890
62195
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
61891
62196
|
}
|
|
61892
62197
|
const hasher = import_node_crypto11.default.createHash("sha256");
|
|
61893
62198
|
let actualSize = 0;
|
|
61894
|
-
const tmpPath =
|
|
62199
|
+
const tmpPath = import_node_path48.default.join(
|
|
61895
62200
|
attachmentsRoot,
|
|
61896
62201
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto11.default.randomBytes(4).toString("hex")}`
|
|
61897
62202
|
);
|
|
@@ -61906,18 +62211,18 @@ async function writeUploadedAttachment(args) {
|
|
|
61906
62211
|
yield buf;
|
|
61907
62212
|
}
|
|
61908
62213
|
},
|
|
61909
|
-
|
|
62214
|
+
import_node_fs43.default.createWriteStream(tmpPath, { mode: 384 })
|
|
61910
62215
|
);
|
|
61911
62216
|
} catch (err) {
|
|
61912
62217
|
try {
|
|
61913
|
-
|
|
62218
|
+
import_node_fs43.default.unlinkSync(tmpPath);
|
|
61914
62219
|
} catch {
|
|
61915
62220
|
}
|
|
61916
62221
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
61917
62222
|
}
|
|
61918
62223
|
if (actualSize !== args.contentLength) {
|
|
61919
62224
|
try {
|
|
61920
|
-
|
|
62225
|
+
import_node_fs43.default.unlinkSync(tmpPath);
|
|
61921
62226
|
} catch {
|
|
61922
62227
|
}
|
|
61923
62228
|
throw new UploadError(
|
|
@@ -61926,34 +62231,34 @@ async function writeUploadedAttachment(args) {
|
|
|
61926
62231
|
);
|
|
61927
62232
|
}
|
|
61928
62233
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
61929
|
-
const hashDir =
|
|
62234
|
+
const hashDir = import_node_path48.default.join(attachmentsRoot, attachmentId);
|
|
61930
62235
|
let finalFileName;
|
|
61931
62236
|
let hashDirExists = false;
|
|
61932
62237
|
try {
|
|
61933
|
-
hashDirExists =
|
|
62238
|
+
hashDirExists = import_node_fs43.default.statSync(hashDir).isDirectory();
|
|
61934
62239
|
} catch {
|
|
61935
62240
|
}
|
|
61936
62241
|
if (hashDirExists) {
|
|
61937
|
-
const existing =
|
|
62242
|
+
const existing = import_node_fs43.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
61938
62243
|
finalFileName = existing[0] ?? args.fileName;
|
|
61939
62244
|
try {
|
|
61940
|
-
|
|
62245
|
+
import_node_fs43.default.unlinkSync(tmpPath);
|
|
61941
62246
|
} catch {
|
|
61942
62247
|
}
|
|
61943
62248
|
} else {
|
|
61944
62249
|
try {
|
|
61945
|
-
|
|
62250
|
+
import_node_fs43.default.mkdirSync(hashDir, { recursive: true });
|
|
61946
62251
|
finalFileName = args.fileName;
|
|
61947
|
-
|
|
62252
|
+
import_node_fs43.default.renameSync(tmpPath, import_node_path48.default.join(hashDir, finalFileName));
|
|
61948
62253
|
} catch (err) {
|
|
61949
62254
|
try {
|
|
61950
|
-
|
|
62255
|
+
import_node_fs43.default.unlinkSync(tmpPath);
|
|
61951
62256
|
} catch {
|
|
61952
62257
|
}
|
|
61953
62258
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
61954
62259
|
}
|
|
61955
62260
|
}
|
|
61956
|
-
const absPath =
|
|
62261
|
+
const absPath = import_node_path48.default.join(hashDir, finalFileName);
|
|
61957
62262
|
const relPath = absPath;
|
|
61958
62263
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
61959
62264
|
relPath: absPath,
|
|
@@ -61968,7 +62273,7 @@ async function writeUploadedAttachment(args) {
|
|
|
61968
62273
|
|
|
61969
62274
|
// src/extension/import.ts
|
|
61970
62275
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
61971
|
-
var
|
|
62276
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
61972
62277
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
61973
62278
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
61974
62279
|
var ImportError = class extends Error {
|
|
@@ -61986,7 +62291,7 @@ async function importZip(buf, root) {
|
|
|
61986
62291
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
61987
62292
|
}
|
|
61988
62293
|
for (const name of Object.keys(zip.files)) {
|
|
61989
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
62294
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path49.default.isAbsolute(name)) {
|
|
61990
62295
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
61991
62296
|
}
|
|
61992
62297
|
}
|
|
@@ -62019,7 +62324,7 @@ async function importZip(buf, root) {
|
|
|
62019
62324
|
);
|
|
62020
62325
|
}
|
|
62021
62326
|
}
|
|
62022
|
-
const destDir =
|
|
62327
|
+
const destDir = import_node_path49.default.join(root, manifest.id);
|
|
62023
62328
|
let destExists = false;
|
|
62024
62329
|
try {
|
|
62025
62330
|
await import_promises8.default.access(destDir);
|
|
@@ -62029,15 +62334,15 @@ async function importZip(buf, root) {
|
|
|
62029
62334
|
if (destExists) {
|
|
62030
62335
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
62031
62336
|
}
|
|
62032
|
-
const stage = await import_promises8.default.mkdtemp(
|
|
62337
|
+
const stage = await import_promises8.default.mkdtemp(import_node_path49.default.join(import_node_os16.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
62033
62338
|
try {
|
|
62034
62339
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
62035
|
-
const dest =
|
|
62340
|
+
const dest = import_node_path49.default.join(stage, name);
|
|
62036
62341
|
if (entry.dir) {
|
|
62037
62342
|
await import_promises8.default.mkdir(dest, { recursive: true });
|
|
62038
62343
|
continue;
|
|
62039
62344
|
}
|
|
62040
|
-
await import_promises8.default.mkdir(
|
|
62345
|
+
await import_promises8.default.mkdir(import_node_path49.default.dirname(dest), { recursive: true });
|
|
62041
62346
|
const content = await entry.async("nodebuffer");
|
|
62042
62347
|
await import_promises8.default.writeFile(dest, content);
|
|
62043
62348
|
}
|
|
@@ -62067,7 +62372,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
62067
62372
|
".wasm": "application/wasm"
|
|
62068
62373
|
};
|
|
62069
62374
|
function shareUiAssetMime(filePath) {
|
|
62070
|
-
const ext =
|
|
62375
|
+
const ext = import_node_path50.default.extname(filePath).toLowerCase();
|
|
62071
62376
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
62072
62377
|
}
|
|
62073
62378
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -62166,7 +62471,7 @@ function isValidUploadFileName(fileName) {
|
|
|
62166
62471
|
if (fileName === "." || fileName === "..") return false;
|
|
62167
62472
|
if (fileName.startsWith(".")) return false;
|
|
62168
62473
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
62169
|
-
return fileName ===
|
|
62474
|
+
return fileName === import_node_path50.default.basename(fileName);
|
|
62170
62475
|
}
|
|
62171
62476
|
function createHttpRouter(deps) {
|
|
62172
62477
|
return async (req, res) => {
|
|
@@ -62254,7 +62559,7 @@ function createHttpRouter(deps) {
|
|
|
62254
62559
|
}
|
|
62255
62560
|
let buf;
|
|
62256
62561
|
try {
|
|
62257
|
-
buf = await
|
|
62562
|
+
buf = await import_node_fs44.default.promises.readFile(abs);
|
|
62258
62563
|
} catch {
|
|
62259
62564
|
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
62260
62565
|
return true;
|
|
@@ -62402,7 +62707,7 @@ function createHttpRouter(deps) {
|
|
|
62402
62707
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
62403
62708
|
return true;
|
|
62404
62709
|
}
|
|
62405
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
62710
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path50.default.basename(r.absPath)));
|
|
62406
62711
|
return true;
|
|
62407
62712
|
}
|
|
62408
62713
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -62523,7 +62828,7 @@ function createHttpRouter(deps) {
|
|
|
62523
62828
|
return true;
|
|
62524
62829
|
}
|
|
62525
62830
|
let absPath;
|
|
62526
|
-
if (
|
|
62831
|
+
if (import_node_path50.default.isAbsolute(pathParam)) {
|
|
62527
62832
|
absPath = pathParam;
|
|
62528
62833
|
} else if (deps.sessionStore) {
|
|
62529
62834
|
const file = deps.sessionStore.read(sid);
|
|
@@ -62531,7 +62836,7 @@ function createHttpRouter(deps) {
|
|
|
62531
62836
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
62532
62837
|
return true;
|
|
62533
62838
|
}
|
|
62534
|
-
absPath =
|
|
62839
|
+
absPath = import_node_path50.default.join(file.cwd, pathParam);
|
|
62535
62840
|
} else {
|
|
62536
62841
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
62537
62842
|
return true;
|
|
@@ -62618,7 +62923,7 @@ function withCtx(ctx, body) {
|
|
|
62618
62923
|
function streamFile(res, absPath, logger) {
|
|
62619
62924
|
let stat;
|
|
62620
62925
|
try {
|
|
62621
|
-
stat =
|
|
62926
|
+
stat = import_node_fs44.default.statSync(absPath);
|
|
62622
62927
|
} catch (err) {
|
|
62623
62928
|
const code = err?.code;
|
|
62624
62929
|
if (code === "ENOENT") {
|
|
@@ -62633,7 +62938,7 @@ function streamFile(res, absPath, logger) {
|
|
|
62633
62938
|
return;
|
|
62634
62939
|
}
|
|
62635
62940
|
const mime = lookupMime(absPath);
|
|
62636
|
-
const basename2 =
|
|
62941
|
+
const basename2 = import_node_path50.default.basename(absPath);
|
|
62637
62942
|
res.writeHead(200, {
|
|
62638
62943
|
"Content-Type": mime,
|
|
62639
62944
|
"Content-Length": String(stat.size),
|
|
@@ -62641,7 +62946,7 @@ function streamFile(res, absPath, logger) {
|
|
|
62641
62946
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
62642
62947
|
"X-Content-Type-Options": "nosniff"
|
|
62643
62948
|
});
|
|
62644
|
-
const stream =
|
|
62949
|
+
const stream = import_node_fs44.default.createReadStream(absPath);
|
|
62645
62950
|
stream.on("error", (err) => {
|
|
62646
62951
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
62647
62952
|
res.destroy();
|
|
@@ -62650,8 +62955,8 @@ function streamFile(res, absPath, logger) {
|
|
|
62650
62955
|
}
|
|
62651
62956
|
|
|
62652
62957
|
// src/attachment/gc.ts
|
|
62653
|
-
var
|
|
62654
|
-
var
|
|
62958
|
+
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
62959
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
62655
62960
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
62656
62961
|
function runAttachmentGc(args) {
|
|
62657
62962
|
const now = (args.now ?? Date.now)();
|
|
@@ -62660,12 +62965,12 @@ function runAttachmentGc(args) {
|
|
|
62660
62965
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
62661
62966
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
62662
62967
|
if (entry.stale) continue;
|
|
62663
|
-
if (
|
|
62968
|
+
if (import_node_path51.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
62664
62969
|
}
|
|
62665
62970
|
}
|
|
62666
62971
|
const visited = /* @__PURE__ */ new Set();
|
|
62667
62972
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
62668
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
62973
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path51.default.join(
|
|
62669
62974
|
args.dataDir,
|
|
62670
62975
|
"sessions",
|
|
62671
62976
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -62678,28 +62983,28 @@ function runAttachmentGc(args) {
|
|
|
62678
62983
|
return true;
|
|
62679
62984
|
});
|
|
62680
62985
|
for (const rootDir of roots) {
|
|
62681
|
-
const attRoot =
|
|
62986
|
+
const attRoot = import_node_path51.default.join(rootDir, ".attachments");
|
|
62682
62987
|
let hashDirs;
|
|
62683
62988
|
try {
|
|
62684
|
-
hashDirs =
|
|
62989
|
+
hashDirs = import_node_fs45.default.readdirSync(attRoot);
|
|
62685
62990
|
} catch (err) {
|
|
62686
62991
|
if (err.code === "ENOENT") continue;
|
|
62687
62992
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
62688
62993
|
continue;
|
|
62689
62994
|
}
|
|
62690
62995
|
for (const hashDir of hashDirs) {
|
|
62691
|
-
const hashDirAbs =
|
|
62996
|
+
const hashDirAbs = import_node_path51.default.join(attRoot, hashDir);
|
|
62692
62997
|
let files;
|
|
62693
62998
|
try {
|
|
62694
|
-
files =
|
|
62999
|
+
files = import_node_fs45.default.readdirSync(hashDirAbs);
|
|
62695
63000
|
} catch {
|
|
62696
63001
|
continue;
|
|
62697
63002
|
}
|
|
62698
63003
|
for (const name of files) {
|
|
62699
|
-
const file =
|
|
63004
|
+
const file = import_node_path51.default.join(hashDirAbs, name);
|
|
62700
63005
|
let stat;
|
|
62701
63006
|
try {
|
|
62702
|
-
stat =
|
|
63007
|
+
stat = import_node_fs45.default.statSync(file);
|
|
62703
63008
|
} catch {
|
|
62704
63009
|
continue;
|
|
62705
63010
|
}
|
|
@@ -62708,18 +63013,18 @@ function runAttachmentGc(args) {
|
|
|
62708
63013
|
if (age < ttlMs) continue;
|
|
62709
63014
|
if (liveAbs.has(file)) continue;
|
|
62710
63015
|
try {
|
|
62711
|
-
|
|
63016
|
+
import_node_fs45.default.unlinkSync(file);
|
|
62712
63017
|
} catch (err) {
|
|
62713
63018
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
62714
63019
|
}
|
|
62715
63020
|
}
|
|
62716
63021
|
try {
|
|
62717
|
-
if (
|
|
63022
|
+
if (import_node_fs45.default.readdirSync(hashDirAbs).length === 0) import_node_fs45.default.rmdirSync(hashDirAbs);
|
|
62718
63023
|
} catch {
|
|
62719
63024
|
}
|
|
62720
63025
|
}
|
|
62721
63026
|
try {
|
|
62722
|
-
if (
|
|
63027
|
+
if (import_node_fs45.default.readdirSync(attRoot).length === 0) import_node_fs45.default.rmdirSync(attRoot);
|
|
62723
63028
|
} catch {
|
|
62724
63029
|
}
|
|
62725
63030
|
}
|
|
@@ -62727,8 +63032,8 @@ function runAttachmentGc(args) {
|
|
|
62727
63032
|
}
|
|
62728
63033
|
|
|
62729
63034
|
// src/attachment/group.ts
|
|
62730
|
-
var
|
|
62731
|
-
var
|
|
63035
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
63036
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
62732
63037
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
62733
63038
|
init_protocol();
|
|
62734
63039
|
var GroupFileStore = class {
|
|
@@ -62740,11 +63045,11 @@ var GroupFileStore = class {
|
|
|
62740
63045
|
this.logger = opts.logger;
|
|
62741
63046
|
}
|
|
62742
63047
|
rootForScope(scope) {
|
|
62743
|
-
return
|
|
63048
|
+
return import_node_path52.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
62744
63049
|
}
|
|
62745
63050
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
62746
63051
|
filePath(scope, sessionId) {
|
|
62747
|
-
return
|
|
63052
|
+
return import_node_path52.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
62748
63053
|
}
|
|
62749
63054
|
cacheKey(scope, sessionId) {
|
|
62750
63055
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -62753,7 +63058,7 @@ var GroupFileStore = class {
|
|
|
62753
63058
|
readFile(scope, sessionId) {
|
|
62754
63059
|
const file = this.filePath(scope, sessionId);
|
|
62755
63060
|
try {
|
|
62756
|
-
const raw =
|
|
63061
|
+
const raw = import_node_fs46.default.readFileSync(file, "utf8");
|
|
62757
63062
|
const parsed = JSON.parse(raw);
|
|
62758
63063
|
if (!Array.isArray(parsed)) {
|
|
62759
63064
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -62779,10 +63084,10 @@ var GroupFileStore = class {
|
|
|
62779
63084
|
}
|
|
62780
63085
|
writeFile(scope, sessionId, entries) {
|
|
62781
63086
|
const file = this.filePath(scope, sessionId);
|
|
62782
|
-
|
|
63087
|
+
import_node_fs46.default.mkdirSync(import_node_path52.default.dirname(file), { recursive: true });
|
|
62783
63088
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
62784
|
-
|
|
62785
|
-
|
|
63089
|
+
import_node_fs46.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
63090
|
+
import_node_fs46.default.renameSync(tmp, file);
|
|
62786
63091
|
}
|
|
62787
63092
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
62788
63093
|
list(scope, sessionId) {
|
|
@@ -62874,7 +63179,7 @@ var GroupFileStore = class {
|
|
|
62874
63179
|
*/
|
|
62875
63180
|
deleteSession(scope, sessionId) {
|
|
62876
63181
|
try {
|
|
62877
|
-
|
|
63182
|
+
import_node_fs46.default.unlinkSync(this.filePath(scope, sessionId));
|
|
62878
63183
|
} catch (err) {
|
|
62879
63184
|
if (err?.code !== "ENOENT") throw err;
|
|
62880
63185
|
}
|
|
@@ -62887,7 +63192,7 @@ var GroupFileStore = class {
|
|
|
62887
63192
|
* 不在 persona 目录里(见文件头的路径约定)。没树的 persona 是 noop。
|
|
62888
63193
|
*/
|
|
62889
63194
|
deletePersona(personaId2) {
|
|
62890
|
-
|
|
63195
|
+
import_node_fs46.default.rmSync(import_node_path52.default.join(this.dataDir, "sessions", safeFileName(personaId2)), { recursive: true, force: true });
|
|
62891
63196
|
const prefix = `persona:${personaId2}:`;
|
|
62892
63197
|
for (const key of this.cache.keys()) {
|
|
62893
63198
|
if (key.startsWith(prefix)) this.cache.delete(key);
|
|
@@ -62896,10 +63201,10 @@ var GroupFileStore = class {
|
|
|
62896
63201
|
};
|
|
62897
63202
|
|
|
62898
63203
|
// src/discovery/state-file.ts
|
|
62899
|
-
var
|
|
62900
|
-
var
|
|
63204
|
+
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
63205
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
62901
63206
|
function defaultStateFilePath(dataDir) {
|
|
62902
|
-
return
|
|
63207
|
+
return import_node_path53.default.join(dataDir, "state.json");
|
|
62903
63208
|
}
|
|
62904
63209
|
function isPidAlive(pid) {
|
|
62905
63210
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -62921,7 +63226,7 @@ var StateFileManager = class {
|
|
|
62921
63226
|
}
|
|
62922
63227
|
read() {
|
|
62923
63228
|
try {
|
|
62924
|
-
const raw =
|
|
63229
|
+
const raw = import_node_fs47.default.readFileSync(this.file, "utf8");
|
|
62925
63230
|
const parsed = JSON.parse(raw);
|
|
62926
63231
|
return parsed;
|
|
62927
63232
|
} catch {
|
|
@@ -62935,20 +63240,20 @@ var StateFileManager = class {
|
|
|
62935
63240
|
return { status: "stale", existing };
|
|
62936
63241
|
}
|
|
62937
63242
|
write(state) {
|
|
62938
|
-
|
|
63243
|
+
import_node_fs47.default.mkdirSync(import_node_path53.default.dirname(this.file), { recursive: true });
|
|
62939
63244
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
62940
|
-
|
|
62941
|
-
|
|
63245
|
+
import_node_fs47.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
63246
|
+
import_node_fs47.default.renameSync(tmp, this.file);
|
|
62942
63247
|
if (process.platform !== "win32") {
|
|
62943
63248
|
try {
|
|
62944
|
-
|
|
63249
|
+
import_node_fs47.default.chmodSync(this.file, 384);
|
|
62945
63250
|
} catch {
|
|
62946
63251
|
}
|
|
62947
63252
|
}
|
|
62948
63253
|
}
|
|
62949
63254
|
delete() {
|
|
62950
63255
|
try {
|
|
62951
|
-
|
|
63256
|
+
import_node_fs47.default.unlinkSync(this.file);
|
|
62952
63257
|
} catch {
|
|
62953
63258
|
}
|
|
62954
63259
|
}
|
|
@@ -62962,14 +63267,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
62962
63267
|
}
|
|
62963
63268
|
|
|
62964
63269
|
// src/tunnel/tunnel-manager.ts
|
|
62965
|
-
var
|
|
62966
|
-
var
|
|
63270
|
+
var import_node_fs51 = __toESM(require("fs"), 1);
|
|
63271
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
62967
63272
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
62968
63273
|
var import_node_child_process14 = require("child_process");
|
|
62969
63274
|
|
|
62970
63275
|
// src/tunnel/tunnel-store.ts
|
|
62971
|
-
var
|
|
62972
|
-
var
|
|
63276
|
+
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
63277
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
62973
63278
|
var TunnelStore = class {
|
|
62974
63279
|
constructor(filePath) {
|
|
62975
63280
|
this.filePath = filePath;
|
|
@@ -62977,7 +63282,7 @@ var TunnelStore = class {
|
|
|
62977
63282
|
filePath;
|
|
62978
63283
|
async get() {
|
|
62979
63284
|
try {
|
|
62980
|
-
const raw = await
|
|
63285
|
+
const raw = await import_node_fs48.default.promises.readFile(this.filePath, "utf8");
|
|
62981
63286
|
const obj = JSON.parse(raw);
|
|
62982
63287
|
if (!isPersistedTunnel(obj)) return null;
|
|
62983
63288
|
return obj;
|
|
@@ -62988,22 +63293,22 @@ var TunnelStore = class {
|
|
|
62988
63293
|
}
|
|
62989
63294
|
}
|
|
62990
63295
|
async set(v2) {
|
|
62991
|
-
const dir =
|
|
62992
|
-
await
|
|
63296
|
+
const dir = import_node_path54.default.dirname(this.filePath);
|
|
63297
|
+
await import_node_fs48.default.promises.mkdir(dir, { recursive: true });
|
|
62993
63298
|
const data = JSON.stringify(v2, null, 2);
|
|
62994
63299
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
62995
|
-
await
|
|
63300
|
+
await import_node_fs48.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
62996
63301
|
if (process.platform !== "win32") {
|
|
62997
63302
|
try {
|
|
62998
|
-
await
|
|
63303
|
+
await import_node_fs48.default.promises.chmod(tmp, 384);
|
|
62999
63304
|
} catch {
|
|
63000
63305
|
}
|
|
63001
63306
|
}
|
|
63002
|
-
await
|
|
63307
|
+
await import_node_fs48.default.promises.rename(tmp, this.filePath);
|
|
63003
63308
|
}
|
|
63004
63309
|
async clear() {
|
|
63005
63310
|
try {
|
|
63006
|
-
await
|
|
63311
|
+
await import_node_fs48.default.promises.unlink(this.filePath);
|
|
63007
63312
|
} catch (err) {
|
|
63008
63313
|
const code = err?.code;
|
|
63009
63314
|
if (code !== "ENOENT") throw err;
|
|
@@ -63098,9 +63403,9 @@ function escape(v2) {
|
|
|
63098
63403
|
}
|
|
63099
63404
|
|
|
63100
63405
|
// src/tunnel/frpc-binary.ts
|
|
63101
|
-
var
|
|
63406
|
+
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
63102
63407
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
63103
|
-
var
|
|
63408
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
63104
63409
|
var import_node_child_process12 = require("child_process");
|
|
63105
63410
|
var import_node_stream3 = require("stream");
|
|
63106
63411
|
var import_promises9 = require("stream/promises");
|
|
@@ -63132,20 +63437,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
63132
63437
|
}
|
|
63133
63438
|
async function ensureFrpcBinary(opts) {
|
|
63134
63439
|
if (opts.override) {
|
|
63135
|
-
if (!
|
|
63440
|
+
if (!import_node_fs49.default.existsSync(opts.override)) {
|
|
63136
63441
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
63137
63442
|
}
|
|
63138
63443
|
return opts.override;
|
|
63139
63444
|
}
|
|
63140
63445
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
63141
63446
|
const platform = opts.platform ?? detectPlatform();
|
|
63142
|
-
const binDir =
|
|
63143
|
-
|
|
63447
|
+
const binDir = import_node_path55.default.join(opts.dataDir, "bin");
|
|
63448
|
+
import_node_fs49.default.mkdirSync(binDir, { recursive: true });
|
|
63144
63449
|
cleanupStaleArtifacts(binDir);
|
|
63145
|
-
const stableBin =
|
|
63146
|
-
if (
|
|
63450
|
+
const stableBin = import_node_path55.default.join(binDir, "frpc");
|
|
63451
|
+
if (import_node_fs49.default.existsSync(stableBin)) return stableBin;
|
|
63147
63452
|
const partialBin = `${stableBin}.partial`;
|
|
63148
|
-
const tarballPath =
|
|
63453
|
+
const tarballPath = import_node_path55.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
63149
63454
|
try {
|
|
63150
63455
|
const url = frpcDownloadUrl(version2, platform);
|
|
63151
63456
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -63154,8 +63459,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
63154
63459
|
} else {
|
|
63155
63460
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
63156
63461
|
}
|
|
63157
|
-
|
|
63158
|
-
|
|
63462
|
+
import_node_fs49.default.chmodSync(partialBin, 493);
|
|
63463
|
+
import_node_fs49.default.renameSync(partialBin, stableBin);
|
|
63159
63464
|
} finally {
|
|
63160
63465
|
safeUnlink(tarballPath);
|
|
63161
63466
|
safeUnlink(partialBin);
|
|
@@ -63165,15 +63470,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
63165
63470
|
function cleanupStaleArtifacts(binDir) {
|
|
63166
63471
|
let entries;
|
|
63167
63472
|
try {
|
|
63168
|
-
entries =
|
|
63473
|
+
entries = import_node_fs49.default.readdirSync(binDir);
|
|
63169
63474
|
} catch {
|
|
63170
63475
|
return;
|
|
63171
63476
|
}
|
|
63172
63477
|
for (const name of entries) {
|
|
63173
63478
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
63174
|
-
const full =
|
|
63479
|
+
const full = import_node_path55.default.join(binDir, name);
|
|
63175
63480
|
try {
|
|
63176
|
-
|
|
63481
|
+
import_node_fs49.default.rmSync(full, { recursive: true, force: true });
|
|
63177
63482
|
} catch {
|
|
63178
63483
|
}
|
|
63179
63484
|
}
|
|
@@ -63181,7 +63486,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
63181
63486
|
}
|
|
63182
63487
|
function safeUnlink(p2) {
|
|
63183
63488
|
try {
|
|
63184
|
-
|
|
63489
|
+
import_node_fs49.default.unlinkSync(p2);
|
|
63185
63490
|
} catch {
|
|
63186
63491
|
}
|
|
63187
63492
|
}
|
|
@@ -63192,13 +63497,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
63192
63497
|
if (!res.ok || !res.body) {
|
|
63193
63498
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
63194
63499
|
}
|
|
63195
|
-
const out =
|
|
63500
|
+
const out = import_node_fs49.default.createWriteStream(dest);
|
|
63196
63501
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
63197
63502
|
await (0, import_promises9.pipeline)(nodeStream, out);
|
|
63198
63503
|
}
|
|
63199
63504
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
63200
|
-
const work =
|
|
63201
|
-
|
|
63505
|
+
const work = import_node_path55.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
63506
|
+
import_node_fs49.default.mkdirSync(work, { recursive: true });
|
|
63202
63507
|
try {
|
|
63203
63508
|
await new Promise((resolve9, reject) => {
|
|
63204
63509
|
const proc = (0, import_node_child_process12.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -63206,32 +63511,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
63206
63511
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
63207
63512
|
});
|
|
63208
63513
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
63209
|
-
const src =
|
|
63210
|
-
if (!
|
|
63514
|
+
const src = import_node_path55.default.join(work, dirName, "frpc");
|
|
63515
|
+
if (!import_node_fs49.default.existsSync(src)) {
|
|
63211
63516
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
63212
63517
|
}
|
|
63213
|
-
|
|
63518
|
+
import_node_fs49.default.copyFileSync(src, destBin);
|
|
63214
63519
|
} finally {
|
|
63215
|
-
|
|
63520
|
+
import_node_fs49.default.rmSync(work, { recursive: true, force: true });
|
|
63216
63521
|
}
|
|
63217
63522
|
}
|
|
63218
63523
|
|
|
63219
63524
|
// src/tunnel/frpc-process.ts
|
|
63220
|
-
var
|
|
63221
|
-
var
|
|
63525
|
+
var import_node_fs50 = __toESM(require("fs"), 1);
|
|
63526
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
63222
63527
|
var import_node_child_process13 = require("child_process");
|
|
63223
63528
|
function frpcPidFilePath(dataDir) {
|
|
63224
|
-
return
|
|
63529
|
+
return import_node_path56.default.join(dataDir, "frpc.pid");
|
|
63225
63530
|
}
|
|
63226
63531
|
function writeFrpcPid(dataDir, pid) {
|
|
63227
63532
|
try {
|
|
63228
|
-
|
|
63533
|
+
import_node_fs50.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
63229
63534
|
} catch {
|
|
63230
63535
|
}
|
|
63231
63536
|
}
|
|
63232
63537
|
function clearFrpcPid(dataDir) {
|
|
63233
63538
|
try {
|
|
63234
|
-
|
|
63539
|
+
import_node_fs50.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
63235
63540
|
} catch {
|
|
63236
63541
|
}
|
|
63237
63542
|
}
|
|
@@ -63247,7 +63552,7 @@ function defaultIsPidAlive(pid) {
|
|
|
63247
63552
|
}
|
|
63248
63553
|
function defaultReadPidFile(file) {
|
|
63249
63554
|
try {
|
|
63250
|
-
return
|
|
63555
|
+
return import_node_fs50.default.readFileSync(file, "utf8");
|
|
63251
63556
|
} catch {
|
|
63252
63557
|
return null;
|
|
63253
63558
|
}
|
|
@@ -63263,7 +63568,7 @@ function defaultSleep2(ms) {
|
|
|
63263
63568
|
}
|
|
63264
63569
|
async function killStaleFrpc(deps) {
|
|
63265
63570
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
63266
|
-
const tomlPath =
|
|
63571
|
+
const tomlPath = import_node_path56.default.join(deps.dataDir, "frpc.toml");
|
|
63267
63572
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
63268
63573
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
63269
63574
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -63287,7 +63592,7 @@ async function killStaleFrpc(deps) {
|
|
|
63287
63592
|
}
|
|
63288
63593
|
if (victims.size === 0) {
|
|
63289
63594
|
try {
|
|
63290
|
-
|
|
63595
|
+
import_node_fs50.default.unlinkSync(pidFile);
|
|
63291
63596
|
} catch {
|
|
63292
63597
|
}
|
|
63293
63598
|
return;
|
|
@@ -63298,7 +63603,7 @@ async function killStaleFrpc(deps) {
|
|
|
63298
63603
|
}
|
|
63299
63604
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
63300
63605
|
try {
|
|
63301
|
-
|
|
63606
|
+
import_node_fs50.default.unlinkSync(pidFile);
|
|
63302
63607
|
} catch {
|
|
63303
63608
|
}
|
|
63304
63609
|
}
|
|
@@ -63335,7 +63640,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
63335
63640
|
var TunnelManager = class {
|
|
63336
63641
|
constructor(deps) {
|
|
63337
63642
|
this.deps = deps;
|
|
63338
|
-
this.store = deps.store ?? new TunnelStore(
|
|
63643
|
+
this.store = deps.store ?? new TunnelStore(import_node_path57.default.join(deps.dataDir, "tunnel.json"));
|
|
63339
63644
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
63340
63645
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
63341
63646
|
}
|
|
@@ -63462,7 +63767,7 @@ var TunnelManager = class {
|
|
|
63462
63767
|
dataDir: this.deps.dataDir,
|
|
63463
63768
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
63464
63769
|
});
|
|
63465
|
-
const tomlPath =
|
|
63770
|
+
const tomlPath = import_node_path57.default.join(this.deps.dataDir, "frpc.toml");
|
|
63466
63771
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto13.default.randomBytes(3).toString("hex")}`;
|
|
63467
63772
|
const toml = buildFrpcToml({
|
|
63468
63773
|
serverAddr: t.frpsHost,
|
|
@@ -63473,14 +63778,14 @@ var TunnelManager = class {
|
|
|
63473
63778
|
localPort,
|
|
63474
63779
|
logLevel: "info"
|
|
63475
63780
|
});
|
|
63476
|
-
await
|
|
63781
|
+
await import_node_fs51.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
63477
63782
|
const proc = (this.deps.spawnImpl ?? import_node_child_process14.spawn)(frpcBin, ["-c", tomlPath], {
|
|
63478
63783
|
stdio: ["ignore", "pipe", "pipe"]
|
|
63479
63784
|
});
|
|
63480
|
-
const logDir =
|
|
63481
|
-
|
|
63482
|
-
const logFilePath =
|
|
63483
|
-
const logStream =
|
|
63785
|
+
const logDir = import_node_path57.default.join(this.deps.dataDir, "log");
|
|
63786
|
+
import_node_fs51.default.mkdirSync(logDir, { recursive: true });
|
|
63787
|
+
const logFilePath = import_node_path57.default.join(logDir, "frpc.log");
|
|
63788
|
+
const logStream = import_node_fs51.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
63484
63789
|
logStream.on("error", () => {
|
|
63485
63790
|
});
|
|
63486
63791
|
const tee = (chunk) => {
|
|
@@ -63563,27 +63868,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
63563
63868
|
|
|
63564
63869
|
// src/tunnel/device-key.ts
|
|
63565
63870
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
63566
|
-
var
|
|
63871
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
63567
63872
|
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
63568
63873
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
63569
63874
|
function deriveStableDeviceKey(opts = {}) {
|
|
63570
63875
|
const hostname = opts.hostname ?? import_node_os18.default.hostname();
|
|
63571
63876
|
const uid = opts.uid ?? (typeof import_node_os18.default.userInfo === "function" ? import_node_os18.default.userInfo().uid : 0);
|
|
63572
63877
|
const home = opts.home ?? import_node_os18.default.homedir();
|
|
63573
|
-
const defaultDataDir =
|
|
63574
|
-
const normalizedDataDir = opts.dataDir ?
|
|
63878
|
+
const defaultDataDir = import_node_path58.default.resolve(import_node_path58.default.join(home, ".clawd"));
|
|
63879
|
+
const normalizedDataDir = opts.dataDir ? import_node_path58.default.resolve(opts.dataDir) : null;
|
|
63575
63880
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
63576
63881
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
63577
63882
|
return import_node_crypto14.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
63578
63883
|
}
|
|
63579
63884
|
|
|
63580
63885
|
// src/auth-store.ts
|
|
63581
|
-
var
|
|
63582
|
-
var
|
|
63886
|
+
var import_node_fs52 = __toESM(require("fs"), 1);
|
|
63887
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
63583
63888
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
63584
63889
|
var AUTH_FILE_NAME = "auth.json";
|
|
63585
63890
|
function authFilePath(dataDir) {
|
|
63586
|
-
return
|
|
63891
|
+
return import_node_path59.default.join(dataDir, AUTH_FILE_NAME);
|
|
63587
63892
|
}
|
|
63588
63893
|
function loadOrCreateAuthFile(opts) {
|
|
63589
63894
|
const file = authFilePath(opts.dataDir);
|
|
@@ -63615,7 +63920,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
63615
63920
|
}
|
|
63616
63921
|
function readAuthFile(file) {
|
|
63617
63922
|
try {
|
|
63618
|
-
const raw =
|
|
63923
|
+
const raw = import_node_fs52.default.readFileSync(file, "utf8");
|
|
63619
63924
|
const parsed = JSON.parse(raw);
|
|
63620
63925
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
63621
63926
|
return null;
|
|
@@ -63635,26 +63940,26 @@ function readAuthFile(file) {
|
|
|
63635
63940
|
}
|
|
63636
63941
|
}
|
|
63637
63942
|
function writeAuthFile(file, content) {
|
|
63638
|
-
|
|
63639
|
-
|
|
63943
|
+
import_node_fs52.default.mkdirSync(import_node_path59.default.dirname(file), { recursive: true });
|
|
63944
|
+
import_node_fs52.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
63640
63945
|
try {
|
|
63641
|
-
|
|
63946
|
+
import_node_fs52.default.chmodSync(file, 384);
|
|
63642
63947
|
} catch {
|
|
63643
63948
|
}
|
|
63644
63949
|
}
|
|
63645
63950
|
|
|
63646
63951
|
// src/owner-profile.ts
|
|
63647
|
-
var
|
|
63952
|
+
var import_node_fs53 = __toESM(require("fs"), 1);
|
|
63648
63953
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
63649
|
-
var
|
|
63954
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
63650
63955
|
var PROFILE_FILENAME = "profile.json";
|
|
63651
63956
|
function profilePath(dataDir) {
|
|
63652
|
-
return
|
|
63957
|
+
return import_node_path60.default.join(dataDir, PROFILE_FILENAME);
|
|
63653
63958
|
}
|
|
63654
63959
|
function loadOwnerProfile(dataDir) {
|
|
63655
63960
|
let raw;
|
|
63656
63961
|
try {
|
|
63657
|
-
raw =
|
|
63962
|
+
raw = import_node_fs53.default.readFileSync(profilePath(dataDir), "utf8");
|
|
63658
63963
|
} catch {
|
|
63659
63964
|
return {};
|
|
63660
63965
|
}
|
|
@@ -63670,7 +63975,7 @@ function loadOwnerProfile(dataDir) {
|
|
|
63670
63975
|
}
|
|
63671
63976
|
function patchOwnerProfile(dataDir, patch) {
|
|
63672
63977
|
const merged = { ...loadOwnerProfile(dataDir), ...patch };
|
|
63673
|
-
|
|
63978
|
+
import_node_fs53.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
|
|
63674
63979
|
return merged;
|
|
63675
63980
|
}
|
|
63676
63981
|
function loadOwnerDisplayName(dataDir) {
|
|
@@ -63686,18 +63991,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
63686
63991
|
}
|
|
63687
63992
|
|
|
63688
63993
|
// src/feishu-auth/owner-identity-store.ts
|
|
63689
|
-
var
|
|
63690
|
-
var
|
|
63994
|
+
var import_node_fs54 = __toESM(require("fs"), 1);
|
|
63995
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
63691
63996
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
63692
63997
|
var OwnerIdentityStore = class {
|
|
63693
63998
|
file;
|
|
63694
63999
|
constructor(dataDir) {
|
|
63695
|
-
this.file =
|
|
64000
|
+
this.file = import_node_path61.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
63696
64001
|
}
|
|
63697
64002
|
read() {
|
|
63698
64003
|
let raw;
|
|
63699
64004
|
try {
|
|
63700
|
-
raw =
|
|
64005
|
+
raw = import_node_fs54.default.readFileSync(this.file, "utf8");
|
|
63701
64006
|
} catch {
|
|
63702
64007
|
return null;
|
|
63703
64008
|
}
|
|
@@ -63725,16 +64030,16 @@ var OwnerIdentityStore = class {
|
|
|
63725
64030
|
};
|
|
63726
64031
|
}
|
|
63727
64032
|
write(record3) {
|
|
63728
|
-
|
|
63729
|
-
|
|
64033
|
+
import_node_fs54.default.mkdirSync(import_node_path61.default.dirname(this.file), { recursive: true });
|
|
64034
|
+
import_node_fs54.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
|
|
63730
64035
|
try {
|
|
63731
|
-
|
|
64036
|
+
import_node_fs54.default.chmodSync(this.file, 384);
|
|
63732
64037
|
} catch {
|
|
63733
64038
|
}
|
|
63734
64039
|
}
|
|
63735
64040
|
clear() {
|
|
63736
64041
|
try {
|
|
63737
|
-
|
|
64042
|
+
import_node_fs54.default.unlinkSync(this.file);
|
|
63738
64043
|
} catch (err) {
|
|
63739
64044
|
const code = err?.code;
|
|
63740
64045
|
if (code !== "ENOENT") throw err;
|
|
@@ -64195,8 +64500,8 @@ function verifyConnectToken(args) {
|
|
|
64195
64500
|
}
|
|
64196
64501
|
|
|
64197
64502
|
// src/feishu-auth/server-key.ts
|
|
64198
|
-
var
|
|
64199
|
-
var
|
|
64503
|
+
var fs71 = __toESM(require("fs"), 1);
|
|
64504
|
+
var path74 = __toESM(require("path"), 1);
|
|
64200
64505
|
var FILE_NAME2 = "server-signing-key.json";
|
|
64201
64506
|
var ServerKeyStore = class {
|
|
64202
64507
|
constructor(dataDir) {
|
|
@@ -64204,12 +64509,12 @@ var ServerKeyStore = class {
|
|
|
64204
64509
|
}
|
|
64205
64510
|
dataDir;
|
|
64206
64511
|
filePath() {
|
|
64207
|
-
return
|
|
64512
|
+
return path74.join(this.dataDir, FILE_NAME2);
|
|
64208
64513
|
}
|
|
64209
64514
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
64210
64515
|
read() {
|
|
64211
64516
|
try {
|
|
64212
|
-
const raw =
|
|
64517
|
+
const raw = fs71.readFileSync(this.filePath(), "utf8");
|
|
64213
64518
|
const parsed = JSON.parse(raw);
|
|
64214
64519
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
64215
64520
|
return parsed.publicKeyPem;
|
|
@@ -64224,12 +64529,12 @@ var ServerKeyStore = class {
|
|
|
64224
64529
|
publicKeyPem,
|
|
64225
64530
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
64226
64531
|
};
|
|
64227
|
-
|
|
64228
|
-
|
|
64532
|
+
fs71.mkdirSync(this.dataDir, { recursive: true });
|
|
64533
|
+
fs71.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
64229
64534
|
}
|
|
64230
64535
|
clear() {
|
|
64231
64536
|
try {
|
|
64232
|
-
|
|
64537
|
+
fs71.unlinkSync(this.filePath());
|
|
64233
64538
|
} catch {
|
|
64234
64539
|
}
|
|
64235
64540
|
}
|
|
@@ -64239,19 +64544,19 @@ var ServerKeyStore = class {
|
|
|
64239
64544
|
init_protocol();
|
|
64240
64545
|
|
|
64241
64546
|
// src/handlers/index.ts
|
|
64242
|
-
var
|
|
64547
|
+
var import_node_path75 = __toESM(require("path"), 1);
|
|
64243
64548
|
|
|
64244
64549
|
// src/handlers/session.ts
|
|
64245
64550
|
init_protocol();
|
|
64246
64551
|
|
|
64247
64552
|
// src/session/fork.ts
|
|
64248
|
-
var
|
|
64553
|
+
var import_node_fs55 = __toESM(require("fs"), 1);
|
|
64249
64554
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
64250
|
-
var
|
|
64555
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
64251
64556
|
var import_node_crypto17 = require("crypto");
|
|
64252
64557
|
init_claude_history();
|
|
64253
64558
|
function readJsonlEntries(file) {
|
|
64254
|
-
const raw =
|
|
64559
|
+
const raw = import_node_fs55.default.readFileSync(file, "utf8");
|
|
64255
64560
|
const out = [];
|
|
64256
64561
|
for (const line of raw.split("\n")) {
|
|
64257
64562
|
const t = line.trim();
|
|
@@ -64264,19 +64569,19 @@ function readJsonlEntries(file) {
|
|
|
64264
64569
|
return out;
|
|
64265
64570
|
}
|
|
64266
64571
|
function forkSession(input) {
|
|
64267
|
-
const baseDir = input.baseDir ??
|
|
64268
|
-
let projectDir =
|
|
64269
|
-
let sourceFile =
|
|
64270
|
-
if (!
|
|
64572
|
+
const baseDir = input.baseDir ?? import_node_path62.default.join(import_node_os20.default.homedir(), ".claude");
|
|
64573
|
+
let projectDir = import_node_path62.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
64574
|
+
let sourceFile = import_node_path62.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
64575
|
+
if (!import_node_fs55.default.existsSync(sourceFile)) {
|
|
64271
64576
|
const found = findTranscriptByToolSessionId(
|
|
64272
|
-
|
|
64577
|
+
import_node_path62.default.join(baseDir, "projects"),
|
|
64273
64578
|
input.toolSessionId
|
|
64274
64579
|
);
|
|
64275
64580
|
if (!found) {
|
|
64276
64581
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
64277
64582
|
}
|
|
64278
64583
|
sourceFile = found;
|
|
64279
|
-
projectDir =
|
|
64584
|
+
projectDir = import_node_path62.default.dirname(found);
|
|
64280
64585
|
}
|
|
64281
64586
|
const entries = readJsonlEntries(sourceFile);
|
|
64282
64587
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -64305,27 +64610,27 @@ function forkSession(input) {
|
|
|
64305
64610
|
}
|
|
64306
64611
|
forkedLines.push(JSON.stringify(forked));
|
|
64307
64612
|
}
|
|
64308
|
-
const outDir = input.targetCwd ?
|
|
64309
|
-
const forkedFilePath =
|
|
64310
|
-
|
|
64311
|
-
|
|
64613
|
+
const outDir = input.targetCwd ? import_node_path62.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
64614
|
+
const forkedFilePath = import_node_path62.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
64615
|
+
import_node_fs55.default.mkdirSync(outDir, { recursive: true });
|
|
64616
|
+
import_node_fs55.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
64312
64617
|
return { forkedToolSessionId, forkedFilePath };
|
|
64313
64618
|
}
|
|
64314
64619
|
|
|
64315
64620
|
// src/session/external-scan.ts
|
|
64316
|
-
var
|
|
64621
|
+
var import_node_fs56 = __toESM(require("fs"), 1);
|
|
64317
64622
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
64318
64623
|
var import_node_os21 = __toESM(require("os"), 1);
|
|
64319
|
-
var
|
|
64624
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
64320
64625
|
var import_node_module = require("module");
|
|
64321
64626
|
var import_node_child_process15 = require("child_process");
|
|
64322
64627
|
var import_meta5 = {};
|
|
64323
64628
|
function defaultRoots() {
|
|
64324
64629
|
const home = import_node_os21.default.homedir();
|
|
64325
64630
|
return {
|
|
64326
|
-
claudeProjectsDir:
|
|
64327
|
-
codexDir:
|
|
64328
|
-
clawdDir:
|
|
64631
|
+
claudeProjectsDir: import_node_path63.default.join(home, ".claude", "projects"),
|
|
64632
|
+
codexDir: import_node_path63.default.join(home, ".codex"),
|
|
64633
|
+
clawdDir: import_node_path63.default.join(home, ".clawd")
|
|
64329
64634
|
};
|
|
64330
64635
|
}
|
|
64331
64636
|
function width(s) {
|
|
@@ -64376,7 +64681,7 @@ function userText(msg) {
|
|
|
64376
64681
|
}
|
|
64377
64682
|
function isDir2(p2) {
|
|
64378
64683
|
try {
|
|
64379
|
-
return
|
|
64684
|
+
return import_node_fs56.default.statSync(p2).isDirectory();
|
|
64380
64685
|
} catch {
|
|
64381
64686
|
return false;
|
|
64382
64687
|
}
|
|
@@ -64385,7 +64690,7 @@ async function scanClaude(roots) {
|
|
|
64385
64690
|
const out = [];
|
|
64386
64691
|
let dirs;
|
|
64387
64692
|
try {
|
|
64388
|
-
dirs =
|
|
64693
|
+
dirs = import_node_fs56.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
64389
64694
|
} catch {
|
|
64390
64695
|
return out;
|
|
64391
64696
|
}
|
|
@@ -64393,16 +64698,16 @@ async function scanClaude(roots) {
|
|
|
64393
64698
|
if (!d.isDirectory()) continue;
|
|
64394
64699
|
let files;
|
|
64395
64700
|
try {
|
|
64396
|
-
files =
|
|
64701
|
+
files = import_node_fs56.default.readdirSync(import_node_path63.default.join(roots.claudeProjectsDir, d.name));
|
|
64397
64702
|
} catch {
|
|
64398
64703
|
continue;
|
|
64399
64704
|
}
|
|
64400
64705
|
for (const name of files) {
|
|
64401
64706
|
if (!name.endsWith(".jsonl")) continue;
|
|
64402
|
-
const file =
|
|
64707
|
+
const file = import_node_path63.default.join(roots.claudeProjectsDir, d.name, name);
|
|
64403
64708
|
let st;
|
|
64404
64709
|
try {
|
|
64405
|
-
st =
|
|
64710
|
+
st = import_node_fs56.default.statSync(file);
|
|
64406
64711
|
} catch {
|
|
64407
64712
|
continue;
|
|
64408
64713
|
}
|
|
@@ -64455,7 +64760,7 @@ async function scanClaude(roots) {
|
|
|
64455
64760
|
return out;
|
|
64456
64761
|
}
|
|
64457
64762
|
async function countCodexTurns(rolloutPath) {
|
|
64458
|
-
if (!rolloutPath || !
|
|
64763
|
+
if (!rolloutPath || !import_node_fs56.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
64459
64764
|
let turns = 0;
|
|
64460
64765
|
let first = "";
|
|
64461
64766
|
for await (const rec5 of jsonLines(rolloutPath)) {
|
|
@@ -64529,7 +64834,7 @@ async function codexFromRows(rows) {
|
|
|
64529
64834
|
async function scanCodex(roots) {
|
|
64530
64835
|
let dbs = [];
|
|
64531
64836
|
try {
|
|
64532
|
-
dbs =
|
|
64837
|
+
dbs = import_node_fs56.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path63.default.join(roots.codexDir, n));
|
|
64533
64838
|
} catch {
|
|
64534
64839
|
}
|
|
64535
64840
|
if (!dbs.length) return [];
|
|
@@ -64538,14 +64843,14 @@ async function scanCodex(roots) {
|
|
|
64538
64843
|
}
|
|
64539
64844
|
async function scanExternalSessions(rootsIn) {
|
|
64540
64845
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
64541
|
-
const personaRoot =
|
|
64846
|
+
const personaRoot = import_node_path63.default.join(roots.clawdDir, "personas");
|
|
64542
64847
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
64543
64848
|
const out = [];
|
|
64544
64849
|
for (const c of all) {
|
|
64545
64850
|
if (c.skip) continue;
|
|
64546
64851
|
if (c.turns < 1) continue;
|
|
64547
64852
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
64548
|
-
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot +
|
|
64853
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path63.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path63.default.sep)) {
|
|
64549
64854
|
continue;
|
|
64550
64855
|
}
|
|
64551
64856
|
out.push({
|
|
@@ -64562,13 +64867,13 @@ async function scanExternalSessions(rootsIn) {
|
|
|
64562
64867
|
}
|
|
64563
64868
|
|
|
64564
64869
|
// src/session/import-ledger.ts
|
|
64565
|
-
var
|
|
64566
|
-
var
|
|
64870
|
+
var import_node_fs57 = __toESM(require("fs"), 1);
|
|
64871
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
64567
64872
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
64568
64873
|
function readImportLedger(dataDir) {
|
|
64569
64874
|
try {
|
|
64570
64875
|
const parsed = JSON.parse(
|
|
64571
|
-
|
|
64876
|
+
import_node_fs57.default.readFileSync(import_node_path64.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
64572
64877
|
);
|
|
64573
64878
|
return Array.isArray(parsed) ? parsed : [];
|
|
64574
64879
|
} catch {
|
|
@@ -64576,10 +64881,10 @@ function readImportLedger(dataDir) {
|
|
|
64576
64881
|
}
|
|
64577
64882
|
}
|
|
64578
64883
|
function appendImportLedger(dataDir, entry) {
|
|
64579
|
-
const file =
|
|
64884
|
+
const file = import_node_path64.default.join(dataDir, LEDGER_FILENAME);
|
|
64580
64885
|
const entries = readImportLedger(dataDir);
|
|
64581
64886
|
entries.push(entry);
|
|
64582
|
-
|
|
64887
|
+
import_node_fs57.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
64583
64888
|
}
|
|
64584
64889
|
|
|
64585
64890
|
// src/handlers/session.ts
|
|
@@ -65135,7 +65440,7 @@ function buildPermissionHandlers(deps) {
|
|
|
65135
65440
|
}
|
|
65136
65441
|
|
|
65137
65442
|
// src/handlers/history.ts
|
|
65138
|
-
var
|
|
65443
|
+
var path79 = __toESM(require("path"), 1);
|
|
65139
65444
|
init_protocol();
|
|
65140
65445
|
|
|
65141
65446
|
// src/session/recent-dirs.ts
|
|
@@ -65153,7 +65458,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
65153
65458
|
}
|
|
65154
65459
|
|
|
65155
65460
|
// src/permission/persona-paths.ts
|
|
65156
|
-
var
|
|
65461
|
+
var path78 = __toESM(require("path"), 1);
|
|
65157
65462
|
function getAllowedPersonaIds(grants, action) {
|
|
65158
65463
|
const ids = /* @__PURE__ */ new Set();
|
|
65159
65464
|
for (const g2 of grants) {
|
|
@@ -65166,42 +65471,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
65166
65471
|
return ids;
|
|
65167
65472
|
}
|
|
65168
65473
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
65169
|
-
const target =
|
|
65474
|
+
const target = path78.resolve(absPath);
|
|
65170
65475
|
if (userWorkDir) {
|
|
65171
|
-
const u =
|
|
65172
|
-
const usep = u.endsWith(
|
|
65476
|
+
const u = path78.resolve(userWorkDir);
|
|
65477
|
+
const usep = u.endsWith(path78.sep) ? "" : path78.sep;
|
|
65173
65478
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
65174
65479
|
}
|
|
65175
|
-
const root =
|
|
65176
|
-
const sep4 = root.endsWith(
|
|
65480
|
+
const root = path78.resolve(personaRoot);
|
|
65481
|
+
const sep4 = root.endsWith(path78.sep) ? "" : path78.sep;
|
|
65177
65482
|
if (!target.startsWith(root + sep4)) return false;
|
|
65178
|
-
const rel =
|
|
65483
|
+
const rel = path78.relative(root, target);
|
|
65179
65484
|
if (!rel || rel.startsWith("..")) return false;
|
|
65180
|
-
const personaId2 = rel.split(
|
|
65485
|
+
const personaId2 = rel.split(path78.sep)[0];
|
|
65181
65486
|
if (!personaId2) return false;
|
|
65182
65487
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
65183
65488
|
if (allowed === "*") return true;
|
|
65184
65489
|
return allowed.has(personaId2);
|
|
65185
65490
|
}
|
|
65186
65491
|
function personaIdFromPath(absPath, personaRoot) {
|
|
65187
|
-
const root =
|
|
65188
|
-
const target =
|
|
65189
|
-
const sep4 = root.endsWith(
|
|
65492
|
+
const root = path78.resolve(personaRoot);
|
|
65493
|
+
const target = path78.resolve(absPath);
|
|
65494
|
+
const sep4 = root.endsWith(path78.sep) ? "" : path78.sep;
|
|
65190
65495
|
if (!target.startsWith(root + sep4)) return null;
|
|
65191
|
-
const rel =
|
|
65496
|
+
const rel = path78.relative(root, target);
|
|
65192
65497
|
if (!rel || rel.startsWith("..")) return null;
|
|
65193
|
-
const id = rel.split(
|
|
65498
|
+
const id = rel.split(path78.sep)[0];
|
|
65194
65499
|
return id || null;
|
|
65195
65500
|
}
|
|
65196
65501
|
function isPathWithin(dir, absPath) {
|
|
65197
|
-
const d =
|
|
65198
|
-
const t =
|
|
65199
|
-
const sep4 = d.endsWith(
|
|
65502
|
+
const d = path78.resolve(dir);
|
|
65503
|
+
const t = path78.resolve(absPath);
|
|
65504
|
+
const sep4 = d.endsWith(path78.sep) ? "" : path78.sep;
|
|
65200
65505
|
return t === d || t.startsWith(d + sep4);
|
|
65201
65506
|
}
|
|
65202
65507
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
65203
65508
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
65204
|
-
return personaIdFromPath(
|
|
65509
|
+
return personaIdFromPath(path78.resolve(absPath), personaRoot) === personaId2;
|
|
65205
65510
|
}
|
|
65206
65511
|
|
|
65207
65512
|
// src/handlers/history.ts
|
|
@@ -65254,7 +65559,7 @@ function buildHistoryHandlers(deps) {
|
|
|
65254
65559
|
if (!pid) return false;
|
|
65255
65560
|
return isGuestPathAllowed(
|
|
65256
65561
|
ctx.grants,
|
|
65257
|
-
|
|
65562
|
+
path79.join(personaRoot, pid),
|
|
65258
65563
|
personaRoot,
|
|
65259
65564
|
"read",
|
|
65260
65565
|
userWorkDir
|
|
@@ -65266,7 +65571,7 @@ function buildHistoryHandlers(deps) {
|
|
|
65266
65571
|
};
|
|
65267
65572
|
const list = async (frame, _client, ctx) => {
|
|
65268
65573
|
const args = HistoryListArgs.parse(frame);
|
|
65269
|
-
assertGuestPath(ctx,
|
|
65574
|
+
assertGuestPath(ctx, path79.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
65270
65575
|
const sessions = await history.listSessions(args);
|
|
65271
65576
|
return { response: { type: "history:list", sessions } };
|
|
65272
65577
|
};
|
|
@@ -65314,14 +65619,14 @@ function buildHistoryHandlers(deps) {
|
|
|
65314
65619
|
};
|
|
65315
65620
|
const subagents = async (frame, _client, ctx) => {
|
|
65316
65621
|
const args = HistorySubagentsArgs.parse(frame);
|
|
65317
|
-
assertGuestPath(ctx,
|
|
65622
|
+
assertGuestPath(ctx, path79.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
65318
65623
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
65319
65624
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
65320
65625
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
65321
65626
|
};
|
|
65322
65627
|
const subagentRead = async (frame, _client, ctx) => {
|
|
65323
65628
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
65324
|
-
assertGuestPath(ctx,
|
|
65629
|
+
assertGuestPath(ctx, path79.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
65325
65630
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
65326
65631
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
65327
65632
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -65331,7 +65636,7 @@ function buildHistoryHandlers(deps) {
|
|
|
65331
65636
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
65332
65637
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
65333
65638
|
const filtered = dirs.filter(
|
|
65334
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
65639
|
+
(d) => isGuestPathAllowed(ctx.grants, path79.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
65335
65640
|
);
|
|
65336
65641
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
65337
65642
|
}
|
|
@@ -65348,17 +65653,17 @@ function buildHistoryHandlers(deps) {
|
|
|
65348
65653
|
}
|
|
65349
65654
|
|
|
65350
65655
|
// src/handlers/projects.ts
|
|
65351
|
-
var
|
|
65656
|
+
var fs75 = __toESM(require("fs"), 1);
|
|
65352
65657
|
var os23 = __toESM(require("os"), 1);
|
|
65353
|
-
var
|
|
65658
|
+
var path80 = __toESM(require("path"), 1);
|
|
65354
65659
|
var import_node_child_process16 = require("child_process");
|
|
65355
65660
|
init_protocol();
|
|
65356
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
65661
|
+
var DEFAULT_PROJECTS_ROOT = path80.join(os23.homedir(), "Documents", "ChatGPT");
|
|
65357
65662
|
function allocateDir(root, name) {
|
|
65358
|
-
let candidate =
|
|
65663
|
+
let candidate = path80.join(root, name);
|
|
65359
65664
|
let n = 2;
|
|
65360
|
-
while (
|
|
65361
|
-
candidate =
|
|
65665
|
+
while (fs75.existsSync(candidate)) {
|
|
65666
|
+
candidate = path80.join(root, `${name} ${n}`);
|
|
65362
65667
|
n += 1;
|
|
65363
65668
|
}
|
|
65364
65669
|
return candidate;
|
|
@@ -65386,7 +65691,7 @@ function buildProjectHandlers(deps) {
|
|
|
65386
65691
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
65387
65692
|
}
|
|
65388
65693
|
try {
|
|
65389
|
-
if (!
|
|
65694
|
+
if (!fs75.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
65390
65695
|
} catch {
|
|
65391
65696
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
65392
65697
|
}
|
|
@@ -65402,7 +65707,7 @@ function buildProjectHandlers(deps) {
|
|
|
65402
65707
|
let target;
|
|
65403
65708
|
if (args.path) {
|
|
65404
65709
|
try {
|
|
65405
|
-
if (!
|
|
65710
|
+
if (!fs75.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
65406
65711
|
} catch {
|
|
65407
65712
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
65408
65713
|
}
|
|
@@ -65410,15 +65715,15 @@ function buildProjectHandlers(deps) {
|
|
|
65410
65715
|
} else {
|
|
65411
65716
|
const name = args.name;
|
|
65412
65717
|
try {
|
|
65413
|
-
|
|
65718
|
+
fs75.mkdirSync(root, { recursive: true });
|
|
65414
65719
|
target = allocateDir(root, name);
|
|
65415
|
-
|
|
65720
|
+
fs75.mkdirSync(target);
|
|
65416
65721
|
} catch (err) {
|
|
65417
65722
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
65418
65723
|
}
|
|
65419
65724
|
const git2 = (0, import_node_child_process16.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
65420
65725
|
if (git2.status !== 0) {
|
|
65421
|
-
|
|
65726
|
+
fs75.rmSync(target, { recursive: true, force: true });
|
|
65422
65727
|
throw new ClawdError(
|
|
65423
65728
|
ERROR_CODES.INVALID_CWD,
|
|
65424
65729
|
`git init \u5931\u8D25\uFF08${git2.error ? String(git2.error) : `exit ${git2.status}`}\uFF09: ${target}`
|
|
@@ -65443,7 +65748,7 @@ function buildProjectHandlers(deps) {
|
|
|
65443
65748
|
}
|
|
65444
65749
|
|
|
65445
65750
|
// src/handlers/workspace.ts
|
|
65446
|
-
var
|
|
65751
|
+
var path81 = __toESM(require("path"), 1);
|
|
65447
65752
|
init_protocol();
|
|
65448
65753
|
var os24 = __toESM(require("os"), 1);
|
|
65449
65754
|
init_protocol();
|
|
@@ -65486,22 +65791,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
65486
65791
|
const args = WorkspaceListArgs.parse(frame);
|
|
65487
65792
|
const isGuest = ctx?.principal.kind === "guest";
|
|
65488
65793
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os24.homedir();
|
|
65489
|
-
const resolvedCwd =
|
|
65490
|
-
const target = args.path ?
|
|
65794
|
+
const resolvedCwd = path81.resolve(args.cwd ?? fallbackCwd);
|
|
65795
|
+
const target = args.path ? path81.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
65491
65796
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
65492
65797
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
65493
65798
|
return { response: { type: "workspace:list", ...res } };
|
|
65494
65799
|
};
|
|
65495
65800
|
const read = async (frame, _client, ctx) => {
|
|
65496
65801
|
const args = WorkspaceReadArgs.parse(frame);
|
|
65497
|
-
const target =
|
|
65802
|
+
const target = path81.isAbsolute(args.path) ? path81.resolve(args.path) : path81.resolve(args.cwd, args.path);
|
|
65498
65803
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
65499
65804
|
const res = workspace.read(args);
|
|
65500
65805
|
return { response: { type: "workspace:read", ...res } };
|
|
65501
65806
|
};
|
|
65502
65807
|
const skillsList = async (frame, _client, ctx) => {
|
|
65503
65808
|
const args = SkillsListArgs.parse(frame);
|
|
65504
|
-
const cwdAbs =
|
|
65809
|
+
const cwdAbs = path81.resolve(args.cwd);
|
|
65505
65810
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
65506
65811
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
65507
65812
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -65513,7 +65818,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
65513
65818
|
};
|
|
65514
65819
|
const agentsList = async (frame, _client, ctx) => {
|
|
65515
65820
|
const args = AgentsListArgs.parse(frame);
|
|
65516
|
-
const cwdAbs =
|
|
65821
|
+
const cwdAbs = path81.resolve(args.cwd);
|
|
65517
65822
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
65518
65823
|
if (isCodexFamily(args.tool) || args.tool === PI_TOOL_ID) {
|
|
65519
65824
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -65535,20 +65840,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
65535
65840
|
}
|
|
65536
65841
|
|
|
65537
65842
|
// src/handlers/git.ts
|
|
65538
|
-
var
|
|
65843
|
+
var path83 = __toESM(require("path"), 1);
|
|
65539
65844
|
init_protocol();
|
|
65540
65845
|
init_protocol();
|
|
65541
65846
|
|
|
65542
65847
|
// src/workspace/git.ts
|
|
65543
65848
|
var import_node_child_process17 = require("child_process");
|
|
65544
|
-
var
|
|
65545
|
-
var
|
|
65849
|
+
var import_node_fs58 = __toESM(require("fs"), 1);
|
|
65850
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
65546
65851
|
var import_node_util = require("util");
|
|
65547
65852
|
var pexec = (0, import_node_util.promisify)(import_node_child_process17.execFile);
|
|
65548
65853
|
function normalizePath(p2) {
|
|
65549
|
-
const resolved =
|
|
65854
|
+
const resolved = import_node_path65.default.resolve(p2);
|
|
65550
65855
|
try {
|
|
65551
|
-
return
|
|
65856
|
+
return import_node_fs58.default.realpathSync(resolved);
|
|
65552
65857
|
} catch {
|
|
65553
65858
|
return resolved;
|
|
65554
65859
|
}
|
|
@@ -65622,7 +65927,7 @@ async function listGitBranches(cwd) {
|
|
|
65622
65927
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
65623
65928
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
65624
65929
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
65625
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
65930
|
+
if (!isGuestPathAllowed(ctx.grants, path83.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
65626
65931
|
throw new ClawdError(
|
|
65627
65932
|
ERROR_CODES.UNAUTHORIZED,
|
|
65628
65933
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -66191,6 +66496,54 @@ function buildFeishuAuthHandlers(deps) {
|
|
|
66191
66496
|
};
|
|
66192
66497
|
}
|
|
66193
66498
|
|
|
66499
|
+
// src/handlers/cloud-connectors.ts
|
|
66500
|
+
init_protocol();
|
|
66501
|
+
function ensureOwner5(ctx) {
|
|
66502
|
+
if (!ctx || ctx.principal.kind !== "owner") {
|
|
66503
|
+
throw new ClawdError(ERROR_CODES.UNAUTHORIZED, "UNAUTHORIZED: cloud:connectors:* requires owner ctx");
|
|
66504
|
+
}
|
|
66505
|
+
}
|
|
66506
|
+
var invalid2 = (msg) => new ClawdError(ERROR_CODES.VALIDATION_ERROR, `VALIDATION_ERROR: ${msg}`);
|
|
66507
|
+
function buildCloudConnectorsHandlers(deps) {
|
|
66508
|
+
function requireLogin() {
|
|
66509
|
+
const rec5 = deps.readIdentity();
|
|
66510
|
+
if (!rec5) throw new ClawdError(ERROR_CODES.FEISHU_LOGIN_REQUIRED, "FEISHU_LOGIN_REQUIRED: \u8FD8\u6CA1\u767B\u5F55\u98DE\u4E66\uFF0C\u4E91\u4E0A persona \u7684\u8FDE\u63A5\u5668\u7528\u4E0D\u4E86");
|
|
66511
|
+
return rec5;
|
|
66512
|
+
}
|
|
66513
|
+
async function personalConnectors(personaId2) {
|
|
66514
|
+
const persona = deps.getPersona(personaId2);
|
|
66515
|
+
if (!persona) throw new ClawdError(ERROR_CODES.PERSONA_NOT_FOUND, `PERSONA_NOT_FOUND: \u6CA1\u6709\u8FD9\u4E2A persona\uFF08${personaId2}\uFF09`);
|
|
66516
|
+
if (!persona.cloud) throw invalid2(`${personaId2} \u4E0D\u662F\u4E91\u4E0A persona\uFF0C\u6CA1\u6709\u8FDE\u63A5\u5668\u533A`);
|
|
66517
|
+
const all = await deps.gatewayConnectors(persona.cloud.personaId);
|
|
66518
|
+
return { gatewayPersonaId: persona.cloud.personaId, connectors: all.filter((c) => c.credentialSource === "personal") };
|
|
66519
|
+
}
|
|
66520
|
+
const list = async (frame, _client, ctx) => {
|
|
66521
|
+
ensureOwner5(ctx);
|
|
66522
|
+
const { personaId: personaId2 } = parseArgs2(CloudConnectorsListArgsSchema, frame, "cloud:connectors:list");
|
|
66523
|
+
const { gatewayPersonaId, connectors } = await personalConnectors(personaId2);
|
|
66524
|
+
if (connectors.length === 0) return { response: { type: "cloud:connectors:list:ok", connectors: [] } };
|
|
66525
|
+
const login = requireLogin();
|
|
66526
|
+
const r = await deps.central.mine({ ...login, personaId: gatewayPersonaId, connectors });
|
|
66527
|
+
const parsed = CloudConnectorsListResultSchema.safeParse(r);
|
|
66528
|
+
if (!parsed.success) throw new ClawdError(ERROR_CODES.INTERNAL, `\u4E2D\u5FC3\u56DE\u7684\u8FDE\u63A5\u5668\u72B6\u6001\u4E0D\u5408\u5F62\u72B6\uFF1A${parsed.error.issues[0]?.message ?? ""}`);
|
|
66529
|
+
return { response: { type: "cloud:connectors:list:ok", connectors: parsed.data.connectors } };
|
|
66530
|
+
};
|
|
66531
|
+
const fill = async (frame, _client, ctx) => {
|
|
66532
|
+
ensureOwner5(ctx);
|
|
66533
|
+
const args = parseArgs2(CloudConnectorFillArgsSchema, frame, "cloud:connectors:fill");
|
|
66534
|
+
const { connectors } = await personalConnectors(args.personaId);
|
|
66535
|
+
const connector = connectors.find((c) => c.name === args.name);
|
|
66536
|
+
if (!connector) throw invalid2(`\u8FD9\u4E2A persona \u6CA1\u6709\u53EB\u300C${args.name}\u300D\u7684\u3001\u8981\u672C\u4EBA\u586B\u5199\u7684\u8FDE\u63A5\u5668`);
|
|
66537
|
+
const login = requireLogin();
|
|
66538
|
+
await deps.central.fill({ ...login, connector, values: args.values });
|
|
66539
|
+
return { response: { type: "cloud:connectors:fill:ok" } };
|
|
66540
|
+
};
|
|
66541
|
+
return {
|
|
66542
|
+
"cloud:connectors:list": list,
|
|
66543
|
+
"cloud:connectors:fill": fill
|
|
66544
|
+
};
|
|
66545
|
+
}
|
|
66546
|
+
|
|
66194
66547
|
// src/handlers/meta.ts
|
|
66195
66548
|
var import_node_os22 = __toESM(require("os"), 1);
|
|
66196
66549
|
init_protocol();
|
|
@@ -66247,6 +66600,10 @@ var METHOD_GRANT_MAP = {
|
|
|
66247
66600
|
"deploy:finishScan": ADMIN_ANY,
|
|
66248
66601
|
"deploy:release": ADMIN_ANY,
|
|
66249
66602
|
"deploy:rerunJob": ADMIN_ANY,
|
|
66603
|
+
// cloud:connectors:*(云 persona 卡片上的连接器;design 2026-09-11-mcp-connector):
|
|
66604
|
+
// 拿本机登录凭证向中心代查 / 代填使用者本人的凭据,guest 一律够不着
|
|
66605
|
+
"cloud:connectors:list": ADMIN_ANY,
|
|
66606
|
+
"cloud:connectors:fill": ADMIN_ANY,
|
|
66250
66607
|
// ---- session:* / chat:* 业务方法(v2 Phase 8 两层模型)----
|
|
66251
66608
|
// dispatcher 不验资源,handler 内按 ctx + frame.args 反查 ownerPersonaId 调 assertGrant。
|
|
66252
66609
|
// owner 自动通过(ctx 自带 '*':'admin' grant 一切 match);guest 在被授权 persona 内可调。
|
|
@@ -66508,21 +66865,21 @@ function computeMethodAccess(args) {
|
|
|
66508
66865
|
}
|
|
66509
66866
|
|
|
66510
66867
|
// src/version.ts
|
|
66511
|
-
var version = "0.2.
|
|
66868
|
+
var version = "0.2.504".length > 0 ? "0.2.504" : "dev";
|
|
66512
66869
|
|
|
66513
66870
|
// src/cli-probe/probe.ts
|
|
66514
|
-
var
|
|
66515
|
-
var
|
|
66871
|
+
var fs77 = __toESM(require("fs"), 1);
|
|
66872
|
+
var path84 = __toESM(require("path"), 1);
|
|
66516
66873
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
66517
66874
|
var BIN_NAME = "clawd";
|
|
66518
66875
|
var MAX_PARENT_HOPS = 5;
|
|
66519
66876
|
function probeGlobalCli(pathEnv) {
|
|
66520
66877
|
if (!pathEnv) return null;
|
|
66521
|
-
for (const dir of pathEnv.split(
|
|
66878
|
+
for (const dir of pathEnv.split(path84.delimiter)) {
|
|
66522
66879
|
if (!dir) continue;
|
|
66523
66880
|
let real;
|
|
66524
66881
|
try {
|
|
66525
|
-
real =
|
|
66882
|
+
real = fs77.realpathSync(path84.join(dir, BIN_NAME));
|
|
66526
66883
|
} catch {
|
|
66527
66884
|
continue;
|
|
66528
66885
|
}
|
|
@@ -66532,15 +66889,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
66532
66889
|
return null;
|
|
66533
66890
|
}
|
|
66534
66891
|
function readOwnPackageVersion(entryPath) {
|
|
66535
|
-
let dir =
|
|
66892
|
+
let dir = path84.dirname(entryPath);
|
|
66536
66893
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
66537
66894
|
try {
|
|
66538
|
-
const raw =
|
|
66895
|
+
const raw = fs77.readFileSync(path84.join(dir, "package.json"), "utf8");
|
|
66539
66896
|
const pkg = JSON.parse(raw);
|
|
66540
66897
|
if (pkg.name !== PKG_NAME) return null;
|
|
66541
66898
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
66542
66899
|
} catch {
|
|
66543
|
-
const parent =
|
|
66900
|
+
const parent = path84.dirname(dir);
|
|
66544
66901
|
if (parent === dir) return null;
|
|
66545
66902
|
dir = parent;
|
|
66546
66903
|
}
|
|
@@ -66716,7 +67073,7 @@ function buildPersonaHandlers(deps) {
|
|
|
66716
67073
|
}
|
|
66717
67074
|
|
|
66718
67075
|
// src/handlers/attachment.ts
|
|
66719
|
-
var
|
|
67076
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
66720
67077
|
init_protocol();
|
|
66721
67078
|
init_protocol();
|
|
66722
67079
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -66796,12 +67153,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
66796
67153
|
`session ${args.sessionId} scope unresolved`
|
|
66797
67154
|
);
|
|
66798
67155
|
}
|
|
66799
|
-
const cwdAbs =
|
|
66800
|
-
const candidateAbs =
|
|
67156
|
+
const cwdAbs = import_node_path66.default.resolve(sessionFile.cwd);
|
|
67157
|
+
const candidateAbs = import_node_path66.default.isAbsolute(args.relPath) ? import_node_path66.default.resolve(args.relPath) : import_node_path66.default.resolve(cwdAbs, args.relPath);
|
|
66801
67158
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
66802
67159
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
66803
67160
|
const entry = entries.find((e) => {
|
|
66804
|
-
const storedAbs =
|
|
67161
|
+
const storedAbs = import_node_path66.default.isAbsolute(e.relPath) ? import_node_path66.default.resolve(e.relPath) : import_node_path66.default.resolve(cwdAbs, e.relPath);
|
|
66805
67162
|
return storedAbs === candidateAbs && !e.stale;
|
|
66806
67163
|
});
|
|
66807
67164
|
if (!entry) {
|
|
@@ -66826,7 +67183,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
66826
67183
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
66827
67184
|
const f = deps.sessionStore.read(sessionId);
|
|
66828
67185
|
if (!f) return;
|
|
66829
|
-
assertGuestAttachmentPath(ctx,
|
|
67186
|
+
assertGuestAttachmentPath(ctx, import_node_path66.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
66830
67187
|
}
|
|
66831
67188
|
const groupAdd = async (frame, _client, ctx) => {
|
|
66832
67189
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -66841,8 +67198,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
66841
67198
|
if (!scope) {
|
|
66842
67199
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
66843
67200
|
}
|
|
66844
|
-
const cwdAbs =
|
|
66845
|
-
const candidateAbs =
|
|
67201
|
+
const cwdAbs = import_node_path66.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
67202
|
+
const candidateAbs = import_node_path66.default.isAbsolute(args.relPath) ? import_node_path66.default.resolve(args.relPath) : import_node_path66.default.resolve(cwdAbs, args.relPath);
|
|
66846
67203
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
66847
67204
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
66848
67205
|
const size = 0;
|
|
@@ -66901,19 +67258,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
66901
67258
|
|
|
66902
67259
|
// src/handlers/extension.ts
|
|
66903
67260
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
66904
|
-
var
|
|
67261
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
66905
67262
|
init_protocol();
|
|
66906
67263
|
|
|
66907
67264
|
// src/extension/bundle-zip.ts
|
|
66908
67265
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
66909
|
-
var
|
|
67266
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
66910
67267
|
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
66911
67268
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
66912
67269
|
async function bundleExtensionDir(dir) {
|
|
66913
67270
|
const entries = await listFilesSorted(dir);
|
|
66914
67271
|
const zip = new import_jszip2.default();
|
|
66915
67272
|
for (const rel of entries) {
|
|
66916
|
-
const abs =
|
|
67273
|
+
const abs = import_node_path67.default.join(dir, rel);
|
|
66917
67274
|
const content = await import_promises11.default.readFile(abs);
|
|
66918
67275
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
66919
67276
|
}
|
|
@@ -66934,7 +67291,7 @@ async function listFilesSorted(rootDir) {
|
|
|
66934
67291
|
return out;
|
|
66935
67292
|
}
|
|
66936
67293
|
async function walk(absRoot, relPrefix, out) {
|
|
66937
|
-
const dirAbs =
|
|
67294
|
+
const dirAbs = import_node_path67.default.join(absRoot, relPrefix);
|
|
66938
67295
|
const entries = await import_promises11.default.readdir(dirAbs, { withFileTypes: true });
|
|
66939
67296
|
for (const e of entries) {
|
|
66940
67297
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -66988,25 +67345,25 @@ function computePublishCheck(args) {
|
|
|
66988
67345
|
|
|
66989
67346
|
// src/extension/install-flow.ts
|
|
66990
67347
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
66991
|
-
var
|
|
67348
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
66992
67349
|
var import_node_os24 = __toESM(require("os"), 1);
|
|
66993
67350
|
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
66994
67351
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
66995
67352
|
|
|
66996
67353
|
// src/extension/paths.ts
|
|
66997
67354
|
var import_node_os23 = __toESM(require("os"), 1);
|
|
66998
|
-
var
|
|
67355
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
66999
67356
|
function clawdHomeRoot(override) {
|
|
67000
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
67357
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path68.default.join(import_node_os23.default.homedir(), ".clawd");
|
|
67001
67358
|
}
|
|
67002
67359
|
function extensionsRoot(override) {
|
|
67003
|
-
return
|
|
67360
|
+
return import_node_path68.default.join(clawdHomeRoot(override), "extensions");
|
|
67004
67361
|
}
|
|
67005
67362
|
function publishedChannelsFile(override) {
|
|
67006
|
-
return
|
|
67363
|
+
return import_node_path68.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
67007
67364
|
}
|
|
67008
67365
|
function bundleCacheRoot(override) {
|
|
67009
|
-
return
|
|
67366
|
+
return import_node_path68.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
67010
67367
|
}
|
|
67011
67368
|
|
|
67012
67369
|
// src/extension/install-flow.ts
|
|
@@ -67033,7 +67390,7 @@ async function installFromChannel(args, deps) {
|
|
|
67033
67390
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
67034
67391
|
}
|
|
67035
67392
|
for (const name of Object.keys(zip.files)) {
|
|
67036
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
67393
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path69.default.isAbsolute(name)) {
|
|
67037
67394
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
67038
67395
|
}
|
|
67039
67396
|
}
|
|
@@ -67065,7 +67422,7 @@ async function installFromChannel(args, deps) {
|
|
|
67065
67422
|
);
|
|
67066
67423
|
}
|
|
67067
67424
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
67068
|
-
const destDir =
|
|
67425
|
+
const destDir = import_node_path69.default.join(deps.extensionsRoot, localExtId);
|
|
67069
67426
|
let destExists = false;
|
|
67070
67427
|
try {
|
|
67071
67428
|
await import_promises12.default.access(destDir);
|
|
@@ -67079,16 +67436,16 @@ async function installFromChannel(args, deps) {
|
|
|
67079
67436
|
);
|
|
67080
67437
|
}
|
|
67081
67438
|
const stage = await import_promises12.default.mkdtemp(
|
|
67082
|
-
|
|
67439
|
+
import_node_path69.default.join(import_node_os24.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
67083
67440
|
);
|
|
67084
67441
|
try {
|
|
67085
67442
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
67086
|
-
const dest =
|
|
67443
|
+
const dest = import_node_path69.default.join(stage, name);
|
|
67087
67444
|
if (entry.dir) {
|
|
67088
67445
|
await import_promises12.default.mkdir(dest, { recursive: true });
|
|
67089
67446
|
continue;
|
|
67090
67447
|
}
|
|
67091
|
-
await import_promises12.default.mkdir(
|
|
67448
|
+
await import_promises12.default.mkdir(import_node_path69.default.dirname(dest), { recursive: true });
|
|
67092
67449
|
if (name === "manifest.json") {
|
|
67093
67450
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
67094
67451
|
await import_promises12.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -67109,7 +67466,7 @@ async function installFromChannel(args, deps) {
|
|
|
67109
67466
|
|
|
67110
67467
|
// src/extension/update-flow.ts
|
|
67111
67468
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
67112
|
-
var
|
|
67469
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
67113
67470
|
var import_node_os25 = __toESM(require("os"), 1);
|
|
67114
67471
|
var import_node_crypto20 = __toESM(require("crypto"), 1);
|
|
67115
67472
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -67126,11 +67483,11 @@ async function updateFromChannel(args, deps) {
|
|
|
67126
67483
|
channelRef.extId,
|
|
67127
67484
|
channelRef.ownerPrincipalId
|
|
67128
67485
|
);
|
|
67129
|
-
const liveDir =
|
|
67486
|
+
const liveDir = import_node_path70.default.join(deps.extensionsRoot, localExtId);
|
|
67130
67487
|
const prevDir = `${liveDir}.prev`;
|
|
67131
67488
|
let existingVersion;
|
|
67132
67489
|
try {
|
|
67133
|
-
const raw = await import_promises13.default.readFile(
|
|
67490
|
+
const raw = await import_promises13.default.readFile(import_node_path70.default.join(liveDir, "manifest.json"), "utf8");
|
|
67134
67491
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
67135
67492
|
if (!parsed2.success) {
|
|
67136
67493
|
throw new UpdateError(
|
|
@@ -67163,7 +67520,7 @@ async function updateFromChannel(args, deps) {
|
|
|
67163
67520
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
67164
67521
|
}
|
|
67165
67522
|
for (const name of Object.keys(zip.files)) {
|
|
67166
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
67523
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path70.default.isAbsolute(name)) {
|
|
67167
67524
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
67168
67525
|
}
|
|
67169
67526
|
}
|
|
@@ -67198,16 +67555,16 @@ async function updateFromChannel(args, deps) {
|
|
|
67198
67555
|
await import_promises13.default.rm(prevDir, { recursive: true, force: true });
|
|
67199
67556
|
await import_promises13.default.rename(liveDir, prevDir);
|
|
67200
67557
|
const stage = await import_promises13.default.mkdtemp(
|
|
67201
|
-
|
|
67558
|
+
import_node_path70.default.join(import_node_os25.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
67202
67559
|
);
|
|
67203
67560
|
try {
|
|
67204
67561
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
67205
|
-
const dest =
|
|
67562
|
+
const dest = import_node_path70.default.join(stage, name);
|
|
67206
67563
|
if (entry.dir) {
|
|
67207
67564
|
await import_promises13.default.mkdir(dest, { recursive: true });
|
|
67208
67565
|
continue;
|
|
67209
67566
|
}
|
|
67210
|
-
await import_promises13.default.mkdir(
|
|
67567
|
+
await import_promises13.default.mkdir(import_node_path70.default.dirname(dest), { recursive: true });
|
|
67211
67568
|
if (name === "manifest.json") {
|
|
67212
67569
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
67213
67570
|
await import_promises13.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -67274,7 +67631,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
67274
67631
|
);
|
|
67275
67632
|
}
|
|
67276
67633
|
}
|
|
67277
|
-
const manifestPath =
|
|
67634
|
+
const manifestPath = import_node_path71.default.join(root, extId, "manifest.json");
|
|
67278
67635
|
const manifest = await readManifest(root, extId);
|
|
67279
67636
|
const next = { ...manifest, version: newVersion };
|
|
67280
67637
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -67282,7 +67639,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
67282
67639
|
await import_promises14.default.rename(tmp, manifestPath);
|
|
67283
67640
|
}
|
|
67284
67641
|
async function readManifest(root, extId) {
|
|
67285
|
-
const file =
|
|
67642
|
+
const file = import_node_path71.default.join(root, extId, "manifest.json");
|
|
67286
67643
|
let raw;
|
|
67287
67644
|
try {
|
|
67288
67645
|
raw = await import_promises14.default.readFile(file, "utf8");
|
|
@@ -67366,7 +67723,7 @@ function buildExtensionHandlers(deps) {
|
|
|
67366
67723
|
};
|
|
67367
67724
|
async function buildSnapshotMeta(extId) {
|
|
67368
67725
|
const manifest = await readManifest(deps.root, extId);
|
|
67369
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
67726
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path71.default.join(deps.root, extId));
|
|
67370
67727
|
return { manifest, contentHash: sha256, buffer };
|
|
67371
67728
|
}
|
|
67372
67729
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -67609,8 +67966,8 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
|
67609
67966
|
|
|
67610
67967
|
// src/handlers/app-builder.ts
|
|
67611
67968
|
init_protocol();
|
|
67612
|
-
var
|
|
67613
|
-
var
|
|
67969
|
+
var import_node_path72 = require("path");
|
|
67970
|
+
var import_node_fs59 = require("fs");
|
|
67614
67971
|
var DEFAULT_TEMPLATE = "nestjs-react";
|
|
67615
67972
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
67616
67973
|
function buildAppBuilderHandlers(deps) {
|
|
@@ -67683,7 +68040,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
67683
68040
|
async function listAllUsersProjects() {
|
|
67684
68041
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
67685
68042
|
const getStore = deps.getStore;
|
|
67686
|
-
const userIds = await
|
|
68043
|
+
const userIds = await import_node_fs59.promises.readdir(deps.usersRoot).catch(() => []);
|
|
67687
68044
|
const perUser = await Promise.all(
|
|
67688
68045
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
67689
68046
|
);
|
|
@@ -67756,13 +68113,13 @@ function buildAppBuilderHandlers(deps) {
|
|
|
67756
68113
|
const created = await deps.createProjectOnDisk({
|
|
67757
68114
|
store: userStore,
|
|
67758
68115
|
name: f.name,
|
|
67759
|
-
templateSrcDir: (0,
|
|
67760
|
-
scaffoldScript: (0,
|
|
68116
|
+
templateSrcDir: (0, import_node_path72.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE),
|
|
68117
|
+
scaffoldScript: (0, import_node_path72.join)(deps.deployKitRoot, "scripts", "new-extension.sh"),
|
|
67761
68118
|
reservedPorts,
|
|
67762
68119
|
// 凭据只进 scaffold 子进程的 env,且**只给这个 persona 的 kit 模板声明要的那几个变量**
|
|
67763
68120
|
// (M1b Step 5)。整表塞进去粒度只到「进程」——那会把 service-role key 交给一个用不到
|
|
67764
68121
|
// 它的脚本。new-extension.sh 用它把模板的 `${VAR}` 渲成项目可跑的 server/.env。
|
|
67765
|
-
extraEnv: secretsForKit(deps.readSecrets?.(), (0,
|
|
68122
|
+
extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path72.join)(personaRoot, "extension-kit")),
|
|
67766
68123
|
...deps.logger ? { logger: deps.logger } : {}
|
|
67767
68124
|
});
|
|
67768
68125
|
project = created.project;
|
|
@@ -67961,7 +68318,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
67961
68318
|
await userStore.clearPublishJob(args.name);
|
|
67962
68319
|
}
|
|
67963
68320
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
67964
|
-
const scriptPath = (0,
|
|
68321
|
+
const scriptPath = (0, import_node_path72.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
67965
68322
|
deps.logger?.info("app-builder.publish.start", {
|
|
67966
68323
|
name: args.name,
|
|
67967
68324
|
sessionId: boundSession.sessionId,
|
|
@@ -67977,7 +68334,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
67977
68334
|
// 凭据只进 publish.sh 这个子进程的 env,且只给它的 kit 模板声明要的那几个变量
|
|
67978
68335
|
// (M1b Step 5)。那个进程里跑着 `eval "$BUILD_CMD"`——项目自带的构建命令会继承这份
|
|
67979
68336
|
// env,多给一个变量就是多交一个凭据给它。personaRoot 上面已按绑定 session 的 persona 解析。
|
|
67980
|
-
extraEnv: secretsForKit(deps.readSecrets?.(), (0,
|
|
68337
|
+
extraEnv: secretsForKit(deps.readSecrets?.(), (0, import_node_path72.join)(personaRoot, "extension-kit")),
|
|
67981
68338
|
hooks: {
|
|
67982
68339
|
// 元数据每次写盘(publishJob 起落 / prodUrl 回填)后重推一帧:UI 渲染 PublishProgress
|
|
67983
68340
|
// 三段 checklist 依赖 project.publishJob.status==='in-flight',而 publishJob 字段只有
|
|
@@ -68688,7 +69045,7 @@ function buildGithubHandlers(deps) {
|
|
|
68688
69045
|
|
|
68689
69046
|
// src/handlers/visitor.ts
|
|
68690
69047
|
init_protocol();
|
|
68691
|
-
function
|
|
69048
|
+
function ensureOwner6(ctx) {
|
|
68692
69049
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
68693
69050
|
throw new ClawdError(
|
|
68694
69051
|
ERROR_CODES.UNAUTHORIZED,
|
|
@@ -68698,7 +69055,7 @@ function ensureOwner5(ctx) {
|
|
|
68698
69055
|
}
|
|
68699
69056
|
function buildVisitorHandlers(deps) {
|
|
68700
69057
|
const list = async (_frame, _client, ctx) => {
|
|
68701
|
-
|
|
69058
|
+
ensureOwner6(ctx);
|
|
68702
69059
|
return {
|
|
68703
69060
|
response: {
|
|
68704
69061
|
type: "visitor:list",
|
|
@@ -68713,7 +69070,7 @@ function buildVisitorHandlers(deps) {
|
|
|
68713
69070
|
|
|
68714
69071
|
// src/extension/registry.ts
|
|
68715
69072
|
var import_promises16 = __toESM(require("fs/promises"), 1);
|
|
68716
|
-
var
|
|
69073
|
+
var import_node_path73 = __toESM(require("path"), 1);
|
|
68717
69074
|
async function loadAll(root) {
|
|
68718
69075
|
let entries;
|
|
68719
69076
|
try {
|
|
@@ -68726,13 +69083,13 @@ async function loadAll(root) {
|
|
|
68726
69083
|
for (const ent of entries) {
|
|
68727
69084
|
if (!ent.isDirectory()) continue;
|
|
68728
69085
|
if (ent.name.startsWith(".")) continue;
|
|
68729
|
-
records.push(await loadOne(
|
|
69086
|
+
records.push(await loadOne(import_node_path73.default.join(root, ent.name), ent.name));
|
|
68730
69087
|
}
|
|
68731
69088
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
68732
69089
|
return records;
|
|
68733
69090
|
}
|
|
68734
69091
|
async function loadOne(dir, dirName) {
|
|
68735
|
-
const manifestPath =
|
|
69092
|
+
const manifestPath = import_node_path73.default.join(dir, "manifest.json");
|
|
68736
69093
|
let raw;
|
|
68737
69094
|
try {
|
|
68738
69095
|
raw = await import_promises16.default.readFile(manifestPath, "utf8");
|
|
@@ -68777,7 +69134,7 @@ async function loadOne(dir, dirName) {
|
|
|
68777
69134
|
|
|
68778
69135
|
// src/extension/uninstall.ts
|
|
68779
69136
|
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
68780
|
-
var
|
|
69137
|
+
var import_node_path74 = __toESM(require("path"), 1);
|
|
68781
69138
|
var UninstallError = class extends Error {
|
|
68782
69139
|
constructor(code, message) {
|
|
68783
69140
|
super(message);
|
|
@@ -68786,7 +69143,7 @@ var UninstallError = class extends Error {
|
|
|
68786
69143
|
code;
|
|
68787
69144
|
};
|
|
68788
69145
|
async function uninstall(deps) {
|
|
68789
|
-
const dir =
|
|
69146
|
+
const dir = import_node_path74.default.join(deps.root, deps.extId);
|
|
68790
69147
|
try {
|
|
68791
69148
|
await import_promises17.default.access(dir);
|
|
68792
69149
|
} catch {
|
|
@@ -68985,6 +69342,7 @@ function buildMethodHandlers(deps) {
|
|
|
68985
69342
|
}),
|
|
68986
69343
|
...buildFeishuAuthHandlers(deps.feishuAuth),
|
|
68987
69344
|
...buildDeviceHandlers(deps.feishuDevice),
|
|
69345
|
+
...buildCloudConnectorsHandlers(deps.cloudConnectors),
|
|
68988
69346
|
...deps.attachment ? buildAttachmentHandlers(deps.attachment) : {},
|
|
68989
69347
|
...buildExtensionHandlers({
|
|
68990
69348
|
loadAll,
|
|
@@ -69023,7 +69381,7 @@ function buildMethodHandlers(deps) {
|
|
|
69023
69381
|
broadcast: deps.broadcastToOwners
|
|
69024
69382
|
}),
|
|
69025
69383
|
...buildMasterHandlers({
|
|
69026
|
-
authorityTablePath:
|
|
69384
|
+
authorityTablePath: import_node_path75.default.join(deps.masterDataDir, "master-authority.json")
|
|
69027
69385
|
}),
|
|
69028
69386
|
...buildTopicHandlers({
|
|
69029
69387
|
topicStore: deps.topicStore,
|
|
@@ -69070,8 +69428,8 @@ function refreshPathFromLoginShell() {
|
|
|
69070
69428
|
timeout: 3e3,
|
|
69071
69429
|
stdio: ["ignore", "pipe", "ignore"]
|
|
69072
69430
|
});
|
|
69073
|
-
const
|
|
69074
|
-
if (
|
|
69431
|
+
const path101 = out.trim();
|
|
69432
|
+
if (path101) process.env.PATH = path101;
|
|
69075
69433
|
} catch {
|
|
69076
69434
|
}
|
|
69077
69435
|
}
|
|
@@ -69195,9 +69553,9 @@ function buildOnboardingHandlers(deps) {
|
|
|
69195
69553
|
}
|
|
69196
69554
|
|
|
69197
69555
|
// src/app-builder-plugin/project-store.ts
|
|
69198
|
-
var
|
|
69556
|
+
var import_node_fs60 = require("fs");
|
|
69199
69557
|
var import_node_child_process22 = require("child_process");
|
|
69200
|
-
var
|
|
69558
|
+
var import_node_path76 = require("path");
|
|
69201
69559
|
init_protocol();
|
|
69202
69560
|
var PROJECTS_DIR = "projects";
|
|
69203
69561
|
var META_FILE = ".clawd-project.json";
|
|
@@ -69227,19 +69585,19 @@ var ProjectStore = class {
|
|
|
69227
69585
|
}
|
|
69228
69586
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
69229
69587
|
metaPath(name) {
|
|
69230
|
-
return (0,
|
|
69588
|
+
return (0, import_node_path76.join)(this.projectsRoot(), name, META_FILE);
|
|
69231
69589
|
}
|
|
69232
69590
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
69233
69591
|
projectDir(name) {
|
|
69234
|
-
return (0,
|
|
69592
|
+
return (0, import_node_path76.join)(this.projectsRoot(), name);
|
|
69235
69593
|
}
|
|
69236
69594
|
projectsRoot() {
|
|
69237
|
-
return (0,
|
|
69595
|
+
return (0, import_node_path76.join)(this.root, PROJECTS_DIR);
|
|
69238
69596
|
}
|
|
69239
69597
|
async list() {
|
|
69240
69598
|
let entries;
|
|
69241
69599
|
try {
|
|
69242
|
-
entries = await
|
|
69600
|
+
entries = await import_node_fs60.promises.readdir(this.projectsRoot());
|
|
69243
69601
|
} catch (err) {
|
|
69244
69602
|
if (err.code === "ENOENT") return [];
|
|
69245
69603
|
throw err;
|
|
@@ -69247,7 +69605,7 @@ var ProjectStore = class {
|
|
|
69247
69605
|
const out = [];
|
|
69248
69606
|
for (const name of entries) {
|
|
69249
69607
|
try {
|
|
69250
|
-
const raw = await
|
|
69608
|
+
const raw = await import_node_fs60.promises.readFile(this.metaPath(name), "utf8");
|
|
69251
69609
|
const json = JSON.parse(raw);
|
|
69252
69610
|
let migrated = false;
|
|
69253
69611
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -69258,7 +69616,7 @@ var ProjectStore = class {
|
|
|
69258
69616
|
if (parsed.success) {
|
|
69259
69617
|
out.push(parsed.data);
|
|
69260
69618
|
if (migrated) {
|
|
69261
|
-
void
|
|
69619
|
+
void import_node_fs60.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
69262
69620
|
});
|
|
69263
69621
|
}
|
|
69264
69622
|
}
|
|
@@ -69302,8 +69660,8 @@ var ProjectStore = class {
|
|
|
69302
69660
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
69303
69661
|
}
|
|
69304
69662
|
const dir = this.projectDir(name);
|
|
69305
|
-
await
|
|
69306
|
-
await
|
|
69663
|
+
await import_node_fs60.promises.mkdir(dir, { recursive: true });
|
|
69664
|
+
await import_node_fs60.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
69307
69665
|
return meta;
|
|
69308
69666
|
}
|
|
69309
69667
|
/**
|
|
@@ -69348,7 +69706,7 @@ var ProjectStore = class {
|
|
|
69348
69706
|
}
|
|
69349
69707
|
async delete(name) {
|
|
69350
69708
|
const dir = this.projectDir(name);
|
|
69351
|
-
await
|
|
69709
|
+
await import_node_fs60.promises.rm(dir, { recursive: true, force: true });
|
|
69352
69710
|
}
|
|
69353
69711
|
async updatePort(name, newPort) {
|
|
69354
69712
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -69365,7 +69723,7 @@ var ProjectStore = class {
|
|
|
69365
69723
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
69366
69724
|
}
|
|
69367
69725
|
const updated = { ...target, port: newPort };
|
|
69368
|
-
await
|
|
69726
|
+
await import_node_fs60.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
69369
69727
|
return updated;
|
|
69370
69728
|
});
|
|
69371
69729
|
}
|
|
@@ -69384,7 +69742,7 @@ var ProjectStore = class {
|
|
|
69384
69742
|
if (!validated.success) {
|
|
69385
69743
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
69386
69744
|
}
|
|
69387
|
-
await
|
|
69745
|
+
await import_node_fs60.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
69388
69746
|
return validated.data;
|
|
69389
69747
|
});
|
|
69390
69748
|
}
|
|
@@ -69407,7 +69765,7 @@ var ProjectStore = class {
|
|
|
69407
69765
|
if (!validated.success) {
|
|
69408
69766
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
69409
69767
|
}
|
|
69410
|
-
await
|
|
69768
|
+
await import_node_fs60.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
69411
69769
|
return validated.data;
|
|
69412
69770
|
});
|
|
69413
69771
|
}
|
|
@@ -69424,7 +69782,7 @@ var ProjectStore = class {
|
|
|
69424
69782
|
if (!validated.success) {
|
|
69425
69783
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
69426
69784
|
}
|
|
69427
|
-
await
|
|
69785
|
+
await import_node_fs60.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
69428
69786
|
return validated.data;
|
|
69429
69787
|
});
|
|
69430
69788
|
}
|
|
@@ -69739,8 +70097,8 @@ var PublishJobRegistry = class {
|
|
|
69739
70097
|
|
|
69740
70098
|
// src/app-builder-plugin/publish-job-runner.ts
|
|
69741
70099
|
var import_node_child_process24 = require("child_process");
|
|
69742
|
-
var
|
|
69743
|
-
var
|
|
70100
|
+
var import_node_fs61 = require("fs");
|
|
70101
|
+
var import_node_path77 = require("path");
|
|
69744
70102
|
|
|
69745
70103
|
// src/app-builder-plugin/publish-stage-parser.ts
|
|
69746
70104
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -69772,10 +70130,10 @@ async function startPublishJob(deps, args) {
|
|
|
69772
70130
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
69773
70131
|
}
|
|
69774
70132
|
const projDir = projectDir(args.name);
|
|
69775
|
-
const logPath = (0,
|
|
70133
|
+
const logPath = (0, import_node_path77.join)(projDir, ".publish.log");
|
|
69776
70134
|
let logStream = null;
|
|
69777
70135
|
try {
|
|
69778
|
-
logStream = (0,
|
|
70136
|
+
logStream = (0, import_node_fs61.createWriteStream)(logPath, { flags: "w" });
|
|
69779
70137
|
} catch {
|
|
69780
70138
|
logStream = null;
|
|
69781
70139
|
}
|
|
@@ -70118,10 +70476,10 @@ async function recoverInterruptedPublishJobs(store, logger) {
|
|
|
70118
70476
|
}
|
|
70119
70477
|
|
|
70120
70478
|
// src/app-builder-plugin/mcp-config.ts
|
|
70121
|
-
var
|
|
70122
|
-
var
|
|
70479
|
+
var import_node_fs62 = __toESM(require("fs"), 1);
|
|
70480
|
+
var import_node_path78 = __toESM(require("path"), 1);
|
|
70123
70481
|
function appBuilderMcpConfigPath(dataDir) {
|
|
70124
|
-
return
|
|
70482
|
+
return import_node_path78.default.join(dataDir, "app-builder.mcp.json");
|
|
70125
70483
|
}
|
|
70126
70484
|
function writeAppBuilderMcpConfig(args) {
|
|
70127
70485
|
const cfgPath = appBuilderMcpConfigPath(args.dataDir);
|
|
@@ -70135,15 +70493,15 @@ function writeAppBuilderMcpConfig(args) {
|
|
|
70135
70493
|
env: {
|
|
70136
70494
|
CLAWD_DAEMON_TOKEN: args.daemonToken,
|
|
70137
70495
|
CLAWD_DAEMON_URL: args.daemonUrl,
|
|
70138
|
-
CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT:
|
|
70139
|
-
CLAWD_APP_BUILDER_PUBLISH_SCRIPT:
|
|
70496
|
+
CLAWD_APP_BUILDER_SCAFFOLD_SCRIPT: import_node_path78.default.join(args.deployKitScriptsDir, "new-extension.sh"),
|
|
70497
|
+
CLAWD_APP_BUILDER_PUBLISH_SCRIPT: import_node_path78.default.join(args.deployKitScriptsDir, "publish.sh"),
|
|
70140
70498
|
...args.logPath ? { CLAWD_APP_BUILDER_LOG: args.logPath } : {}
|
|
70141
70499
|
}
|
|
70142
70500
|
}
|
|
70143
70501
|
}
|
|
70144
70502
|
};
|
|
70145
|
-
|
|
70146
|
-
|
|
70503
|
+
import_node_fs62.default.mkdirSync(args.dataDir, { recursive: true });
|
|
70504
|
+
import_node_fs62.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
|
|
70147
70505
|
return cfgPath;
|
|
70148
70506
|
}
|
|
70149
70507
|
|
|
@@ -70190,7 +70548,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
70190
70548
|
|
|
70191
70549
|
// src/extension/runtime.ts
|
|
70192
70550
|
var import_node_child_process26 = require("child_process");
|
|
70193
|
-
var
|
|
70551
|
+
var import_node_path79 = __toESM(require("path"), 1);
|
|
70194
70552
|
var import_promises18 = require("timers/promises");
|
|
70195
70553
|
|
|
70196
70554
|
// src/extension/port-allocator.ts
|
|
@@ -70291,7 +70649,7 @@ var Runtime = class {
|
|
|
70291
70649
|
/\$CLAWOS_EXT_PORT/g,
|
|
70292
70650
|
String(port)
|
|
70293
70651
|
);
|
|
70294
|
-
const dir =
|
|
70652
|
+
const dir = import_node_path79.default.join(this.root, extId);
|
|
70295
70653
|
const env = {
|
|
70296
70654
|
...process.env,
|
|
70297
70655
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -70403,7 +70761,7 @@ ${handle.stderrTail}`
|
|
|
70403
70761
|
|
|
70404
70762
|
// src/extension/published-channels.ts
|
|
70405
70763
|
var import_promises19 = __toESM(require("fs/promises"), 1);
|
|
70406
|
-
var
|
|
70764
|
+
var import_node_path80 = __toESM(require("path"), 1);
|
|
70407
70765
|
init_zod();
|
|
70408
70766
|
var PublishedChannelsError = class extends Error {
|
|
70409
70767
|
constructor(code, message) {
|
|
@@ -70502,7 +70860,7 @@ var PublishedChannelStore = class {
|
|
|
70502
70860
|
)
|
|
70503
70861
|
};
|
|
70504
70862
|
const tmp = `${this.filePath}.tmp`;
|
|
70505
|
-
await import_promises19.default.mkdir(
|
|
70863
|
+
await import_promises19.default.mkdir(import_node_path80.default.dirname(this.filePath), { recursive: true });
|
|
70506
70864
|
await import_promises19.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
70507
70865
|
await import_promises19.default.rename(tmp, this.filePath);
|
|
70508
70866
|
}
|
|
@@ -70510,7 +70868,7 @@ var PublishedChannelStore = class {
|
|
|
70510
70868
|
|
|
70511
70869
|
// src/extension/bundle-cache.ts
|
|
70512
70870
|
var import_promises20 = __toESM(require("fs/promises"), 1);
|
|
70513
|
-
var
|
|
70871
|
+
var import_node_path81 = __toESM(require("path"), 1);
|
|
70514
70872
|
var BundleCache = class {
|
|
70515
70873
|
constructor(rootDir) {
|
|
70516
70874
|
this.rootDir = rootDir;
|
|
@@ -70519,14 +70877,14 @@ var BundleCache = class {
|
|
|
70519
70877
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
70520
70878
|
async write(snapshotHash, buffer) {
|
|
70521
70879
|
await import_promises20.default.mkdir(this.rootDir, { recursive: true });
|
|
70522
|
-
const file =
|
|
70880
|
+
const file = import_node_path81.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
70523
70881
|
const tmp = `${file}.tmp`;
|
|
70524
70882
|
await import_promises20.default.writeFile(tmp, buffer, { mode: 384 });
|
|
70525
70883
|
await import_promises20.default.rename(tmp, file);
|
|
70526
70884
|
}
|
|
70527
70885
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
70528
70886
|
async read(snapshotHash) {
|
|
70529
|
-
const file =
|
|
70887
|
+
const file = import_node_path81.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
70530
70888
|
try {
|
|
70531
70889
|
return await import_promises20.default.readFile(file);
|
|
70532
70890
|
} catch (e) {
|
|
@@ -70536,7 +70894,7 @@ var BundleCache = class {
|
|
|
70536
70894
|
}
|
|
70537
70895
|
/** Idempotent — missing file is not an error. */
|
|
70538
70896
|
async delete(snapshotHash) {
|
|
70539
|
-
const file =
|
|
70897
|
+
const file = import_node_path81.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
70540
70898
|
await import_promises20.default.rm(file, { force: true });
|
|
70541
70899
|
}
|
|
70542
70900
|
};
|
|
@@ -70559,24 +70917,24 @@ async function startDaemon(config) {
|
|
|
70559
70917
|
sampling: logShippingCfg.sampling,
|
|
70560
70918
|
homeDir: import_node_os28.default.homedir()
|
|
70561
70919
|
});
|
|
70562
|
-
const logDir =
|
|
70563
|
-
|
|
70920
|
+
const logDir = import_node_path82.default.join(config.dataDir, "log");
|
|
70921
|
+
import_node_fs63.default.mkdirSync(logDir, { recursive: true });
|
|
70564
70922
|
const logger = createLogger({
|
|
70565
70923
|
level: config.logLevel,
|
|
70566
|
-
file:
|
|
70924
|
+
file: import_node_path82.default.join(logDir, "clawd.log"),
|
|
70567
70925
|
logClient
|
|
70568
70926
|
});
|
|
70569
70927
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
70570
70928
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
70571
|
-
file:
|
|
70929
|
+
file: import_node_path82.default.join(logDir, "screen-idle-probe.log"),
|
|
70572
70930
|
level: "debug"
|
|
70573
70931
|
});
|
|
70574
70932
|
logger.info("screen-idle probe logger enabled", {
|
|
70575
|
-
file:
|
|
70933
|
+
file: import_node_path82.default.join(logDir, "screen-idle-probe.log")
|
|
70576
70934
|
});
|
|
70577
70935
|
const CAP_TARGETS = [
|
|
70578
|
-
|
|
70579
|
-
|
|
70936
|
+
import_node_path82.default.join(logDir, "clawd.log"),
|
|
70937
|
+
import_node_path82.default.join(logDir, "screen-idle-probe.log")
|
|
70580
70938
|
];
|
|
70581
70939
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
70582
70940
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -70698,8 +71056,8 @@ async function startDaemon(config) {
|
|
|
70698
71056
|
const agents = new AgentsScanner();
|
|
70699
71057
|
const history = new ClaudeHistoryReader();
|
|
70700
71058
|
let transport = null;
|
|
70701
|
-
const personaStore = new PersonaStore(
|
|
70702
|
-
const usersRoot =
|
|
71059
|
+
const personaStore = new PersonaStore(import_node_path82.default.join(config.dataDir, "personas"));
|
|
71060
|
+
const usersRoot = import_node_path82.default.join(config.dataDir, "users");
|
|
70703
71061
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
70704
71062
|
if (defaultsRoot) {
|
|
70705
71063
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -70723,7 +71081,7 @@ async function startDaemon(config) {
|
|
|
70723
71081
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
70724
71082
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
70725
71083
|
const dispatchStore = createDispatchStore({
|
|
70726
|
-
filePath:
|
|
71084
|
+
filePath: import_node_path82.default.join(config.dataDir, "dispatch.json"),
|
|
70727
71085
|
now: () => Date.now(),
|
|
70728
71086
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
70729
71087
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -70732,7 +71090,7 @@ async function startDaemon(config) {
|
|
|
70732
71090
|
await dispatchStore.load();
|
|
70733
71091
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
70734
71092
|
const channelStore = createChannelStore({
|
|
70735
|
-
filePath:
|
|
71093
|
+
filePath: import_node_path82.default.join(config.dataDir, "channels.json"),
|
|
70736
71094
|
now: () => Date.now(),
|
|
70737
71095
|
genId: () => `ch-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
|
|
70738
71096
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
@@ -70741,7 +71099,7 @@ async function startDaemon(config) {
|
|
|
70741
71099
|
});
|
|
70742
71100
|
await channelStore.load();
|
|
70743
71101
|
const topicStore = createTopicStore({
|
|
70744
|
-
filePath:
|
|
71102
|
+
filePath: import_node_path82.default.join(config.dataDir, "topics.json"),
|
|
70745
71103
|
now: () => Date.now(),
|
|
70746
71104
|
genId: () => `tp-${(0, import_node_crypto23.randomUUID)().slice(0, 8)}`,
|
|
70747
71105
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
@@ -70768,28 +71126,28 @@ async function startDaemon(config) {
|
|
|
70768
71126
|
});
|
|
70769
71127
|
}
|
|
70770
71128
|
});
|
|
70771
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
71129
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path82.default.dirname((0, import_node_url5.fileURLToPath)(import_meta8.url));
|
|
70772
71130
|
const mcpConfigs = [];
|
|
70773
71131
|
const secretsBundleRoot = findSecretsBundleRoot(logger);
|
|
70774
|
-
const localSecretsDir =
|
|
71132
|
+
const localSecretsDir = import_node_path82.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
|
|
70775
71133
|
const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
|
|
70776
71134
|
const resolvePersonaMcpConfig = (personaId2) => renderPersonaMcpSecrets({
|
|
70777
71135
|
personaId: personaId2,
|
|
70778
|
-
personaDir:
|
|
71136
|
+
personaDir: import_node_path82.default.join(config.dataDir, "personas", personaId2),
|
|
70779
71137
|
secrets: readSecrets(),
|
|
70780
|
-
outDir:
|
|
71138
|
+
outDir: import_node_path82.default.join(config.dataDir, "persona-mcp"),
|
|
70781
71139
|
logger
|
|
70782
71140
|
});
|
|
70783
71141
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
70784
71142
|
const dispatchServerCandidates = [
|
|
70785
|
-
|
|
71143
|
+
import_node_path82.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
70786
71144
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
70787
|
-
|
|
71145
|
+
import_node_path82.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
70788
71146
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
70789
71147
|
];
|
|
70790
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
71148
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs63.default.existsSync(p2));
|
|
70791
71149
|
if (dispatchServerScriptPath) {
|
|
70792
|
-
const dispatchLogPath =
|
|
71150
|
+
const dispatchLogPath = import_node_path82.default.join(logDir, "dispatch-mcp-server.log");
|
|
70793
71151
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
70794
71152
|
dataDir: config.dataDir,
|
|
70795
71153
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -70809,12 +71167,12 @@ async function startDaemon(config) {
|
|
|
70809
71167
|
});
|
|
70810
71168
|
}
|
|
70811
71169
|
const ticketServerCandidates = [
|
|
70812
|
-
|
|
70813
|
-
|
|
71170
|
+
import_node_path82.default.join(here, "ticket", "mcp-server.cjs"),
|
|
71171
|
+
import_node_path82.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
70814
71172
|
];
|
|
70815
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
71173
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs63.default.existsSync(p2));
|
|
70816
71174
|
if (ticketServerScriptPath) {
|
|
70817
|
-
const ticketLogPath =
|
|
71175
|
+
const ticketLogPath = import_node_path82.default.join(logDir, "ticket-mcp-server.log");
|
|
70818
71176
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
70819
71177
|
dataDir: config.dataDir,
|
|
70820
71178
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -70836,12 +71194,12 @@ async function startDaemon(config) {
|
|
|
70836
71194
|
});
|
|
70837
71195
|
}
|
|
70838
71196
|
const shiftServerCandidates = [
|
|
70839
|
-
|
|
70840
|
-
|
|
71197
|
+
import_node_path82.default.join(here, "shift", "mcp-server.cjs"),
|
|
71198
|
+
import_node_path82.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
70841
71199
|
];
|
|
70842
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
71200
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs63.default.existsSync(p2));
|
|
70843
71201
|
if (shiftServerScriptPath) {
|
|
70844
|
-
const shiftLogPath =
|
|
71202
|
+
const shiftLogPath = import_node_path82.default.join(logDir, "shift-mcp-server.log");
|
|
70845
71203
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
70846
71204
|
dataDir: config.dataDir,
|
|
70847
71205
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -70862,12 +71220,12 @@ async function startDaemon(config) {
|
|
|
70862
71220
|
);
|
|
70863
71221
|
}
|
|
70864
71222
|
const inboxServerCandidates = [
|
|
70865
|
-
|
|
70866
|
-
|
|
71223
|
+
import_node_path82.default.join(here, "inbox", "mcp-server.cjs"),
|
|
71224
|
+
import_node_path82.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
70867
71225
|
];
|
|
70868
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p2) =>
|
|
71226
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs63.default.existsSync(p2));
|
|
70869
71227
|
if (inboxServerScriptPath) {
|
|
70870
|
-
const inboxLogPath =
|
|
71228
|
+
const inboxLogPath = import_node_path82.default.join(logDir, "inbox-mcp-server.log");
|
|
70871
71229
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
70872
71230
|
dataDir: config.dataDir,
|
|
70873
71231
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -70888,10 +71246,10 @@ async function startDaemon(config) {
|
|
|
70888
71246
|
);
|
|
70889
71247
|
}
|
|
70890
71248
|
const peerOpsServerCandidates = [
|
|
70891
|
-
|
|
70892
|
-
|
|
71249
|
+
import_node_path82.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
71250
|
+
import_node_path82.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
70893
71251
|
];
|
|
70894
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) =>
|
|
71252
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs63.default.existsSync(p2));
|
|
70895
71253
|
if (peerOpsServerScriptPath) {
|
|
70896
71254
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
70897
71255
|
dataDir: config.dataDir,
|
|
@@ -70911,12 +71269,12 @@ async function startDaemon(config) {
|
|
|
70911
71269
|
);
|
|
70912
71270
|
}
|
|
70913
71271
|
const rpcToolServerCandidates = [
|
|
70914
|
-
|
|
70915
|
-
|
|
71272
|
+
import_node_path82.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
71273
|
+
import_node_path82.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
70916
71274
|
];
|
|
70917
|
-
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) =>
|
|
71275
|
+
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs63.default.existsSync(p2));
|
|
70918
71276
|
if (rpcToolServerScriptPath) {
|
|
70919
|
-
const rpcToolLogPath =
|
|
71277
|
+
const rpcToolLogPath = import_node_path82.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
70920
71278
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
70921
71279
|
dataDir: config.dataDir,
|
|
70922
71280
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -70937,18 +71295,18 @@ async function startDaemon(config) {
|
|
|
70937
71295
|
);
|
|
70938
71296
|
}
|
|
70939
71297
|
const appBuilderServerCandidates = [
|
|
70940
|
-
|
|
70941
|
-
|
|
71298
|
+
import_node_path82.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
|
|
71299
|
+
import_node_path82.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
|
|
70942
71300
|
];
|
|
70943
|
-
const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) =>
|
|
71301
|
+
const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs63.default.existsSync(p2));
|
|
70944
71302
|
if (appBuilderServerScriptPath) {
|
|
70945
|
-
const appBuilderLogPath =
|
|
71303
|
+
const appBuilderLogPath = import_node_path82.default.join(logDir, "app-builder-mcp-server.log");
|
|
70946
71304
|
const appBuilderCfgPath = writeAppBuilderMcpConfig({
|
|
70947
71305
|
dataDir: config.dataDir,
|
|
70948
71306
|
serverScriptPath: appBuilderServerScriptPath,
|
|
70949
71307
|
daemonToken: resolvedAuthToken,
|
|
70950
71308
|
daemonUrl: mcpDaemonUrl,
|
|
70951
|
-
deployKitScriptsDir:
|
|
71309
|
+
deployKitScriptsDir: import_node_path82.default.join(config.dataDir, "deploy-kit", "scripts"),
|
|
70952
71310
|
logPath: appBuilderLogPath
|
|
70953
71311
|
});
|
|
70954
71312
|
mcpConfigs.push({ id: "app-builder", path: appBuilderCfgPath, personas: APP_BUILDER_PERSONAS });
|
|
@@ -70964,7 +71322,7 @@ async function startDaemon(config) {
|
|
|
70964
71322
|
);
|
|
70965
71323
|
}
|
|
70966
71324
|
const shiftStore = createShiftStore({
|
|
70967
|
-
filePath:
|
|
71325
|
+
filePath: import_node_path82.default.join(config.dataDir, "shift.json"),
|
|
70968
71326
|
ownerIdProvider: () => ownerPrincipalId,
|
|
70969
71327
|
now: () => Date.now()
|
|
70970
71328
|
});
|
|
@@ -70986,7 +71344,7 @@ async function startDaemon(config) {
|
|
|
70986
71344
|
getAdapter,
|
|
70987
71345
|
historyReader: history,
|
|
70988
71346
|
dataDir: config.dataDir,
|
|
70989
|
-
personaRoot:
|
|
71347
|
+
personaRoot: import_node_path82.default.join(config.dataDir, "personas"),
|
|
70990
71348
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
70991
71349
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
70992
71350
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -71043,10 +71401,10 @@ async function startDaemon(config) {
|
|
|
71043
71401
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
71044
71402
|
attachmentGroup: {
|
|
71045
71403
|
onFileEdit: (input) => {
|
|
71046
|
-
const absPath =
|
|
71404
|
+
const absPath = import_node_path82.default.isAbsolute(input.relPath) ? input.relPath : import_node_path82.default.join(input.cwd, input.relPath);
|
|
71047
71405
|
let size = 0;
|
|
71048
71406
|
try {
|
|
71049
|
-
size =
|
|
71407
|
+
size = import_node_fs63.default.statSync(absPath).size;
|
|
71050
71408
|
} catch (err) {
|
|
71051
71409
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
71052
71410
|
sessionId: input.sessionId,
|
|
@@ -71087,9 +71445,9 @@ async function startDaemon(config) {
|
|
|
71087
71445
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
71088
71446
|
}
|
|
71089
71447
|
const projectsStore = new ProjectsStore({
|
|
71090
|
-
file:
|
|
71448
|
+
file: import_node_path82.default.join(config.dataDir, "projects.json"),
|
|
71091
71449
|
clawdDir: config.dataDir,
|
|
71092
|
-
codexStateFile:
|
|
71450
|
+
codexStateFile: import_node_path82.default.join(import_node_os28.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
71093
71451
|
logger
|
|
71094
71452
|
});
|
|
71095
71453
|
const observer = new SessionObserver({
|
|
@@ -71157,13 +71515,13 @@ async function startDaemon(config) {
|
|
|
71157
71515
|
logger
|
|
71158
71516
|
});
|
|
71159
71517
|
registerAdapter("claude", claudeAdapter);
|
|
71160
|
-
const codexIsolatedHome =
|
|
71518
|
+
const codexIsolatedHome = import_node_path82.default.join(config.dataDir, "codex-home");
|
|
71161
71519
|
try {
|
|
71162
|
-
|
|
71520
|
+
import_node_fs63.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
71163
71521
|
for (const f of ["auth.json", "config.toml"]) {
|
|
71164
|
-
const link =
|
|
71165
|
-
const target =
|
|
71166
|
-
if (!
|
|
71522
|
+
const link = import_node_path82.default.join(codexIsolatedHome, f);
|
|
71523
|
+
const target = import_node_path82.default.join(import_node_os28.default.homedir(), ".codex", f);
|
|
71524
|
+
if (!import_node_fs63.default.existsSync(link) && import_node_fs63.default.existsSync(target)) import_node_fs63.default.symlinkSync(target, link);
|
|
71167
71525
|
}
|
|
71168
71526
|
} catch (err) {
|
|
71169
71527
|
logger.warn("codex isolated home setup failed", { err: String(err) });
|
|
@@ -71174,17 +71532,17 @@ async function startDaemon(config) {
|
|
|
71174
71532
|
logger,
|
|
71175
71533
|
historyReader: new CodexHistoryReader({
|
|
71176
71534
|
roots: codexRolloutRoots(config.dataDir),
|
|
71177
|
-
sharedHome:
|
|
71535
|
+
sharedHome: import_node_path82.default.join(import_node_os28.default.homedir(), ".codex"),
|
|
71178
71536
|
logger
|
|
71179
71537
|
}),
|
|
71180
71538
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
71181
71539
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
71182
71540
|
cwd,
|
|
71183
|
-
personaRoot:
|
|
71541
|
+
personaRoot: import_node_path82.default.join(config.dataDir, "personas"),
|
|
71184
71542
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
71185
71543
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
71186
71544
|
projectPaths: projectsStore.listMerged().map((x) => x.path),
|
|
71187
|
-
sharedHome:
|
|
71545
|
+
sharedHome: import_node_path82.default.join(import_node_os28.default.homedir(), ".codex"),
|
|
71188
71546
|
isolatedHome: codexIsolatedHome
|
|
71189
71547
|
}),
|
|
71190
71548
|
// 附件图片验签:与 http-router /files 路由同一把 secret
|
|
@@ -71193,10 +71551,10 @@ async function startDaemon(config) {
|
|
|
71193
71551
|
);
|
|
71194
71552
|
registerAdapter(CODEX_CLOUD_TOOL_ID, new CloudCodexAdapter({ client: cloudGateway, logger, getSignSecret: () => authFile.token }));
|
|
71195
71553
|
const piMcpBridgeCandidates = [
|
|
71196
|
-
|
|
71197
|
-
|
|
71554
|
+
import_node_path82.default.join(here, "pi-mcp-bridge", "extension.cjs"),
|
|
71555
|
+
import_node_path82.default.join(here, "..", "dist", "pi-mcp-bridge", "extension.cjs")
|
|
71198
71556
|
];
|
|
71199
|
-
const piMcpBridgePath = piMcpBridgeCandidates.find((p2) =>
|
|
71557
|
+
const piMcpBridgePath = piMcpBridgeCandidates.find((p2) => import_node_fs63.default.existsSync(p2));
|
|
71200
71558
|
if (piMcpBridgePath) {
|
|
71201
71559
|
logger.info("pi-mcp-bridge extension resolved", { path: piMcpBridgePath });
|
|
71202
71560
|
} else {
|
|
@@ -71507,11 +71865,11 @@ async function startDaemon(config) {
|
|
|
71507
71865
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
71508
71866
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
71509
71867
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
71510
|
-
personaRoot:
|
|
71868
|
+
personaRoot: import_node_path82.default.join(config.dataDir, "personas"),
|
|
71511
71869
|
usersRoot
|
|
71512
71870
|
},
|
|
71513
71871
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
71514
|
-
personaRoot:
|
|
71872
|
+
personaRoot: import_node_path82.default.join(config.dataDir, "personas"),
|
|
71515
71873
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
71516
71874
|
usersRoot,
|
|
71517
71875
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -71590,6 +71948,20 @@ async function startDaemon(config) {
|
|
|
71590
71948
|
issue: (args) => centralIssueApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args })
|
|
71591
71949
|
}
|
|
71592
71950
|
},
|
|
71951
|
+
// 云 persona 卡片上的连接器区(design 2026-09-11-mcp-connector §3.8):装了什么以 gateway 登记行为真源,
|
|
71952
|
+
// 连没连上问中心。登录凭证只在 daemon 内部传给中心,与 apiKeyClient 同一条纪律。
|
|
71953
|
+
cloudConnectors: {
|
|
71954
|
+
getPersona: (personaId2) => personaRegistry.get(personaId2),
|
|
71955
|
+
gatewayConnectors: (gatewayPersonaId) => cloudGateway.personaConnectors(gatewayPersonaId),
|
|
71956
|
+
readIdentity: () => {
|
|
71957
|
+
const r = ownerIdentityStore.read();
|
|
71958
|
+
return r ? { ttcJwt: r.ttcToken, provider: r.identity.provider } : null;
|
|
71959
|
+
},
|
|
71960
|
+
central: {
|
|
71961
|
+
mine: (args) => centralConnectorsMine({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args }),
|
|
71962
|
+
fill: (args) => centralConnectorFill({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args })
|
|
71963
|
+
}
|
|
71964
|
+
},
|
|
71593
71965
|
// 设备目录 + 连接(决策 #15:daemon 代理中心 server)。
|
|
71594
71966
|
// exchange/listDevices 包掉 owner ttcJwt(每次现读 store——热切换后立即用新身份);
|
|
71595
71967
|
// dispatcher 的 FEISHU_GATED_METHODS gate 已保证未登录时这些 RPC 到不了 handler,
|
|
@@ -71618,11 +71990,11 @@ async function startDaemon(config) {
|
|
|
71618
71990
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
71619
71991
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
71620
71992
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
71621
|
-
appBuilderPersonaRoot:
|
|
71993
|
+
appBuilderPersonaRoot: import_node_path82.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
71622
71994
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
71623
|
-
deployKitRoot:
|
|
71995
|
+
deployKitRoot: import_node_path82.default.join(config.dataDir, "deploy-kit"),
|
|
71624
71996
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
71625
|
-
resolvePersonaRoot: (personaId2) =>
|
|
71997
|
+
resolvePersonaRoot: (personaId2) => import_node_path82.default.join(config.dataDir, "personas", personaId2),
|
|
71626
71998
|
// 凭据表(M1b Step 5):与 MCP 那条同一张表、同一个来源,只是交付给另一个子进程。
|
|
71627
71999
|
readSecrets,
|
|
71628
72000
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
@@ -71819,7 +72191,7 @@ async function startDaemon(config) {
|
|
|
71819
72191
|
});
|
|
71820
72192
|
shiftScheduler.start();
|
|
71821
72193
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
71822
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
72194
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path82.default.join(config.dataDir, "personas"));
|
|
71823
72195
|
const larkBotCloud = createLarkBotCloudClient({
|
|
71824
72196
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
71825
72197
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -71833,7 +72205,7 @@ async function startDaemon(config) {
|
|
|
71833
72205
|
store: larkBotStore,
|
|
71834
72206
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
71835
72207
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
71836
|
-
mediaRootFor: (chatId) =>
|
|
72208
|
+
mediaRootFor: (chatId) => import_node_path82.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
71837
72209
|
isShuttingDown: () => larkDraining,
|
|
71838
72210
|
logger: {
|
|
71839
72211
|
warn: (msg) => logger.warn(msg),
|
|
@@ -72140,8 +72512,8 @@ async function startDaemon(config) {
|
|
|
72140
72512
|
const lines = [
|
|
72141
72513
|
`Tunnel: ${r.url}`,
|
|
72142
72514
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
72143
|
-
`Frpc config: ${
|
|
72144
|
-
`Frpc log: ${
|
|
72515
|
+
`Frpc config: ${import_node_path82.default.join(config.dataDir, "frpc.toml")}`,
|
|
72516
|
+
`Frpc log: ${import_node_path82.default.join(logDir, "frpc.log")}`
|
|
72145
72517
|
];
|
|
72146
72518
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
72147
72519
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -72154,8 +72526,8 @@ ${bar}
|
|
|
72154
72526
|
|
|
72155
72527
|
`);
|
|
72156
72528
|
try {
|
|
72157
|
-
const connectPath =
|
|
72158
|
-
|
|
72529
|
+
const connectPath = import_node_path82.default.join(config.dataDir, "connect.txt");
|
|
72530
|
+
import_node_fs63.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
72159
72531
|
} catch {
|
|
72160
72532
|
}
|
|
72161
72533
|
} catch (err) {
|
|
@@ -72242,9 +72614,9 @@ ${bar}
|
|
|
72242
72614
|
};
|
|
72243
72615
|
}
|
|
72244
72616
|
function migrateDropPersonsDir(dataDir) {
|
|
72245
|
-
const dir =
|
|
72617
|
+
const dir = import_node_path82.default.join(dataDir, "persons");
|
|
72246
72618
|
try {
|
|
72247
|
-
|
|
72619
|
+
import_node_fs63.default.rmSync(dir, { recursive: true, force: true });
|
|
72248
72620
|
} catch {
|
|
72249
72621
|
}
|
|
72250
72622
|
}
|